X-Git-Url: https://git.cworth.org/git?p=ttt;a=blobdiff_plain;f=src%2Fttt-client.c;h=81f6e13e14268227e23a640f8288d933e7e66e15;hp=3fdcf83afea53e444c14fa521cc8b6d60f97ced2;hb=b18c78a24034922e7b9152a03683cf930d703dd0;hpb=84db9bf52aa25c19f7d547ea2dbec69ca4452300 diff --git a/src/ttt-client.c b/src/ttt-client.c index 3fdcf83..81f6e13 100644 --- a/src/ttt-client.c +++ b/src/ttt-client.c @@ -21,7 +21,8 @@ #include "ttt-client.h" -#include "ttt-command.h" +#define YY_DECL int yylex (yyscan_t yyscanner, ttt_token_t *token) + #include "ttt-error.h" #include "ttt-lex.h" #include "ttt-server.h" @@ -30,16 +31,18 @@ struct _ttt_client { pthread_mutex_t mutex; - pthread_t thread; - - ttt_server_t *server; - int socket; - yyscan_t scanner; - - char *name; - - char **request_strings; - int num_request_strings; + pthread_t thread; + + ttt_server_t *server; + int socket; + yyscan_t scanner; + + 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, @@ -51,17 +54,49 @@ _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_message (ttt_client_t *client, + char **args, + int num_args); + +static ttt_error_t +_ttt_client_execute_help (ttt_client_t *client, + char **args, + int num_args); + +static ttt_error_t +_ttt_client_execute_version (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); + typedef struct _ttt_command_description { - const char *command; - int args_min; - int args_max; + const char *command; + int args_min; + int args_max; ttt_command_func_t execute; } ttt_command_description_t; ttt_command_description_t command_descriptions[] = { - {"HELO", 0, 1, _ttt_client_execute_helo} + {"HELO", 1, 1, _ttt_client_execute_helo }, + {"WHO", 0, 0, _ttt_client_execute_who }, + {"MESSAGE", 1, 1, _ttt_client_execute_message}, + {"HELP", 0, 1, _ttt_client_execute_help }, + {"VERSION", 1, 1, _ttt_client_execute_version}, + {"QUIT", 0, 0, _ttt_client_execute_quit } }; +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) + static ttt_error_t _ttt_client_execute_helo (ttt_client_t *client, char **args, @@ -69,18 +104,46 @@ _ttt_client_execute_helo (ttt_client_t *client, { ttt_error_t error; char *response; + char *notice; + + assert (num_args == 1); - if (num_args == 1) - ttt_client_set_name (client, args[0]); + 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, + xasprintf (&response, "HELO %s %s %s\r\n", + client->name, ttt_server_get_host (client->server), ttt_server_get_port (client->server)); + ttt_client_send (client, response); + + xasprintf (¬ice, "NOTICE USER %s\r\n", + client->name); + ttt_server_broadcast (client->server, notice); + + free (notice); + 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); + + if (!client->registered) + return TTT_ERROR_NO_NAME_SET; + + response = xstrdup (ttt_server_who (client->server)); ttt_client_send (client, response); free (response); @@ -88,7 +151,88 @@ _ttt_client_execute_helo (ttt_client_t *client, return TTT_ERROR_NONE; } -#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) +static ttt_error_t +_ttt_client_execute_message (ttt_client_t *client, + char **args, + int num_args) +{ + char *response; + char *notice; + + assert (num_args == 1); + + if (!client->registered) + return TTT_ERROR_NO_NAME_SET; + + xasprintf(&response, "MESSAGE\r\n"); + ttt_client_send (client, response); + + xasprintf(¬ice, "NOTICE MESSAGE %s \"%s\"\r\n", + client->name, + args[0]); + ttt_server_broadcast (client->server, notice); + + free (notice); + free (response); + + return TTT_ERROR_NONE; +} + +static ttt_error_t +_ttt_client_execute_help (ttt_client_t *client, + char **args, + int num_args) +{ + char *response; + + /* XXX: NYI */ + + xasprintf(&response, "HELP - NYI\r\n"); + ttt_client_send (client, response); + + free (response); + return TTT_ERROR_NONE; +} + +static ttt_error_t +_ttt_client_execute_version (ttt_client_t *client, + char **args, + int num_args) +{ + char *response; + + assert (num_args == 1); + + /* XXX: Argument is being ignored. + This is not completely implemented. */ + + xasprintf (&response, "VERSION 1\r\n"); + 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) +{ + char *notice; + + assert (num_args == 0); + + if (!client->registered) + return TTT_ERROR_QUIT_REQUESTED; + + xasprintf (¬ice, "NOTICE QUIT %s\r\n", + client->name); + ttt_server_broadcast (client->server, notice); + + free (notice); + + return TTT_ERROR_QUIT_REQUESTED; +} static void _free_request (ttt_client_t *client); @@ -106,13 +250,15 @@ _ttt_client_init (ttt_client_t *client, client->socket = socket; file = xfdopen (socket, "r"); - yylex_init(&client->scanner); + yylex_init (&client->scanner); yyset_in (file, client->scanner); client->request_strings = NULL; client->num_request_strings = 0; client->name = NULL; + client->registered = FALSE; + client->num_wins = 0; } static void @@ -120,7 +266,8 @@ _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; @@ -166,25 +313,28 @@ static ttt_status_t _read_request (ttt_client_t *client) { ttt_token_t token; + ttt_token_type_t token_type; _free_request (client); while (1) { - token = yylex (client->scanner); + token_type = yylex (client->scanner, &token); /* Yes, EOF in two different enums is pretty ugly. */ - if (token == TTT_TOKEN_EOF) + if (token_type == TTT_TOKEN_TYPE_EOF) return TTT_STATUS_EOF; - if (token == TTT_TOKEN_NEWLINE) { + if (token_type == TTT_TOKEN_TYPE_NEWLINE) { if (client->num_request_strings) return TTT_STATUS_SUCCESS; else continue; } - assert (token == TTT_TOKEN_STRING); - - _append_to_request (client, yyget_text (client->scanner)); + assert (token_type == TTT_TOKEN_TYPE_STRING); + + _append_to_request (client, token.u.string); + + free (token.u.string); } } @@ -206,8 +356,8 @@ _execute_request (ttt_client_t *client) if ((num_args < desc->args_min) || (num_args > desc->args_max)) return TTT_ERROR_SYNTAX; return (desc->execute) (client, &client->request_strings[1], num_args); - } } + } return TTT_ERROR_COMMAND; } @@ -228,6 +378,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)); } @@ -253,7 +405,7 @@ ttt_client_new (void *closure, int client_socket) err = pthread_create (&client->thread, NULL, _handle_requests_thread, client); if (err != 0) { - fprintf (stderr, "Error: pthread_create failed: %s. Aborting.\n", + fprintf (stderr, "Error: pthread_create failed: %s. Aborting.\r\n", strerror (err)); exit (1); } @@ -284,3 +436,10 @@ 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_num_wins (ttt_client_t *client) +{ + return client->num_wins; +}