Abstracting a few features in the client and server. Adding additional overflow protection in splitting command and arguments.

master
andrew 2009-02-17 22:14:43 -06:00
parent b3127887bd
commit e8c09582d6
3 changed files with 76 additions and 49 deletions

4
cftp.c
View File

@ -54,7 +54,7 @@ void split_command(char *buffer, char *command, char *argument)
memset(argument, '\0', MSGLEN); memset(argument, '\0', MSGLEN);
/* find everything up to the colon delimiter */ /* 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++]; command[d++] = buffer[c++];
} }
@ -65,7 +65,7 @@ void split_command(char *buffer, char *command, char *argument)
d = 0; d = 0;
} }
/* copy argument, if found */ /* copy argument, if found */
while(buffer[c] != '\0') while(buffer[c] != '\0' && c < MSGLEN && d < MSGLEN)
{ {
argument[d++] = buffer[c++]; argument[d++] = buffer[c++];
} }

View File

@ -66,6 +66,44 @@ int connect_to_server(const char *address, int portnum)
return skt; 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. * 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) void run_client(const char *address, int portnum)
{ {
int skt; int skt;
char msg[MSGLEN], command[CMDLEN], argument[MSGLEN]; char msg[MSGLEN];
/* clear strings */
memset(msg, '\0', MSGLEN); memset(msg, '\0', MSGLEN);
memset(command, '\0', MSGLEN);
memset(argument, '\0', MSGLEN);
/* simple informational header */
sprintf(msg, "Using Server: %s:%d", address, portnum); sprintf(msg, "Using Server: %s:%d", address, portnum);
cdebug(msg); cdebug(msg);
memset(msg, '\0', MSGLEN); memset(msg, '\0', MSGLEN);
@ -89,33 +124,13 @@ void run_client(const char *address, int portnum)
if(strlen(msg) > 0 && validate_command(msg)) if(strlen(msg) > 0 && validate_command(msg))
{ {
skt = connect_to_server(address, portnum); skt = connect_to_server(address, portnum);
if(send(skt, msg, strlen(msg), 0) < 0) send_message(skt, msg);
{
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);
close(skt); close(skt);
} }
else if(strlen(msg) > 0 && !strcmp(msg, "help")) else if(strlen(msg) > 0 && !strcmp(msg, "help"))
{ {
sprintf(msg, "Using Server: %s:%d", address, portnum);
cdebug(msg);
cdebug("Available commands:"); cdebug("Available commands:");
cdebug(" * ping - returns an unix timestamp from the server"); cdebug(" * ping - returns an unix timestamp from the server");
cdebug(" * get:filename - gets a file, if possible"); cdebug(" * get:filename - gets a file, if possible");

View File

@ -21,6 +21,30 @@ void sdebug(const char *msg)
debug("Server", 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 * Proccesses a client connection and performs the necessary command. Called
* on each connection from a client. * on each connection from a client.
@ -28,34 +52,22 @@ void sdebug(const char *msg)
*/ */
void handle_client(int skt, const char *clientip) void handle_client(int skt, const char *clientip)
{ {
char buffer[MSGLEN], msg[ERRMSGLEN], command[CMDLEN], argument[MSGLEN]; char buffer[MSGLEN], msg[ERRMSGLEN];
time_t pong;
memset(buffer, '\0', MSGLEN); memset(buffer, '\0', MSGLEN);
memset(msg, '\0', ERRMSGLEN); memset(msg, '\0', ERRMSGLEN);
memset(command, '\0', CMDLEN);
memset(argument, '\0', MSGLEN);
/* figure out what to do */ /* figure out what to do */
if(recv(skt, buffer, MSGLEN, 0) >= 0 && validate_command(buffer)) if(recv(skt, buffer, MSGLEN, 0) >= 0 && validate_command(buffer))
{ {
split_command(buffer, command, argument); server_command(buffer);
if(!strcmp(command, "ping")) }
{ else if(errno)
pong = time(NULL); {
sprintf(buffer, "Pong:%llud", (uintmax_t)pong); sprintf(buffer, "ERR:%s", strerror(errno));
}
} }
else else
{ {
if(errno) sprintf(buffer, "ERR:Invalid Command");
{
sprintf(buffer, "ERR:%s", strerror(errno));
}
else
{
sprintf(buffer, "ERR:Invalid Command");
}
error(buffer);
} }
/* send message to client */ /* send message to client */