char * proxyHost;
nsXPIDLCString proxyHost;
nsSOCKSIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime /*timeout*/){    PRStatus status;        nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;    if (info == NULL) return PR_FAILURE;        // First, we need to look up our proxy...    char scratch[PR_NETDB_BUF_SIZE];    PRHostEnt hostentry;    char * proxyHost;    nsresult rv = info->GetProxyHost(&proxyHost);    if (NS_FAILED(rv) || !proxyHost || !(*proxyHost)) {        return PR_FAILURE;    }    PRInt32 socksVersion = -1;    rv = info->GetSOCKSVersion(&socksVersion);    if (NS_FAILED(rv)) {          return PR_FAILURE;    }    LOGDEBUG(("nsSOCKSIOLayerConnect SOCKS %u; proxyHost: %s.", socksVersion, proxyHost));    status = PR_GetHostByName(proxyHost, scratch, PR_NETDB_BUF_SIZE, &hostentry);        if (PR_SUCCESS != status) {        LOGERROR(("PR_GetHostByName() failed. proxyHost = %s, status = %x.",proxyHost, status));        return status;    }        // Extract the proxy addr    PRIntn entEnum = 0;    PRNetAddr proxyAddr;    PRInt32 proxyPort;    info->GetProxyPort(&proxyPort);    entEnum = PR_EnumerateHostEnt(entEnum, &hostentry, proxyPort, &proxyAddr);        if (entEnum <= 0) {        LOGERROR(("PR_EnumerateHostEnt() failed. proxyPort = %u, entEnum = %u.", proxyPort, entEnum));        return PR_FAILURE;    }        info->SetInternalProxyAddr(&proxyAddr);        // For now, we'll do this as a blocking connect,    // but with nspr 4.1, the necessary functions to    // do a non-blocking connect will be available        // Preserve the non-blocking state of the socket    PRBool nonblocking;    PRSocketOptionData sockopt;    sockopt.option = PR_SockOpt_Nonblocking;    status = PR_GetSocketOption(fd, &sockopt);        if (PR_SUCCESS != status) {        LOGERROR(("PR_GetSocketOption() failed. status = %x.", status));        return status;    }        // Store blocking option    nonblocking = sockopt.value.non_blocking;        sockopt.option = PR_SockOpt_Nonblocking;    sockopt.value.non_blocking = PR_FALSE;    status = PR_SetSocketOption(fd, &sockopt);        if (PR_SUCCESS != status) {        LOGERROR(("PR_SetSocketOption() failed. status = %x.", status));        return status;    }        // Now setup sockopts, so we can restore the value later.    sockopt.option = PR_SockOpt_Nonblocking;    sockopt.value.non_blocking = nonblocking;        // This connectWait should be long enough to connect to local proxy    // servers, but not much longer. Since this protocol negotiation    // uses blocking network calls, the app can appear to hang for a maximum    // of this time if the user presses the STOP button during the SOCKS    // connection negotiation. Note that this value only applies to the     // connecting to the SOCKS server: once the SOCKS connection has been    // established, the value is not used anywhere else.    PRIntervalTime connectWait = PR_SecondsToInterval(10);    // Connect to the proxy server.    status = fd->lower->methods->connect(fd->lower, &proxyAddr, connectWait);        if (PR_SUCCESS != status) {        LOGERROR(("Failed to TCP connect to the proxy server (%s): timeout = %d, status = %x.",proxyHost, connectWait, status));        PR_SetSocketOption(fd, &sockopt);        return status;    }            // We are now connected to the SOCKS proxy server.    // Now we will negotiate a connection to the desired server.        // External IP address returned from ConnectSOCKS5(). Not supported in SOCKS4.    PRNetAddr extAddr;	    PR_InitializeNetAddr(PR_IpAddrNull, 0, &extAddr);     NS_ASSERTION((socksVersion == 4) || (socksVersion == 5), "SOCKS Version must be selected");    // Try to connect via SOCKS 5.    if (socksVersion == 5) {        rv = ConnectSOCKS5(fd, addr, &extAddr, connectWait);        if (NS_FAILED(rv)) {            PR_SetSocketOption(fd, &sockopt);            return PR_FAILURE;	        }    }    // Try to connect via SOCKS 4.    else {        rv = ConnectSOCKS4(fd, addr, connectWait);        if (NS_FAILED(rv)) {            PR_SetSocketOption(fd, &sockopt);            return PR_FAILURE;	        }    }        info->SetDestinationAddr((PRNetAddr*)addr);    info->SetExternalProxyAddr(&extAddr);        // restore non-blocking option    PR_SetSocketOption(fd, &sockopt);        // we're set-up and connected.     // this socket can be used as normal now.        return PR_SUCCESS;}