sending works

master
andrew 2009-02-19 00:01:58 -06:00
parent 1c942c3f05
commit df019f8eab
7 changed files with 212 additions and 90 deletions

2
README
View File

@ -3,7 +3,7 @@ Andrew Coleman
CSC-4200
To compile:
gcc -o cftp -Wall server.c client.c filesystem.c cftp.c
gcc -o cftp -lm -Wall server.c client.c filesystem.c cftp.c
For explanation on running:
./cftp -h

58
cftp.c
View File

@ -28,15 +28,15 @@ int validate_command(const char *msg)
char errmsg[ERRMSGLEN];
/* GET file command */
if(!strcmp(msg, "get"))
if(!strncmp(msg, "get", 3))
return 1;
/* PUT file command */
if(!strcmp(msg, "put"))
if(!strncmp(msg, "put", 3))
return 1;
/* PING send back the time stamp of right now */
if(!strcmp(msg, "ping"))
if(!strncmp(msg, "ping", 4))
return 1;
/* nothing else was found, so clearly this is not true */
@ -49,7 +49,7 @@ int validate_command(const char *msg)
* Splits a buffer into a command and argument.
*
*/
void split_command(char *buffer, char *command, char *argument)
void split_command(const char *buffer, char *command, char *argument)
{
int c = 0, d = 0;
memset(command, '\0', CMDLEN);
@ -94,6 +94,43 @@ void debug(const char *prefix, const char *msg)
printf("%s: %s\n", prefix, msg);
}
/*
* Wrapper to send a packet to a socket given a string. Handles errors and
* returns a bool based on success.
*
*/
int send_packet(int skt, const char *msg)
{
char errmsg[ERRMSGLEN];
memset(errmsg, '\0', ERRMSGLEN);
if(send(skt, msg, strlen(msg), 0) < 0)
{
sprintf(errmsg, "Send Packet Error: %s", strerror(errno));
error(errmsg);
return 0;
}
return 1;
}
/*
* Wrapper to receive a packet from a socket and stores the result in a given
* buffer. Handles errors and returns a bool based on success.
*
*/
int receive_packet(int skt, char *msg)
{
char errmsg[ERRMSGLEN];
memset(errmsg, '\0', ERRMSGLEN);
memset(msg, '\0', MSGLEN);
if(recv(skt, msg, MSGLEN, 0) < 0)
{
sprintf(errmsg, "Receive Packet Error: %s", strerror(errno));
error(errmsg);
return 0;
}
return 1;
}
/*
* 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
@ -103,18 +140,9 @@ void debug(const char *prefix, const char *msg)
*/
void send_message(int skt, char *msg)
{
char errmsg[ERRMSGLEN];
memset(errmsg, '\0', ERRMSGLEN);
if(send(skt, msg, strlen(msg), 0) < 0)
if(send_packet(skt, msg))
{
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);
receive_packet(skt, msg);
}
}

4
cftp.h
View File

@ -10,9 +10,11 @@
#define ERRMSGLEN 256
#define CMDLEN 5
int validate_command(const char *);
void split_command(char *, char *, char *);
void split_command(const char *, char *, char *);
void error(const char *);
void debug(const char *, const char *);
int send_packet(int, const char *);
int receive_packet(int, char *);
void send_message(int, char *);
#endif

View File

@ -88,14 +88,18 @@ void run_client(const char *address, int portnum)
{
skt = connect_to_server(address, portnum);
split_command(msg, cmd, argument);
if(!strcmp(cmd, "put"))
send_message(skt, msg);
/* response message from server, now in msg */
cdebug(msg);
/* send file to server */
if(!strcmp(cmd, "put") && !strncmp(msg, "cts", 3))
{
send_file(skt, argument);
send_file(skt, argument, 0);
}
else
/* get file from server */
else if(!strcmp(cmd, "get") && !strncmp(msg, "cts", 3))
{
send_message(skt, msg);
cdebug(msg);
receive_file(skt, argument, 0);
}
close(skt);
}
@ -111,7 +115,7 @@ void run_client(const char *address, int portnum)
memset(msg, '\0', MSGLEN);
printf("> ");
scanf("%s", msg);
} while(strcmp(msg, "quit") != 0);
} while(strcmp(msg, "quit"));
/* cleanup and quit */
cdebug("Bye!");

View File

