2005-11-24 Carl Worth <cworth@cworth.org>
authorCarl Worth <carl@theworths.org>
Thu, 24 Nov 2005 16:18:18 +0000 (16:18 +0000)
committerCarl Worth <carl@theworths.org>
Thu, 24 Nov 2005 16:18:18 +0000 (16:18 +0000)
        * PROTOCOL: Document QUIT.

        * src/ttt-client.c: (_ttt_client_execute_helo),
        (_ttt_client_execute_quit), (_ttt_client_init), (_ttt_client_fini),
        (_execute_request), (_handle_requests_thread): Implement QUIT. Add
        client->registered flag and unregister only if registered. Change
        from args_min and args_max to args_required.

        * src/ttt-error.h:
        * src/ttt-error.c: (ttt_error_string):
        * src/ttt-server.c: (ttt_server_register_client): Put underscores
        in TTT_ERRROR names for better readability.

ChangeLog
PROTOCOL
src/ttt-client.c
src/ttt-error.c
src/ttt-error.h
src/ttt-server.c

index 525bdfd33f631cee48339ae5b08e79316875226b..dc9d723180edd2541cb990da2d4fe2ee5f51b28f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2005-11-24  Carl Worth  <cworth@cworth.org>
+
+       * PROTOCOL: Document QUIT.
+
+       * src/ttt-client.c: (_ttt_client_execute_helo),
+       (_ttt_client_execute_quit), (_ttt_client_init), (_ttt_client_fini),
+       (_execute_request), (_handle_requests_thread): Implement QUIT. Add
+       client->registered flag and unregister only if registered. Change
+       from args_min and args_max to args_required.
+
+       * src/ttt-error.h:
+       * src/ttt-error.c: (ttt_error_string):
+       * src/ttt-server.c: (ttt_server_register_client): Put underscores
+       in TTT_ERRROR names for better readability.
+
 2005-11-24  Carl Worth  <cworth@cworth.org>
 
        * PROTOCOL:
index 666379735435cb56aebda1c4aed3be5adfeac89a..519b1bab79dca6e820428ae48ac787b903bf77c6 100644 (file)
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -85,6 +85,8 @@ Document Conventions
 
        QUIT
 
+       Disconnects the client from the server.
+
     1.2.5. Version
 
        VERSION <client-version-number>
index 508aa88e91ecffba87e9c7e63a3caaa92db521ea..1c23fcc3aced5d29ffa25ba19b4c3bebde00fa50 100644 (file)
@@ -36,6 +36,7 @@ struct _ttt_client {
     yyscan_t scanner;
 
     char *name;
+    ttt_bool_t registered;
 
     char **request_strings;
     int num_request_strings;
@@ -50,16 +51,22 @@ _ttt_client_execute_helo (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;
+    int args_required;
     ttt_command_func_t execute;
 } ttt_command_description_t;
 
 ttt_command_description_t command_descriptions[] = {
-    {"HELO", 1, 1, _ttt_client_execute_helo}
+    {"HELO", 1, _ttt_client_execute_helo},
+    {"QUIT", 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,
@@ -69,13 +76,16 @@ _ttt_client_execute_helo (ttt_client_t *client,
     ttt_error_t error;
     char *response;
 
-    if (num_args == 1)
-       ttt_client_set_name (client, args[0]);
+    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));
@@ -87,7 +97,15 @@ _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_quit (ttt_client_t  *client,
+                         char          **args,
+                         int             num_args)
+{
+    assert (num_args == 0);
+
+    return TTT_ERROR_QUIT_REQUESTED;
+}
 
 static void
 _free_request (ttt_client_t *client);
@@ -112,6 +130,7 @@ _ttt_client_init (ttt_client_t      *client,
     client->num_request_strings = 0;
 
     client->name = NULL;
+    client->registered = FALSE;
 }
 
 static void
@@ -119,7 +138,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;
@@ -202,7 +222,7 @@ _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_min) || (num_args > desc->args_max))
+           if (num_args != desc->args_required)
                return TTT_ERROR_SYNTAX;
            return (desc->execute) (client, &client->request_strings[1], num_args);
            }
