* PROTOCOL: Removed unused servername
authorRichard Worth <richard@theworths.org>
Wed, 23 Nov 2005 22:11:28 +0000 (22:11 +0000)
committerRichard Worth <richard@theworths.org>
Wed, 23 Nov 2005 22:11:28 +0000 (22:11 +0000)
        * src/ttt-client.h: * src/ttt-client.c:
        (_ttt_client_execute_helo), (_ttt_client_init),
        (_ttt_client_fini), (_execute_request), (ttt_client_get_name),
        (ttt_client_set_name): Added command descriptions structure. Match
        command case-insensitively, dispatch to execute
        function. Implement HELO command. Register on HELO instead of on
        connect.

        * src/ttt-server.h: * src/ttt-server.c: (ttt_server_init),
        (ttt_server_register_client), (ttt_server_unregister_client),
        (ttt_server_get_host), (ttt_server_get_port), (main): Added host
        and port to server. Make client registration name-based rather
        than id-based.

        * src/x.c: (xstrdup): Return NULL on NULL

        * src/ttt-lex.h: Regenerated

src/ttt-client.c
src/ttt-client.h
src/ttt-lex.h
src/ttt-server.c
src/ttt-server.h
src/x.c

index 8139ada1de03cb04a2e7c7c986ebd0aa1d136983..3fdcf83afea53e444c14fa521cc8b6d60f97ced2 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "ttt-client.h"
 
+#include "ttt-command.h"
 #include "ttt-error.h"
 #include "ttt-lex.h"
 #include "ttt-server.h"
@@ -35,12 +36,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", 0, 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 +112,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 +122,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 +193,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 +271,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);
 }
index ef74b87760d893acfaaf671dd6470a3b4c9baf2d..06af64b079a1a113287a4f1038226632724b1c00 100644 (file)
@@ -41,8 +41,12 @@ ttt_client_new (void *closure, int client_socket);
 void
 ttt_client_send (ttt_client_t *client, const char *message);
 
-/* Get a client's unique ID. */
-int
-ttt_client_get_id (ttt_client_t *client);
+/* Get a client's name. */
+const char*
+ttt_client_get_name (ttt_client_t *client);
+
+/* Set a client's name. */
+void
+ttt_client_set_name (ttt_client_t *client, const char *name);
 
 #endif /* _TTT_CLIENT_H_ */
index 84463a28e399cc9f5f68c11054568915ce2c4d85..964b6a0af66f72d546d6d8d4ddf210bbd27e6f62 100644 (file)
@@ -202,6 +202,9 @@ void *yyalloc (yy_size_t ,yyscan_t yyscanner );
 void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
 void yyfree (void * ,yyscan_t yyscanner );
 
+#define yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
 #define yytext_ptr yytext_r
 
 #ifdef YY_HEADER_EXPORT_START_CONDITIONS
@@ -309,8 +312,8 @@ extern int yylex (yyscan_t yyscanner);
 #undef YY_DECL_IS_OURS
 #undef YY_DECL
 #endif
-#line 15 "ttt-lex.l"
+#line 17 "ttt-lex.l"
 
-#line 317 "ttt-lex.h"
+#line 320 "ttt-lex.h"
 #undef yyIN_HEADER
 #endif /* yyHEADER_H */
index c50a797b259ec8bf1dbb6b74886bba2468ca4131..e9043b4e2cb25309e65e68ee202af9a617e2a90f 100644 (file)
 
 #include "ttt-args.h"
 #include "ttt-client.h"
+#include "ttt-error.h"
 #include "ttt-socket.h"
 
 struct _ttt_server {
     pthread_mutex_t mutex;
 
+    const char *host;
+    const char *port;
+
     int next_client_id;
 
     ttt_client_t **clients;
@@ -36,10 +40,13 @@ struct _ttt_server {
 };
 
 static void
-ttt_server_init (ttt_server_t *server)
+ttt_server_init (ttt_server_t *server, const char *host, const char *port)
 {
     pthread_mutex_init (&server->mutex, NULL);
 
+    server->host = host;
+    server->port = port;
+
     server->next_client_id = 0;
 
     server->clients = NULL;
@@ -48,16 +55,33 @@ ttt_server_init (ttt_server_t *server)
 }
 
 /* Exported: See ttt-server.h for documentation. */
-int
+ttt_error_t
 ttt_server_register_client (ttt_server_t *server, ttt_client_t *client)
 {
-    int id;
+    int i;
+    ttt_error_t error = TTT_ERROR_NONE;
+    char *name;
 
     pthread_mutex_lock (&server->mutex);
 
-    id = server->next_client_id++;
+    name = xstrdup (ttt_client_get_name (client));
+
+    if (name == NULL) {
+       xasprintf(&name, "user%03d", server->next_client_id++);
+       ttt_client_set_name (client, name);
+    }
+
+    /* XXX: If generated name is not unique, this will return an error,
+       which violates the protocol. */
+    for (i = 0; i < server->num_clients; i++) {
+       if (strcmp (ttt_client_get_name (server->clients[i]), name) == 0) {
+           error = TTT_ERROR_INVALIDNAME;
+           goto CLEANUP_LOCK;
+       }
+    }
 
-    printf ("Client %d has joined.\n", id);
+    printf ("Client %s has joined.\n", name);
+    free (name);
 
     server->num_clients++;
 
@@ -73,9 +97,10 @@ ttt_server_register_client (ttt_server_t *server, ttt_client_t *client)
 
     server->clients [server->num_clients - 1] = client;
 
+ CLEANUP_LOCK:
     pthread_mutex_unlock (&server->mutex);
 
-    return id;
+    return error;
 }
 
 /* Exported: See ttt-server.h for documentation. */
@@ -92,7 +117,7 @@ ttt_server_unregister_client (ttt_server_t *server, ttt_client_t *client)
 
     assert (i < server->num_clients);
 
-    printf ("Client %d has left.\n", ttt_client_get_id (client));
+    printf ("Client %s has left.\n", ttt_client_get_name (client));
 
     memmove (&server->clients[i], &server->clients[i+1],
             (server->num_clients - i - 1) * sizeof (ttt_client_t *));
@@ -115,6 +140,20 @@ ttt_server_broadcast (ttt_server_t *server, const char *message)
     pthread_mutex_unlock (&server->mutex);
 }
 
+/* Exported: See ttt-server.h for documentation. */
+const char*
+ttt_server_get_host (ttt_server_t *server)
+{
+    return server->host;
+}
+
+/* Exported: See ttt-server.h for documentation. */
+const char*
+ttt_server_get_port (ttt_server_t *server)
+{
+    return server->port;
+}
+
 static const char *WELCOME_MESSAGE = 
 "Welcome to ttt-server. So far, this program is still a demonstration\n"
 "TCP/IP server, acting something like a rather braindead chat server.\n"
@@ -161,7 +200,7 @@ main (int argc, char **argv)
 
     printf (WELCOME_MESSAGE, args.host, args.port, args.host, args.port);
 
-    ttt_server_init (&server);
+    ttt_server_init (&server, args.host, args.port);
 
     while (1)
        ttt_socket_accept (socket, _ttt_server_accept, &server);
index 77fb4bf79df7c023a2f971b27015131b8e7e09e9..7cf3d9707ecc95aec9bbfa8e02dc8a20ea9d1137 100644 (file)
  */
 
 #include "ttt.h"
+#include "ttt-error.h"
 
 #ifndef _TTT_SERVER_H_
 #define _TTT_SERVER_H_
 
 /* Register a new client with the server.
- *
- * Returns: the unique id of the client.
+ * 
+ * Returns: TTT_ERROR_NONE on success, else TTT_ERROR_INVALIDNAME if client's
+ * name is not unique.
  *
  * Locking: The server mutex will be acquired and held throughout the
  * execution of this function.
@@ -34,7 +36,7 @@
  * Errors: If an error (such as out-of-memory) occurs, this function
  * will not return.
  */
-int
+ttt_error_t
 ttt_server_register_client (ttt_server_t *server, ttt_client_t *client);
 
 /* Un-register a client from the server.
@@ -57,4 +59,16 @@ ttt_server_unregister_client (ttt_server_t *server, ttt_client_t *client);
 void
 ttt_server_broadcast (ttt_server_t *server, const char *message);
 
+/* Gets the server hostname.
+ *
+ */
+const char*
+ttt_server_get_host (ttt_server_t *server);
+
+/* Gets the server port
+ *
+ */
+const char*
+ttt_server_get_port (ttt_server_t *server);
+
 #endif /* _TTT_SERVER_H_ */
diff --git a/src/x.c b/src/x.c
index 8da355e3e015b0c390cb0869e53a96d1e2bb01e1..dc5c1dd38e807ee300f9a1d77cc1ef187ef79f7d 100644 (file)
--- a/src/x.c
+++ b/src/x.c
@@ -151,6 +151,9 @@ xstrdup (const char *s)
 {
     char *ret;
 
+    if (s == NULL)
+       return NULL;
+
     ret = strdup (s);
 
     if (ret == NULL) {