]> git.cworth.org Git - ttt/blobdiff - src/ttt-server.c
2005-12-10 Richard D. Worth <richard@theworths.org>
[ttt] / src / ttt-server.c
index cb28741885721763fd54abd4a8a83b270e07f442..4b29cf2f774d277dc14dd5bc675f4b5a9a25df6d 100644 (file)
 #include "ttt-error.h"
 #include "ttt-socket.h"
 
 #include "ttt-error.h"
 #include "ttt-socket.h"
 
+struct _ttt_invite {
+    ttt_client_t    *actor;
+    ttt_client_t    *invitee;
+};
+
 struct _ttt_server {
     pthread_mutex_t mutex;
 
 struct _ttt_server {
     pthread_mutex_t mutex;
 
-    const char *host;
-    const char *port;
+    const char      *host;
+    const char      *port;
 
 
-    ttt_client_t **clients;
-    int clients_size;
-    int num_clients;
+    ttt_client_t    **clients;
+    int             clients_size;
+    int             num_clients;
+
+    ttt_invite_t    **invites;
+    int             invites_size;
+    int             num_invites;
 };
 
 static void
 };
 
 static void
@@ -48,6 +57,10 @@ ttt_server_init (ttt_server_t *server, const char *host, const char *port)
     server->clients = NULL;
     server->clients_size = 0;
     server->num_clients = 0;
     server->clients = NULL;
     server->clients_size = 0;
     server->num_clients = 0;
+
+    server->invites = NULL;
+    server->invites_size = 0;
+    server->num_invites = 0;
 }
 
 /* Exported: See ttt-server.h for documentation. */
 }
 
 /* Exported: See ttt-server.h for documentation. */
@@ -68,7 +81,7 @@ ttt_server_register_client (ttt_server_t *server, ttt_client_t *client)
        return TTT_ERROR_INVALID_NAME;
 
     for (i = 0; i < server->num_clients; i++) {
        return TTT_ERROR_INVALID_NAME;
 
     for (i = 0; i < server->num_clients; i++) {
-       if (strcmp (ttt_client_get_username (server->clients[i]), username) == 0) {
+       if (strcasecmp (ttt_client_get_username (server->clients[i]), username) == 0) {
            error = TTT_ERROR_INVALID_NAME;
            goto CLEANUP_LOCK;
        }
            error = TTT_ERROR_INVALID_NAME;
            goto CLEANUP_LOCK;
        }
@@ -88,7 +101,7 @@ ttt_server_register_client (ttt_server_t *server, ttt_client_t *client)
                                    server->clients_size * sizeof (ttt_client_t *));
     }
 
                                    server->clients_size * sizeof (ttt_client_t *));
     }
 
-    server->clients [server->num_clients - 1] = client;
+    server->clients[server->num_clients - 1] = client;
 
  CLEANUP_LOCK:
     pthread_mutex_unlock (&server->mutex);
 
  CLEANUP_LOCK:
     pthread_mutex_unlock (&server->mutex);
@@ -100,10 +113,39 @@ ttt_server_register_client (ttt_server_t *server, ttt_client_t *client)
 void
 ttt_server_unregister_client (ttt_server_t *server, ttt_client_t *client)
 {
 void
 ttt_server_unregister_client (ttt_server_t *server, ttt_client_t *client)
 {
+    ttt_invite_t *invite;
+    char         *notice;
+    ttt_bool_t   send_notice = FALSE;
     int i;
 
     pthread_mutex_lock (&server->mutex);
 
     int i;
 
     pthread_mutex_lock (&server->mutex);
 
+    /* Auto-retract and decline pending notices */
+    /* Notices are sent after mutex unlock */
+    for (i = 0; i < server->num_invites; i++)
+    {
+       invite = server->invites[i];
+       if ((invite->actor == client) || (invite->invitee == client))
+       {
+           send_notice = TRUE;
+           if (invite->actor == client)
+               xasprintf (&notice, "%s" "NOTICE RETRACT %s %s\r\n",
+                          notice,
+                          ttt_client_get_username(invite->actor),
+                          ttt_client_get_username(invite->invitee));
+           else
+               xasprintf (&notice, "%s" "NOTICE DECLINE %s %s\r\n",
+                          notice,
+                          ttt_client_get_username(invite->invitee),
+                          ttt_client_get_username(invite->actor));
+
+           memmove (&server->invites[i], &server->invites[i+1],
+                    (server->num_invites - i - 1) * sizeof (ttt_invite_t *));
+           server->num_invites--;
+           i--;
+       }
+    }
+
     for (i = 0; i < server->num_clients; i++)
        if (server->clients[i] == client)
            break;
     for (i = 0; i < server->num_clients; i++)
        if (server->clients[i] == client)
            break;
@@ -118,6 +160,12 @@ ttt_server_unregister_client (ttt_server_t *server, ttt_client_t *client)
     server->num_clients--;
 
     pthread_mutex_unlock (&server->mutex);
     server->num_clients--;
 
     pthread_mutex_unlock (&server->mutex);
+
+    if (send_notice)
+    {
+       ttt_server_broadcast(server, notice);
+       free (notice);
+    }
 }
 
 /* Exported: See ttt-server.h for documentation. */
 }
 
 /* Exported: See ttt-server.h for documentation. */
@@ -159,24 +207,34 @@ ttt_server_who (ttt_server_t *server)
 
 /* Exported: See ttt-server.h for documentation. */
 ttt_error_t
 
 /* Exported: See ttt-server.h for documentation. */
 ttt_error_t
