rv = SSM_SSLThreadMakeConnectionSSL(conn, &nSockets,
rv = SSM_SSLThreadMakeConnectionSSL(conn,
void SSM_SSLDataServiceThread(void* arg){    SSMStatus rv = PR_SUCCESS;    SSMSSLDataConnection* conn = NULL;    PRPollDesc pds[SSL_PDS];    PRIntn nSockets = 0;    PRInt32 nReady;    int i;    char *outbound = NULL;    char *inbound = NULL;    PRIntn oBufSize;        SSM_RegisterNewThread("ssl data", (SSMResource *) arg);    conn = (SSMSSLDataConnection*)arg;    SSM_DEBUG("initializing.\n");    if (arg == NULL) {        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);        goto loser;    }    SSMDATACONNECTION(conn)->m_dataServiceThread = PR_GetCurrentThread();	/* initialize xfer buffers */	outbound = (char *) PR_CALLOC(READSSL_CHUNKSIZE+1);	if (outbound == NULL)		goto loser;	inbound = (char *) PR_CALLOC(READSSL_CHUNKSIZE+1);	if (inbound == NULL)		goto loser;    /* initialize the poll descriptors */    for (i = 0; i < SSL_PDS; i++) {        pds[i].fd = NULL;    }    /* set up sockets */    /* set up the client data socket */    rv = SSMDataConnection_SetupClientSocket(SSMDATACONNECTION(conn));    if (rv != PR_SUCCESS) {        goto loser;    }    /* save the client data socket in the array */    pds[0].fd = SSMDATACONNECTION(conn)->m_clientSocket;    pds[0].in_flags = PR_POLL_READ;    nSockets++;    /* set up the SSL socket */    rv = SSM_GetSSLSocket(conn);    if (rv != PR_SUCCESS) {        goto loser;    }    /* save the SSL socket in the array */    pds[1].fd = conn->socketSSL;    pds[1].in_flags = PR_POLL_READ;    nSockets++;    if (conn->isTLS) {        /* SSL/SMTP connections usually require a large outbound buffer */        oBufSize = READSSL_CHUNKSIZE;        /* Add step-up FD to the list of FDs until we've been asked to           encrypt */        pds[2].fd = conn->stepUpFD;        pds[2].in_flags = PR_POLL_READ;        nSockets++;    }    else {        oBufSize = LINESIZE;    }    /* spinning mode.  Exchange data between the client socket and the SSL     * socket.     */    while ((nSockets > 0) &&            (SSM_Count(SSMDATACONNECTION(conn)->m_shutdownQ) == 0)) {        /* XXX Nova-specific: Nova does not handle active close from the         *     server properly in case of keep-alive connections: what         *     happens is that although we perform a shutdown on the client         *     socket, Nova never sends us a close.  If the SSL socket is          *     removed, we might as well close the client socket by hand.         */        /* if the outbound connection is shut down and there is no data         * pending in the client socket, perhaps the client is acting up         */        if (pds[1].fd == NULL) {            /* don't block in polling */            nReady = PR_Poll(pds, SSL_PDS, PR_TicksPerSecond()*600);            if (nReady <= 0) {                /* either error or the client socket is blocked.  Bail. */                rv = SSMSSLDataConnection_UpdateErrorCode(conn);                if (SSMDATACONNECTION(conn)->m_clientSocket != NULL) {                    PR_Shutdown(SSMDATACONNECTION(conn)->m_clientSocket,                                PR_SHUTDOWN_SEND);                }                nSockets--;                if (nSockets > 1)                    {                        /*                            We were waiting for notification to step up,                           but that notification won't happen. So,                           remove stepUpFD from the list as well.                        */                        pds[2].fd = NULL;                        nSockets = 1;                    }                break;    /* go to loser; */            }        }        SSM_DEBUG("Polling sockets for pending data.\n");        /* poll sockets for pending data */#if 0        if (conn->isTLS == PR_TRUE) {            /* we require the lock for this operation and do a non-blocking             * poll in case of TLS because we want to yield to the step-up              * operation             */            SSM_LockResource(SSMRESOURCE(conn));            nReady = PR_Poll(pds, SSL_PDS, PR_INTERVAL_NO_WAIT);            SSM_UnlockResource(SSMRESOURCE(conn));            if (nReady == 0) {                continue;            }        }        else {#endif            /* Poll for however many sockets we're interested in. */            nReady = PR_Poll(pds, nSockets, PR_INTERVAL_NO_TIMEOUT);#if 0        }#endif        if (nReady <= 0) {            rv = SSMSSLDataConnection_UpdateErrorCode(conn);            goto loser;        }        /* Wind down from SSL_PDS because the pollable event           takes priority over the I/O sockets. */        for (i = (SSL_PDS-1); i >= 0; i--) {            if (pds[i].fd == NULL) {                continue;            }            /* check sockets for data */            if (pds[i].out_flags & (PR_POLL_READ | PR_POLL_EXCEPT)) {                if (pds[i].fd == SSMDATACONNECTION(conn)->m_clientSocket) {                    /* got data at the client socket */		    rv = SSM_SSLThreadReadFromClient(conn, &nSockets,						     oBufSize, outbound,						     &pds[i]);		    SSM_DEBUG("Just finished reading from client with rv=%d\n",			      rv);                }                else if (pds[i].fd == conn->socketSSL) {                    /* got data at the SSL socket */		    rv = SSM_SSLThreadReadFromServer(conn, &nSockets,						     inbound, 						     READSSL_CHUNKSIZE,						     &pds[i]);		    SSM_DEBUG("Just finished reading from server with rv=%d\n",			      rv);                }                else if (pds[i].fd == conn->stepUpFD)                {		    rv = SSM_SSLThreadMakeConnectionSSL(conn, &nSockets,							&pds[i]);		    SSM_DEBUG("Just finished steeping up connection with rv=%d\n",			      rv);                }            }        }    /* end of for loop */    }    /* end of while loop */loser:    SSM_DEBUG("** Closing, return value %ld. **\n", rv);    if (conn != NULL) {      	SSM_ShutdownResource(SSMRESOURCE(conn), rv);        SSM_FreeResource(SSMRESOURCE(conn));    }    if (outbound != NULL) {        PR_Free(outbound);    }    if (inbound != NULL) {        PR_Free(inbound);    }    SSM_DEBUG("SSL data service thread terminated.\n");}