X-Git-Url: https://git.cworth.org/git?p=ttt;a=blobdiff_plain;f=src%2Fttt-client.c;h=53cc4ff3556ce728669a8833919a85c19d197a01;hp=8139ada1de03cb04a2e7c7c986ebd0aa1d136983;hb=e2c8706061d31d48f9516297d118d230354a5949;hpb=c6398c6a1b59f6eddefc9f9ce577017b15677251 diff --git a/src/ttt-client.c b/src/ttt-client.c index 8139ada..53cc4ff 100644 --- a/src/ttt-client.c +++ b/src/ttt-client.c @@ -29,18 +29,146 @@ struct _ttt_client { pthread_mutex_t mutex; - pthread_t thread; + pthread_t thread; - ttt_server_t *server; - int socket; - yyscan_t scanner; + ttt_server_t *server; + int socket; + yyscan_t scanner; - int id; + char **request_strings; + int num_request_strings; - char **request_strings; - int num_request_strings; + char *name; + ttt_bool_t registered; + int num_wins; }; +typedef ttt_error_t (*ttt_command_func_t) (ttt_client_t *client, + char **args, + int num_args); + +static ttt_error_t +_ttt_client_execute_helo (ttt_client_t *client, + char **args, + int num_args); + +static ttt_error_t +_ttt_client_execute_who (ttt_client_t *client, + char **args, + int num_args); + +static ttt_error_t +_ttt_client_execute_quit (ttt_client_t *client, + char **args, + int num_args); + +static ttt_error_t +_ttt_client_execute_message (ttt_client_t *client, + char **args, + int num_args); + + + +typedef struct _ttt_command_description { + const char *command; + int args_required; + ttt_command_func_t execute; +} ttt_command_description_t; + +ttt_command_description_t command_descriptions[] = { + {"HELO", 1, _ttt_client_execute_helo}, + {"WHO", 0, _ttt_client_execute_who }, + {"QUIT", 0, _ttt_client_execute_quit}, + {"MESSAGE", 1, _ttt_client_execute_message} +}; + +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) + +static ttt_error_t +_ttt_client_execute_helo (ttt_client_t *client, + char **args, + int num_args) +{ + ttt_error_t error; + char *response; + + assert (num_args == 1); + + ttt_client_set_name (client, args[0]); + + error = ttt_server_register_client (client->server, client); + if (error) + return error; + + client->registered = TRUE; + + xasprintf (&response, "HELO %s %s %s\n", + client->name, + ttt_server_get_host (client->server), + ttt_server_get_port (client->server)); + + ttt_client_send (client, response); + + free (response); + + return TTT_ERROR_NONE; +} + +static ttt_error_t +_ttt_client_execute_who (ttt_client_t *client, + char **args, + int num_args) +{ + char *response; + + assert (num_args == 0); + + response = ttt_server_who (client->server); + + ttt_client_send (client, response); + + free (response); + + return TTT_ERROR_NONE; +} + +static ttt_error_t +_ttt_client_execute_quit (ttt_client_t *client, + char **args, + int num_args) +{ + assert (num_args == 0); + + return TTT_ERROR_QUIT_REQUESTED; +} + +static ttt_error_t +_ttt_client_execute_message (ttt_client_t *client, + char **args, + int num_args) +{ + char *response; + int i; + + assert (num_args > 0); + + xasprintf(&response, "MESSAGE\n"); + ttt_client_send (client, response); + + xasprintf(&response, "NOTICE MESSAGE %s", client->name); + for (i=0; iserver,response); + + free (response); + return TTT_ERROR_NONE; + + +} + static void _free_request (ttt_client_t *client); @@ -63,10 +191,9 @@ _ttt_client_init (ttt_client_t *client, client->request_strings = NULL; client->num_request_strings = 0; - /* XXX: Probably want to register only as the result of the HELO - command. Not only will that match the protocol correctly, but - it will also eliminate a race condition here. */ - client->id = ttt_server_register_client (server, client); + client->name = NULL; + client->registered = FALSE; + client->num_wins = 0; } static void @@ -74,7 +201,11 @@ _ttt_client_fini (ttt_client_t *client) { pthread_mutex_lock (&client->mutex); - ttt_server_unregister_client (client->server, client); + if (client->registered) + ttt_server_unregister_client (client->server, client); + + free (client->name); + client->name = NULL; yylex_destroy (client->scanner); shutdown (client->socket, SHUT_RDWR); @@ -144,10 +275,23 @@ _execute_request (ttt_client_t *client) { int i; - for (i=0; i < client->num_request_strings; i++) - ttt_server_broadcast (client->server, client->request_strings[i]); + char *command = client->request_strings[0]; + int num_args = client->num_request_strings-1; + ttt_command_description_t *desc; - return TTT_ERROR_NONE; + for (i=0; i < strlen (command); i++) + command[i] = toupper (command[i]); + + for (i=0; i < ARRAY_SIZE(command_descriptions); i++) { + desc = &command_descriptions[i]; + if (strcmp(command, desc->command) == 0) { + if (num_args < desc->args_required) + return TTT_ERROR_SYNTAX; + return (desc->execute) (client, &client->request_strings[1], num_args); + } + } + + return TTT_ERROR_COMMAND; } static void * @@ -166,6 +310,8 @@ _handle_requests_thread (void *closure) ASSERT_NOT_REACHED; error = _execute_request (client); + if (error == TTT_ERROR_QUIT_REQUESTED) + break; if (error) ttt_client_send (client, ttt_error_string (error)); } @@ -208,9 +354,24 @@ ttt_client_send (ttt_client_t *client, const char *message) pthread_mutex_unlock (&client->mutex); } +/* Exported: See ttt-client.h for documentation. */ +const char* +ttt_client_get_name (ttt_client_t *client) +{ + return client->name; +} + +/* Exported: See ttt-client.h for documentation. */ +void +ttt_client_set_name (ttt_client_t *client, const char *name) +{ + free (client->name); + client->name = xstrdup (name); +} + /* Exported: See ttt-client.h for documentation. */ int -ttt_client_get_id (ttt_client_t *client) +ttt_client_get_num_wins (ttt_client_t *client) { - return client->id; + return client->num_wins; }