1
0
This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
TP-Link_Archer-XR500v/EN7526G_3.18Kernel_SDK/apps/public/tftp-1.0/tftpc.c
2024-07-22 01:58:46 -03:00

917 lines
27 KiB
C
Executable File

/**********************************************************
Date: NOV 28th, 2006
Project : TFTP Client
Programers:
Jonathan Felske
Andrew Fullard
Craig Holmes
Reza Rahmanian
Adam Tomalty
File: TFTP Client (main)
Purpose: A TFTP client that will request a connections from
the server and transefet files.
Notes: Here we are using the sendto and recvfrom
functions so the server and client can exchange data.
***********************************************************/
#include "tftp.h"
/*a function to print the Help menu*/
void help (char *);
/*a function to create the request packet, read or write*/
int req_packet (int opcode, char *filename, char *mode, char buf[]);
/*a function to creat an ACK packet*/
int ack_packet (int block, char buf[]);
/*a function to create the Error packets*/
int err_packet (int err_code, char *err_msg, char buf[]);
/*a function that will print the ip:port pair of the server or client, plus data sent or recieved*/
void ip_port (struct sockaddr_in host);
/*a function to send a file to the server*/
void tsend (char *pFilename, struct sockaddr_in server, char *pMode,
int sock);
/*a function to get a file from the server*/
void tget (char *pFilename, struct sockaddr_in server, char *pMode, int sock);
/* default values which can be controlled by command line */
char path[64] = "/tmp/";
int port = 69;
unsigned short int ackfreq = 1;
int datasize = 512;
int debug = 0, w_size = 1, p_length = 512;
int
main (int argc, char **argv)
{
/*local variables */
extern char *optarg;
int sock, server_len, len, opt; //,n;
char opcode, filename[196], mode[12] = "octet";
struct hostent *host; /*for host information */
struct sockaddr_in server; //, client; /*the address structure for both the server and client */
FILE *fp; /*a pointer to a file that the client will send or get from the server */
if (argc < 2)
{
help (argv[0]);
return 0;
}
if (!(host = gethostbyname (argv[1])))
{
perror ("Client could not get host address information");
exit (2);
}
/* All of the following deals with command line switches */
while ((opt = getopt (argc, argv, "dnoh:P:p:g:l:w:")) != -1) /* this function is handy */
{
switch (opt)
{
case 'd': /* debug mode (no opts) */
debug = 1;
break;
case 'P': /* Port (opt required) */
port = atoi (optarg);
if (debug)
{
printf ("Client: The port number is: %d\n", port);
}
break;
case 'p': /* put a file on the server */
strncpy (filename, optarg, sizeof (filename) - 1);
opcode = WRQ;
fp = fopen (filename, "r"); /*opened the file for reading */
if (fp == NULL)
{
printf ("Client: file could not be opened\n");
return 0;
}
if (debug)
{
printf ("Client: The file name is: %s and can be read",
filename);
}
fclose (fp);
break;
case 'g': /*get a file from the server */
strncpy (filename, optarg, sizeof (filename) - 1);
opcode = RRQ;
fp = fopen (filename, "w"); /*opened the file for writting */
if (fp == NULL)
{
printf ("Client: file could not be created\n");
return 0;
}
if (debug)
{
printf ("Client: The file name is: %s and it has been created",
filename);
}
fclose (fp);
break;
case 'w': /* Get the window size */
ackfreq = atoi (optarg);
if (debug)
{
printf ("Client: Window size is: %i\n", ackfreq);
}
//ackfreq = atoi (optarg);
if (ackfreq > MAXACKFREQ)
{
printf
("Client: Sorry, you specified an ack frequency higher than the maximum allowed (Requested: %d Max: %d)\n",
ackfreq, MAXACKFREQ);
return 0;
}
else if (w_size == 0)
{
printf ("Client: Sorry, you have to ack sometime.\n");
return 0;
}
break;
case 'l': /* packet length */
datasize = atoi (optarg);
if (debug)
{
printf ("Client: Packet length is: %i bytes\n", datasize);
}
if (datasize > MAXDATASIZE)
{
printf
("Client: Sorry, you specified a data size higher than the maximum allowed (Requested: %d Max: %d)\n",
datasize, MAXDATASIZE);
return 0;
}
break;
case 'h': /* Help (no opts) */
help (argv[0]);
return (0);
break;
case 'o':
strncpy (mode, "octet", sizeof (mode) - 1);
if (debug)
{
printf ("Client: The mode is set to octet\n");
}
break;
case 'n':
strncpy (mode, "netascii", sizeof (mode) - 1);
if (debug)
{
printf ("Client: The mode is set to netascii\n");
}
break;
default: /* everything else */
help (argv[0]);
return (0);
break;
} //end of switch
} //end of while loop
/*check for valid input*/
if (argc < 5 || argc > 12)
{
printf ("Client: wrong number of arguments: %d\n", argc);
help (argv[0]);
exit (ERROR);
}
/* Done dealing with switches and the command line*/
/*Create the socket, a -1 will show us an error */
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
printf ("Client: Socket could not be created");
return 0;
}
/*set the address values for the server */
memset (&server, 0, sizeof (server)); /*Clear the structure */
server.sin_family = AF_INET; /*address family for TCP and UDP */
memcpy (&server.sin_addr, host->h_addr, host->h_length); /*set address of server taken from gethostbyname function */
//server.sin_addr.s_addr = htonl (INADDR_ANY); /*use any address */
server.sin_port = htons (port); /*pick a free port */
server_len = sizeof (server); /*get the length of the server address */
if (debug)
printf ("Client: size of server_address is : %d bytes\n", server_len);
memset (buf, 0, BUFSIZ); /*clear the buffer */
/* this is the first request message */
len = req_packet (opcode, filename, mode, buf);
if (debug)
printf ("Client: The request packt's length is: %d bytes\n", len);
if (sendto (sock, buf, len, 0, (struct sockaddr *) &server, server_len) !=
len)
{
perror ("Client: sendto has returend an error");
exit (ERROR);
}
if (debug)
ip_port (server);
switch (opcode)
{
case RRQ: /*read from the server, download */
tget (filename, server, mode, sock);
break;
case WRQ: /*write to the server, upload */
tsend (filename, server, mode, sock);
break;
default:
printf ("Invalid opcode detected. Ignoring packet.");
}
close (sock); /* close the socket */
return 1;
} //end of main
/******************************************************************
Function deffinitions
*******************************************************************/
/*usage of the command:
./tftpc server -P port# -g(get file)|-p(put file) <filename> -w (window size) -l (packetlength)
if windowsize and packet length are not chosen then a default value of 1, for the
window size and 512 bytes for the packet length will be set.*/
/* a function to display the help menu*/
void
help (char *app)
{
printf
("Usage:\n%s server [-h] [-d] [-P port] [-g] | [-p] [file-name] [-w size] [-l length] [-o] [-n]\n",
app);
printf
("Options:\n-h (help; this message)\n-d (Debug mode)\n-P port(Port number default is 69)\n-g (get a file from the server)\n-p (send a file to the server)\n");
printf
("-w size (set window size, default is 1)\n-l len (set max packet length, default is 512 bytes)\n");
printf
("-o for octet file transfer (default).\n-n for netascii file transfer\n");
}
/* A function that will create a request packet*/
/*I'm not sure if I need the last 0x00 because sprintf will end the string with \0*/
int
req_packet (int opcode, char *filename, char *mode, char buf[])
{
int len;
len =
sprintf (buf, "%c%c%s%c%s%c", 0x00, opcode, filename, 0x00, mode, 0x00);
if (len == 0)
{
printf ("Error in creating the request packet\n"); /*could not print to the client buffer */
exit (ERROR);
}
if (debug)
{
printf ("I am creating the request packet.\n");
}
return len;
}
/* A function that will create an ACK packet*/
/*problem that we will have here is that we can only get up to 255 blocks*/
int
ack_packet (int block, char buf[])
{
int len;
len = sprintf (buf, "%c%c%c%c", 0x00, ACK, 0x00, 0x00);
buf[2] = (block & 0xFF00) >> 8;
buf[3] = (block & 0x00FF);
if (len == 0)
{
printf ("Error in creating the ACK packet\n"); /*could not print to the client buffer */
exit (ERROR);
}
if (debug)
{
printf ("I am creating the ACK packet.\n");
}
return len;
}
/* A function that will create an error packet based on the error code*/
int
err_packet (int err_code, char *err_msg, char buf[])
{
int len;
memset (buf, 0, sizeof (buf));
len =
sprintf (buf, "%c%c%c%c%s%c", 0x00, ERR, 0x00, err_code, err_msg, 0x00);
if (len == 0)
{
printf ("Error in creating the ACK packet\n"); /*could not print to the client buffer */
exit (ERROR);
}
if (debug)
{
printf ("I am creating an ERROR packet.\n");
}
return len;
}
/* A function used for debuging to show the port numbers used*/
void
ip_port (struct sockaddr_in host)
{
printf ("The IP port pair for the host is: IP:%s Port:%d \n",
inet_ntoa (host.sin_addr), ntohs (host.sin_port));
}
/*
*This function is called when the client would like to upload a file to the server.
*/
void
tsend (char *pFilename, struct sockaddr_in server, char *pMode, int sock)
{
int len, server_len, opcode, ssize = 0, n, i, j, bcount = 0, tid;
unsigned short int count = 0, rcount = 0, acked = 0;
unsigned char filebuf[MAXDATASIZE + 1];
unsigned char packetbuf[MAXACKFREQ][MAXDATASIZE + 12],
recvbuf[MAXDATASIZE + 12];
char filename[128], mode[12], *bufindex; //fullpath[196],
struct sockaddr_in ack;
FILE *fp; /* pointer to the file we will be sending */
strcpy (filename, pFilename); //copy the pointer to the filename into a real array
strcpy (mode, pMode); //same as above
if (debug)
printf ("Client: branched to file send function\n");
/*At this point I have to wait to recieve an ACK from the server before I start sending the file*/
/*open the file to read */
fp = fopen (filename, "r");
if (fp == NULL)
{ //if the pointer is null then the file can't be opened - Bad perms OR no such file
if (debug)
printf ("Client: sending bad file: file not found (%s)\n", filename);
return;
}
else
{
if (debug)
printf ("Client: Sending file... (source: %s)\n", filename);
}
//get ACK for WRQ
/* The following 'for' loop is used to recieve/timeout ACKs */
for (j = 0; j < RETRIES - 2; j++)
{
server_len = sizeof (ack);
errno = EAGAIN;
n = -1;
for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++)
{
n = recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT,
(struct sockaddr *) &ack, (socklen_t *) & server_len);
usleep (1000);
}
/* if(debug)
ip_port (ack); print the vlaue recived from the server */
tid = ntohs (ack.sin_port); //get the tid of the server.
server.sin_port = htons (tid); //set the tid for rest of the transfer
if (n < 0 && errno != EAGAIN)
{
if (debug)
printf
("Client: could not receive from the server (errno: %d n: %d)\n",
errno, n);
//resend packet
}
else if (n < 0 && errno == EAGAIN)
{
if (debug)
printf ("Client: Timeout waiting for ack (errno: %d n: %d)\n",
errno, n);
//resend packet
}
else
{ /*changed client to server here */
if (server.sin_addr.s_addr != ack.sin_addr.s_addr) /* checks to ensure send to ip is same from ACK IP */
{
if (debug)
printf
("Client: Error recieving ACK (ACK from invalid address)\n");
j--; /* in this case someone else connected to our port. Ignore this fact and retry getting the ack */
continue;
}
if (tid != ntohs (server.sin_port)) /* checks to ensure get from the correct TID */
{
if (debug)
printf
("Client: Error recieving file (data from invalid tid)\n");
len = err_packet (5, err_msg[5], buf);
if (sendto (sock, buf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
{
printf
("Client: Mismatch in number of sent bytes while trying to send mode error packet\n");
}
/* if (debug)
ip_port(server); */
j--;
continue; /* we aren't going to let another connection spoil our first connection */
}
/* this formatting code is just like the code in the main function */
bufindex = (char *) recvbuf; //start our pointer going
if (bufindex++[0] != 0x00)
printf ("Client: bad first nullbyte!\n");
opcode = *bufindex++;
rcount = *bufindex++ << 8;
rcount &= 0xff00;
rcount += (*bufindex++ & 0x00ff);
if (opcode != 4 || rcount != count) /* ack packet should have code 4 (ack) and should be acking the packet we just sent */
{
if (debug)
printf
("Client: Remote host failed to ACK proper data packet # %d (got OP: %d Block: %d)\n",
count, opcode, rcount);
/* sending error message */
if (opcode > 5)
{
len = err_packet (4, err_msg[4], buf);
if (sendto (sock, buf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
{
printf
("Client: Mismatch in number of sent bytes while trying to send mode error packet\n");
}
}
/* from here we will loop back and resend */
/* if (debug)
ip_port(server); */
}
else
{
if (debug)
printf ("Client: Remote host successfully ACK'd (#%d)\n",
rcount);
break;
}
} //end of else
if (debug)
printf ("Client: Ack(s) lost. Resending complete.\n");
}
/* The ack sending 'for' loop ends here */
memset (filebuf, 0, sizeof (filebuf)); //clear the filebuf
while (1) /* our break statement will escape us when we are done */
{
acked = 0;
ssize = fread (filebuf, 1, datasize, fp);
if (debug)
{
printf
("The first data block has been read from the file and will be sent to the server\n");
printf ("The size read from the file is: %d\n", ssize);
}
count++; /* count number of datasize byte portions we read from the file */
if (count == 1) /* we always look for an ack on the FIRST packet */
bcount = 0;
else if (count == 2) /* The second packet will always start our counter at zreo. This special case needs to exist to avoid a DBZ when count = 2 - 2 = 0 */
bcount = 0;
else
bcount = (count - 2) % ackfreq;
sprintf ((char *) packetbuf[bcount], "%c%c%c%c", 0x00, 0x03, 0x00, 0x00); /* build data packet but write out the count as zero */
memcpy ((char *) packetbuf[bcount] + 4, filebuf, ssize);
len = 4 + ssize;
packetbuf[bcount][2] = (count & 0xFF00) >> 8; //fill in the count (top number first)
packetbuf[bcount][3] = (count & 0x00FF); //fill in the lower part of the count
if (debug)
printf ("Client: Sending packet # %04d (length: %d file chunk: %d)\n",
count, len, ssize);
/* send the data packet */
if (sendto
(sock, packetbuf[bcount], len, 0, (struct sockaddr *) &server,
sizeof (server)) != len)
{
if (debug)
printf ("Client: Mismatch in number of sent bytes\n");
return;
}
if (debug)
{
ip_port (server);
printf ("==count: %d bcount: %d ssize: %d datasize: %d\n", count,
bcount, ssize, datasize);
}
//if ((count - 1) == 0 || ((count - 1) % ackfreq) == 0 || ssize != datasize)
if (((count) % ackfreq) == 0 || ssize != datasize)
{
if (debug)
printf ("-- I will get an ACK\n");
/* The following 'for' loop is used to recieve/timeout ACKs */
for (j = 0; j < RETRIES; j++)
{
server_len = sizeof (ack);
errno = EAGAIN;
n = -1;
for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++)
{
n =
recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT,
(struct sockaddr *) &ack,
(socklen_t *) & server_len);
/* if (debug)
ip_port(ack); */
usleep (1000);
}
if (n < 0 && errno != EAGAIN)
{
if (debug)
printf
("Client: could not receive from the server (errno: %d n: %d)\n",
errno, n);
//resend packet
}
else if (n < 0 && errno == EAGAIN)
{
if (debug)
printf
("Client: Timeout waiting for ack (errno: %d n: %d)\n",
errno, n);
//resend packet
}
else
{ /* checks to ensure send to ip is same from ACK IP */
if (server.sin_addr.s_addr != ack.sin_addr.s_addr)
{
if (debug)
printf
("Client: Error recieving ACK (ACK from invalid address)\n");
/* in this case someone else connected to our port. Ignore this fact and retry getting the ack */
j--;
continue;
}
if (tid != ntohs (server.sin_port)) /* checks to ensure get from the correct TID */
{
if (debug)
printf
("Client: Error recieving file (data from invalid tid)\n");
len = err_packet (5, err_msg[5], buf);
/* send the data packet */
if (sendto
(sock, buf, len, 0, (struct sockaddr *) &server,
sizeof (server)) != len)
{
printf
("Client: Mismatch in number of sent bytes while trying to send mode error packet\n");
}
/*if (debug)
ip_port(server); */
j--;
continue; /* we aren't going to let another connection spoil our first connection */
}
/* this formatting code is just like the code in the main function */
bufindex = (char *) recvbuf; //start our pointer going
if (bufindex++[0] != 0x00)
printf ("Client: bad first nullbyte!\n");
opcode = *bufindex++;
rcount = *bufindex++ << 8;
rcount &= 0xff00;
rcount += (*bufindex++ & 0x00ff);
if (opcode != 4 || rcount != count) /* ack packet should have code 4 (ack) and should be acking the packet we just sent */
{
if (debug)
printf
("Client: Remote host failed to ACK proper data packet # %d (got OP: %d Block: %d)\n",
count, opcode, rcount);
/* sending error message */
if (opcode > 5)
{
len = err_packet (4, err_msg[4], buf);
if (sendto (sock, buf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
{
printf
("Client: Mismatch in number of sent bytes while trying to send mode error packet\n");
}
/*if (debug)
ip_port(server); */
}
/* from here we will loop back and resend */
}
else
{
if (debug)
printf
("Client: Remote host successfully ACK'd (#%d)\n",
rcount);
break;
}
}
for (i = 0; i <= bcount; i++)
{
if (sendto (sock, packetbuf[i], len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* resend the data packet */
{
if (debug)
printf ("Client: Mismatch in number of sent bytes\n");
return;
}
if (debug)
{
printf ("Client: Ack(s) lost. Resending: %d\n",
count - bcount + i);
ip_port (server);
}
}
if (debug)
printf ("Client: Ack(s) lost. Resending complete.\n");
}
/* The ack sending 'for' loop ends here */
}
else if (debug)
{
printf
("Client: Not attempting to recieve ack. Not required. count: %d\n",
count);
n = recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT, (struct sockaddr *) &ack, (socklen_t *) & server_len); /* just do a quick check incase the remote host is trying with ackfreq = 1 */
/*if (debug)
ip_port(ack); */
}
if (j == RETRIES)
{
if (debug)
printf ("Client: Ack Timeout. Aborting transfer\n");
fclose (fp);
return;
}
if (ssize != datasize)
break;
memset (filebuf, 0, sizeof (filebuf)); /* fill the filebuf with zeros so that when the fread fills it, it is a null terminated string */
}
fclose (fp);
if (debug)
printf ("Client: File sent successfully\n");
return;
} //end of tsend function
/*
*This function is called when the client would like to download a file from the server.
*/
void
tget (char *pFilename, struct sockaddr_in server, char *pMode, int sock)
{
/* local variables */
int len, server_len, opcode, i, j, n, tid = 0, flag = 1;
unsigned short int count = 0, rcount = 0;
unsigned char filebuf[MAXDATASIZE + 1];
unsigned char packetbuf[MAXDATASIZE + 12];
extern int errno;
char filename[128], mode[12], *bufindex, ackbuf[512];
struct sockaddr_in data;
FILE *fp; /* pointer to the file we will be getting */
strcpy (filename, pFilename); //copy the pointer to the filename into a real array
strcpy (mode, pMode); //same as above
if (debug)
printf ("branched to file receive function\n");
fp = fopen (filename, "w"); /* open the file for writing */
if (fp == NULL)
{ //if the pointer is null then the file can't be opened - Bad perms
if (debug)
printf ("Client requested bad file: cannot open for writing (%s)\n",
filename);
return;
}
else /* File is open and ready to be written to */
{
if (debug)
printf ("Getting file... (destination: %s) \n", filename);
}
/* zero the buffer before we begin */
memset (filebuf, 0, sizeof (filebuf));
n = datasize + 4;
do
{
/* zero buffers so if there are any errors only NULLs will be exposed */
memset (packetbuf, 0, sizeof (packetbuf));
memset (ackbuf, 0, sizeof (ackbuf));
if (n != (datasize + 4)) /* remember if our datasize is less than a full packet this was the last packet to be received */
{
if (debug)
printf
("Last chunk detected (file chunk size: %d). exiting while loop\n",
n - 4);
len = sprintf (ackbuf, "%c%c%c%c", 0x00, 0x04, 0x00, 0x00);
ackbuf[2] = (count & 0xFF00) >> 8; //fill in the count (top number first)
ackbuf[3] = (count & 0x00FF); //fill in the lower part of the count
if (debug)
printf ("Sending ack # %04d (length: %d)\n", count, len);
if (sendto
(sock, ackbuf, len, 0, (struct sockaddr *) &server,
sizeof (server)) != len)
{
if (debug)
printf ("Mismatch in number of sent bytes\n");
return;
}
if (debug)
printf ("The Client has sent an ACK for packet\n");
goto done; /* gotos are not optimal, but a good solution when exiting a multi-layer loop */
}
count++;
for (j = 0; j < RETRIES; j++) /* this allows us to loop until we either break out by getting the correct ack OR time out because we've looped more than RETRIES times */
{
server_len = sizeof (data);
errno = EAGAIN; /* this allows us to enter the loop */
n = -1;
for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++) /* this for loop will just keep checking the non-blocking socket until timeout */
{
n =
recvfrom (sock, packetbuf, sizeof (packetbuf) - 1,
MSG_DONTWAIT, (struct sockaddr *) &data,
(socklen_t *) & server_len);
usleep (1000);
}
/*if(debug)
ip_port (data); print the vlaue recived from the server */
if (!tid)
{
tid = ntohs (data.sin_port); //get the tid of the server.
server.sin_port = htons (tid); //set the tid for rest of the transfer
}
if (n < 0 && errno != EAGAIN) /* this will be true when there is an error that isn't the WOULD BLOCK error */
{
if (debug)
printf
("The server could not receive from the client (errno: %d n: %d)\n",
errno, n);
//resend packet
}
else if (n < 0 && errno == EAGAIN) /* this is true when the error IS would block. This means we timed out */
{
if (debug)
printf ("Timeout waiting for data (errno: %d == %d n: %d)\n",
errno, EAGAIN, n);
//resend packet
}
else
{
if (server.sin_addr.s_addr != data.sin_addr.s_addr) /* checks to ensure get from ip is same from ACK IP */
{
if (debug)
printf
("Error recieving file (data from invalid address)\n");
j--;
continue; /* we aren't going to let another connection spoil our first connection */
}
if (tid != ntohs (server.sin_port)) /* checks to ensure get from the correct TID */
{
if (debug)
printf ("Error recieving file (data from invalid tid)\n");
len = sprintf ((char *) packetbuf,
"%c%c%c%cBad/Unknown TID%c",
0x00, 0x05, 0x00, 0x05, 0x00);
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
{
printf
("Mismatch in number of sent bytes while trying to send mode error packet\n");
}
j--;
continue; /* we aren't going to let another connection spoil our first connection */
}
/* this formatting code is just like the code in the main function */
bufindex = (char *) packetbuf; //start our pointer going
if (bufindex++[0] != 0x00)
printf ("bad first nullbyte!\n");
opcode = *bufindex++;
rcount = *bufindex++ << 8;
rcount &= 0xff00;
rcount += (*bufindex++ & 0x00ff);
memcpy ((char *) filebuf, bufindex, n - 4); /* copy the rest of the packet (data portion) into our data array */
if (debug)
printf
("Remote host sent data packet #%d (Opcode: %d packetsize: %d filechunksize: %d)\n",
rcount, opcode, n, n - 4);
if (flag)
{
if (n > 516)
datasize = n - 4;
else if (n < 516)
datasize = 512;
flag = 0;
}
if (opcode != 3) /* ack packet should have code 3 (data) and should be ack+1 the packet we just sent */
{
if (debug)
printf
("Badly ordered/invalid data packet (Got OP: %d Block: %d) (Wanted Op: 3 Block: %d)\n",
opcode, rcount, count);
/* sending error message */
if (opcode > 5)
{
len = sprintf ((char *) packetbuf,
"%c%c%c%cIllegal operation%c",
0x00, 0x05, 0x00, 0x04, 0x00);
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
{
printf
("Mismatch in number of sent bytes while trying to send mode error packet\n");
}
}
}
else
{
len = sprintf (ackbuf, "%c%c%c%c", 0x00, 0x04, 0x00, 0x00);
ackbuf[2] = (count & 0xFF00) >> 8; //fill in the count (top number first)
ackbuf[3] = (count & 0x00FF); //fill in the lower part of the count
if (debug)
printf ("Sending ack # %04d (length: %d)\n", count, len);
if (((count - 1) % ackfreq) == 0)
{
if (sendto
(sock, ackbuf, len, 0, (struct sockaddr *) &server,
sizeof (server)) != len)
{
if (debug)
printf ("Mismatch in number of sent bytes\n");
return;
}
if (debug)
printf ("The client has sent an ACK for packet %d\n",
count);
} //check for ackfreq
else if (count == 1)
{
if (sendto
(sock, ackbuf, len, 0, (struct sockaddr *) &server,
sizeof (server)) != len)
{
if (debug)
printf ("Mismatch in number of sent bytes\n");
return;
}
if (debug)
printf ("The Client has sent an ACK for packet 1\n");
}
break;
} //end of else
}
}
if (j == RETRIES)
{
if (debug)
printf ("Data recieve Timeout. Aborting transfer\n");
fclose (fp);
return;
}
}
while (fwrite (filebuf, 1, n - 4, fp) == n - 4); /* if it doesn't write the file the length of the packet received less 4 then it didn't work */
fclose (fp);
sync ();
if (debug)
printf
("fclose and sync unsuccessful. File failed to recieve properly\n");
return;
done:
fclose (fp);
sync ();
if (debug)
printf ("fclose and sync successful. File received successfully\n");
return;
}