📄 drv_tftp.c
字号:
#include "vxWorks.h" /* always first */
#include "config.h" /* board support configuration header */
#include "typedef.h"
#include "Drv_Tftp.h"
#include "../board/Minip/Drv_Minip.h"
#include "../bsp.h"
#define DRV_TFTP_DEBUG 0
extern int taskDelay (int ticks);
extern void sysMsDelay(_U32 delay);
/**************************************************************************
* Function: LOAD_TftpMakeReqPkt
* Description: 组装TFTP包
* Input: usOpcode: 操作码
szFileName: TFTP服务器上的文件名。
lMode: TFTP传输方式
pstPacket: 组装完成后的TFTP包
* Output: None
* Return: return 0 if succeed, return others if fail.
* Others:
**************************************************************************/
long LOAD_TftpMakeReqPkt(_U16 usOpcode, _U8 *szFileName, long lMode,
LOAD_TFTP_PACKET_S *pstPacket)
{
_U8 *pCp;
if (pstPacket == NULL )
{
return (long)FAILURE;
}
if( usOpcode != LOAD_TFTP_RRQ && usOpcode != LOAD_TFTP_WRQ )
{
return (long)FAILURE;
}
if ( (lMode != LOAD_TFTP_TRANSFER_MODE_ASCII)
&&(lMode != LOAD_TFTP_TRANSFER_MODE_BINARY) )
{
return (long)FAILURE;
}
pstPacket->usOpcode = htons((_U16)usOpcode);
pCp = (_U8*)(pstPacket->uMsg.szName_Mode);
strcpy((char *)pCp, (char *)szFileName);
pCp += strlen((char *)szFileName);
*pCp++ = '\0';
if (lMode == LOAD_TFTP_TRANSFER_MODE_ASCII)
{
strcpy((char *)pCp,"netascii");
}
else
{
strcpy((char *)pCp,"octet");
}
pCp += strlen((char *)pCp);
*pCp++ = '\0';
return ((long)pCp - (long)pstPacket);
}
/**************************************************************************
* Function: LOAD_TftpGet
* Description: 从TFTP服务器获取文件
* Input: szRmtHost: TFTP服务器的IP地址字符串。
szRmtFile: TFTP服务器上的文件名。
szLocalFile: 本地硬盘或Flash上的文件名。
lTransMode: TFTP传输方式
ulUserID: 执行此远程下载命令的用户的标识。
* Output: None
* Return: return 0 if succeed, return others if fail.
* Others:
**************************************************************************/
_U32 LOAD_TftpGet(_U8 *szRmtHost, _U8 *szRmtFile, _U8 *szRamAddr, long lTransMode)
{
long lSockNum;
struct sockaddr_in stClientAddr, stServerAddr;
long lEn;
LOAD_TFTP_PACKET_S stRcvPkt, stSndPkt;
long lPktSize = 0;
long lFromLen;
struct timeval stTimeout;
long lTotTime = 0;
long lRc;
_U16 usCurBlkNum = 1;
int i;
struct timeval pasttv;
if(( szRmtHost == NULL )||( szRmtFile == NULL )||( szRamAddr == NULL ))
{
Drv_Print("\r\nInput param error!");
return FAILURE;
}
stTimeout.tv_sec = LOAD_TFTP_TIMEOUT_TIME;
stTimeout.tv_usec = 0;
/*creat a socket*/
if((lSockNum = minip_socket(MINIP_AF_INET, MINIP_SOCK_DGRAM, 0)) <= 0)
{
#if DRV_TFTP_DEBUG
Drv_Print( "\r\nSocket initialize fail!\r\n");
#endif
return FAILURE;
}
#if DRV_TFTP_DEBUG
Drv_Print( "\r\nSocket initialize finish!\r\n");
#endif
/* specify a local address for this socket */
memset((void *)&stClientAddr, 0 , sizeof(stClientAddr));
stClientAddr.sin_family = MINIP_AF_INET;
stClientAddr.sin_port = htons(10240); /* 最小协议栈不支持端口号动态分配 */
stClientAddr.sin_addr.s_addr = htonl(MINIP_INADDR_ANY);
lEn = minip_bind(lSockNum, (struct sockaddr *)(char *)&stClientAddr, sizeof(stClientAddr));
if( lEn != 0 )
{
#if DRV_TFTP_DEBUG
Drv_Print("\r\nSocket bind failure!\r\n");
#endif
goto exit1;
}
/* set server internet address*/
memset((void *)&stServerAddr, 0 , sizeof(stServerAddr));
stServerAddr.sin_family = MINIP_AF_INET;
stServerAddr.sin_port = htons(LOAD_TFTP_SERVER_PORT);
stServerAddr.sin_addr.s_addr = minip_strtoip(szRmtHost);
if(stServerAddr.sin_addr.s_addr == 0XFFFFFFFF)
{
#if DRV_TFTP_DEBUG
Drv_Print("\r\nCannot resolve hostname!\r\n");
#endif
goto exit1;
}
/* form request packet - RRQ */
lPktSize = LOAD_TftpMakeReqPkt(LOAD_TFTP_RRQ,szRmtFile,lTransMode,&stSndPkt);
if (lPktSize <= 0)
{
#if DRV_TFTP_DEBUG
Drv_Print("\r\nLoad tftp create msg error = %ld!",lPktSize);
#endif
}
lFromLen = sizeof(stClientAddr);
#ifdef TCPIP_INCLUDE_MINIP
/* 加载前先等待1秒 */
(void)taskDelay(1);
#endif
for(;;)
{
lEn = minip_sendto(lSockNum,(char *)&stSndPkt,(int)lPktSize,0,
(struct sockaddr *)(char*)&stServerAddr,sizeof(stServerAddr));
if(lEn != lPktSize)
{
#if DRV_TFTP_DEBUG
Drv_Print("\r\nhave sent %ld, need to send %ld",lEn,lPktSize);
Drv_Print("\r\nCannot send require message to TFTP server, download fails!\r\n");
#endif
(void)taskDelay(1);
goto exit1;
}
/* wait for DATA packet */
pasttv.tv_sec = 0;
pasttv.tv_usec = 0;
for(i = 0; i < 6000; i ++)
{
sysMsDelay(1);
(void)taskDelay(0);
lEn = minip_recvfrom(lSockNum,(char *)&stRcvPkt,LOAD_TFTP_PKTSIZE,0,
(struct sockaddr *)(char *)&stClientAddr,(int*)&lFromLen);
if(lEn > 0)
{
break;
}
pasttv.tv_usec += 1000;
pasttv.tv_sec += pasttv.tv_usec/(1000000);
pasttv.tv_usec %= 1000000;
if(pasttv.tv_sec >= stTimeout.tv_sec){
break;
}
}
if(lEn < 0)
{
#if DRV_TFTP_DEBUG
Drv_Print("\r\nDownload fails\r\n");
#endif
goto exit1;
}
else if (lEn == 0)
{
lTotTime++;
if (lTotTime < LOAD_TFTP_ATTEMPTS)
{
continue;
}
else
{
#if DRV_TFTP_DEBUG
Drv_Print("\r\nCannot receive message from TFTP server because of time out, download fails!\r\n");
#endif
goto exit1;
}
}
stServerAddr.sin_port = stClientAddr.sin_port;
lTotTime = 0;
/* packet size of received */
lRc = lEn;
/* convert network opcode to host format after receive. */
stRcvPkt.usOpcode = ntohs(stRcvPkt.usOpcode);
/* if this packet is OPT packet */
if(stRcvPkt.usOpcode == LOAD_TFTP_OPT)
{
stSndPkt.usOpcode = htons(LOAD_TFTP_ACK);
stSndPkt.uMsg.usBlkNum = htons(0);
lPktSize = LOAD_TFTP_HDRSIZE;
continue;
}
/* if this packet is ERROR packet */
if(stRcvPkt.usOpcode == LOAD_TFTP_ERROR)
{
#if DRV_TFTP_DEBUG
Drv_Print("\r\nBad packet received from TFTP server, download fails!\r\n");
#endif
goto exit1;
}
/* if this packet is unkonwn or incorrect packet */
if(stRcvPkt.usOpcode != LOAD_TFTP_DATA)
{
#if DRV_TFTP_DEBUG
Drv_Print("\r\nUnkonwn or incorrect packet received from TFTP server, download fails!\r\n");
#endif
goto exit1;
}
/* if this packet is DATA packet */
stRcvPkt.uMsg.stData.blknum = ntohs(stRcvPkt.uMsg.stData.blknum);
if(stRcvPkt.uMsg.stData.blknum == usCurBlkNum)
{
/* this packet is the correct DATA packet */
good_pkt:
/* form the ACK packet for the DATA packet received */
stSndPkt.usOpcode = htons(LOAD_TFTP_ACK);
stSndPkt.uMsg.usBlkNum = htons(usCurBlkNum);
lPktSize = LOAD_TFTP_HDRSIZE;
lRc -= LOAD_TFTP_HDRSIZE;
/* display bytes num that have received */
memcpy((char *)szRamAddr, stRcvPkt.uMsg.stData.buf, (_U32)lRc);
szRamAddr += lRc;
/* print a pot every 100 packets */
if( (usCurBlkNum - 1)%100 == 0 )
{
Drv_Print(".");
}
/* this packet is the final DATA packet */
if(lRc != LOAD_TFTP_BLKSIZE)
{
(void)minip_sendto(lSockNum,(char *)&stSndPkt,(int)lPktSize,0,
(struct sockaddr *)(char *)&stServerAddr,sizeof(stServerAddr));
#if DRV_TFTP_DEBUG
Drv_Print( "done!\r\n");
#endif
/* receiving complete */
if (minip_close(lSockNum) != SUCCESS)
{
// err
}
return SUCCESS;
}
usCurBlkNum++;
}
else
{
(void)taskDelay(1);
/* get rid of any accumulated datagrams */
stTimeout.tv_sec = 5;
pasttv.tv_sec = 0;
pasttv.tv_usec = 0;
for(i = 0; i < 6000; i ++)
{
sysMsDelay(1);
(void)taskDelay(0);
lEn = minip_recvfrom(lSockNum,(char *)&stRcvPkt,LOAD_TFTP_PKTSIZE,0,
(struct sockaddr *)(char *)&stClientAddr,(int*)&lFromLen);
if(lEn > 0)
{
break;
}
pasttv.tv_usec += 1*1000;
pasttv.tv_sec += pasttv.tv_usec/(1000000);
pasttv.tv_usec %= 1000000;
if(pasttv.tv_sec >= stTimeout.tv_sec){
break;
}
}
if(lRc <=0)
{
#if DRV_TFTP_DEBUG
Drv_Print( "\r\nDownload fails!\r\n");
#endif
goto exit1;
}
stServerAddr.sin_port = stClientAddr.sin_port;
stRcvPkt.usOpcode = ntohs(stRcvPkt.usOpcode);
if(stRcvPkt.usOpcode == LOAD_TFTP_DATA)
{
stRcvPkt.uMsg.stData.blknum = ntohs(stRcvPkt.uMsg.stData.blknum);
}
else
{
#if DRV_TFTP_DEBUG
Drv_Print( "\r\nUnkonwn or incorrect packet received from TFTP server, download fails!\r\n");
#endif
goto exit1;
}
stTimeout.tv_sec = LOAD_TFTP_TIMEOUT_TIME;
/*if we now have the previous data block, the host probably
never got our ACK, so we should re-send it.*/
if (stRcvPkt.uMsg.stData.blknum < usCurBlkNum)
{
continue;
}
else if(stRcvPkt.uMsg.stData.blknum == usCurBlkNum)
{
goto good_pkt;
}
}
}
exit1:
if (minip_close(lSockNum) != SUCCESS)
{
}
return FAILURE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -