⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tftp.cpp

📁 s3c2410 wince bootload update tools
💻 CPP
字号:
// Tftp.cpp: implementation of the CTftp class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Tftp.h"
#include "resource.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CTftp::CTftp()
{
	Sock = INVALID_SOCKET;
	strcpy(DestHost,"127.0.0.1");
	FileMode=TFTP_Octet;
	ReviceSendBytes=0;
}

CTftp::~CTftp()
{

}
//////////////////////////////////////////////////////////////////////////
// 初始化windows winsock环境,如果不能正确初始化则返回错误
//////////////////////////////////////////////////////////////////////////
BOOL CTftp::InitSock(void)
{
	sockaddr_in addr;
	WSADATA stWSAData;

	if(WSAStartup(WSA_VERSION, &stWSAData)!=0)return false;
	Sock = socket(PF_INET,SOCK_DGRAM,0);
	if(Sock==INVALID_SOCKET)return false;
	addr.sin_family = PF_INET;
	addr.sin_port = INADDR_ANY;
	addr.sin_addr.s_addr  = INADDR_ANY;
	if(bind(Sock,(struct sockaddr *)&addr,sizeof(addr))!=0)return false;
	return true;
}
//////////////////////////////////////////////////////////////////////////
// 向主机获得文件 
//////////////////////////////////////////////////////////////////////////
UINT CTftp::GetFile(char *FileName)
{
	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;
	FILE *file;
	int flen = 0;

	if(!InitSock())
	{
		return TFTP_INIT_WINSOCK_ERROR;
	}
	if((file=fopen(FileName,"rb"))!=NULL)
	{
		char str[256];
		sprintf(str,"File %s already exits,overwrite?",FileName);
		if(MessageBox(NULL,str,"File Exites Error",MB_YESNO)==IDOK)
		{
			fclose(file);
		}
		else
		{
			fclose(file);
			return TFTP_FILE_EXITES_ERROR;
		}
	}
	if((file=fopen(FileName,"w+b"))==NULL)
	{
		return TFTP_FILE_EXITES_ERROR;
	}
	fseek(file,0,SEEK_END);
	ftell(file);
	if(sb)sb->SetRange(0,UINT(ftell(file)/10000));
	fseek(file,0,SEEK_SET);

	len = MakeReq(TFTP_RRQ,FileMode,FileName,sendbuf);
	addr.sin_family =PF_INET;
	from.sin_family =PF_INET;
	addr.sin_port = htons(TFTP_PORT_NUMBER);
	addr.sin_addr.s_addr   = inet_addr(DestHost);
	ret = sendto(Sock,sendbuf,len,0,(sockaddr *)&addr,sizeof(addr));
	while(true)
	{
		FD_ZERO(&fdr);
		FD_SET(Sock, &fdr);
		ret = select(Sock, &fdr, NULL,NULL, &timeout);
		if(SOCKET_ERROR==ret)
		{
			fclose(file);
			return TFTP_WINSOCK_ERROR;
		}
		else if(0==ret)
		{
			if(MAX_RETRY==retry)
			{
				fclose(file);
				return TFTP_TIMEOUT_ERROR;
			}
			sendto(Sock,sendbuf,len,0,(sockaddr *)&addr,sizeof(addr));
			retry++;
		}
		else
		{
			if (FD_ISSET(Sock,&fdr))
			{
				retry = 0;
				fromlen = sizeof(sockaddr);
				ret = recvfrom(Sock,recvbuf,sizeof(recvbuf),0,(sockaddr *)&from,&fromlen);
				if(TFTP_ERROR==recvbuf[1])
				{
					fclose(file);
					return TFTP_ACK_ERROR;
				}
				if(0==stat)
				{
					addr.sin_port = from.sin_port ;
					stat = 1;
				}
				if(TFTP_DATA==recvbuf[1])
				{
					lastdata = recvbuf[2]*256 + recvbuf[3];
					len = MakeAck(lastdata,sendbuf);
					sendto(Sock,sendbuf,len,0,(sockaddr *)&addr,sizeof(addr));
					if(ret<TFTP_NOTEND_DATALEN)
					{
						fwrite(&recvbuf[4],1,ret-4,file);
						flen = flen + ret -4;
						fclose(file);
						ReviceSendBytes=flen;
						if(sb)sb->SetPos(flen/10000);
						return TFTP_OK;
					}
					else
					{
						fwrite(&recvbuf[4],1,512,file);
						flen = flen + 512;
						ReviceSendBytes=flen;
						if(sb)sb->SetPos(flen/10000);
					}
				}
			}
		}
		
	}

}
//////////////////////////////////////////////////////////////////////////
// 由从机向主机传送文件
//////////////////////////////////////////////////////////////////////////
UINT CTftp::PutFile(char *localfile,char *remotefile)
{
	CHAR sendbuf[1024] = {0};
	CHAR recvbuf[1024] = {0};
	CHAR databuf[1024] = {0};
	sockaddr_in addr;
	sockaddr_in from;
	int fromlen = 0;
	long ret = 0;
	long len = 0 ;
	fd_set  fdr;
	int retry = 0;
	struct  timeval timeout = {8,0};
	long stat = TFTP_WSTAT_FIRSTACK;
	LONG lastack= 0;
	FILE *file;
	long flen = 0;
	long blocknum = 0;
	long rlen = 0;

	if(!InitSock())
	{
		return TFTP_INIT_WINSOCK_ERROR;
	}
	if((file=fopen(localfile,"rb"))==NULL)
	{
		return TFTP_FILE_NOEXITES_ERROR;
	}
	len = MakeReq(TFTP_WRQ,FileMode,remotefile,sendbuf);
	addr.sin_family =PF_INET;
	addr.sin_port = htons(TFTP_PORT_NUMBER);
	addr.sin_addr.s_addr   = inet_addr(DestHost);
	ret = sendto(Sock,sendbuf,len,0,(sockaddr *)&addr,sizeof(addr));
	if((file=fopen(localfile,"rb"))==NULL)
	{
		return TFTP_INPUT_FILE_ERROR;
	}
	fseek(file,0,SEEK_END);
	ftell(file);
	if(sb)sb->SetRange(0,UINT(ftell(file)/10000));
	fseek(file,0,SEEK_SET);
	while(true)
	{
		FD_ZERO(&fdr);
		FD_SET(Sock, &fdr);
		ret = select(Sock, &fdr, NULL,NULL, &timeout);
		if(SOCKET_ERROR==ret)
		{
			fclose(file);
			return TFTP_WINSOCK_ERROR;
		}
		else if(0==ret)
		{
			if(MAX_RETRY==retry)
			{
				fclose(file);
				return TFTP_TIMEOUT_ERROR;
			}
			sendto(Sock,sendbuf,len,0,(sockaddr *)&addr,sizeof(addr));
			retry++;
		}
		else
		{
			retry = 0;
			fromlen = sizeof(sockaddr);
			ret = recvfrom(Sock,recvbuf,sizeof(recvbuf),0,(sockaddr *)&from,&fromlen);
			if(TFTP_ERROR==recvbuf[1])	//TFP返回错误的应答信号
			{
				fclose(file);
				return TFTP_ACK_ERROR;
			}
			if(TFTP_ACK==recvbuf[1])	//返回正确的ACK信号
			{
				lastack = (UCHAR)recvbuf[2]*256 + (UCHAR)recvbuf[3];
				switch(stat)
				{
				case TFTP_WSTAT_FIRSTACK:
					if(0==lastack)
					{
						stat = TFTP_WSTAT_NEXTACK;
						addr.sin_port = from.sin_port ;
						fseek(file,0,SEEK_SET);
						rlen = fread(databuf,1,512,file);//每次发送512字节的数据
						flen = flen + rlen;
						if(rlen<512 && feof(file))//如果到了文件结尾则发送结束ACK信号
						{
							stat = TFTP_WSTAT_LASTACK;
						}
						else if(ferror(file))
						{
							fclose(file);
							return TFTP_FILE_READ_ERROR;
						}
						blocknum++;
						len = MakeData(blocknum,databuf,rlen,sendbuf);
						sendto(Sock,sendbuf,len,0,(sockaddr *)&addr,sizeof(addr));
						ReviceSendBytes=flen;
						if(sb)sb->SetPos(flen/10000);
					}
					else
					{
						fclose(file);
						return TFTP_ACK_ERROR;
					}
					break;
				case TFTP_WSTAT_NEXTACK:
					if(lastack==blocknum)
					{
						rlen = fread(databuf,1,512,file);
						flen = flen + rlen;
						if(rlen<512 && feof(file))
						{
							stat = TFTP_WSTAT_LASTACK;
						}
						else if(ferror(file))
						{
							fclose(file);
							return TFTP_FILE_READ_ERROR;
						}
						blocknum++;
						len = MakeData(blocknum,databuf,rlen,sendbuf);
						sendto(Sock,sendbuf,len,0,(sockaddr *)&addr,sizeof(addr));
						ReviceSendBytes=flen;
						if(sb)sb->SetPos(flen/10000);
					}
					else
					{
						fclose(file);
						return TFTP_ACK_ERROR;
					}
					break;
				case TFTP_WSTAT_LASTACK:
					if(lastack==blocknum)
					{
						return TFTP_OK;
					}
					else
					{
						fclose(file);
						return TFTP_ACK_ERROR;
					}
					break;
				}
			}
		}
  }
}
//////////////////////////////////////////////////////////////////////////
// 生成读写请求数据包
// 2 bytes    string   1 byte string 1 byte
// ------------------------------------------------
// | Opcode | Filename | 0 | Mode | 0 |
// ------------------------------------------------
//////////////////////////////////////////////////////////////////////////
int CTftp::MakeReq(char type,int mode,char *filename,char *buffer)
{
	int pos = 0;
	unsigned int i = 0;
	char s[32] = "";
	if(mode==TFTP_NETASCII)
		strcpy(s,"netascii");
	else
		strcpy(s,"octet");
	buffer[pos] = 0;
	pos++;
	buffer[pos] = type;//Read request: TFTP_RRQ=1   Write request: TFTP_WRQ=2   
	pos++;
	for(i=0;i<strlen(filename);i++) //填充文件名
	{
		buffer[pos] = filename[i];
		pos++;
	}
	buffer[pos] = 0;
	pos++;
	for(i=0;i<strlen(s);i++)	//填充传送模式代码(ASCII OCTET)
	{
		buffer[pos] = s[i];
		pos++;
	}
	buffer[pos] = 0;
	pos++;
	return pos;
}
//////////////////////////////////////////////////////////////////////////
// 生成ACK应答数据包
// 2 bytes   2 bytes   n bytes
// ----------------------------------
// | Opcode | Block # |
// ----------------------------------
//////////////////////////////////////////////////////////////////////////
int CTftp::MakeAck(unsigned short BlockNum,char *buffer)
{
	int pos = 0;
	buffer[pos] = 0;
	pos++;
	buffer[pos] = TFTP_ACK;
	pos++;
	buffer[pos] = (char)(BlockNum>>8);
	pos++;
	buffer[pos] = (char)BlockNum;
	pos++;
	return pos;
}
//////////////////////////////////////////////////////////////////////////
// 生成DATA数据包
// 2 bytes   2 bytes   n bytes
// ----------------------------------
// | Opcode | Block # | Data |
// ----------------------------------
//////////////////////////////////////////////////////////////////////////
int CTftp::MakeData(int num,char *data,int datasize,char *buffer)
{
	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;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -