📄 rosftplib.c
字号:
/* ROS FTP server test result done by tongxj 2001-07-18 */
#include "RosFtpLib.h"
#include "lib/5906lib.h" /*yuqiang changed on 2003-2-17:统一各产品启动打印信息*/
extern int tcp_keepintvl;
extern int tcp_keepcnt;
extern int tcp_keepidle;
extern int tcp_maxidle;
int RosFtpClntDebug = 0;
int FtpClntSndWindow = 1460;
int FtpClntSndLowWait= 1460;
static unsigned int fileLength = 0;
static int getFileLength = 0;
LOCAL STATUS ftpClntSocketConfig( SOCKET sock);
LOCAL STATUS ftpClntNodeInit(FTP_CLIENT_NODE *pClnt);
LOCAL STATUS ftpClntClose(FTP_CLIENT_NODE *pClnt);
LOCAL STATUS ftpClntEventHandler( FTP_CLIENT_NODE* ,struct fd_set *,struct fd_set *);
LOCAL STATUS ftpClntReplyHandler(FTP_CLIENT_NODE* pClnt);
LOCAL STATUS ftpClntDataNodeReadHandler(FTP_CLIENT_NODE* pClnt);
LOCAL STATUS ftpClntCtrlNodeReadHandler(FTP_CLIENT_NODE* pClnt);
LOCAL STATUS ftpClntSendCommand(FTP_CLIENT_NODE *pClnt,char* pBuf);
LOCAL STATUS ftpClntDownload(FTP_CLIENT_NODE* pClnt);
LOCAL STATUS ftpClntSockNodeAccept(FTP_SOCK_NODE* pn);
LOCAL STATUS ftpClntSockNodeListen(FTP_SOCK_NODE* pn);
#define FTP_ERR_MSG(x,p1,p2,p3,p4) { \
if( RosFtpClntDebug>0 ) logMsg(x,p1,p2,p3,p4,5,6);\
if( RosFtpClntDebug>1 ) taskSuspend(taskIdSelf()); \
}
#define FTP_DBG_MSG(x,p1,p2,p3,p4) { \
if( RosFtpClntDebug>0 ) logMsg(x,p1,p2,p3,p4,5,6);\
}
LOCAL void ctrlSockNodeClose(FTP_SOCK_NODE* pn)
{
if (pn->sockFd != INVALID_SOCK)
{
close(pn->sockFd);
pn->sockFd = INVALID_SOCK;
}
pn->state = End;
}
/*----------------------------------------------------------------------
* NAME: ftpClntNodeInit
* PARAMETERS:
* RETURN: OK
* FUNCTION: initialze socket node with specific type.
*/
LOCAL STATUS ftpClntNodeInit(FTP_CLIENT_NODE *pClnt)
{
pClnt->ctrlNode.sockFd = INVALID_SOCK;
pClnt->ctrlNode.state = Initial;
pClnt->dataNode.sockFd = INVALID_SOCK;
pClnt->dataNode.state = Initial;
pClnt->mode = 0; /* positive */
pClnt->reply = FTP_NONE;
pClnt->continuedReply = FALSE;
bzero(pClnt->replyBuf,sizeof(pClnt->replyBuf));
pClnt->replyLen = 0;
bzero(pClnt->user,sizeof(pClnt->user));
bzero(pClnt->password,sizeof(pClnt->password));
bzero(pClnt->sfile,sizeof(pClnt->sfile));
bzero(pClnt->dfile,sizeof(pClnt->dfile));
bzero(pClnt->cmdBuf,sizeof(pClnt->cmdBuf));
pClnt->totalRcv = 0;
pClnt->dMem = NULL;
pClnt->memSize = 0;
pClnt->dfp = NULL;
pClnt->pRcvBuf = NULL;
return OK;
}
/*----------------------------------------------------------------------
* NAME: ftpClntClose
* PARAMETERS:
* RETURN: OK
* FUNCTION: close client anytime.
*/
LOCAL STATUS ftpClntClose(FTP_CLIENT_NODE *pClnt)
{
taskDelay(1); /* delay for server close connection.*/
if (pClnt->ctrlNode.sockFd != INVALID_SOCK)
close(pClnt->ctrlNode.sockFd);
if (pClnt->dataNode.sockFd != INVALID_SOCK)
close(pClnt->dataNode.sockFd);
if (pClnt->dfp != NULL)
fclose(pClnt->dfp);
if (pClnt->pRcvBuf != NULL)
free(pClnt->pRcvBuf);
/* for deflated-version */
return OK;
}
/*----------------------------------------------------------------------
* NAME: ftpClntSockNodeAccept
* PARAMETERS:
* RETURN: OK/ERROR
* FUNCTION: intialize data node by accept a data client.
*/
LOCAL STATUS ftpClntSockNodeAccept(FTP_SOCK_NODE* pn)
{
SOCKET sockFd;
struct sockaddr from;
int fromLen;
if(pn->sockFd == INVALID_SOCK )
return ERROR;
fromLen = sizeof(from);
sockFd = accept(pn->sockFd,&from, &fromLen);
if(sockFd == ERROR || ftpClntSocketConfig(sockFd) == ERROR )
return ERROR;
close(pn->sockFd);
pn->sockFd = sockFd;
pn->state = Active;
return OK;
}
/*----------------------------------------------------------------------
* NAME: sockEventHandle
* PARAMETERS:
* RETURN: OK/ERROR
* FUNCTION: socket event handle.
*/
LOCAL STATUS ftpClntEventHandler( FTP_CLIENT_NODE *pClnt,
struct fd_set *pReadFds,
struct fd_set *pExceptFds )
{
STATUS result=OK;
if ( pClnt->ctrlNode.sockFd != INVALID_SOCK )
{
if ( FD_ISSET(pClnt->ctrlNode.sockFd,pExceptFds) )
return ERROR;
/* handle control stream read event */
if ( FD_ISSET(pClnt->ctrlNode.sockFd,pReadFds) )
if ( ftpClntCtrlNodeReadHandler(pClnt) == ERROR)
return ERROR;
}
if ( pClnt->dataNode.sockFd != INVALID_SOCK )
{
if ( FD_ISSET(pClnt->dataNode.sockFd,pExceptFds) )
return ERROR;
/* handle control stream read event */
if ( FD_ISSET(pClnt->dataNode.sockFd,pReadFds) )
if ( ftpClntDataNodeReadHandler(pClnt) == ERROR)
return ERROR;
}
return (result);
}
/*----------------------------------------------------------------------
* NAME: ftpClntSocketConfig
* PARAMETERS: sock
* RETURN: OK/ERROR
* FUNCTION: set stream socket with options.
*/
LOCAL STATUS ftpClntSocketConfig( SOCKET sock)
{
int optKeepAlive,optDebug,optNoDelay;
int optVal;
int optSndLowWait,optRcvLowWait;
struct timeval tmout;
optKeepAlive = 1; /* 1 keepalive */
optDebug = 0; /* 1 debug enable */
optNoDelay = 1; /* 1 no neagle algorithm */
optSndLowWait = FtpClntSndLowWait;
optRcvLowWait = 1;
tmout.tv_sec = 0;
tmout.tv_usec = 0;
optVal = 1;
if(setsockopt( sock, SOL_SOCKET, SO_KEEPALIVE,(char*)&optKeepAlive, sizeof (optKeepAlive))==ERROR)
{
FTP_ERR_MSG("setsockopt %u with SO_KEEPALIVE failed.\n",sock,2,3,4);
return ERROR;
}
if(setsockopt(sock, SOL_SOCKET, SO_DEBUG,(char*)&optDebug, sizeof (optDebug))==ERROR)
{
FTP_ERR_MSG("setsockopt %u with SO_DEBUG failed.\n",sock,2,3,4);
return ERROR;
}
if( setsockopt (sock, IPPROTO_TCP, TCP_NODELAY,(char*)&optNoDelay, sizeof (optNoDelay))==ERROR)
{
FTP_ERR_MSG("setsockopt %u with TCP_NODELAY failed.\n",sock,2,3,4);
return ERROR;
}
if (setsockopt (sock, SOL_SOCKET, SO_SNDLOWAT,(char*)&optSndLowWait, sizeof (optSndLowWait))==ERROR)
{
FTP_ERR_MSG("setsockopt %u with SO_SNDLOWAT failed.\n",sock,2,3,4);
return ERROR;
}
if(setsockopt (sock, SOL_SOCKET, SO_RCVLOWAT,(char*)&optRcvLowWait, sizeof (optRcvLowWait))==ERROR)
{
FTP_ERR_MSG("setsockopt %u with SO_RCVLOWAT failed.\n",sock,2,3,4);
return ERROR;
}
if( setsockopt (sock, SOL_SOCKET, SO_SNDTIMEO,(char*)&tmout, sizeof (tmout))==ERROR)
{
FTP_ERR_MSG("setsockopt %u with SO_SNDTIMEO failed.\n",sock,2,3,4);
return ERROR;
}
if( setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO,(char*)&tmout, sizeof (tmout))==ERROR)
{
FTP_ERR_MSG("setsockopt %u with SO_RCVTIMEO failed.\n",sock,2,3,4);
return ERROR;
}
/* set nonblock mode */
optVal = 1;
if( ioctl (sock, FIONBIO, (int)&optVal) == ERROR)
{
FTP_ERR_MSG("ioctl %u with FIONBIO failed.\n",sock,2,3,4);
return ERROR;
}
return OK;
}
/*----------------------------------------------------------------------
* NAME: ftpClntReplyHandler
* PARAMETERS:
* RETURN: OK/ERROR
* FUNCTION: handle control node code string.
*/
LOCAL STATUS ftpClntReplyHandler(FTP_CLIENT_NODE* pClnt)
{
int reply,sockFd,nCnt,result;
struct sockaddr_in sockAddr;
int sockAddrSize;
char buf[MAX_CMD_STR_LEN],*pChar;
char ipStr[INET_ADDR_LEN];
UINT16 dataPort;
UINT32 portNum [6];
struct timeval timeo;
STATUS comdResult;
result = ERROR;
FTP_DBG_MSG("%s\n",(int)pClnt->replyBuf,2,3,4);
/* intermediary line */
if ( isdigit((int)(pClnt->replyBuf[0])) == 0
|| isdigit((int)(pClnt->replyBuf[1])) == 0
|| isdigit((int)(pClnt->replyBuf[2])) == 0 )
return OK;
reply = (pClnt->replyBuf[0]-'0')*100
+ (pClnt->replyBuf[1]-'0')*10
+ (pClnt->replyBuf[2]-'0');
if ( reply == pClnt->reply && pClnt->continuedReply == TRUE )
{
pClnt->continuedReply = FALSE;
return OK;
}
if ( pClnt->replyBuf[3] == '-')
pClnt->continuedReply = TRUE;
pClnt->reply = reply;
switch(reply)
{
case 227: /* pasv mode */
/* 1. connect to server.*/
sscanf (strrchr(pClnt->replyBuf,'(')+1, "%u,%u,%u,%u,%u,%u",
&portNum [0], &portNum [1], &portNum [2],
&portNum [3], &portNum [4], &portNum [5]);
bzero ((char *) &sockAddr, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_len = (u_char) sizeof(sockAddr);
sockAddr.sin_port = (UINT16)(portNum [4] * 256 + portNum [5]);
sockAddr.sin_port = htons(sockAddr.sin_port);
sockAddr.sin_addr.s_addr= (portNum [0] << 24) | (portNum [1] << 16) |
(portNum [2] << 8) | portNum [3];
sockAddr.sin_addr.s_addr = htonl(sockAddr.sin_addr.s_addr);
if( (sockFd = socket( AF_INET,SOCK_STREAM,0))== ERROR)
return ERROR;
timeo.tv_sec = FTP_CONNECT_TIMEO;
timeo.tv_usec = 0;
nCnt = 0;
while(nCnt++ < 3)
if( (result = connectWithTimeout( sockFd,(struct sockaddr *)&sockAddr,
sizeof(sockAddr), &timeo) ) == OK )
break;
if (result != OK)
{
close(sockFd);
return ERROR;
}
if(pClnt->dataNode.sockFd != INVALID_SOCK)
close(pClnt->dataNode.sockFd);
pClnt->dataNode.state = Active;
pClnt->dataNode.sockFd = sockFd;
/* 2. RETR. */
sprintf(buf,"RETR %s"CR_LF,pClnt->sfile);
return(ftpClntSendCommand(pClnt,buf));
case 200: /*Command okay.*/
if(strncmp(pClnt->cmdBuf,"TYPE",4)==0)
{
if(pClnt->mode & PASV_MODE)
{ /* PASV */
sprintf(buf,"PASV "CR_LF);
return(ftpClntSendCommand(pClnt,buf));
}
else
{ /* PORT */
if ( ftpClntSockNodeListen(&pClnt->dataNode) == ERROR)
return ERROR;
sockAddrSize = sizeof(sockAddr);
getsockname(pClnt->ctrlNode.sockFd,(struct sockaddr*)&sockAddr,&sockAddrSize);
inet_ntoa_b(sockAddr.sin_addr,ipStr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -