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 CSC-4200
To compile: 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: For explanation on running:
./cftp -h ./cftp -h

58
cftp.c
View File

@ -28,15 +28,15 @@ int validate_command(const char *msg)
char errmsg[ERRMSGLEN]; char errmsg[ERRMSGLEN];
/* GET file command */ /* GET file command */
if(!strcmp(msg, "get")) if(!strncmp(msg, "get", 3))
return 1; return 1;
/* PUT file command */ /* PUT file command */
if(!strcmp(msg, "put")) if(!strncmp(msg, "put", 3))
return 1; return 1;
/* PING send back the time stamp of right now */ /* PING send back the time stamp of right now */
if(!strcmp(msg, "ping")) if(!strncmp(msg, "ping", 4))
return 1; return 1;
/* nothing else was found, so clearly this is not true */ /* 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. * 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; int c = 0, d = 0;
memset(command, '\0', CMDLEN); memset(command, '\0', CMDLEN);
@ -94,6 +94,43 @@ void debug(const char *prefix, const char *msg)
printf("%s: %s\n", prefix, 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 * 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 * 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) void send_message(int skt, char *msg)
{ {
char errmsg[ERRMSGLEN]; if(send_packet(skt, msg))
memset(errmsg, '\0', ERRMSGLEN);
if(send(skt, msg, strlen(msg), 0) < 0)
{ {
sprintf(errmsg, "Send Error: %s", strerror(errno)); receive_packet(skt, msg);
error(errmsg);
}
else if(recv(skt, msg, MSGLEN, 0) < 0)
{
sprintf(errmsg, "Receive Error: %s", strerror(errno));
error(errmsg);
} }
} }

4
cftp.h
View File

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

View File

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

View File

@ -7,6 +7,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <libgen.h> #include <libgen.h>
#include <math.h>
#include "cftp.h" #include "cftp.h"
#include "filesystem.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 * This function will receive a packet and send a response back. Backwards of
* and a string containing the full path to the local file name. File cannot * send_message. Takes an integer for the socket and a buffer to write the
* exceed MAXFILE definition. * 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 response[CMDLEN];
char *basefname; 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; int fsize = 0, segments = 0, cur_segment;
FILE *infile; FILE *infile;
memset(errmsg, '\0', ERRMSGLEN); memset(errmsg, '\0', ERRMSGLEN);
memset(cmd, '\0', CMDLEN);
memset(arg, '\0', MSGLEN);
memset(msg, '\0', MSGLEN); memset(msg, '\0', MSGLEN);
/* file must exist */ /* file must exist */
if(!exist(filename)) if(!exist(filename))
{ {
if(server)
{
send_packet(skt, "err:That file does not exist");
}
error("The file does not exist!"); error("The file does not exist!");
return; return;
} }
@ -69,65 +94,50 @@ void send_file(int skt, const char *filename)
fsize = filesize(filename); fsize = filesize(filename);
if(fsize <= 0 || fsize >= MAXFILE) if(fsize <= 0 || fsize >= MAXFILE)
{ {
error("That file is inappropriately sized!"); if(server)
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); send_packet(skt, "err:File is too big");
error(errmsg); }
return; error("File is too big");
}
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);
return; return;
} }
segments = (int) ceil(fsize / MSGLEN);
/* open file or die */ /* open file or die */
infile = fopen(filename, "r"); infile = fopen(filename, "r");
if(infile == NULL) if(infile == NULL)
{ {
if(server)
{
send_packet(skt, "err:File could not be read");
}
sprintf(errmsg, "File could not be read: %s", strerror(errno)); sprintf(errmsg, "File could not be read: %s", strerror(errno));
error(errmsg); error(errmsg);
return; 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); send_packet(skt, "cts");
sprintf(errmsg, "\rFilesystem: Sending file %.2f%%", (cur_segment / segments * 100.0)); sleep(1);
printf(errmsg);
send_message(skt, msg);
} }
/* 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); 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. * 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; 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 #define MAXFILE 1279872
void send_file(int, const char *); void send_file(int, const char *, int);
void receive_file(int, const char *); void receive_file(int, const char *, int);
#endif #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. * 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]; char command[CMDLEN], argument[MSGLEN];
time_t pong; time_t pong;
memset(command, '\0', CMDLEN);
memset(argument, '\0', MSGLEN);
/* get individual command and argument for processing */ /* get individual command and argument for processing */
split_command(msg, command, argument); split_command(msg, command, argument);
/* now check each command and perform the expected results */ /* now check each command and perform the expected results */
if(!strcmp(command, "ping")) if(!strncmp(msg, "ping", 4))
{ {
pong = time(NULL); pong = time(NULL);
sprintf(msg, "pong:%llud", (uintmax_t)pong); 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); memset(msg, '\0', ERRMSGLEN);
/* figure out what to do */ /* 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) else if(errno)
{ {
sprintf(buffer, "err:%s", strerror(errno)); sprintf(buffer, "err:%s", strerror(errno));
} }
/* regular fail */
else else
{ {
sprintf(buffer, "err:Invalid Command"); sprintf(buffer, "err:Invalid Command");
@ -74,12 +84,10 @@ void handle_client(int skt, const char *clientip)
/* send message to client */ /* send message to client */
if(strlen(buffer) > 0) if(strlen(buffer) > 0)
{ {
sprintf(msg, "%s: %s", clientip, buffer); sprintf(msg, "Response to %s: %s", clientip, buffer);
sdebug(msg); sdebug(msg);
send(skt, buffer, strlen(buffer), 0); send_packet(skt, buffer);
} }
/* cleanup */
close(skt); close(skt);
} }