1 /* ttt-server.c - tic-tac-toe game server
3 * Copyright © 2005 Carl Worth
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)
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.
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.
19 * Author: Carl Worth <cworth@cworth.org>
22 #include "ttt-server.h"
25 #include "ttt-client.h"
26 #include "ttt-error.h"
27 #include "ttt-socket.h"
30 pthread_mutex_t mutex;
35 ttt_client_t **clients;
41 ttt_server_init (ttt_server_t *server, const char *host, const char *port)
43 pthread_mutex_init (&server->mutex, NULL);
48 server->clients = NULL;
49 server->clients_size = 0;
50 server->num_clients = 0;
53 /* Exported: See ttt-server.h for documentation. */
55 ttt_server_register_client (ttt_server_t *server, ttt_client_t *client)
58 ttt_error_t error = TTT_ERROR_NONE;
61 pthread_mutex_lock (&server->mutex);
63 name = ttt_client_get_name (client);
65 assert (name != NULL);
68 return TTT_ERROR_INVALID_NAME;
70 for (i = 0; i < server->num_clients; i++) {
71 if (strcmp (ttt_client_get_name (server->clients[i]), name) == 0) {
72 error = TTT_ERROR_INVALID_NAME;
77 printf ("Client %s has joined.\n", name);
79 server->num_clients++;
81 if (server->num_clients > server->clients_size) {
82 if (server->clients_size == 0)
83 server->clients_size = 1;
85 server->clients_size *= 2;
87 server->clients = xrealloc (server->clients,
88 server->clients_size * sizeof (ttt_client_t *));
91 server->clients [server->num_clients - 1] = client;
94 pthread_mutex_unlock (&server->mutex);
99 /* Exported: See ttt-server.h for documentation. */
101 ttt_server_unregister_client (ttt_server_t *server, ttt_client_t *client)
105 pthread_mutex_lock (&server->mutex);
107 for (i = 0; i < server->num_clients; i++)
108 if (server->clients[i] == client)
111 assert (i < server->num_clients);
113 printf ("Client %s has left.\n", ttt_client_get_name (client));
115 memmove (&server->clients[i], &server->clients[i+1],
116 (server->num_clients - i - 1) * sizeof (ttt_client_t *));
118 server->num_clients--;
120 pthread_mutex_unlock (&server->mutex);
123 /* Exported: See ttt-server.h for documentation. */
125 ttt_server_broadcast (ttt_server_t *server, const char *message)
129 pthread_mutex_lock (&server->mutex);
131 for (i = 0; i < server->num_clients; i++)
132 ttt_client_send (server->clients[i], message);
134 pthread_mutex_unlock (&server->mutex);
137 /* Exported: See ttt-server.h for documentation. */
139 ttt_server_who (ttt_server_t *server)
144 pthread_mutex_lock (&server->mutex);
146 xasprintf (&response, "WHO");
148 for (i = 0; i < server->num_clients; i++)
149 xasprintf (&response, "%s %s %d",
151 ttt_client_get_name (server->clients[i]),
152 ttt_client_get_num_wins (server->clients[i]));
154 xasprintf (&response, "%s\n", response);
156 pthread_mutex_unlock (&server->mutex);
161 /* Exported: See ttt-server.h for documentation. */
163 ttt_server_get_host (ttt_server_t *server)
168 /* Exported: See ttt-server.h for documentation. */
170 ttt_server_get_port (ttt_server_t *server)
175 static const char *WELCOME_MESSAGE =
176 "Welcome to ttt-server. So far, this program is still a demonstration\n"
177 "TCP/IP server, acting something like a rather braindead chat server.\n"
178 "The server is currently listening on:\n"
180 "\nTo test this, simply connect one or more clients to that host and port.\n"
183 "\nOnce you have connected a client, the server will send each line of text\n"
184 "it receives to all connected clients. The server reports client joins and\n"
185 "departures on stdout.\n"
186 "\nNote that to terminate the telnet client you type Control-], then\n"
187 "<Enter>, then \"close\" (and <Enter>) at the \"telnet> \" prompt.\n"
190 "\nPS. At this point we're ready to leave the demonstration phase and to\n"
191 "begin implementing TTTP (tic-tac-toe protocol) as well as fixing the\n"
192 "protocol specifcation. We don't need a custom client to move forward on\n"
193 "the server (that is one of the ideas behind using a telnet-compatible\n"
194 "protocol), but a custom client would still be a fine project for a\n"
195 "motivated beginning programmer.\n\n";
198 _ttt_server_accept (void *closure, int client_socket)
200 ttt_server_t *server = closure;
202 ttt_client_new (server, client_socket);
206 main (int argc, char **argv)
212 ttt_args_parse (&args, argc, argv);
215 xfreopen (args.log_file, "a", stderr);
217 socket = ttt_socket_create_server (args.host, args.port);
219 printf (WELCOME_MESSAGE, args.host, args.port, args.host, args.port);
221 ttt_server_init (&server, args.host, args.port);
224 ttt_socket_accept (socket, _ttt_server_accept, &server);
226 /* We only reach here if something bad happened. */