-ttt_server_statistics (ttt_server_t *server, const char *username, char **response)
+ttt_server_verify_username (ttt_server_t *server,
+                           const char   *username)
+{
+    ttt_client_t *client;
+
+    return ttt_server_get_client_from_username (server,
+                                               username,
+                                               &client);
+}
+
+/* Exported: See ttt-server.h for documentation. */
+ttt_error_t
+ttt_server_get_client_from_username (ttt_server_t *server,
+                                    const char   *username,
+                                    ttt_client_t **client)
 {
     ttt_bool_t usernamefound = FALSE;
     const char *client_username;
 {
     ttt_bool_t usernamefound = FALSE;
     const char *client_username;
-    int client_num_wins;
     int i;
 
     pthread_mutex_lock (&server->mutex);
 
     for (i = 0; i < server->num_clients; i++) {
        client_username = ttt_client_get_username (server->clients[i]);
     int i;
 
     pthread_mutex_lock (&server->mutex);
 
     for (i = 0; i < server->num_clients; i++) {
        client_username = ttt_client_get_username (server->clients[i]);
-       if (strcasecmp (username, client_username) == 0) {
+       if (strcasecmp (username, client_username) == 0)
+       {
            usernamefound = TRUE;
            usernamefound = TRUE;
-           client_num_wins = ttt_client_get_num_wins (server->clients[i]);
-           xasprintf (response, "STATISTICS %s \"\r\n"
-                      "TICTACTOE WINS %d\r\n\"\r\n",
-                      client_username,
-                      client_num_wins);
+           *client = server->clients[i];
        }
     }
 
        }
     }
 
@@ -190,28 +248,77 @@ ttt_server_statistics (ttt_server_t *server, const char *username, char **respon
 
 /* Exported: See ttt-server.h for documentation. */
 ttt_error_t
 
 /* Exported: See ttt-server.h for documentation. */
 ttt_error_t
-ttt_server_verify_username (ttt_server_t *server, const char *username)
+ttt_server_add_invite (ttt_server_t *server,
+                      ttt_client_t *actor,
+                      ttt_client_t *invitee)
 {
 {
-    ttt_bool_t usernamefound = FALSE;
-    const char *client_username;
-    int i;
+    ttt_invite_t *invite;
 
     pthread_mutex_lock (&server->mutex);
 
 
     pthread_mutex_lock (&server->mutex);
 
-    for (i = 0; i < server->num_clients; i++) {
-       client_username = ttt_client_get_username (server->clients[i]);
-       if (strcasecmp (username, client_username) == 0)
-           usernamefound = TRUE;
+    invite = xmalloc (sizeof (ttt_invite_t));
+
+    invite->actor = actor;
+    invite->invitee = invitee;
+
+    server->num_invites++;
+
+    if (server->num_invites > server->invites_size) {
+       if (server->invites_size == 0)
+           server->invites_size = 1;
+       else
+           server->invites_size *= 2;
+
+       server->invites = xrealloc (server->invites,
+                                   server->invites_size * sizeof (ttt_invite_t *));
     }
 
     }
 
-    pthread_mutex_unlock (&server->mutex);
+    server->invites[server->num_invites - 1] = invite;
 
 
-    if (!usernamefound)
-       return TTT_ERROR_NO_USER;
+    pthread_mutex_unlock (&server->mutex);
 
     return TTT_ERROR_NONE;
 }
 
 
     return TTT_ERROR_NONE;
 }
 
+/* Exported: See ttt-server.h for documentation. */
+ttt_error_t
+ttt_server_remove_invite (ttt_server_t *server,
+                         ttt_client_t *actor,
+                         ttt_client_t *invitee)
+{
+    ttt_invite_t *invite;
+    ttt_error_t  error;
+    int i;
+
+    pthread_mutex_lock (&server->mutex);
+
+    error = TTT_ERROR_NO_INVITE;
+    for (i = 0; i < server->num_invites; i++)
+    {
+       invite = server->invites[i];
+       if ((invite->actor == actor) && (invite->invitee == invitee))
+       {
+           error = TTT_ERROR_NONE;
+           break;
+       }
+    }
+
+    if (error)
+       goto CLEANUP_LOCK;
+
+    assert (i < server->num_invites);
+
+    memmove (&server->invites[i], &server->invites[i+1],
+            (server->num_invites - i - 1) * sizeof (ttt_invite_t *));
+
+    server->num_invites--;
+
+ CLEANUP_LOCK:
+    pthread_mutex_unlock (&server->mutex);
+
+    return error;
+}
+
 /* Exported: See ttt-server.h for documentation. */
 const char*
 ttt_server_get_host (ttt_server_t *server)
 /* Exported: See ttt-server.h for documentation. */
 const char*
 ttt_server_get_host (ttt_server_t *server)
@@ -237,7 +344,7 @@ static const char *WELCOME_MESSAGE =
 "      telnet %s %s\r\n"
 "\r\n"
 "The TTTP (tic-tac-toe protocol) has been partially implemented.\r\n"
 "      telnet %s %s\r\n"
 "\r\n"
 "The TTTP (tic-tac-toe protocol) has been partially implemented.\r\n"
-"The following commands should work: HELO, HELP, MESSAGE, VERSION, QUIT, WHO.\r\n"
+"The following commands should work: HELO, HELP, INVITE, ACCEPT, RETRACT, DECLINE, MESSAGE, STATISTICS, QUIT, VERSION, WHO.\r\n"
 "\r\n";
 
 static void
 "\r\n";
 
 static void