Back to index

lightning-sunbird  0.9+nobinonly
Public Types | Public Member Functions | Private Member Functions | Private Attributes
nsFTPConn Class Reference

#include <nsFTPConn.h>

Collaboration diagram for nsFTPConn:
Collaboration graph
[legend]

List of all members.

Public Types

enum  { ASCII = 0, BINARY }
enum  { OPEN = 0, GETTING, CLOSED }
enum  {
  OK = 0, E_MEM = -801, E_PARAM = -802, E_ALREADY_OPEN = -803,
  E_NOT_OPEN = -804, E_CMD_ERR = -805, E_CMD_FAIL = -806, E_CMD_UNEXPECTED = -807,
  E_WRITE = -808, E_READ = -809, E_SMALL_BUF = -810, E_CANT_OVWRITE = -811,
  E_LOCL_INIT = -812, E_USER_CANCEL = -813, E_INVALID_ADDR = -814
}

Public Member Functions

 nsFTPConn (char *aHost)
 nsFTPConn (char *aHost, int(*aEventPumpCB)(void))
 ~nsFTPConn ()
int Open ()
int Open (char *aHost)
int ResumeOrGet (char *aSrvPath, char *aLoclPath, int aType, int aOvWrite, FTPGetCB aCBFunc)
int Get (char *aSrvPath, char *aLoclPath, int aType, int aOvWrite, FTPGetCB aCBFunc)
int Get (char *aSrvPath, char *aLoclPath, int aType, int aResumePos, int aOvWrite, FTPGetCB aCBFunc)
int Close ()

Private Member Functions

int FlushCntlSock (nsSocket *aSock, int bailOnTimeOut=1)
int IssueCmd (const char *aCmd, char *aResp, int aRespSize, nsSocket *aSock)
int ParseAddr (char *aBuf, char **aHost, int *aPort)
int DataInit (char *aHost, int aPort, nsSocket **aSock)

Private Attributes

int(* mEventPumpCB )(void)
char * mHost
int mState
int mPassive
nsSocketmCntlSock
nsSocketmDataSock

Detailed Description

Definition at line 47 of file nsFTPConn.h.


Member Enumeration Documentation

anonymous enum
Enumerator:
ASCII 
BINARY 

Definition at line 55 of file nsFTPConn.h.

    {
        ASCII = 0,
        BINARY
    };
anonymous enum
Enumerator:
OPEN 
GETTING 
CLOSED 

Definition at line 62 of file nsFTPConn.h.

    {
        OPEN = 0,
        GETTING,
        CLOSED
    };
anonymous enum
Enumerator:
OK 
E_MEM 
E_PARAM 
E_ALREADY_OPEN 
E_NOT_OPEN 
E_CMD_ERR 
E_CMD_FAIL 
E_CMD_UNEXPECTED 
E_WRITE 
E_READ 
E_SMALL_BUF 
E_CANT_OVWRITE 
E_LOCL_INIT 
E_USER_CANCEL 
E_INVALID_ADDR 

Definition at line 82 of file nsFTPConn.h.

    {
        OK                  = 0,
        E_MEM               = -801, /* out of memory */
        E_PARAM             = -802, /* parameter null or incorrect */
        E_ALREADY_OPEN      = -803, /* connection already established */
        E_NOT_OPEN          = -804, /* connection not established, can't use */
        E_CMD_ERR           = -805, /* ftp command error */
        E_CMD_FAIL          = -806, /* ftp command failed */
        E_CMD_UNEXPECTED    = -807, /* ftp command unexpected response */
        E_WRITE             = -808, /* write to socket/fd failed */
        E_READ              = -809, /* read on socket/fd failed */
        E_SMALL_BUF         = -810, /* buffer too small, provide bigger one */
        E_CANT_OVWRITE      = -811, /* cannot overwrite existing file */
        E_LOCL_INIT         = -812, /* local file open/init failed */
        E_USER_CANCEL       = -813, /* user canceled the download */
        E_INVALID_ADDR      = -814  /* couldn't parse address/port */
    };

Constructor & Destructor Documentation

nsFTPConn::nsFTPConn ( char *  aHost)

Definition at line 80 of file nsFTPConn.cpp.