@@ -227,6 +247,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));
     }
index 26ab09dc24e9b12ef3860f56cd717270fe2b74b9..4bd5498ea602f974e286404acc177d4624768a21 100644 (file)
@@ -27,26 +27,30 @@ ttt_error_string (ttt_error_t error)
     switch (error) {
     case TTT_ERROR_NONE:
        return "ERROT NONE\n";
-    case TTT_ERROR_NONAMESET:
+    case TTT_ERROR_NO_NAME_SET:
        return "ERROR NONAMESET\n";
-    case TTT_ERROR_INVALIDNAME:
+    case TTT_ERROR_INVALID_NAME:
        return "ERROR INVALIDNAME\n";
     case TTT_ERROR_COMMAND:
        return "ERROR COMMAND\n";
     case TTT_ERROR_SYNTAX:
        return "ERROR SYNTAX\n";
-    case TTT_ERROR_NOTNUMBER:
+    case TTT_ERROR_NOT_NUMBER:
        return "ERROR NOTNUMBER\n";
-    case TTT_ERROR_NOTGRID:
+    case TTT_ERROR_NOT_GRID:
        return "ERROR NOTGRID\n";
-    case TTT_ERROR_NOUSER:
+    case TTT_ERROR_NO_USER:
        return "ERROR NOUSER\n";
-    case TTT_ERROR_NOTINGAME:
+    case TTT_ERROR_NOT_IN_GAME:
        return "ERROR_NOTINGAME\n";
-    case TTT_ERROR_NOTPLAYING:
+    case TTT_ERROR_NOT_PLAYING:
        return "ERROR_NOTPLAYING\n";
-    case TTT_ERROR_NOTYOURTURN:
+    case TTT_ERROR_NOT_YOUR_TURN:
        return "ERROR NOTYOURTURN\n";
+    /* Not an actual protocol errror, so this should never happen. */
+    case TTT_ERROR_QUIT_REQUESTED:
+       ASSERT_NOT_REACHED;
+       break;
     }
 
     ASSERT_NOT_REACHED;
index a800ea6b8e512ddd62b4e32a6c6943ba493fc9dd..eabe64c8785d519ba59fd394b9f7c3e855533d88 100644 (file)
 
 typedef enum {
     TTT_ERROR_NONE,
-    TTT_ERROR_NONAMESET,
-    TTT_ERROR_INVALIDNAME,
+    TTT_ERROR_NO_NAME_SET,
+    TTT_ERROR_INVALID_NAME,
     TTT_ERROR_COMMAND,
     TTT_ERROR_SYNTAX,
-    TTT_ERROR_NOTNUMBER,
-    TTT_ERROR_NOTGRID,
-    TTT_ERROR_NOUSER,
-    TTT_ERROR_NOTINGAME,
-    TTT_ERROR_NOTPLAYING,
-    TTT_ERROR_NOTYOURTURN
+    TTT_ERROR_NOT_NUMBER,
+    TTT_ERROR_NOT_GRID,
+    TTT_ERROR_NO_USER,
+    TTT_ERROR_NOT_IN_GAME,
+    TTT_ERROR_NOT_PLAYING,
+    TTT_ERROR_NOT_YOUR_TURN,
+
+    /* Here's a non-protocol pseudo-error used to implement QUIT. */
+    TTT_ERROR_QUIT_REQUESTED
 } ttt_error_t;
 
 const char *
index f1a1eef7310473c39f2aa09b5ab6a821cfcad934..450582b7667dae57fa374abc2d126dbfb76e4bf1 100644 (file)
@@ -65,11 +65,11 @@ ttt_server_register_client (ttt_server_t *server, ttt_client_t *client)
     assert (name != NULL);
 
     if (name[0] == '\0')
-       return TTT_ERROR_INVALIDNAME;
+       return TTT_ERROR_INVALID_NAME;
 
     for (i = 0; i < server->num_clients; i++) {
        if (strcmp (ttt_client_get_name (server->clients[i]), name) == 0) {
-           error = TTT_ERROR_INVALIDNAME;
+           error = TTT_ERROR_INVALID_NAME;
            goto CLEANUP_LOCK;
        }
     }