remoteaddr);if((fil" />

#include #include #include #include #include #ifndef MAKEWORD #define MAKEWORD(l,h) ((WORD)(((BYTE)(l))|(((WORD)(BYTE)(h))<<8))) #endif #define WSA_MAJOR_VERSION 1 #define WSA_MINOR_VERSION 1 #define WSA_VERSION MAKEWORD(WSA_MAJOR_VERSION, WSA_MINOR_VERSION) /* read/write request packet format 2 bytes string 1 byte string 1 byte ------------------------------------------------ | Opcode | Filename | 0 | Mode | 0 | ------------------------------------------------ */ #define TFTP_RRQ 1 /*Read request (RRQ)*/ #define TFTP_WRQ 2 /*Write request (WRQ) */ /* DATA packet format 2 bytes 2 bytes n bytes ---------------------------------- | Opcode | Block # | Data | ---------------------------------- */ #define TFTP_DATA 3 /*Data (DATA)*/ /* ACK packet format 2 bytes 2 bytes --------------------- | Opcode | Block # | --------------------- */ #define TFTP_ACK 4 /*Acknowledgment (ACK)*/ /*ERROR packet format 2 bytes 2 bytes string 1 byte ----------------------------------------- | Opcode | ErrorCode | ErrMsg | 0 | ----------------------------------------- */ #define TFTP_ERROR 5 /*Error (ERROR)*/ #define TFTP_NETASCII 0 #define TFTP_OCTET 1 #define TFTP_WSTAT_FIRSTACKE 0 #define TFTP_WSTAT_NEXTACK 1 #define TFTP_WSTAT_LASTACK 2 #define MAX_RETRY 3 #define TFTP_NOTEND_DATALEN 512+2+2 #ifdef _VC #pragma comment(lib,"Wsock32.lib") #endif /*typedef void (* CMDFUNC)(char [][256],int pcout); typedef struct _cmdnum{ char *cmd; int num; int paramcount; CMDFUNC callback; }CMDNUM,*PCMDNUM;*/ typedef struct DATA{ int socknum; char *filename; unsigned short remoteport; char *remoteaddr; }; DATA passdata[6]; ofstream logfile("log.txt",ios::app); int makeack(unsigned short num,char *buffer,int size); void showsysinfo(); void getfile(DATA *needdata); void putfile(DATA *needdata); int makeerror(int errcode,char errstring[256],char *buffer,int bufsize); SOCKET sock[6]={INVALID_SOCKET,INVALID_SOCKET,INVALID_SOCKET,INVALID_SOCKET,INVALID_SOCKET,INVALID_SOCKET}; int filemode =TFTP_OCTET; #define MYPORT 69 void main(int argc,char *argv[]) { WSADATA stWSAData; int ret=0; sockaddr_in addr; char recvbuf[1024]={0}; char sendbuf[1024]={0}; sockaddr_in from; sockaddr_in newaddr; int fromlen=0; char filename[256]; int i,len; DWORD ThreadID[6]; showsysinfo(); if(WSAStartup(WSA_VERSION,&stWSAData)!=0){ printf("can't start socket \\r\\n"); exit(0); } if ((sock[0]=socket(AF_INET,SOCK_DGRAM,0))<0){ perror("socket"); exit(1); } addr.sin_family=AF_INET; addr.sin_port=htons(MYPORT); addr.sin_addr.s_addr=INADDR_ANY; memset(&(addr.sin_zero),0,8); if (bind(sock[0],(struct sockaddr *)&addr,sizeof(struct sockaddr))<0){ perror("bind"); exit(1); } for (;;){ fromlen=sizeof(from); recvfrom(sock[0],recvbuf,sizeof(recvbuf),0,(sockaddr *)&from,&fromlen); if (recvbuf[0]==0 && recvbuf[1]<3 && recvbuf[1]>0){ for (i=0;;i++){ filename[i]=recvbuf[i+2]; if (filename[i]=='\\0') break; } for (i=1;i<=5;i++) { if (sock[i]==INVALID_SOCKET) { passdata[i].socknum=i; if ((sock[i]=socket(AF_INET,SOCK_DGRAM,0))<0){ perror("socket"); exit(1); } newaddr.sin_family=AF_INET; newaddr.sin_port=0; newaddr.sin_addr.s_addr=INADDR_ANY; memset(&(newaddr.sin_zero),0,8); if (bind(sock[i],(struct sockaddr *)&newaddr,sizeof(struct sockaddr))<0){ perror("bind"); exit(1); } break; } } passdata[i].filename=filename; passdata[i].remoteport=ntohs(from.sin_port); passdata[i].remoteaddr=inet_ntoa(from.sin_addr); if (recvbuf[1]==TFTP_WRQ){ CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getfile,&passdata[i],0,&ThreadID[i]); } if (recvbuf[1]==TFTP_RRQ){ CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)putfile,&passdata[i],0,&ThreadID[i]); } } else { len=makeerror(4,"llegal TFTP operation\\0",sendbuf,sizeof(sendbuf)); sendto(sock[0],sendbuf,len,0,(sockaddr *)&from,sizeof(from)); } } } void showsysinfo() { printf("TFTP server version 1.0\\r\\n"); } int makeack(unsigned short num,char *buffer,int size) { int pos=0; buffer[pos]=0; pos++; buffer[pos]=TFTP_ACK; pos++; buffer[pos]=(char)(num>>8); pos++; buffer[pos]=(char)num; pos++; return pos; } int makedata(int num,char *data,int datasize,char *buffer,int bufsize) { int pos=0; buffer[pos]=0; pos++; buffer[pos]=TFTP_DATA; pos++; buffer[pos]=(char)(num>>8); pos++; buffer[pos]=(char)num; pos++; memcpy(&buffer[pos],data,datasize); pos=pos+datasize; return pos; } int makeerror(int errcode,char *errstring,char *buffer,int bufsize) { int pos=0; int i; buffer[pos]=0; pos++; buffer[pos]=TFTP_ERROR; pos++; buffer[pos]=(char)(errcode>>8); pos++; buffer[pos]=(char)errcode; pos++; for(i=0;;i++){ buffer[pos]=errstring[i]; pos++; if (errstring[i]=='\\0') break; } return pos; } void getfile(DATA *needdata) { char sendbuf[1024]={0}; char recvbuf[1024]={0}; sockaddr_in addr; sockaddr_in from; int fromlen=0; int ret=0; int len=0; // fd_set fdr; int retry=0; // struct timeval timeout={5,0}; int stat=0; int lastdata=0; long flen=0; FILE *file; addr.sin_family=AF_INET; from.sin_family=AF_INET; addr.sin_port=htons(needdata->remoteport); addr.sin_addr.s_addr=inet_addr(needdata->remoteaddr); // printf("received WRQ form %s\\n",needdata->remoteaddr); if((file=fopen(needdata->filename,"rb"))!=NULL){ fclose(file); printf("file %s already exist\\n",needdata->filename); len=makeerror(6,"file already exist\\0",sendbuf,sizeof(sendbuf)); sendto(sock[needdata->socknum],sendbuf,len,0,(sockaddr *)&addr,sizeof(addr)); closesocket(sock[needdata->socknum]); sock[needdata->socknum]=INVALID_SOCKET; return; } if ((file=fopen(needdata->filename,"w+b"))==NULL){ printf("can't create file \\r\\n"); closesocket(sock[needdata->socknum]); sock[needdata->socknum]=INVALID_SOCKET; return; } len=makeack(lastdata,sendbuf,sizeof(sendbuf)); ret=sendto(sock[needdata->socknum],sendbuf,len,0,(sockaddr *)&addr,sizeof(addr)); // printf("send ack 0# to %s\\n",needdata->remoteaddr); while(true){ /* FD_ZERO(&fdr); FD_SET(sock[needdata->socknum],&fdr); ret=select(sock[needdata->socknum],&fdr,NULL,NULL,NULL); if(SOCKET_ERROR==ret){ printf("socket error \\r\\n"); fclose(file); return; } else if (0==ret){ if (MAX_RETRY==retry){ printf("Time out\\r\\n"); fclose(file); return; } sendto(sock[needdata->socknum],sendbuf,len,0,(sockaddr *)&addr,sizeof(addr)); retry++; } else { if (FD_ISSET(sock[needdata->socknum],&fdr)){ retry=0;*/ fromlen=sizeof(sockaddr); ret=recvfrom(sock[needdata->socknum],recvbuf,sizeof(recvbuf),0,(sockaddr *)&from,&fromlen); if(0==stat){ addr.sin_port=from.sin_port; stat=1; } if(TFTP_DATA==recvbuf[1]){ lastdata=((recvbuf[2]+256)%256)*256+(recvbuf[3]+256)%256; // printf("received data block %d# from %s\\n",lastdata,needdata->remoteaddr); len=makeack(lastdata,sendbuf,sizeof(sendbuf)); sendto(sock[needdata->socknum],sendbuf,len,0,(sockaddr *)&addr,sizeof(addr)); // printf("send ack %d# to %s\\n",lastdata,needdata->remoteaddr); if(ret flen=flen+ret-4; fclose(file); printf("total %d byte received from %s\\n",flen,needdata->remoteaddr); logfile << "received " < sock[needdata->socknum]=INVALID_SOCKET; return; } else { fwrite(&recvbuf[4],1,512,file); flen=flen+512; // printf("%d byte received\\r",flen); } } // } // } } } void putfile(DATA *needdata) { char sendbuf[1024]={0}; char recvbuf[1024]={0}; char databuf[1024]={0}; sockaddr_in addr; sockaddr_in from; int fromlen=0; int ret=0; int len=0; fd_set fdr; int retry=0; struct timeval timeout={5,0}; int stat=TFTP_WSTAT_NEXTACK; int lastack=0; FILE *file; int flen=0; int blocknum=0; size_t rlen=0; addr.sin_family=AF_INET; from.sin_family=AF_INET; addr.sin_port=htons(needdata->remoteport); addr.sin_addr.s_addr=inet_addr(needdata->remoteaddr); // printf("received RRQ form %s\\n",needdata->remoteaddr); if((file=fopen(needdata->filename,"rb"))==NULL){ printf("file %s not found\\r\\n",needdata->filename); len=makeerror(1,"file not found\\0",sendbuf,sizeof(sendbuf)); sendto(sock[needdata->socknum],sendbuf,len,0,(sockaddr *)&addr,sizeof(addr)); closesocket(sock[needdata->socknum]); sock[needdata->socknum]=INVALID_SOCKET; return; } rlen=fread(databuf,1,512,file); if (rlen<512 && feof(file)){ stat=TFTP_WSTAT_LASTACK; } else if (ferror(file)){ printf("error:read file\\r\\n"); fclose(file); return; } flen=flen+rlen; blocknum++; len=makedata(blocknum,databuf,rlen,sendbuf,sizeof(sendbuf)); sendto(sock[needdata->socknum],sendbuf,len,0,(sockaddr *)&addr,sizeof(addr)); // printf("send data block %d# to %s\\n",blocknum,needdata->remoteaddr); for(;;){ FD_ZERO(&fdr); FD_SET(sock[needdata->socknum],&fdr); ret=select(sock[needdata->socknum],&fdr,NULL,NULL,&timeout); if(SOCKET_ERROR==ret){ printf("socket error\\r\\n"); fclose(file); return; } else if (0==ret){ if (MAX_RETRY==retry){ printf("time out\\r\\n"); fclose(file); closesocket(sock[needdata->socknum]); sock[needdata->socknum]=INVALID_SOCKET; return; } sendto(sock[needdata->socknum],sendbuf,len,0,(sockaddr *)&addr,sizeof(addr)); // printf("send data block %d# to %s\\n",blocknum,needdata->remoteaddr); retry++; } else { retry=0; fromlen=sizeof(sockaddr); ret=recvfrom(sock[needdata->socknum],recvbuf,sizeof(recvbuf),0,(sockaddr *)&from,&fromlen); if(TFTP_ACK==recvbuf[1]){ lastack=((recvbuf[2]+256)%256)*256+(recvbuf[3]+256)%256; // printf("received ack %d# from %s\\n",lastack,needdata->remoteaddr); switch(stat){ case TFTP_WSTAT_NEXTACK: if (lastack==blocknum){ // printf("%d byte send\\r",flen); rlen=fread(databuf,1,512,file); flen=flen+rlen; if(rlen<512 && feof(file)){ stat=TFTP_WSTAT_LASTACK; } else if (ferror(file)) { printf("error:read file"); fclose(file); return; } if (blocknum<65535) { blocknum++; } else blocknum=1; len=makedata(blocknum,databuf,rlen,sendbuf,sizeof(sendbuf)); sendto(sock[needdata->socknum],sendbuf,len,0,(sockaddr *)&addr,sizeof(addr)); // printf("send data block %d# to %s\\n",blocknum,needdata->remoteaddr); } else { fclose(file); printf("error ack number\\n"); closesocket(sock[needdata->socknum]); sock[needdata->socknum]=INVALID_SOCKET; return; } break; case TFTP_WSTAT_LASTACK: if (lastack==blocknum){ fclose(file); printf("totle %d byte send to %s\\n",flen,needdata->remoteaddr); logfile << "send " < sock[needdata->socknum]=INVALID_SOCKET; return; } else { fclose(file); printf("error ack number"); closesocket(sock[needdata->socknum]); sock[needdata->socknum]=INVALID_SOCKET; return; } break; } } } } }