@ -7,6 +7,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <libgen.h>
#include <math.h>
#include "cftp.h"
#include "filesystem.h"
@ -41,26 +42,50 @@ int filesize(const char *filename)
}
/*
* This function will send a file to a remote host. Expects a socket integer
* and a string containing the full path to the local file name. File cannot
* exceed MAXFILE definition.
* This function will receive a packet and send a response back. Backwards of
* send_message. Takes an integer for the socket and a buffer to write the
* message into. This is only designed to take a reponse from send_file and
* send back either "cts" or "err".
*
*/
void send_file(int skt, const char *filename)
void receive_message(int skt, char *buf)
{
char errmsg[ERRMSGLEN], cmd[CMDLEN], arg[MSGLEN], msg[MSGLEN];
char *basefname;
char response[CMDLEN];
memset(response, '\0', CMDLEN);
if(!receive_packet(skt, buf))
{
strcpy(response, "err");
}
else
{
strcpy(response, "cts");
}
send_packet(skt, response);
}
/*
* This function will send a file to a remote host. Expects a socket integer
* and a string containing the full path to the local file name. File cannot
* exceed MAXFILE definition. Takes a server boolean for some additional
* checks.
*
*/
void send_file(int skt, const char *filename, int server)
{
char errmsg[ERRMSGLEN], msg[MSGLEN];
int fsize = 0, segments = 0, cur_segment;
FILE *infile;
memset(errmsg, '\0', ERRMSGLEN);
memset(cmd, '\0', CMDLEN);
memset(arg, '\0', MSGLEN);
memset(msg, '\0', MSGLEN);
/* file must exist */
if(!exist(filename))
{
if(server)
{
send_packet(skt, "err:That file does not exist");
}
error("The file does not exist!");
return;
}
@ -69,65 +94,50 @@ void send_file(int skt, const char *filename)
fsize = filesize(filename);
if(fsize <= 0 || fsize >= MAXFILE)
{
error("That file is inappropriately sized!");
return;
}
segments = MAXFILE / MSGLEN;
/* make a copy then figure out just the filename */
strcpy(msg, filename);
basefname = basename(msg);
sprintf(errmsg, "Sending file (%s) in %d segments.", basefname, segments);
debug("Filesystem", errmsg);
/* send the command, we do not send the user command because we just want
* to send the base filename. also, we expect a response from the server,
* either cts or err.
*/
sprintf(msg, "put:%s", basefname);
send_message(skt, msg);
split_command(msg, cmd, arg);
if(!strcmp(cmd, "err"))
{
sprintf(errmsg, "ERROR Not sending the file: %s", arg);
error(errmsg);
return;
}
else if(strcmp(cmd, "cts"))
{
sprintf(errmsg, "ERROR invalid reponse from remote: %s", msg);
error(errmsg);
return;
}
/* send number of segments and file size to the other size cmd:arg style */
sprintf(msg, "%d:%d", segments, fsize);
/* do not expect a response, only data after this */
if(send(skt, msg, strlen(msg), 0) < 0)
{
sprintf(errmsg, "Failed to send the number of segments: %s", strerror(errno));
error(errmsg);
if(server)
{
send_packet(skt, "err:File is too big");
}
error("File is too big");
return;
}
segments = (int) ceil(fsize / MSGLEN);
/* open file or die */
infile = fopen(filename, "r");
if(infile == NULL)
{
if(server)
{
send_packet(skt, "err:File could not be read");
}
sprintf(errmsg, "File could not be read: %s", strerror(errno));
error(errmsg);
return;
}
/* now read in the file, MSGLEN at a time and send the chunk to the host */
for(cur_segment = 0; cur_segment < segments; cur_segment++)
/* send cts to client */
if(server)
{
fread(msg, MSGLEN, 1, infile);
sprintf(errmsg, "\rFilesystem: Sending file %.2f%%", (cur_segment / segments * 100.0));
printf(errmsg);
send_message(skt, msg);
send_packet(skt, "cts");
sleep(1);
}
/* send number of segments and file size to the other size cmd:arg style */
sprintf(msg, "%d:%d", segments, fsize);
/* do not expect a response, only data after this */
send_packet(skt, msg);
/* now read in the file, MSGLEN at a time and send the chunk to the host */
for(cur_segment = 0; cur_segment <= segments; cur_segment++)
{
memset(msg, '\0', MSGLEN);
fread(msg, MSGLEN, 1, infile);
printf("\rFilesystem: Sending file %d / %d", cur_segment, segments);
send_packet(skt, msg);
}
printf("\n");
fclose(infile);
debug("Filesystem", "File sent successfully");
}
/*
@ -135,9 +145,79 @@ void send_file(int skt, const char *filename)
* a filename. The file will be basename'd and saved into /tmp.
*
*/
void receive_file(int skt, const char *filename)
void receive_file(int skt, const char *filename, int server)
{
unsigned char fbuf[MAXFILE];
char msg[MSGLEN], cmd[CMDLEN], arg[MSGLEN], lname[MSGLEN], errmsg[ERRMSGLEN];
char *basefname;
FILE *outfile;
int fsize = 0, segments = 0, cur_segment = 0;
/* get the local file name in /tmp */
memset(lname, '\0', MSGLEN);
memset(errmsg, '\0', ERRMSGLEN);
strcpy(msg, filename);
basefname = basename(msg);
sprintf(lname, "/tmp/%s", basefname);
/* if file exists, send err to remote, otherwise send cts and await size */
if(exist(lname))
{
debug("Filesystem", "Not receiving file since it already exists");
if(server)
{
send_packet(skt, "err:File already exists");
}
return;
}
/* open file for writing */
outfile = fopen(lname, "w");
if(outfile == NULL)
{
sprintf(errmsg, "Could not open file for writing: %s", strerror(errno));
debug("Filesystem", errmsg);
if(server)
{
send_packet(skt, "err:File could not be written");
}
return;
}
/* ready to receive file */
if(server)
{
memset(msg, '\0', MSGLEN);
strcpy(msg, "cts");
send_message(skt, msg);
}
else
{
receive_packet(skt, msg);
}
split_command(msg, cmd, arg);
segments = atoi(cmd);
fsize = atoi(arg);
sprintf(errmsg, "Going to receive %d bytes in %d segments", fsize, segments);
debug("Filesystem", errmsg);
/* loop through segments packet count and get the file */
for(cur_segment = 0; cur_segment <= segments; cur_segment++)
{
printf("\rFilesystem: Receiving File: %d / %d", cur_segment, segments);
memset(msg, '\0', MSGLEN);
receive_packet(skt, msg);
if(cur_segment == segments)
{
/* write remaining bytes */
fwrite(msg, (fsize - (segments * MSGLEN)), 1, outfile);
}
else
{
/* write complete segment */
fwrite(msg, MSGLEN, 1, outfile);
}
}
printf("\n");
fclose(outfile);
}

View File

@ -17,8 +17,8 @@
*
*/
#define MAXFILE 1279872
void send_file(int, const char *);
void receive_file(int, const char *);
void send_file(int, const char *, int);
void receive_file(int, const char *, int);
#endif

View File

@ -28,22 +28,30 @@ void sdebug(const char *msg)
* from the client. The response is stored in the same buffer for return.
*
*/
void server_command(char *msg)
void server_command(int skt, 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"))
if(!strncmp(msg, "ping", 4))
{
pong = time(NULL);
sprintf(msg, "pong:%llud", (uintmax_t)pong);
}
else if(!strncmp(msg, "put", 3))
{
memset(msg, '\0', MSGLEN);
receive_file(skt, argument, 1);
}
else if(!strncmp(msg, "get", 3))
{
memset(msg, '\0', MSGLEN);
send_file(skt, argument, 1);
}
}
/*
@ -58,14 +66,16 @@ void handle_client(int skt, const char *clientip)
memset(msg, '\0', ERRMSGLEN);
/* figure out what to do */
if(recv(skt, buffer, MSGLEN, 0) >= 0 && validate_command(buffer))
if(receive_packet(skt, buffer) && validate_command(buffer))
{
server_command(buffer);
server_command(skt, buffer);
}
/* epic fail */
else if(errno)
{
sprintf(buffer, "err:%s", strerror(errno));
}
/* regular fail */
else
{
sprintf(buffer, "err:Invalid Command");
@ -74,12 +84,10 @@ void handle_client(int skt, const char *clientip)
/* send message to client */
if(strlen(buffer) > 0)
{
sprintf(msg, "%s: %s", clientip, buffer);
sprintf(msg, "Response to %s: %s", clientip, buffer);
sdebug(msg);
send(skt, buffer, strlen(buffer), 0);
send_packet(skt, buffer);
}
/* cleanup */
close(skt);
}