From 2c26ef201aac506aedf92bab0b55bce460fd591b Mon Sep 17 00:00:00 2001 From: Igor Socec Date: Fri, 18 Nov 2016 23:06:20 +0100 Subject: [PATCH] Extract client functions into a separate header --- client.c | 120 +++++++++++++++++++++++++++++++---------------------- client.h | 48 +++++++++++++++++++++ moxerver.h | 48 --------------------- 3 files changed, 118 insertions(+), 98 deletions(-) create mode 100644 client.h diff --git a/client.c b/client.c index d88fdf1..1e34481 100644 --- a/client.c +++ b/client.c @@ -1,43 +1,47 @@ -/* - * Handling communication with clients. - */ +#include -#include "moxerver.h" - -/* Closes client connection. */ -int client_close(client_t *client) { +void client_close(client_t *client) +{ char timestamp[TIMESTAMP_LEN]; + /* force closing in case of error */ - if (close(client->socket) == -1) { + if (close(client->socket) == -1) + { close(client->socket); } client->socket = -1; + time2string(time(NULL), timestamp); - fprintf(stderr,"[%s] socket closed for client %s @ %s\n", __func__, client->ip_string, timestamp); - return 0; + fprintf(stderr,"[%s] socket closed for client %s @ %s\n", __func__, + client->ip_string, timestamp); } -/* Reads data from client into client data buffer. Returns number of read bytes. */ -int client_read(client_t *client) { - +int client_read(client_t *client) +{ int len; - /* read client data */ + /* read data from the client */ len = recv(client->socket, client->data, sizeof(client->data)-1, 0); - if (len == -1) { - fprintf(stderr, "[%s:%d] error %d: %s\n", __func__, __LINE__, errno, strerror(errno)); + if (len == -1) + { + fprintf(stderr, "[%s:%d] error %d: %s\n", __func__, __LINE__, + errno, strerror(errno)); return -errno; } /* a disconnected client socket is ready for reading but read returns 0 */ - if (len == 0) { - fprintf(stderr, "[%s:%d] no data available from client\n", __func__, __LINE__); + if (len == 0) + { + fprintf(stderr, "[%s:%d] no data available from client\n", + __func__, __LINE__); return -ENODATA; } //TODO let's print received bytes during development phase... - if (debug_messages) { + if (debug_messages) + { int i; - for(i = 0; i < len; i++) { + for(i = 0; i < len; i++) + { fprintf(stderr, "client %s <- %u '%c'\n", client->ip_string, (unsigned char) client->data[i], @@ -45,27 +49,28 @@ int client_read(client_t *client) { } } - /* handle special telnet characters coming from client */ + /* handle special telnet characters coming from the client */ telnet_handle_client_read(client->data, &len); - /* grab current time and store it as client last activity */ + /* grab current time and store it as client's last activity */ client->last_active = time(NULL); return len; } -/* Sends data from a buffer to client. Returns number of sent bytes. */ -int client_write(client_t *client, char *databuf, int datalen) { - +int client_write(client_t *client, char *databuf, int datalen) +{ int len; /* handle special telnet characters to display them correctly on client */ //telnet_handle_client_write(databuf, &datalen); //TODO let's print received bytes during development phase... - if (debug_messages) { + if (debug_messages) + { int i; - for(i = 0; i < datalen; i++) { + for(i = 0; i < datalen; i++) + { fprintf(stderr, "client %s -> %u '%c'\n", client->ip_string, (unsigned char) databuf[i], @@ -73,72 +78,87 @@ int client_write(client_t *client, char *databuf, int datalen) { } } - /* send data to client */ + /* send data to the client */ len = send(client->socket, databuf, datalen, 0); - if (len == -1) { - fprintf(stderr, "[%s:%d] error %d: %s\n", __func__, __LINE__, errno, strerror(errno)); + if (len == -1) + { + fprintf(stderr, "[%s:%d] error %d: %s\n", __func__, __LINE__, + errno, strerror(errno)); return -errno; } return len; } -/* Waits for client input in "line mode". Blocks until input arrives. */ -int client_wait_line(client_t *client) { - +int client_wait_line(client_t *client) +{ fd_set read_fds; struct timeval tv; client->data[0] = '\0'; /* loop waiting for client input */ - while (client->data[0] == '\0') { + while (client->data[0] == '\0') + { /* setup select() parameters */ tv.tv_sec = 15; /* 15 second timeout */ tv.tv_usec = 0; FD_ZERO(&read_fds); FD_SET(client->socket, &read_fds); - /* send prompt character to client */ + /* send prompt character to the client */ client_write(client, "> ", 2); /* block until input arrives */ - if (select((client->socket)+1, &read_fds, NULL, NULL, &tv) <= 0) return -1; - if (FD_ISSET(client->socket, &read_fds)) { + if (select((client->socket)+1, &read_fds, NULL, NULL, &tv) <= 0) + { + return -1; + } + if (FD_ISSET(client->socket, &read_fds)) + { /* read client input */ - if (client_read(client) == -1) return -1; + if (client_read(client) == -1) + { + return -1; + } /* we don't want empty data so stop on \r or \n */ - if ( (client->data[0] == '\r') || (client->data[0] == '\n') ) { + if ( (client->data[0] == '\r') || (client->data[0] == '\n') ) + { client->data[0] = '\0'; } } } - + return 0; } -/* Waits for client to provide a username. Blocks until a username is entered. */ -int client_ask_username(client_t *client) { - +int client_ask_username(client_t *client) +{ int i; char msg[DATABUF_LEN]; - /* send username request to client */ + /* show username request to the client */ snprintf(msg, DATABUF_LEN, - "\nPlease provide a username to identify yourself to other users (max %d characters):\n", USERNAME_LEN); + "\nPlease provide a username to identify yourself to" + "other users (max %d characters):\n", USERNAME_LEN); client_write(client, msg, strlen(msg)); /* wait for client input */ - if (client_wait_line(client) != 0) return -1; + if (client_wait_line(client) != 0) + { + return -1; + } /* save received data as client username */ - for (i = 0; i < USERNAME_LEN; i++) { - if ( (client->data[i] == '\r') || (client->data[i] == '\n') ) { - /* don't include \r or \n in username */ + for (i = 0; i < USERNAME_LEN; i++) + { + if ( (client->data[i] == '\r') || (client->data[i] == '\n') ) + { + /* don't include \r or \n in the username */ client->username[i] = '\0'; break; } client->username[i] = client->data[i]; } - /* send welcome message to client */ + /* show welcome message to client */ snprintf(msg, DATABUF_LEN, "\nWelcome %s!\n\n", client->username); client_write(client, msg, strlen(msg)); diff --git a/client.h b/client.h new file mode 100644 index 0000000..e5bd25a --- /dev/null +++ b/client.h @@ -0,0 +1,48 @@ +/* Handles communication with clients. */ + +#include + +/** + * Closes a client connection. + */ +void client_close(client_t *client); + +/** + * Reads data from a client into the client data buffer. + * Also updates the timestamp of the client's last activity. + * + * Returns: + * - number of read bytes on success, + * - negative ENODATA value (-ENODATA) if the client has disconnected, + * - negative errno value set by an error while reading + */ +int client_read(client_t *client); + +/** + * Sends data from a buffer to the client. + * + * Returns: + * - number of sent bytes on success, + * - negative errno value set by an error while sending + */ +int client_write(client_t *client, char *databuf, int datalen); + +/** + * Waits for input from the client in "line mode" (client sends a whole line of + * characters). The function blocks until input arrives. + * + * Returns: + * - 0 on success + * - negative value if error occurred + */ +int client_wait_line(client_t *client); + +/** + * Asks the client to provide a username. + * Blocks until a string is provided. + * + * Returns: + * - 0 on success + * - negative value if error occurred + */ +int client_ask_username(client_t *client); diff --git a/moxerver.h b/moxerver.h index 6ade182..4d0b4ce 100644 --- a/moxerver.h +++ b/moxerver.h @@ -110,55 +110,7 @@ int server_accept(server_t *server, client_t *accepted_client); void* server_new_client_thread(void *args); -/* Functions handling communication with clients. */ -/** - * Closes client connection. - * - * Returns: - * 0 always, but internally tries closing again if it fails - */ -int client_close(client_t *client); - -/** - * Reads data from client into client data buffer. - * Also updates client's last activity timestamp. - * - * Returns: - * - number of read bytes on success, - * - negative ENODATA value (-ENODATA) if client disconnected, - * - negative errno value set appropriately by error in reading - */ -int client_read(client_t *client); - -/** - * Sends data from a buffer to client. - * - * Returns: - * - number of sent bytes on success, - * - negative errno value set appropriately by error in sending - */ -int client_write(client_t *client, char *databuf, int datalen); - -/** - * Waits for client input in "line mode", where client sends a whole line of characters. - * Blocks until input arrives. - * - * Returns: - * - 0 on success - * - negative value if error occurred - */ -int client_wait_line(client_t *client); - -/** - * Waits for client to provide a username. - * Blocks until a username is entered. - * - * Returns: - * - 0 on success - * - negative value if error occurred - */ -int client_ask_username(client_t *client);