X-Git-Url: https://git.cworth.org/git?p=ttt;a=blobdiff_plain;f=src%2Fttt-server.c;h=4b29cf2f774d277dc14dd5bc675f4b5a9a25df6d;hp=cb28741885721763fd54abd4a8a83b270e07f442;hb=df6ad6c8658a9f3a537a070a89a067c5ae598fcc;hpb=da40516db47b4c719aaad66a05302f13d1b6358e diff --git a/src/ttt-server.c b/src/ttt-server.c index cb28741..4b29cf2 100644 --- a/src/ttt-server.c +++ b/src/ttt-server.c @@ -26,15 +26,24 @@ #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; - 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 @@ -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->invites = NULL; + server->invites_size = 0; + server->num_invites = 0; } /* 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++) { - 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; } @@ -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 [server->num_clients - 1] = client; + server->clients[server->num_clients - 1] = client; 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) { + ttt_invite_t *invite; + char *notice; + ttt_bool_t send_notice = FALSE; 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 (¬ice, "%s" "NOTICE RETRACT %s %s\r\n", + notice, + ttt_client_get_username(invite->actor), + ttt_client_get_username(invite->invitee)); + else + xasprintf (¬ice, "%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; @@ -118,6 +160,12 @@ ttt_server_unregister_client (ttt_server_t *server, ttt_client_t *client) 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. */ @@ -159,24 +207,34 @@ ttt_server_who (ttt_server_t *server) /* 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; - 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]); - if (strcasecmp (username, client_username) == 0) { + if (strcasecmp (username, client_username) == 0) + { 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 -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); - 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; } +/* 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) @@ -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" -"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