nsFTPConn::nsFTPConn ( char *  aHost,
int(*)(void aEventPumpCB 
)

Definition at line 70 of file nsFTPConn.cpp.

                                                           :
    mEventPumpCB(aEventPumpCB),
    mHost(aHost),
    mState(CLOSED),
    mPassive(FALSE),
    mCntlSock(NULL),
    mDataSock(NULL)
{
}

Definition at line 90 of file nsFTPConn.cpp.

{
    // don't release mHost cause we don't own it
}

Member Function Documentation

Definition at line 322 of file nsFTPConn.cpp.

{
    int err = OK;
    char cmd[kCmdBufSize], resp[kRespBufSize];

    /* close sockets */
    if (mCntlSock)
    {
        /* issue QUIT command on control connection */
        sprintf(cmd, "ABORT\r\n");
        IssueCmd(cmd, resp, kRespBufSize, mCntlSock);
    }
    if (mDataSock)
    {
        mDataSock->Close();
        delete mDataSock;
        mDataSock = NULL;
        FlushCntlSock(mCntlSock);
    }
    if (mCntlSock)
    {
        mCntlSock->Close();
        delete mCntlSock;
        mCntlSock = NULL;
    }

    return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsFTPConn::DataInit ( char *  aHost,
int  aPort,
nsSocket **  aSock 
) [private]

Definition at line 558 of file nsFTPConn.cpp.

{
    int err = OK;
    char cmd[kCmdBufSize], resp[kRespBufSize];
    char *srvHost = NULL; 
    int srvPort = 0;
    char *hostPort = NULL;

    /* param check */
    if (!aHost || !aSock)
        return E_PARAM;

    /* issue PASV command */
    sprintf(cmd, "PASV\r\n");
    err = IssueCmd(cmd, resp, kRespBufSize, mCntlSock);
    if (err != OK)
    {
        err = OK;
        goto ACTIVE; /* failover to active mode */
    }
       
    mPassive = TRUE;

    ERR_CHECK(ParseAddr(resp, &srvHost, &srvPort));
    *aSock = new nsSocket(srvHost, srvPort, mEventPumpCB);
    if (!*aSock)
    {
        err = E_MEM;
        goto BAIL;
    }
    
    ERR_CHECK((*aSock)->Open());

    if (srvHost) 
    {
        free(srvHost);
        srvHost = NULL;
    }

    return err;

ACTIVE:

    *aSock = new nsSocket(aHost, aPort, mEventPumpCB);
    if (!*aSock)
    {
        err = E_MEM;
        goto BAIL;
    }

    /* init data socket making it listen */
    ERR_CHECK((*aSock)->SrvOpen());

    ERR_CHECK((*aSock)->GetHostPortString(&hostPort)); // allocates
    if (!hostPort)
    {
        err = E_MEM;
        goto BAIL;
    }

    sprintf(cmd, "PORT %s\r\n", hostPort);
    ERR_CHECK(IssueCmd(cmd, resp, kRespBufSize, mCntlSock));

BAIL:
    if (mPassive && err != OK)
        mPassive = FALSE;

    if (err != OK && (*aSock))
    {
        delete *aSock;
        *aSock = NULL;
    }

    if (srvHost)
    {
        free(srvHost);
        srvHost = NULL;
    }

    if (hostPort)
    {
        free(hostPort);
        hostPort = NULL;
    }

    return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsFTPConn::FlushCntlSock ( nsSocket aSock,
int  bailOnTimeOut = 1 
) [private]

Definition at line 352 of file nsFTPConn.cpp.

{
    int err = OK;
    char resp[kRespBufSize];
    int bailOnTimeOutCount = 0;

    /* param check */
    if (!aSock)
        return E_PARAM;

    do
    {
        // Time out value is in Usecs. This should give us 3 tries.
        const int timeout = 300000;
        ++bailOnTimeOutCount;
        int respSize = kRespBufSize;
        err = aSock->Recv((unsigned char *)resp, &respSize, timeout);
        if (err != nsSocket::OK && 
            err != nsSocket::E_READ_MORE && 
            err != nsSocket::E_EOF_FOUND)
        {
            if((err == nsSocket::E_TIMEOUT) &&
               (bailOnTimeOutCount < bailOnTimeOut))
                // wait a little longer for response
                err = nsSocket::E_READ_MORE;
            else
                goto BAIL;
        }

        DUMP(resp);
        if ( mEventPumpCB )
            if (mEventPumpCB() == E_USER_CANCEL)
                return E_USER_CANCEL;
    }
    while (err == nsSocket::E_READ_MORE);

    switch (*resp)
    {
        case '2':
            break;
        case '1':
        case '3':
            err = E_CMD_ERR;
            break;
        case '4':
        case '5':
            err = E_CMD_FAIL;
            break;
        default:
            err = E_CMD_UNEXPECTED;
            break;
    }

BAIL:
    return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsFTPConn::Get ( char *  aSrvPath,
char *  aLoclPath,
int  aType,
int  aOvWrite,
FTPGetCB  aCBFunc 
)

Definition at line 176 of file nsFTPConn.cpp.

{
    // deprecated API; wrapper for backwards compatibility

    return ResumeOrGet(aSrvPath, aLoclPath, aType, aOvWrite, aCBFunc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsFTPConn::Get ( char *  aSrvPath,
char *  aLoclPath,
int  aType,
int  aResumePos,
int  aOvWrite,
FTPGetCB  aCBFunc 
)

Definition at line 185 of file nsFTPConn.cpp.

{
    struct stat dummy;
    int err = OK, totBytesRd = 0;
    char cmd[kCmdBufSize], resp[kRespBufSize];
    int fileSize = 0;
    FILE *loclfd = NULL;

    if (!aSrvPath || !aLoclPath)
        return E_PARAM;
    if (mState != OPEN || !mCntlSock)
        return E_NOT_OPEN;

    /* stat local path and verify aOvWrite is set if file already exists */
    err = stat(aLoclPath, &dummy);
    if (err != -1 && aOvWrite == FALSE)
        return E_CANT_OVWRITE;

    mState = GETTING;

    /* initialize data connection */
    ERR_CHECK(DataInit(mHost, kDataPort, &mDataSock));

    /* issue TYPE command on control connection */
    sprintf(cmd, "TYPE %s\r\n", aType==BINARY ? "I" : "A");
    ERR_CHECK(IssueCmd(cmd, resp, kRespBufSize, mCntlSock));
    
    /* issue SIZE command on control connection */
    sprintf(cmd, "SIZE %s\r\n", aSrvPath);
    err = IssueCmd(cmd, resp, kRespBufSize, mCntlSock); /* non-fatal */
    if (err == OK && (resp[0] == '2'))
        fileSize = atoi(&resp[4]);   // else ???

    if (aResumePos > 0)
    {
        /* issue restart command */
        sprintf(cmd, "REST %d\r\n", aResumePos);
        ERR_CHECK(IssueCmd(cmd, resp, kRespBufSize, mCntlSock));
    }

    /* issue RETR command on control connection */
    sprintf(cmd, "RETR %s\r\n", aSrvPath);
    ERR_CHECK(IssueCmd(cmd, resp, kRespBufSize, mCntlSock));

    /* get file contents on data connection */
    if (!mPassive)
        ERR_CHECK(mDataSock->SrvAccept());

    /* initialize locl file */
    if (aResumePos <= 0)
    {
        if (!(loclfd = fopen(aLoclPath, aType==BINARY ? "w+b" : "w+")))
        {
            err = E_LOCL_INIT;
            goto BAIL;
        }
    }
    else
    {
        if (!(loclfd = fopen(aLoclPath, aType==BINARY ? "r+b" : "r+")) ||
            (fseek(loclfd, aResumePos, SEEK_SET) != 0)) 
        {
            err = E_LOCL_INIT;
            goto BAIL;
        }
    }

    do 
    {
        int respBufSize = kDlBufSize;
        err = mDataSock->Recv((unsigned char *)resp, &respBufSize);
        if (err != nsSocket::E_READ_MORE && 
            err != nsSocket::E_EOF_FOUND &&
            err != nsSocket::OK)
            goto BAIL;
        totBytesRd += respBufSize;
        if (err == nsSocket::E_READ_MORE && aCBFunc)
            if ((err = aCBFunc(totBytesRd, fileSize)) == E_USER_CANCEL)
                goto BAIL;
            
        /* append to local file */
        const int wrote = fwrite((void *)resp, 1, respBufSize, loclfd);
        if (wrote != respBufSize)
        {   
            err = E_WRITE;
            goto BAIL;
        }
        if ( mEventPumpCB )
            mEventPumpCB();
    }
    while (err == nsSocket::E_READ_MORE || err == nsSocket::OK);
    if (err == nsSocket::E_EOF_FOUND)
        err = OK;

BAIL:
       if ( err != OK && err != E_USER_CANCEL ) {
              sprintf(cmd, "QUIT\r\n");
              IssueCmd(cmd, resp, kRespBufSize, mCntlSock);
       FlushCntlSock(mCntlSock);
    }
    
    /* close locl file if open */
    if (loclfd)
        fclose(loclfd);
    if ( err == E_USER_CANCEL ) {
        return err;
    }
    /* kill data connection if it exists */
    if (mDataSock)
    {
        /* err != OK means that the file attempted to be downloaded
         * was not successfully initiated.  This means that the server
         * will not post a response when the data socket is closed.
         * Since it's not going to post a response, we don't have to
         * wait kMaxBailOnTimeOut. */
        int bailOnTimeOut = err != OK ? 1 : kMaxBailOnTimeOut;

        mDataSock->Close();
        delete mDataSock;
        mDataSock = NULL;

        /* We are expecting a response from this call to FlushCntlSock()
         * _only_ if err == OK (meaning that a file was downloaded).
         * We return only when a responce has been received, or else the next
         * file that is to be downloaded will catch this response
         * and fail. */
        FlushCntlSock(mCntlSock, bailOnTimeOut);
    }

    mState = OPEN;
    mPassive = FALSE;

    return err;
}

Here is the call graph for this function:

int nsFTPConn::IssueCmd ( const char *  aCmd,
char *  aResp,
int  aRespSize,
nsSocket aSock 
) [private]

Definition at line 410 of file nsFTPConn.cpp.

{
    int err = OK;
    int len;

    /* param check */
    if (!aSock || !aCmd || !aResp || aRespSize <= 0)
        return E_PARAM;

    /* send command */
    len = strlen(aCmd);
    ERR_CHECK(aSock->Send((unsigned char *)aCmd, &len));
    DUMP(aCmd);

    /* receive response */
    do
    {
        int respSize = aRespSize;
        err = aSock->Recv((unsigned char *)aResp, &respSize);
        if (err != nsSocket::OK && 
            err != nsSocket::E_READ_MORE && 
            err != nsSocket::E_EOF_FOUND)
            goto BAIL;
        DUMP(aResp);
        if ( mEventPumpCB )
            if (mEventPumpCB() == E_USER_CANCEL)
                return E_USER_CANCEL;
    }
    while (err == nsSocket::E_READ_MORE);

    /* alternate interpretation of err codes */
    if ( (strncmp(aCmd, "APPE", 4) == 0) ||
         (strncmp(aCmd, "LIST", 4) == 0) ||
         (strncmp(aCmd, "NLST", 4) == 0) ||
         (strncmp(aCmd, "REIN", 4) == 0) ||
         (strncmp(aCmd, "RETR", 4) == 0) ||
         (strncmp(aCmd, "STOR", 4) == 0) ||
         (strncmp(aCmd, "STOU", 4) == 0) )
    {
        switch (*aResp)
        {
            case '1':   /* exception: 100 series is OK */
            case '2':
                break;
            case '3':
                err = E_CMD_ERR;
                break;
            case '4':
            case '5':
                err = E_CMD_FAIL;
                break;
            default:
                err = E_CMD_UNEXPECTED;
                break;
        }
    }

    /* restart command case */
    else if (strncmp(aCmd, "REST", 4) == 0)
    {
        switch (*aResp)
        {
            case '1':
            case '2':
                err = E_CMD_ERR;
                break;
            case '3':
                break;
            case '4':
            case '5':
                err = E_CMD_FAIL;
                break;
            default:
                err = E_CMD_UNEXPECTED;
                break;
        }
    }

    /* quit command case */
    else if (strncmp(aCmd, "QUIT", 4) == 0)
    {
        err = OK;
        goto BAIL;
    }

    /* regular interpretation of err codes */
    else
    {
        switch (*aResp)
        {
            case '2':
                break;
            case '1':
            case '3':
                err = E_CMD_ERR;
                break;
            case '4':
            case '5':
                err = E_CMD_FAIL;
                break;
            default:
                err = E_CMD_UNEXPECTED;
                break;
        }
    }

BAIL:
    return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 96 of file nsFTPConn.cpp.

{
    int err = OK;
    char cmd[kCmdBufSize], resp[kRespBufSize];

    if (!mHost)
        return E_PARAM;
    if (mState != CLOSED)
        return E_ALREADY_OPEN;

    /* open control connection on port 21 */
    mCntlSock = new nsSocket(mHost, kCntlPort, mEventPumpCB);
    if (!mCntlSock)
        return E_MEM;
    ERR_CHECK(mCntlSock->Open());
    FlushCntlSock(mCntlSock);

    /* issue USER command on control connection */
    err = IssueCmd("USER anonymous\r\n", resp, kRespBufSize, mCntlSock);

    /* issue PASS command on control connection */
    ERR_CHECK(IssueCmd("PASS -linux@installer.sbg\r\n", resp, kRespBufSize, mCntlSock));

    mState = OPEN;

    return err;

BAIL:
    if (mCntlSock)
    {
        /* issue QUIT command on control connection */
        sprintf(cmd, "QUIT\r\n");
        IssueCmd(cmd, resp, kRespBufSize, mCntlSock);
    }
    if (mDataSock)
    {
        mDataSock->Close();
        delete mDataSock;
        mDataSock = NULL;
        FlushCntlSock(mCntlSock);
    }
    if (mCntlSock)
    {
        mCntlSock->Close();
        delete mCntlSock;
        mCntlSock = NULL;
    }
    return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsFTPConn::Open ( char *  aHost)

Definition at line 147 of file nsFTPConn.cpp.

{
    if (!aHost)
        return E_PARAM;

    mHost = aHost;
    return Open();
}

Here is the call graph for this function:

int nsFTPConn::ParseAddr ( char *  aBuf,
char **  aHost,
int aPort 
) [private]

Definition at line 521 of file nsFTPConn.cpp.

{
    int err = OK;
    char *c;
    int addr[6];

    /* param check */
    if (!aBuf || !aHost || !aPort)
        return E_PARAM;

    c = aBuf + strlen("227 "); /* pass by return code */
    while (!isdigit((int)(*c)))
    {
        if (*c == '\0')
            return E_INVALID_ADDR;
        c++;
    }

    if (sscanf(c, "%d,%d,%d,%d,%d,%d", 
        &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6)
        return E_INVALID_ADDR;

    *aHost = (char *)malloc(strlen("XXX.XXX.XXX.XXX") + 1);
    sprintf(*aHost, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);

    *aPort = ((addr[4] & 0xFF) << 8) | (addr[5] & 0xFF);

#ifdef DEBUG
    printf("%s %d: PASV response: %d,%d,%d,%d,%d,%d\n", __FILE__, __LINE__,
            addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
    printf("%s %d: Host = %s\tPort = %d\n", __FILE__, __LINE__, *aHost, *aPort);
#endif
    
    return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsFTPConn::ResumeOrGet ( char *  aSrvPath,
char *  aLoclPath,
int  aType,
int  aOvWrite,
FTPGetCB  aCBFunc 
)

Definition at line 157 of file nsFTPConn.cpp.

{
    struct stat stbuf;
    int err = OK;
    int resPos = 0;

    if (!aLoclPath)
        return E_PARAM;

    /* stat local file */
    err = stat(aLoclPath, &stbuf);
    if (err == 0)
        resPos = stbuf.st_size;

    return Get(aSrvPath, aLoclPath, aType, resPos, aOvWrite, aCBFunc);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 112 of file nsFTPConn.h.

Definition at line 113 of file nsFTPConn.h.

Definition at line 108 of file nsFTPConn.h.

char* nsFTPConn::mHost [private]

Definition at line 109 of file nsFTPConn.h.

Definition at line 111 of file nsFTPConn.h.

Definition at line 110 of file nsFTPConn.h.


The documentation for this class was generated from the following files: