📄 tftpc.c
字号:
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*/voidip_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.*/voidtsend (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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -