From b18c78a24034922e7b9152a03683cf930d703dd0 Mon Sep 17 00:00:00 2001 From: Richard Worth Date: Fri, 2 Dec 2005 01:38:34 +0000 Subject: [PATCH 1/1] 2005-12-01 Richard D. Worth * TODO: Check off NOTICE MESSAGE, ERROR NONAMESET. * PROTOCOL: Add NONAMESET error in possible errors where applicable. Add description for MESSAGE. * src/ttt-token.h: Add token typedef. Rename token type enum. * src/ttt-lex.l: Add support for quoted string as single token. * src/ttt-lex.h: Autogenerated. * src/ttt-client.c: (_ttt_client_execute_helo), (_ttt_client_execute_who), (_ttt_client_execute_message), (_ttt_client_execute_help), (_ttt_client_execute_version), (_ttt_client_execute_quit), (_ttt_client_init), (_read_request), (_execute_request): Whitespace changes. Implement VERSION, HELP. Change args_required back to args_min and args_max (see PROTOCOL\HELP). Modify MESSAGE to accept one token arg and quote output. Return NONAMESET error where applicable. --- ChangeLog | 21 +++++++ PROTOCOL | 25 ++++++-- TODO | 4 +- src/ttt-client.c | 153 +++++++++++++++++++++++++++++++++-------------- src/ttt-lex.h | 5 +- src/ttt-lex.l | 54 ++++++++++++++++- src/ttt-token.h | 14 ++++- 7 files changed, 214 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index 27e0d4b..2361926 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2005-12-01 Richard D. Worth + + * TODO: Check off NOTICE MESSAGE, ERROR NONAMESET. + + * PROTOCOL: Add NONAMESET error in possible errors where + applicable. Add description for MESSAGE. + + * src/ttt-token.h: Add token typedef. Rename token type enum. + + * src/ttt-lex.l: Add support for quoted string as single token. + * src/ttt-lex.h: Autogenerated. + + * src/ttt-client.c: (_ttt_client_execute_helo), + (_ttt_client_execute_who), (_ttt_client_execute_message), + (_ttt_client_execute_help), (_ttt_client_execute_version), + (_ttt_client_execute_quit), (_ttt_client_init), (_read_request), + (_execute_request): Whitespace changes. Implement VERSION, + HELP. Change args_required back to args_min and args_max (see + PROTOCOL\HELP). Modify MESSAGE to accept one token arg and quote + output. Return NONAMESET error where applicable. + 2005-11-29 Carl Worth * src/ttt-socket.h: diff --git a/PROTOCOL b/PROTOCOL index c507ffe..d855cdf 100644 --- a/PROTOCOL +++ b/PROTOCOL @@ -59,7 +59,9 @@ Document Conventions WHO ... - lists connected users and the number of games they've won. + Lists connected users and the number of games they've won. + + Possible errors: NONAMESET 1.2.2. Message @@ -69,6 +71,12 @@ Document Conventions MESSAGE + Sends a message to all connected users. The text must be a + single token. Use a quoted-string to include spaces in the + message text. + + Possible errors: NONAMESET + 1.2.3. Help HELP { } @@ -111,7 +119,7 @@ Document Conventions INVITE - Possible errors: NOUSER, BUSY + Possible errors: NOUSER, BUSY, NONAMESET 1.3.2. Accepting an invitation @@ -121,6 +129,8 @@ Document Conventions ACCEPT + Possible errors: NONAMESET + 1.4. In-game commands 1.4.1. Get the game contents @@ -148,7 +158,7 @@ Document Conventions _|X|_ X|O|O" - Possible errors: NOTINGAME + Possible errors: NOTINGAME, NONAMESET 1.4.2. Part @@ -160,7 +170,7 @@ Document Conventions Departs the current game - Possible errors: NOTINGAME + Possible errors: NOTINGAME, NONAMESET 1.4.3. Making a move @@ -177,7 +187,7 @@ Document Conventions 3|4|5 6|7|8 - Possible errors: NOTINGAME, NOTYOURMOVE, NOTGRID + Possible errors: NOTINGAME, NOTYOURMOVE, NOTGRID, NONAMESET 2. Asynchronous notification. @@ -254,7 +264,10 @@ Document Conventions ERROR NONAMESET - 'helo' must be sent before any command other than 'quit'. + 'helo' must be sent before any command other than 'help', + 'version', 'quit'. + + Possibly returned by: WHO MESSAGE INVITE ACCEPT SHOW PART MOVE 3.1.2. Invalid name diff --git a/TODO b/TODO index c55f890..ec6630f 100644 --- a/TODO +++ b/TODO @@ -25,7 +25,7 @@ S C ✓ 2.1.2. NOTICE QUIT 2.1.3. NOTICE INVITE 2.1.4. NOTICE DISPOSE - 2.1.5. NOTICE MESSAGE +✓ 2.1.5. NOTICE MESSAGE 2.2. Game notices 2.2.1. Global game notices 2.2.1.1. NOTICE NEWGAME @@ -34,7 +34,7 @@ S C 2.2.2.1. NOTICE MOVE 3. Errors 3.1. Connection setup errors - 3.1.1. ERROR NONAMESET +✓ 3.1.1. ERROR NONAMESET ✓ 3.1.2. ERROR INVALIDNAME 3.2. Command format errors 3.2.1. ERROR COMMAND diff --git a/src/ttt-client.c b/src/ttt-client.c index 5f2a193..81f6e13 100644 --- a/src/ttt-client.c +++ b/src/ttt-client.c @@ -21,6 +21,8 @@ #include "ttt-client.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,14 +32,14 @@ struct _ttt_client { pthread_mutex_t mutex; 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; @@ -57,29 +59,40 @@ _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); +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_required; + int args_min; + int args_max; 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} + {"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])) @@ -91,6 +104,7 @@ _ttt_client_execute_helo (ttt_client_t *client, { ttt_error_t error; char *response; + char *notice; assert (num_args == 1); @@ -99,19 +113,19 @@ _ttt_client_execute_helo (ttt_client_t *client, error = ttt_server_register_client (client->server, client); if (error) return error; - client->registered = TRUE; 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 (&response, "NOTICE USER %s\r\n",client->name); - ttt_server_broadcast(client->server,response); + xasprintf (¬ice, "NOTICE USER %s\r\n", + client->name); + ttt_server_broadcast (client->server, notice); + free (notice); free (response); return TTT_ERROR_NONE; @@ -126,8 +140,10 @@ _ttt_client_execute_who (ttt_client_t *client, assert (num_args == 0); - response = ttt_server_who (client->server); + if (!client->registered) + return TTT_ERROR_NO_NAME_SET; + response = xstrdup (ttt_server_who (client->server)); ttt_client_send (client, response); free (response); @@ -136,44 +152,86 @@ _ttt_client_execute_who (ttt_client_t *client, } static ttt_error_t -_ttt_client_execute_quit (ttt_client_t *client, - char **args, - int num_args) +_ttt_client_execute_message (ttt_client_t *client, + char **args, + int num_args) { + char *response; char *notice; - assert (num_args == 0); - xasprintf (¬ice,"NOTICE QUIT %s\r\n",client->name); - ttt_server_broadcast(client->server,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); - return TTT_ERROR_QUIT_REQUESTED; + free (response); + + return TTT_ERROR_NONE; } static ttt_error_t -_ttt_client_execute_message (ttt_client_t *client, +_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; - int i; - assert (num_args > 0); + assert (num_args == 1); - xasprintf(&response, "MESSAGE\r\n"); - ttt_client_send (client, response); - - xasprintf(&response, "NOTICE MESSAGE %s", client->name); - for (i=0; iserver,response); + 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 @@ -192,7 +250,7 @@ _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; @@ -255,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); } } @@ -292,11 +353,11 @@ _execute_request (ttt_client_t *client) 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) + 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; } diff --git a/src/ttt-lex.h b/src/ttt-lex.h index d70d5d8..1f98457 100644 --- a/src/ttt-lex.h +++ b/src/ttt-lex.h @@ -209,6 +209,7 @@ void yyfree (void * ,yyscan_t yyscanner ); #ifdef YY_HEADER_EXPORT_START_CONDITIONS #define INITIAL 0 +#define STRING 1 #endif @@ -314,8 +315,8 @@ extern int yylex (yyscan_t yyscanner); #undef YY_DECL_IS_OURS #undef YY_DECL #endif -#line 17 "ttt-lex.l" +#line 65 "ttt-lex.l" -#line 320 "ttt-lex.h" +#line 321 "ttt-lex.h" #undef yyIN_HEADER #endif /* yyHEADER_H */ diff --git a/src/ttt-lex.l b/src/ttt-lex.l index 2a9d8e2..06685c4 100644 --- a/src/ttt-lex.l +++ b/src/ttt-lex.l @@ -5,12 +5,60 @@ %{ #include "ttt-token.h" + +#define YY_DECL int yylex (yyscan_t yyscanner, ttt_token_t *token) + +#define STRING_BUF_SIZE 8000 %} +%x STRING + %% + char string_buf[STRING_BUF_SIZE]; + char *string_buf_ptr; + /* Rules */ -\r\n return TTT_TOKEN_NEWLINE; -[^ \t\r\n][^ \t\r\n]* return TTT_TOKEN_STRING; -[ \t\r\n] ; +\r\n { + token->type = TTT_TOKEN_TYPE_NEWLINE; + return token->type; + } + +\" { + string_buf_ptr = string_buf; + BEGIN (STRING); + } + +{ + \\\" { + *string_buf_ptr++ = '"'; + } + + \\ { + *string_buf_ptr++ = '\\'; + } + + [^\\\"\\]+ { + char *s = yytext; + + while (*s) + *string_buf_ptr++ = *s++; + } + + \" { + BEGIN (INITIAL); + *string_buf_ptr = '\0'; + token->type = TTT_TOKEN_TYPE_STRING; + token->u.string = xstrdup (string_buf); + return token->type; + } +} + +[^ \t\r\n\"][^ \t\r\n\"]* { + token->type = TTT_TOKEN_TYPE_STRING; + token->u.string = xstrdup (yytext); + return token->type; + } + +[ \t\r\n] ; diff --git a/src/ttt-token.h b/src/ttt-token.h index f063d60..a927b05 100644 --- a/src/ttt-token.h +++ b/src/ttt-token.h @@ -25,9 +25,17 @@ #define _TTT_TOKEN_H_ typedef enum { - TTT_TOKEN_EOF = 0, - TTT_TOKEN_STRING, - TTT_TOKEN_NEWLINE + TTT_TOKEN_TYPE_EOF = 0, + TTT_TOKEN_TYPE_COMMAND, + TTT_TOKEN_TYPE_STRING, + TTT_TOKEN_TYPE_NEWLINE +} ttt_token_type_t; + +typedef struct _ttt_token { + ttt_token_type_t type; + union { + char *string; + } u; } ttt_token_t; #endif /* _TTT_TOKEN_H_ */ -- 2.43.0