2005-11-24 Carl Worth <cworth@cworth.org>
[ttt] / src / ttt-client.c
index 8139ada1de03cb04a2e7c7c986ebd0aa1d136983..508aa88e91ecffba87e9c7e63a3caaa92db521ea 100644 (file)
@@ -35,12 +35,60 @@ struct _ttt_client {
     int socket;
     yyscan_t scanner;
 
-    int id;
+    char *name;
 
     char **request_strings;
     int num_request_strings;
 };
 
+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);
+
+typedef struct _ttt_command_description {
+    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", 1, 1, _ttt_client_execute_helo}
+};
+
+static ttt_error_t
+_ttt_client_execute_helo (ttt_client_t *client,
+                         char         **args,
+                         int          num_args)
+{
+    ttt_error_t error;
+    char *response;
+
+    if (num_args == 1)
+       ttt_client_set_name (client, args[0]);
+
+    error = ttt_server_register_client (client->server, client);
+    if (error)
+       return error;
+
+    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;
+}
+
+#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
+
 static void
 _free_request (ttt_client_t *client);
 
@@ -63,10 +111,7 @@ _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;
 }
 
 static void
@@ -76,6 +121,9 @@ _ttt_client_fini (ttt_client_t *client)
 
     ttt_server_unregister_client (client->server, client);
 
+    free (client->name);
+    client->name = NULL;
+
     yylex_destroy (client->scanner);
     shutdown (client->socket, SHUT_RDWR);
 
@@ -144,10 +192,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_min) || (num_args > desc->args_max))
+               return TTT_ERROR_SYNTAX;
+           return (desc->execute) (client, &client->request_strings[1], num_args);
+           }
+       }
+
+    return TTT_ERROR_COMMAND;
 }
 
 static void *
@@ -209,8 +270,16 @@ ttt_client_send (ttt_client_t *client, const char *message)
 }
 
 /* Exported: See ttt-client.h for documentation. */
-int
-ttt_client_get_id (ttt_client_t *client)
+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)
 {
-    return client->id;
+    free (client->name);
+    client->name = xstrdup (name);
 }