]> git.cworth.org Git - ttt/blobdiff - src/ttt-client.c
2005-12-08 Carl Worth <cworth@cworth.org>
[ttt] / src / ttt-client.c
index 1dd755f83651e3d7c6f80f176e0befa05f8af8dc..e68f70ca5cbde835021b053814eec7098ec22ff4 100644 (file)
  */
 
 #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"
 #include "ttt-socket.h"
 #include "ttt-token.h"
 
+#define YY_DECL int yylex (yyscan_t yyscanner, ttt_token_t *token)
+#include "ttt-lex.h"
+YY_DECL;
+
 struct _ttt_client {
     pthread_mutex_t mutex;
     pthread_t       thread;
@@ -40,14 +40,14 @@ struct _ttt_client {
     char            **request_strings;
     int             num_request_strings;
     
-    char            *name;
+    char            *username;
     ttt_bool_t      registered;
     int             num_wins;
 };
 
 typedef ttt_error_t (*ttt_command_func_t) (ttt_client_t *client,
-                                          char **args,
-                                          int num_args);
+                                          char         **args,
+                                          int          num_args);
 
 static ttt_error_t
 _ttt_client_execute_helo (ttt_client_t *client,
@@ -59,6 +59,11 @@ _ttt_client_execute_who (ttt_client_t *client,
                         char         **args,
                         int          num_args);
 
+static ttt_error_t
+_ttt_client_execute_statistics (ttt_client_t *client,
+                               char         **args,
+                               int          num_args);
+
 static ttt_error_t
 _ttt_client_execute_message (ttt_client_t *client,
                             char         **args,
@@ -66,19 +71,39 @@ _ttt_client_execute_message (ttt_client_t *client,
 
 static ttt_error_t
 _ttt_client_execute_help (ttt_client_t  *client,
-                         char     **args,
-                         int      num_args);
+                         char          **args,
+                         int           num_args);
 
 static ttt_error_t
 _ttt_client_execute_version (ttt_client_t  *client,
-                            char          **args,
-                            int           num_args);
+                            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_invite (ttt_client_t *client,
+                           char         **args,
+                           int          num_args);
+
+static ttt_error_t
+_ttt_client_execute_accept (ttt_client_t *client,
+                           char         **args,
+                           int          num_args);
+
+static ttt_error_t
+_ttt_client_execute_retract (ttt_client_t *client,
+                            char         **args,
+                            int          num_args);
+
+static ttt_error_t
+_ttt_client_execute_decline (ttt_client_t *client,
+                            char         **args,
+                            int          num_args);
+
 typedef struct _ttt_command_description {
     const char         *command;
     int                args_min;
@@ -95,9 +120,24 @@ ttt_command_description_t command_descriptions[] = {
     {"HELP",    0, 1, _ttt_client_execute_help,
      "HELP <command>          ", "Display help for a command."},
 
+    {"INVITE",  1, 1, _ttt_client_execute_invite,
+     "INVITE <username>       ", "Invite a player to play a game."},
+
+    {"ACCEPT",  1, 1, _ttt_client_execute_accept,
+     "ACCEPT <username>       ", "Accept a game invitation."},
+
+    {"RETRACT", 1, 1, _ttt_client_execute_retract,
+     "RETRACT <username>       ", "Retract a game invitation."},
+
+    {"DECLINE", 1, 1, _ttt_client_execute_decline,
+     "DECLINE <username>       ", "Decline a game invitation."},
+
     {"MESSAGE", 1, 1, _ttt_client_execute_message,
      "MESSAGE <message>       ", "Send a message to everyone."},
 
+    {"STATISTICS", 1, 1, _ttt_client_execute_statistics,
+     "STATISTICS <username>   ", "Lists the statistics for the specified user."},
+
     {"QUIT",    0, 0, _ttt_client_execute_quit,
      "QUIT                    ", "Quit session."},
 
@@ -121,7 +161,7 @@ _ttt_client_execute_helo (ttt_client_t *client,
 
     assert (num_args == 1);
 
-    ttt_client_set_name (client, args[0]);
+    ttt_client_set_username (client, args[0]);
 
     error = ttt_server_register_client (client->server, client);
     if (error)
@@ -129,13 +169,13 @@ _ttt_client_execute_helo (ttt_client_t *client,
     client->registered = TRUE;
 
     xasprintf (&response, "HELO %s %s %s\r\n",
-              client->name,
+              client->username,
               ttt_server_get_host (client->server),
               ttt_server_get_port (client->server));
     ttt_client_send (client, response);
 
     xasprintf (&notice, "NOTICE USER %s\r\n",
-              client->name);
+              client->username);
     ttt_server_broadcast (client->server, notice);
 
     free (notice);
@@ -164,10 +204,37 @@ _ttt_client_execute_who (ttt_client_t *client,
     return TTT_ERROR_NONE;
 }
 
+static ttt_error_t
+_ttt_client_execute_statistics (ttt_client_t *client,
+                               char         **args,
+                               int          num_args)
+{
+    char *response;
+    char *username;
+    ttt_error_t error;
+
+    assert (num_args == 1);
+
+    username = args[0];
+
+    if (!client->registered)
+       return TTT_ERROR_NO_NAME_SET;
+
+    error = ttt_server_statistics (client->server, username, &response);
+    if (error)
+       return error;
+
+    ttt_client_send (client, response);
+
+    free (response);
+
+    return TTT_ERROR_NONE;
+}
+
 static ttt_error_t
 _ttt_client_execute_message (ttt_client_t  *client,
-                            char          **args,
-                            int           num_args)
+                            char          **args,
+                            int           num_args)
 {
     char *response;
     char *notice;
@@ -181,7 +248,7 @@ _ttt_client_execute_message (ttt_client_t  *client,
     ttt_client_send (client, response);
 
     xasprintf (&notice, "NOTICE MESSAGE %s \"%s\"\r\n",
-             client->name,
+             client->username,
              args[0]);
     ttt_server_broadcast (client->server, notice);
 
@@ -193,8 +260,8 @@ _ttt_client_execute_message (ttt_client_t  *client,
 
 static ttt_error_t
 _ttt_client_execute_help (ttt_client_t  *client,
-                         char     **args,
-                         int      num_args)
+                         char          **args,
+                         int           num_args)
 {
     char *response;
     char *command;
@@ -246,17 +313,32 @@ _ttt_client_execute_help (ttt_client_t  *client,
 
 static ttt_error_t
 _ttt_client_execute_version (ttt_client_t  *client,
-                            char          **args,
-                            int           num_args)
+                            char          **args,
+                            int           num_args)
 {
     char *response;
+    char *clientversion;
+    int version;
+    int i;
 
     assert (num_args == 1);
 
-    /* XXX: Argument is being ignored.
-       This is not completely implemented. */
+    clientversion = args[0];
+
+    /* Verify that provided version arg is a positive integer */
+    for (i = 0; i < strlen(clientversion); i++)
+       if (!isdigit (clientversion[i]))
+           return TTT_ERROR_SYNTAX;
+
+    version = atoi (clientversion);
 
-    xasprintf (&response, "VERSION 1\r\n");
+    if (version < 1)
+       return TTT_ERROR_SYNTAX;
+
+    if (version > TTT_SERVER_PROTOCOL_VERSION)
+       version = TTT_SERVER_PROTOCOL_VERSION;
+
+    xasprintf (&response, "VERSION %d\r\n", version);
     ttt_client_send (client, response);
 
     free (response);
@@ -276,7 +358,7 @@ _ttt_client_execute_quit (ttt_client_t *client,
        return TTT_ERROR_QUIT_REQUESTED;
     
     xasprintf (&notice, "NOTICE QUIT %s\r\n",
-              client->name);
+              client->username);
     ttt_server_broadcast (client->server, notice);
     
     free (notice);
@@ -284,6 +366,160 @@ _ttt_client_execute_quit (ttt_client_t *client,
     return TTT_ERROR_QUIT_REQUESTED;
 }
 
+static ttt_error_t
+_ttt_client_execute_invite (ttt_client_t *client,
+                           char         **args,
+                           int          num_args)
+{
+    const char *username;
+    char *response;
+    char *notice;
+    ttt_error_t error;
+
+    assert (num_args == 1);
+
+    username = args[0];
+
+    if (!client->registered)
+        return TTT_ERROR_NO_NAME_SET;
+
+    error = ttt_server_verify_username (client->server,        username);
+    if (error)
+       return error;
+
+    xasprintf (&response, "INVITE\r\n");
+    ttt_client_send (client, response);
+
+    xasprintf (&notice, "NOTICE INVITE %s %s\r\n",
+              client->username,
+              username);
+    ttt_server_broadcast (client->server, notice);
+
+    /* XXX: Store invitation in state */
+
+    free (notice);
+    free (response);
+
+    return TTT_ERROR_NONE;
+}
+
+static ttt_error_t
+_ttt_client_execute_accept (ttt_client_t *client,
+                           char         **args,
+                           int          num_args)
+{
+    const char *username;
+    char *response;
+    char *notice;
+    ttt_error_t error;
+
+    assert (num_args == 1);
+
+    username = args[0];
+
+    if (!client->registered)
+        return TTT_ERROR_NO_NAME_SET;
+
+    error = ttt_server_verify_username (client->server,        username);
+    if (error)
+       return error;
+
+    /* XXX: Verify invitation, else return ERROR NO_INVITE */
+
+    xasprintf (&response, "ACCEPT\r\n");
+    ttt_client_send (client, response);
+
+    xasprintf (&notice, "NOTICE ACCEPT %s %s\r\n",
+              client->username,
+              username);
+    ttt_server_broadcast (client->server, notice);
+
+    /* XXX: Start a new game */
+
+    free (notice);
+    free (response);
+
+    return TTT_ERROR_NONE;
+}
+
+static ttt_error_t
+_ttt_client_execute_retract (ttt_client_t *client,
+                            char         **args,
+                            int          num_args)
+{
+    const char *username;
+    char *response;
+    char *notice;
+    ttt_error_t error;
+
+    assert (num_args == 1);
+
+    username = args[0];
+
+    if (!client->registered)
+        return TTT_ERROR_NO_NAME_SET;
+
+    error = ttt_server_verify_username (client->server,        username);
+    if (error)
+       return error;
+
+    /* XXX: Verify invitation, else return ERROR NO_INVITE */
+
+    xasprintf (&response, "RETRACT\r\n");
+    ttt_client_send (client, response);
+
+    xasprintf (&notice, "NOTICE RETRACT %s %s\r\n",
+              client->username,
+              username);
+    ttt_server_broadcast (client->server, notice);
+
+    /* XXX: Remove invitiation from state */
+
+    free (notice);
+    free (response);
+
+    return TTT_ERROR_NONE;
+}
+
+static ttt_error_t
+_ttt_client_execute_decline (ttt_client_t *client,
+                            char         **args,
+                            int          num_args)
+{
+    const char *username;
+    char *response;
+    char *notice;
+    ttt_error_t error;
+
+    assert (num_args == 1);
+
+    username = args[0];
+
+    if (!client->registered)
+        return TTT_ERROR_NO_NAME_SET;
+
+    error = ttt_server_verify_username (client->server,        username);
+    if (error)
+       return error;
+
+    /* XXX: Verify invitation, else return ERROR NO_INVITE */
+
+    xasprintf (&response, "DECLINE\r\n");
+    ttt_client_send (client, response);
+
+    xasprintf (&notice, "NOTICE DECLINE %s %s\r\n",
+              client->username,
+              username);
+    ttt_server_broadcast (client->server, notice);
+
+    /* XXX: Remove invitation from state */
+
+    free (notice);
+    free (response);
+
+    return TTT_ERROR_NONE;
+}
+
 static void
 _free_request (ttt_client_t *client);
 
@@ -306,7 +542,7 @@ _ttt_client_init (ttt_client_t      *client,
     client->request_strings = NULL;
     client->num_request_strings = 0;
 
-    client->name = NULL;
+    client->username = NULL;
     client->registered = FALSE;
     client->num_wins = 0;
 }
@@ -319,8 +555,8 @@ _ttt_client_fini (ttt_client_t *client)
     if (client->registered)
        ttt_server_unregister_client (client->server, client);
 
-    free (client->name);
-    client->name = NULL;
+    free (client->username);
+    client->username = NULL;
 
     yylex_destroy (client->scanner);
     shutdown (client->socket, SHUT_RDWR);
@@ -476,17 +712,17 @@ ttt_client_send (ttt_client_t *client, const char *message)
 
 /* Exported: See ttt-client.h for documentation. */
 const char*
-ttt_client_get_name (ttt_client_t *client)
+ttt_client_get_username (ttt_client_t *client)
 {
-    return client->name;
+    return client->username;
 }
 
 /* Exported: See ttt-client.h for documentation. */
 void
-ttt_client_set_name (ttt_client_t *client, const char *name)
+ttt_client_set_username (ttt_client_t *client, const char *username)
 {
-    free (client->name);
-    client->name = xstrdup (name);
+    free (client->username);
+    client->username = xstrdup (username);
 }
 
 /* Exported: See ttt-client.h for documentation. */
@@ -495,3 +731,9 @@ ttt_client_get_num_wins (ttt_client_t *client)
 {
     return client->num_wins;
 }
+
+/* This is just to keep the compiler quiet about a function declared
+ * static but never defined. Just an annoying bug in flex's output. */
+static int yy_init_globals (yyscan_t yyscanner) {return 0;}
+void use_yy_init_globals (void);
+void use_yy_init_globals (void) {yyscan_t scan; yy_init_globals(scan);}