X-Git-Url: https://git.cworth.org/git?p=ttt;a=blobdiff_plain;f=src%2Fttt-client.c;h=9d44945e506664678854fab51c41fa3fd04e870d;hp=e6c97a1c6ad9c2f16ba1f07d9bbc0336e68daa93;hb=907321c065fb1383e800f0794981df91d4327f57;hpb=15672ac8305a1c5ba0d9bf6edabb0a194c30628e diff --git a/src/ttt-client.c b/src/ttt-client.c index e6c97a1..9d44945 100644 --- a/src/ttt-client.c +++ b/src/ttt-client.c @@ -20,20 +20,39 @@ */ #include "ttt-client.h" + +#include "ttt-server.h" #include "ttt-socket.h" +#include "ttt-error.h" -ttt_client_t * -ttt_client_create (ttt_server_t *server, int socket, int id) -{ - ttt_client_t *client; +struct _ttt_client { + pthread_mutex_t mutex; + pthread_t thread; - client = xmalloc (sizeof (ttt_client_t)); + ttt_server_t *server; + int socket; + + int id; + + char buf[TTT_CLIENT_BUF_SIZE]; + char *buf_head; + char *buf_tail; + + char *request; + int request_size; + int request_len; +}; + +static void +_ttt_client_init (ttt_client_t *client, + ttt_server_t *server, + int socket) +{ + pthread_mutex_init (&client->mutex, NULL); client->server = server; client->socket = socket; - client->id = id; - client->buf_head = client->buf; client->buf_tail = client->buf; @@ -41,17 +60,26 @@ ttt_client_create (ttt_server_t *server, int socket, int id) client->request_size = 0; client->request_len = 0; - return client; + /* 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); } -void -ttt_client_destroy (ttt_client_t *client) +static void +_ttt_client_fini (ttt_client_t *client) { + pthread_mutex_lock (&client->mutex); + + ttt_server_unregister_client (client->server, client); + shutdown (client->socket, SHUT_RDWR); free (client->request); - free (client); + pthread_mutex_unlock (&client->mutex); + + pthread_mutex_destroy (&client->mutex); } static void @@ -79,7 +107,7 @@ _append_to_request (ttt_client_t *client, } static ttt_status_t -ttt_client_read_into_request_until (ttt_client_t *client, char delimeter) +_read_into_request_until (ttt_client_t *client, char delimeter) { ttt_bool_t found_delimeter = FALSE; int bytes_read; @@ -117,27 +145,90 @@ ttt_client_read_into_request_until (ttt_client_t *client, char delimeter) } } -char * -ttt_client_read_line (ttt_client_t *client) +static ttt_status_t +_read_request (ttt_client_t *client) { ttt_status_t status; static const char null_terminator = '\0'; - status = ttt_client_read_into_request_until (client, '\n'); - if (status) { - assert (status == TTT_STATUS_EOF); - return NULL; - } + status = _read_into_request_until (client, '\n'); + if (status) + return status; _append_to_request (client, &null_terminator, 1); - return client->request; + return TTT_STATUS_SUCCESS; +} + +static ttt_error_t +_execute_request (ttt_client_t *client) +{ + ttt_server_broadcast (client->server, client->request); + + return TTT_ERROR_NONE; +} + +static void * +_handle_requests_thread (void *closure) +{ + ttt_status_t status; + ttt_error_t error; + ttt_client_t *client = closure; + + while (1) { + + status = _read_request (client); + if (status == TTT_STATUS_EOF) + break; + if (status) + ASSERT_NOT_REACHED; + + error = _execute_request (client); + if (error) + ttt_client_send (client, ttt_error_string (error)); + } + + _ttt_client_fini (client); + free (client); + + return (void *) 0; +} + +/* Exported: See ttt-client.h for documentation. */ +void +ttt_client_new (void *closure, int client_socket) +{ + ttt_server_t *server = closure; + ttt_client_t *client; + int err; + + client = xmalloc (sizeof (ttt_client_t)); + + _ttt_client_init (client, server, client_socket); + + err = pthread_create (&client->thread, NULL, + _handle_requests_thread, client); + if (err != 0) { + fprintf (stderr, "Error: pthread_create failed: %s. Aborting.\n", + strerror (err)); + exit (1); + } } +/* Exported: See ttt-client.h for documentation. */ void ttt_client_send (ttt_client_t *client, const char *message) { + pthread_mutex_lock (&client->mutex); + ttt_socket_write (client->socket, message, strlen (message)); -} + pthread_mutex_unlock (&client->mutex); +} +/* Exported: See ttt-client.h for documentation. */ +int +ttt_client_get_id (ttt_client_t *client) +{ + return client->id; +}