]> git.cworth.org Git - ttt/blob - src/ttt-server.c
2005-11-15 Carl Worth <cworth@cworth.org>
[ttt] / src / ttt-server.c
1 /* ttt-server.c - tic-tac-toe game server
2  *
3  * Copyright © 2005 Carl Worth
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Author: Carl Worth <cworth@cworth.org>
20  */
21
22 #include "ttt-server.h"
23
24 #include "ttt-args.h"
25 #include "ttt-client.h"
26 #include "ttt-socket.h"
27
28 struct _ttt_server {
29     pthread_mutex_t mutex;
30
31     int next_client_id;
32
33     ttt_client_t **clients;
34     int clients_size;
35     int num_clients;
36 };
37
38 static void
39 ttt_server_init (ttt_server_t *server)
40 {
41     pthread_mutex_init (&server->mutex, NULL);
42
43     server->next_client_id = 0;
44
45     server->clients = NULL;
46     server->clients_size = 0;
47     server->num_clients = 0;
48 }
49
50 /* Exported: See ttt-server.h for documentation. */
51 int
52 ttt_server_register_client (ttt_server_t *server, ttt_client_t *client)
53 {
54     int id;
55
56     pthread_mutex_lock (&server->mutex);
57
58     id = server->next_client_id++;
59
60     printf ("Client %d has joined.\n", id);
61
62     server->num_clients++;
63
64     if (server->num_clients > server->clients_size) {
65         if (server->clients_size == 0)
66             server->clients_size = 1;
67         else
68             server->clients_size *= 2;
69
70         server->clients = xrealloc (server->clients,
71                                     server->clients_size * sizeof (ttt_client_t *));
72     }
73
74     server->clients [server->num_clients - 1] = client;
75
76     pthread_mutex_unlock (&server->mutex);
77
78     return id;
79 }
80
81 /* Exported: See ttt-server.h for documentation. */
82 void
83 ttt_server_unregister_client (ttt_server_t *server, ttt_client_t *client)
84 {
85     int i;
86
87     pthread_mutex_lock (&server->mutex);
88
89     for (i = 0; i < server->num_clients; i++)
90         if (server->clients[i] == client)
91             break;
92
93     assert (i < server->num_clients);
94
95     printf ("Client %d has left.\n", ttt_client_get_id (client));
96
97     memmove (&server->clients[i], &server->clients[i+1],
98              (server->num_clients - i - 1) * sizeof (ttt_client_t *));
99
100     server->num_clients--;
101
102     pthread_mutex_unlock (&server->mutex);
103 }
104
105 void
106 ttt_server_broadcast (ttt_server_t *server, const char *message)
107 {
108     int i;
109
110     pthread_mutex_lock (&server->mutex);
111
112     for (i = 0; i < server->num_clients; i++)
113         ttt_client_send (server->clients[i], message);
114
115     pthread_mutex_unlock (&server->mutex);
116 }
117
118 static const char *WELCOME_MESSAGE = 
119 "Welcome to ttt-server. So far, this program is still a demonstration\n"
120 "TCP/IP server, acting something like a rather braindead chat server.\n"
121 "The server is currently listening on:\n"
122 "\n     %s:%s\n"
123 "\nTo test this, simply connect one or more clients to that host and port.\n"
124 "For example:\n"
125 "\n     telnet %s %s\n"
126 "\nOnce you have connected a client, the server will send each line of text\n"
127 "it receives to all connected clients. The server reports client joins and\n"
128 "departures on stdout.\n"
129 "\nNote that to terminate the telnet client you type Control-], then\n"
130 "<Enter>, then \"close\" (and <Enter>) at the \"telnet> \" prompt.\n"
131 "\nHave fun!\n"
132 "-Carl\n"
133 "\nPS. At this point we're ready to leave the demonstration phase and to\n"
134 "begin implementing TTTP (tic-tac-toe protocol) as well as fixing the\n"
135 "protocol specifcation. We don't need a custom client to move forward on\n"
136 "the server (that is one of the ideas behind using a telnet-compatible\n"
137 "protocol), but a custom client would still be a fine project for a\n"
138 "motivated beginning programmer.\n\n";
139
140 static void
141 _ttt_server_accept (void *closure, int client_socket)
142 {
143     ttt_server_t *server = closure;
144
145     ttt_client_new (server, client_socket);
146 }
147
148 int 
149 main (int argc, char **argv)
150 {
151     ttt_args_t args;
152     ttt_server_t server;
153     int socket;
154
155     ttt_args_parse (&args, argc, argv);
156
157     if (args.log_file)
158         xfreopen (args.log_file, "a", stderr);
159
160     socket = ttt_socket_create_server (args.host, args.port);
161
162     printf (WELCOME_MESSAGE, args.host, args.port, args.host, args.port);
163
164     ttt_server_init (&server);
165
166     while (1)
167         ttt_socket_accept (socket, _ttt_server_accept, &server);
168
169     /* We only reach here if something bad happened. */
170     return 1;
171 }