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
pE