visual-c++mfcwininet

CFtpFileFind::FindFile() fails with Xfinity (Comcast) but not with CenturyLink


I have a Windows MFC C++ app that uses CFtpFileFind::FindFile() to read a list of files from a (shared) server and then uses CFtpConnection::PutFile() to upload several files. This works when the ISP is CenturyLink but fails when the ISP is Xfinity. I am able to read http files using CInternetSession() but I cannot read or write using ftp. I can access files using ftp apps like FileZilla with the same credentials and port number.

The following code experiences this problem. The code does not throw exceptions and all of the pointers look valid regardless of the ISP, but it fails as mentioned in the comments when the ISP is Xfinity.

CInternetSession* pSession = nullptr;
try
{
    CInternetSession* pSession = new CInternetSession(DOWNLOAD_SESSION_NAME, 1UL, 0UL, NULL, NULL, INTERNET_FLAG_DONT_CACHE);
    CFtpConnection* pConnect = pSession->GetFtpConnection(L"my_ftp_url.com", L"my_username", L"my_password", 21);
    CFtpFileFind finder(pConnect);
    BOOL bFoundFile = finder.FindFile(_T("*")); // This returns false with Xfinity.
    int iFileCount = 0;
    while(bFoundFile)
    {
        bFoundFile = finder.FindNextFile();
        iFileCount++;
    }
    TRACE(L"Found %d files.", iFileCount); // This returns 0 with Xfinity.

    if(iFileCount > 0)
    {
        if(!pConnect->PutFile(L"C:\\test.txt", L"test.txt"))
        {
            const int iError = GetLastError(); // This returns 12003 with Xfinity.
        }
    }
}
catch(CException* e)
{
    // Exceptions are not thrown.
}

Ideas? The code was working fine before we changed ISPs.

Thanks!


Solution

  • The solution was to use ftp passive mode. Passing true for the bPassive parameter in the call to GetFtpConnection() as shown here allowed ftp-ing using both CenturyLink and Xfinity:

    pSession->GetFtpConnection(L"my_ftp_url.com", L"my_username", L"my_password", 21, true);
    

    If you are calling InternetConnect() rather than using MFC, add the INTERNET_FLAG_PASSIVE flag as shown here:

    InternetConnect(hInternet, L"my_ftp_url.com", INTERNET_DEFAULT_FTP_PORT, L"my_username", L"my_password", INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
    

    Also, FWIW, when I wasn't using passive mode GetLastError() was returning 12003 as the error code.