From e8c09582d60dc87a09e80c0926b658c391ac1acd Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 17 Feb 2009 22:14:43 -0600 Subject: [PATCH] Abstracting a few features in the client and server. Adding additional overflow protection in splitting command and arguments. --- cftp.c | 4 ++-- client.c | 71 ++++++++++++++++++++++++++++++++++---------------------- server.c | 50 ++++++++++++++++++++++++--------------- 3 files changed, 76 insertions(+), 49 deletions(-) diff --git a/cftp.c b/cftp.c index 22fd468..dac0081 100644 --- a/cftp.c +++ b/cftp.c @@ -54,7 +54,7 @@ void split_command(char *buffer, char *command, char *argument) memset(argument, '\0', MSGLEN); /* find everything up to the colon delimiter */ - while(buffer[c] != '\0' && buffer[c] != ':') + while(buffer[c] != '\0' && buffer[c] != ':' && c < CMDLEN && d < CMDLEN) { command[d++] = buffer[c++]; } @@ -65,7 +65,7 @@ void split_command(char *buffer, char *command, char *argument) d = 0; } /* copy argument, if found */ - while(buffer[c] != '\0') + while(buffer[c] != '\0' && c < MSGLEN && d < MSGLEN) { argument[d++] = buffer[c++]; } diff --git a/client.c b/client.c index ac00a4a..8e84069 100644 --- a/client.c +++ b/client.c @@ -66,6 +66,44 @@ int connect_to_server(const char *address, int portnum) return skt; } +/* + * Sends a message to the socket. Pass in the socket and message. Expects msg + * to be already validated by validate_command first! Formats response into + * string buffer given. + * + */ +void send_message(int skt, char *msg) +{ + char command[CMDLEN], argument[MSGLEN], errmsg[ERRMSGLEN]; + memset(command, '\0', CMDLEN); + memset(argument, '\0', MSGLEN); + memset(errmsg, '\0', ERRMSGLEN); + + if(send(skt, msg, strlen(msg), 0) < 0) + { + sprintf(errmsg, "Send Error: %s", strerror(errno)); + error(errmsg); + } + else if(recv(skt, msg, MSGLEN, 0) < 0) + { + sprintf(errmsg, "Receive Error: %s", strerror(errno)); + error(errmsg); + } + else + { + split_command(msg, command, argument); + if(strlen(argument) > 0) + { + sprintf(errmsg, "Response: %s: %s", command, argument); + } + else + { + sprintf(errmsg, "Response: %s", command); + } + cdebug(errmsg); + } +} + /* * Runs the command processor to the server. Handles commands and responses. * @@ -73,13 +111,10 @@ int connect_to_server(const char *address, int portnum) void run_client(const char *address, int portnum) { int skt; - char msg[MSGLEN], command[CMDLEN], argument[MSGLEN]; - - /* clear strings */ + char msg[MSGLEN]; memset(msg, '\0', MSGLEN); - memset(command, '\0', MSGLEN); - memset(argument, '\0', MSGLEN); + /* simple informational header */ sprintf(msg, "Using Server: %s:%d", address, portnum); cdebug(msg); memset(msg, '\0', MSGLEN); @@ -89,33 +124,13 @@ void run_client(const char *address, int portnum) if(strlen(msg) > 0 && validate_command(msg)) { skt = connect_to_server(address, portnum); - if(send(skt, msg, strlen(msg), 0) < 0) - { - sprintf(msg, "Send Error: %s", strerror(errno)); - error(msg); - } - else if(recv(skt, msg, MSGLEN, 0) < 0) - { - sprintf(msg, "Receive Error: %s", strerror(errno)); - error(msg); - } - else - { - split_command(msg, command, argument); - if(strlen(argument) > 0) - { - sprintf(msg, "Server Said: %s: %s", command, argument); - } - else - { - sprintf(msg, "Server Said: %s", command); - } - } - cdebug(msg); + send_message(skt, msg); close(skt); } else if(strlen(msg) > 0 && !strcmp(msg, "help")) { + sprintf(msg, "Using Server: %s:%d", address, portnum); + cdebug(msg); cdebug("Available commands:"); cdebug(" * ping - returns an unix timestamp from the server"); cdebug(" * get:filename - gets a file, if possible"); diff --git a/server.c b/server.c index ce94dcd..5df5b2e 100644 --- a/server.c +++ b/server.c @@ -21,6 +21,30 @@ void sdebug(const char *msg) debug("Server", msg); } +/* + * Handles each command received from the server. Expects that the message has + * been validated by validate_command first! Takes one parameter, the message + * from the client. The response is stored in the same buffer for return. + * + */ +void server_command(char *msg) +{ + char command[CMDLEN], argument[MSGLEN]; + time_t pong; + memset(command, '\0', CMDLEN); + memset(argument, '\0', MSGLEN); + + /* get individual command and argument for processing */ + split_command(msg, command, argument); + + /* now check each command and perform the expected results */ + if(!strcmp(command, "ping")) + { + pong = time(NULL); + sprintf(msg, "Pong:%llud", (uintmax_t)pong); + } +} + /* * Proccesses a client connection and performs the necessary command. Called * on each connection from a client. @@ -28,34 +52,22 @@ void sdebug(const char *msg) */ void handle_client(int skt, const char *clientip) { - char buffer[MSGLEN], msg[ERRMSGLEN], command[CMDLEN], argument[MSGLEN]; - time_t pong; + char buffer[MSGLEN], msg[ERRMSGLEN]; memset(buffer, '\0', MSGLEN); memset(msg, '\0', ERRMSGLEN); - memset(command, '\0', CMDLEN); - memset(argument, '\0', MSGLEN); /* figure out what to do */ if(recv(skt, buffer, MSGLEN, 0) >= 0 && validate_command(buffer)) { - split_command(buffer, command, argument); - if(!strcmp(command, "ping")) - { - pong = time(NULL); - sprintf(buffer, "Pong:%llud", (uintmax_t)pong); - } + server_command(buffer); + } + else if(errno) + { + sprintf(buffer, "ERR:%s", strerror(errno)); } else { - if(errno) - { - sprintf(buffer, "ERR:%s", strerror(errno)); - } - else - { - sprintf(buffer, "ERR:Invalid Command"); - } - error(buffer); + sprintf(buffer, "ERR:Invalid Command"); } /* send message to client */