www.pudn.com > FTPC.zip > X
E&l0l1O(10U(s16.67H&l5.05c5.05C&a1l2r1C /*--------------------------------------------------------------------- * * Program: Asynch Ftp Client (TCP) * * filename: FTP_DATA.C * * copyright by Bob Quinn, 1995 * * Description: * Client application that uses "file transfer protocol" (ftp) * service as described by RFC 959. * * This module contains the functions that deal with the FTP * data connection (for sending and receiving data between * client and server to service LIST, RECV and STOR commands). * ---------------------------------------------------------------------*/ #include "..\wsa_xtra.h" #include#include #include "..\winsockx.h" #include /* for _fmemcpy() & _fmemset() */ #include /* for _ltoa() */ #include #include "resource.h" #include /* for Microsoft find file structure */ #include "ac_ftp.h" /*-------------------------------------------------------------- * Function: InitDataConn() * * Description: */ SOCKET InitDataConn(PSOCKADDR_IN lpstName, HWND hDlg, u_int nAsyncMsg) { int nRet; SOCKET hLstnSock; int nLen = SOCKADDR_LEN; if (bDebug) { wsprintf(achTempBuf, "InitDataConn() Qlen:%d Cmd[0]:%d [1]:%d [2]:%d [3]:%d, State:%d\n", nQLen, astFtpCmd[0].nFtpCmd, astFtpCmd[1].nFtpCmd, astFtpCmd[2].nFtpCmd, astFtpCmd[3].nFtpCmd, nAppState); OutputDebugString (achTempBuf); } lByteCount = 0; /* init byte counter */ /* Get a TCP socket to use for data connection listen*/ hLstnSock = socket (AF_INET, SOCK_STREAM, 0); if (hLstnSock == INVALID_SOCKET) { WSAperror(WSAGetLastError(), "socket()"); } else { /* Request async notification for most events */ nRet = WSAAsyncSelect(hLstnSock, hDlg, nAsyncMsg, (FD_ACCEPT | FD_READ | FD_WRITE | FD_CLOSE)); if (nRet == SOCKET_ERROR) { WSAperror(WSAGetLastError(), "WSAAsyncSelect()"); } else { /* Name the local socket with bind() */ lpstName->sin_family = PF_INET; lpstName->sin_port = 0; /* any port will do */ nRet = bind(hLstnSock,(LPSOCKADDR)lpstName,SOCKADDR_LEN); if (nRet == SOCKET_ERROR) { &a94l2r94C WSAperror(WSAGetLastError(), "bind()"); } else { /* Get local port number assigned by bind() */ nRet = getsockname(hLstnSock,(LPSOCKADDR)lpstName, (int FAR *)&nLen); if (nRet == SOCKET_ERROR) { WSAperror(WSAGetLastError(), "getsockname()"); } else { /* Listen for incoming connection requests */ nRet = listen(hLstnSock, 5); if (nRet == SOCKET_ERROR) { WSAperror(WSAGetLastError(), "listen()"); } } } } /* If we haven't had an error but we still don't know the local * IP address, then we need to try to get it before we return */ if (!lpstName->sin_addr.s_addr) { lpstName->sin_addr.s_addr = GetHostID(); if (!lpstName->sin_addr.s_addr) { MessageBox (hDlg, "Can't get local IP address", "InitDataConn() Failed", MB_OK | MB_ICONASTERISK); nRet = SOCKET_ERROR; } } /* If we had an error or we still don't know our IP address, * then we have a problem. Clean up */ if (nRet == SOCKET_ERROR) { closesocket(hLstnSock); hLstnSock = INVALID_SOCKET; } } return (hLstnSock); } /* end InitDataConn() */ /*-------------------------------------------------------------- * Function: AcceptDataConn() * * Description: */ SOCKET AcceptDataConn(SOCKET hLstnSock, PSOCKADDR_IN pstName) { SOCKET hDataSock; int nRet, nLen = SOCKADDR_LEN, nOptval; if (bDebug) { wsprintf(achTempBuf, "AcceptDataConn() Qlen:%d Cmd[0]:%d [1]:%d [2]:%d [3]:%d, State:%d\n", nQLen, astFtpCmd[0].nFtpCmd, astFtpCmd[1].nFtpCmd, astFtpCmd[2].nFtpCmd, astFtpCmd[3].nFtpCmd, nAppState); OutputDebugString (achTempBuf); } hDataSock = accept (hLstnSock, (LPSOCKADDR)pstName, (LPINT)&nLen); if (hDataSock == SOCKET_ERROR) { int WSAErr = WSAGetLastError(); if (WSAErr != WSAEWOULDBLOCK) WSAperror (WSAErr, "accept"); } else if (bReAsync) { /* This SHOULD be unnecessary, since all new sockets are supposed * to inherit properties of the listening socket (like all the * asynch events registered but some WinSocks don't do this. * Request async notification for most events */ &a0L&a1r1C*c3366a1b0P&a68r1C*c3366a1b0P&a1r1C*c1a2116b0P&a94C*c1a2116b0P&a188C*c1a2116b0P&a1r137CPage 1&a1r35CFTP_DATA.C 1-08-95 12:00&a64r188C h p p&a1l2r1C nRet = WSAAsyncSelect(hDataSock, hWinMain, WSA_ASYNC+1, (FD_READ | FD_WRITE | FD_CLOSE)); if (nRet == SOCKET_ERROR) { WSAperror(WSAGetLastError(), "WSAAsyncSelect()"); } /* Try to get lots of buffer space */ nOptval = astFtpCmd[0].nFtpCmd==STOR ? SO_SNDBUF : SO_RCVBUF; GetBuf(hDataSock, INPUT_SIZE*2, nOptval); } return (hDataSock); } /* end AcceptData() */ /*-------------------------------------------------------------- * Function: SendData() * * Description: Receive data and write to open data file. */ long SendData(SOCKET *hDataSock, HFILE hDataFile, int len) { static int cbReadFromFile; /* bytes read from file */ static int cbSentToServer; /* number of buffered bytes sent */ static HFILE hLastFile; /* handle of last file sent */ long cbTotalSent = 0; /* total bytes sent */ int nRet, WSAErr, cbBytesToSend; /* Reset our counters when we access a new file */ if (hLastFile != hDataFile) { cbReadFromFile = 0; cbSentToServer = 0; hLastFile = hDataFile; } /* Read data from file, and send it. */ do { if (bIOBeep) MessageBeep(0xFFFF); /* calculate what's left to send */ cbBytesToSend = cbReadFromFile - cbSentToServer; if (cbBytesToSend <= 0) { /* read data from input file, if we need it */ if (!bFromNul) { cbReadFromFile = _lread(hDataFile, achOutBuf, INPUT_SIZE); if (cbReadFromFile == HFILE_ERROR) { MessageBox (hWinMain, "Error reading data file", "SendData() Failed", MB_OK | MB_ICONASTERISK); break; } else if (!cbReadFromFile){ /* EOF: no more data to send */ CloseConn(hDataSock, (PSTR)0, 0, hWinMain); EndData(); break; } else { cbBytesToSend = cbReadFromFile; /* send as much as we read */ } } else { /* just send whatever's in memory (up to our max) */ if (lByteCount < MAXNULPUT) { cbBytesToSend = INPUT_SIZE; } else { CloseConn(hDataSock, (PSTR)0, 0, hWinMain); EndData(); } } cbSentToServer = 0; /* reset tally */ &a94l2r94C } /* Send data to server */ nRet = send (*hDataSock, &(achOutBuf[cbSentToServer]), ((len < cbBytesToSend) ? len : cbBytesToSend), 0); if (nRet == SOCKET_ERROR) { WSAErr = WSAGetLastError(); /* Display significant errors */ if (WSAErr != WSAEWOULDBLOCK) WSAperror(WSAErr, (LPSTR)"send()"); } else { /* Update byte counter, and display. */ lByteCount += nRet; _ltoa(lByteCount, achTempBuf, 10); SetDlgItemText(hWinMain, IDC_DATA_RATE, achTempBuf); cbSentToServer += nRet;/* tally bytes sent since last file read */ cbTotalSent += nRet;/* tally total bytes sent since we started */ } } while (nRet != SOCKET_ERROR); return (cbTotalSent); } /* end SendData() */ /*-------------------------------------------------------------- * Function: RecvData() * * Description: Receive data from net and write to open data file */ int RecvData(SOCKET hDataSock, HFILE hDataFile, LPSTR achInBuf, int len) { static HFILE hLastFile; /* handle of last file sent */ static int cbBytesBuffered; /* total bytes received */ int cbBytesRcvd = 0; int nRet=0, WSAErr; if (hDataFile != hLastFile) { hLastFile = hDataFile; cbBytesBuffered = 0; } /* Read as much as we can from server */ while (cbBytesBuffered < len) { nRet = recv (hDataSock,&(achInBuf[cbBytesBuffered]), len-cbBytesBuffered, 0); if (nRet == SOCKET_ERROR) { WSAErr = WSAGetLastError(); /* Display significant errors */ if (WSAErr != WSAEWOULDBLOCK) WSAperror(WSAErr, (LPSTR)"recv()"); /* exit recv() loop on any error */ goto recv_end; } else if (nRet == 0) { /* Other side closed socket */ /* quit if server closed connection */ goto recv_end; } else { /* Update byte counter, and display */ lByteCount += nRet; _ltoa(lByteCount, achTempBuf, 10); SetDlgItemText(hWinMain, IDC_DATA_RATE, achTempBuf); cbBytesRcvd += nRet; /* tally bytes read */ cbBytesBuffered += nRet; } } &a0L&a1r1C*c3366a1b0P&a68r1C*c3366a1b0P&a1r1C*c1a2116b0P&a94C*c1a2116b0P&a188C*c1a2116b0P&a1r137CPage 2&a1r35CFTP_DATA.C 1-08-95 12:00&a64r188C h p p&a1l2r1C recv_end: if (!bToNul && ((cbBytesBuffered > (len-MTU_SIZE)) || ((nRet == SOCKET_ERROR) && WSAGetLastError() != WSAEWOULDBLOCK) || (nRet == 0))) { /* If we have a lot buffered, write to data file */ nRet = _lwrite(hDataFile, achInBuf, cbBytesBuffered); if (nRet == HFILE_ERROR) MessageBox (hWinMain, "Can't write to local file", "RecvData() Failed", MB_OK | MB_ICONASTERISK); cbBytesBuffered = 0; } else if (bToNul) cbBytesBuffered = 0; return (cbBytesRcvd); } /* end RecvData() */ /*-------------------------------------------------------------- * Function: EndData() * * Description: */ void EndData (void) { LONG dByteRate; LONG lMSecs; /* Calculate data transfer rate, and display */ lMSecs = (LONG) GetTickCount() - lStartTime; if (lMSecs <= 55) lMSecs = 27; /* about half of 55Msec PC clock resolution */ /* Socket Check should not be necessary, but some WinSocks * mistakenly post FD_CLOSE to listen socket after close */ // BQ NOTE: Should check if Novell does that after you call shutdown on // a listening socket, or also after closesocket()?? nAppState &= ~(DATACONNECTED); SetDlgItemText (hWinMain, IDC_STATUS, "Status: connected"); if (lByteCount > 0L) { dByteRate = (lByteCount/lMSecs); /* data rate (bytes/Msec) */ wsprintf (achTempBuf,"%ld bytes %s in %ld.%ld seconds (%ld.%ld Kbytes/sec)", lByteCount, ((astFtpCmd[0].nFtpCmd==STOR) ? "sent":"received"), lMSecs/1000, lMSecs%1000, (dByteRate*1000)/1024, (dByteRate*1000)%1024); SetDlgItemText (hWinMain, IDC_DATA_RATE, achTempBuf); if (hLogFile != HFILE_ERROR) _lwrite (hLogFile, achTempBuf, strlen(achTempBuf)); } lStartTime = 0L; if (hDataFile != HFILE_ERROR) { _lclose (hDataFile); hDataFile = HFILE_ERROR; if (astFtpCmd[0].nFtpCmd == LIST) { wsprintf (achTempBuf, "notepad %s", szTempFile); WinExec (achTempBuf, SW_SHOW); } } astFtpCmd[0].nFtpCmd = 0; /* reset pending command */ } /* end EndData() */ &a94l2r94C&a0L&a1r1C*c3366a1b0P&a68r1C*c3366a1b0P&a1r1C*c1a2116b0P&a94C*c1a2116b0P&a188C*c1a2116b0P&a1r137CPage 3&a1r35CFTP_DATA.C 1-08-95 12:00&a64r188C h p pE