Example usage for javax.net.ssl SSLSocket setSoTimeout

List of usage examples for javax.net.ssl SSLSocket setSoTimeout

Introduction

In this page you can find the example usage for javax.net.ssl SSLSocket setSoTimeout.

Prototype

public synchronized void setSoTimeout(int timeout) throws SocketException 

Source Link

Document

Enable/disable SocketOptions#SO_TIMEOUT SO_TIMEOUT with the specified timeout, in milliseconds.

Usage

From source file:org.hyperic.hq.bizapp.agent.client.SecureAgentConnection.java

@Override
protected Socket getSocket() throws IOException {
    SSLSocket socket;

    log.debug("Creating secure socket");

    try {/*from ww  w .  j ava 2s.  co  m*/
        // Check for configured agent read timeout from System properties
        int readTimeout;

        try {
            readTimeout = Integer.parseInt(System.getProperty(PROP_READ_TIMEOUT));
        } catch (NumberFormatException e) {
            readTimeout = READ_TIMEOUT;
        }

        // Check for configured agent post handshake timeout
        // from System properties
        int postHandshakeTimeout;
        try {
            postHandshakeTimeout = Integer.parseInt(System.getProperty(PROP_POST_HANDSHAKE_TIMEOUT));
        } catch (NumberFormatException e) {
            postHandshakeTimeout = POST_HANDSHAKE_TIMEOUT;
        }

        SSLProvider sslProvider = new DefaultSSLProviderImpl(keystoreConfig, acceptUnverifiedCertificate);

        SSLSocketFactory factory = sslProvider.getSSLSocketFactory();

        // See the following links...
        // http://www.apache.org/dist/httpcomponents/httpcore/RELEASE_NOTES-4.1.x.txt
        // http://www-128.ibm.com/developerworks/forums/dw_thread.jsp?message=13695343&cat=10&thread=73546&treeDisplayType=threadmode1&forum=178#13695343
        // In any case, it would seem as though the bug has since been fixed in IBM's JRE, no need to work around it anymore...
        socket = (SSLSocket) factory.createSocket();

        // Make sure the InetAddress used to initialize the socket has a non-null hostname (empty string).
        // This prevents slow and unnecessary reverse DNS querying when the connection is opened.
        InetAddress withoutHost = InetAddress.getByName(this.agentAddress);
        InetAddress withHost = InetAddress.getByAddress("", withoutHost.getAddress());
        InetSocketAddress address = new InetSocketAddress(withHost, this.agentPort);

        socket.connect(address, readTimeout);

        // Set the socket timeout during the initial handshake to detect
        // connection issues with the agent.  
        socket.setSoTimeout(readTimeout);

        log.debug("Secure socket is connected to " + address + " - starting handshake.");

        socket.startHandshake();

        log.debug("SSL handshake complete");

        // [HHQ-3694] The timeout is set to a post handshake value.
        socket.setSoTimeout(postHandshakeTimeout);

    } catch (IOException exc) {
        IOException toThrow = new IOException(
                "Unable to connect to " + this.agentAddress + ":" + this.agentPort + ": " + exc.getMessage());
        // call initCause instead of constructor to be java 1.5 compat
        toThrow.initCause(exc);
        throw toThrow;
    }

    // Write our security settings
    try {
        DataOutputStream dOs;

        dOs = new DataOutputStream(socket.getOutputStream());
        dOs.writeUTF(this.authToken);
    } catch (IOException exc) {
        IOException toThrow = new IOException("Unable to write auth params to server");
        // call initCause instead of constructor to be java 1.5 compat
        toThrow.initCause(exc);
        throw toThrow;
    }

    return socket;
}

From source file:org.lockss.protocol.BlockingStreamComm.java

protected void handshake(SSLSocket s) throws SSLPeerUnverifiedException {
    long oldTimeout = -2;
    try {//from   ww  w  . java  2 s.  c  om
        oldTimeout = s.getSoTimeout();
        if (absTimeout(paramSslHandshakeTimeout) < absTimeout(oldTimeout)) {
            s.setSoTimeout((int) paramSslHandshakeTimeout);
        }
    } catch (SocketException e) {
        log.warning("Couldn't save/set socket timeout before handshake", e);
    }
    try {
        SSLSession session = s.getSession();
        java.security.cert.Certificate[] certs = session.getPeerCertificates();
        log.debug(session.getPeerHost() + " via " + session.getProtocol() + " verified");
    } catch (SSLPeerUnverifiedException ex) {
        log.error(s.getInetAddress() + ":" + s.getPort() + " not verified");
        try {
            s.close();
        } catch (IOException ex2) {
            log.error("Socket close threw " + ex2);
        }
        throw ex;
    } finally {
        if (!s.isClosed() && absTimeout(paramSslHandshakeTimeout) < absTimeout(oldTimeout)) {
            try {
                s.setSoTimeout((int) oldTimeout);
            } catch (SocketException e) {
                log.warning("Couldn't restore socket timeout after handshake", e);
            }
        }
    }
}

From source file:android.net.http.HttpsConnection.java

/**
 * Opens the connection to a http server or proxy.
 *
 * @return the opened low level connection
 * @throws IOException if the connection fails for any reason.
 *//*from   w w w.  ja  v a 2s.  com*/
@Override
AndroidHttpClientConnection openConnection(Request req) throws IOException {
    SSLSocket sslSock = null;

    if (mProxyHost != null) {
        // If we have a proxy set, we first send a CONNECT request
        // to the proxy; if the proxy returns 200 OK, we negotiate
        // a secure connection to the target server via the proxy.
        // If the request fails, we drop it, but provide the event
        // handler with the response status and headers. The event
        // handler is then responsible for cancelling the load or
        // issueing a new request.
        AndroidHttpClientConnection proxyConnection = null;
        Socket proxySock = null;
        try {
            proxySock = new Socket(mProxyHost.getHostName(), mProxyHost.getPort());

            proxySock.setSoTimeout(60 * 1000);

            proxyConnection = new AndroidHttpClientConnection();
            HttpParams params = new BasicHttpParams();
            HttpConnectionParams.setSocketBufferSize(params, 8192);

            proxyConnection.bind(proxySock, params);
        } catch (IOException e) {
            if (proxyConnection != null) {
                proxyConnection.close();
            }

            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to establish a connection to the proxy";
            }

            throw new IOException(errorMessage);
        }

        StatusLine statusLine = null;
        int statusCode = 0;
        Headers headers = new Headers();
        try {
            BasicHttpRequest proxyReq = new BasicHttpRequest("CONNECT", mHost.toHostString());

            // add all 'proxy' headers from the original request
            for (Header h : req.mHttpRequest.getAllHeaders()) {
                String headerName = h.getName().toLowerCase();
                if (headerName.startsWith("proxy") || headerName.equals("keep-alive")) {
                    proxyReq.addHeader(h);
                }
            }

            proxyConnection.sendRequestHeader(proxyReq);
            proxyConnection.flush();

            // it is possible to receive informational status
            // codes prior to receiving actual headers;
            // all those status codes are smaller than OK 200
            // a loop is a standard way of dealing with them
            do {
                statusLine = proxyConnection.parseResponseHeader(headers);
                statusCode = statusLine.getStatusCode();
            } while (statusCode < HttpStatus.SC_OK);
        } catch (ParseException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        } catch (HttpException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        } catch (IOException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        }

        if (statusCode == HttpStatus.SC_OK) {
            try {
                sslSock = (SSLSocket) getSocketFactory().createSocket(proxySock, mHost.getHostName(),
                        mHost.getPort(), true);
            } catch (IOException e) {
                if (sslSock != null) {
                    sslSock.close();
                }

                String errorMessage = e.getMessage();
                if (errorMessage == null) {
                    errorMessage = "failed to create an SSL socket";
                }
                throw new IOException(errorMessage);
            }
        } else {
            // if the code is not OK, inform the event handler
            ProtocolVersion version = statusLine.getProtocolVersion();

            req.mEventHandler.status(version.getMajor(), version.getMinor(), statusCode,
                    statusLine.getReasonPhrase());
            req.mEventHandler.headers(headers);
            req.mEventHandler.endData();

            proxyConnection.close();

            // here, we return null to indicate that the original
            // request needs to be dropped
            return null;
        }
    } else {
        // if we do not have a proxy, we simply connect to the host
        try {
            sslSock = (SSLSocket) getSocketFactory().createSocket();

            sslSock.setSoTimeout(SOCKET_TIMEOUT);
            sslSock.connect(new InetSocketAddress(mHost.getHostName(), mHost.getPort()));
        } catch (IOException e) {
            if (sslSock != null) {
                sslSock.close();
            }

            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to create an SSL socket";
            }

            throw new IOException(errorMessage);
        }
    }

    // do handshake and validate server certificates
    SslError error = CertificateChainValidator.getInstance().doHandshakeAndValidateServerCertificates(this,
            sslSock, mHost.getHostName());

    // Inform the user if there is a problem
    if (error != null) {
        // handleSslErrorRequest may immediately unsuspend if it wants to
        // allow the certificate anyway.
        // So we mark the connection as suspended, call handleSslErrorRequest
        // then check if we're still suspended and only wait if we actually
        // need to.
        synchronized (mSuspendLock) {
            mSuspended = true;
        }
        // don't hold the lock while calling out to the event handler
        boolean canHandle = req.getEventHandler().handleSslErrorRequest(error);
        if (!canHandle) {
            throw new IOException("failed to handle " + error);
        }
        synchronized (mSuspendLock) {
            if (mSuspended) {
                try {
                    // Put a limit on how long we are waiting; if the timeout
                    // expires (which should never happen unless you choose
                    // to ignore the SSL error dialog for a very long time),
                    // we wake up the thread and abort the request. This is
                    // to prevent us from stalling the network if things go
                    // very bad.
                    mSuspendLock.wait(10 * 60 * 1000);
                    if (mSuspended) {
                        // mSuspended is true if we have not had a chance to
                        // restart the connection yet (ie, the wait timeout
                        // has expired)
                        mSuspended = false;
                        mAborted = true;
                        if (HttpLog.LOGV) {
                            HttpLog.v("HttpsConnection.openConnection():"
                                    + " SSL timeout expired and request was cancelled!!!");
                        }
                    }
                } catch (InterruptedException e) {
                    // ignore
                }
            }
            if (mAborted) {
                // The user decided not to use this unverified connection
                // so close it immediately.
                sslSock.close();
                throw new SSLConnectionClosedByUserException("connection closed by the user");
            }
        }
    }

    // All went well, we have an open, verified connection.
    AndroidHttpClientConnection conn = new AndroidHttpClientConnection();
    BasicHttpParams params = new BasicHttpParams();
    params.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8192);
    conn.bind(sslSock, params);

    return conn;
}

From source file:android.net.http.HttpsConnection.java

/**
 * Opens the connection to a http server or proxy.
 *
 * @return the opened low level connection
 * @throws IOException if the connection fails for any reason.
 *//*  w w  w  .j  a  v  a2 s .c o m*/
@Override
AndroidHttpClientConnection openConnection(Request req) throws IOException {
    SSLSocket sslSock = null;

    if (mProxyHost != null) {
        // If we have a proxy set, we first send a CONNECT request
        // to the proxy; if the proxy returns 200 OK, we negotiate
        // a secure connection to the target server via the proxy.
        // If the request fails, we drop it, but provide the event
        // handler with the response status and headers. The event
        // handler is then responsible for cancelling the load or
        // issueing a new request.
        AndroidHttpClientConnection proxyConnection = null;
        Socket proxySock = null;
        try {
            proxySock = new Socket(mProxyHost.getHostName(), mProxyHost.getPort());

            proxySock.setSoTimeout(60 * 1000);

            proxyConnection = new AndroidHttpClientConnection();
            HttpParams params = new BasicHttpParams();
            HttpConnectionParams.setSocketBufferSize(params, 8192);

            proxyConnection.bind(proxySock, params);
        } catch (IOException e) {
            if (proxyConnection != null) {
                proxyConnection.close();
            }

            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to establish a connection to the proxy";
            }

            throw new IOException(errorMessage);
        }

        StatusLine statusLine = null;
        int statusCode = 0;
        Headers headers = new Headers();
        try {
            BasicHttpRequest proxyReq = new BasicHttpRequest("CONNECT", mHost.toHostString());

            // add all 'proxy' headers from the original request
            for (Header h : req.mHttpRequest.getAllHeaders()) {
                String headerName = h.getName().toLowerCase();
                if (headerName.startsWith("proxy") || headerName.equals("keep-alive")) {
                    proxyReq.addHeader(h);
                }
            }

            proxyConnection.sendRequestHeader(proxyReq);
            proxyConnection.flush();

            // it is possible to receive informational status
            // codes prior to receiving actual headers;
            // all those status codes are smaller than OK 200
            // a loop is a standard way of dealing with them
            do {
                statusLine = proxyConnection.parseResponseHeader(headers);
                statusCode = statusLine.getStatusCode();
            } while (statusCode < HttpStatus.SC_OK);
        } catch (ParseException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        } catch (HttpException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        } catch (IOException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        }

        if (statusCode == HttpStatus.SC_OK) {
            try {
                sslSock = (SSLSocket) getSocketFactory().createSocket(proxySock, mHost.getHostName(),
                        mHost.getPort(), true);
            } catch (IOException e) {
                if (sslSock != null) {
                    sslSock.close();
                }

                String errorMessage = e.getMessage();
                if (errorMessage == null) {
                    errorMessage = "failed to create an SSL socket";
                }
                throw new IOException(errorMessage);
            }
        } else {
            // if the code is not OK, inform the event handler
            ProtocolVersion version = statusLine.getProtocolVersion();

            req.mEventHandler.status(version.getMajor(), version.getMinor(), statusCode,
                    statusLine.getReasonPhrase());
            req.mEventHandler.headers(headers);
            req.mEventHandler.endData();

            proxyConnection.close();

            // here, we return null to indicate that the original
            // request needs to be dropped
            return null;
        }
    } else {
        // if we do not have a proxy, we simply connect to the host
        try {
            sslSock = (SSLSocket) getSocketFactory().createSocket();

            sslSock.setSoTimeout(SOCKET_TIMEOUT);
            sslSock.connect(new InetSocketAddress(mHost.getHostName(), mHost.getPort()));
        } catch (IOException e) {
            if (sslSock != null) {
                sslSock.close();
            }

            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to create an SSL socket";
            }

            throw new IOException(errorMessage);
        }
    }

    // do handshake and validate server certificates
    SslError error = CertificateChainValidator.getInstance().doHandshakeAndValidateServerCertificates(this,
            sslSock, mHost.getHostName());

    EventHandler eventHandler = req.getEventHandler();

    // Update the certificate info (to be consistent, it is better to do it
    // here, before we start handling SSL errors, if any)
    eventHandler.certificate(mCertificate);

    // Inform the user if there is a problem
    if (error != null) {
        // handleSslErrorRequest may immediately unsuspend if it wants to
        // allow the certificate anyway.
        // So we mark the connection as suspended, call handleSslErrorRequest
        // then check if we're still suspended and only wait if we actually
        // need to.
        synchronized (mSuspendLock) {
            mSuspended = true;
        }
        // don't hold the lock while calling out to the event handler
        boolean canHandle = eventHandler.handleSslErrorRequest(error);
        if (!canHandle) {
            throw new IOException("failed to handle " + error);
        }
        synchronized (mSuspendLock) {
            if (mSuspended) {
                try {
                    // Put a limit on how long we are waiting; if the timeout
                    // expires (which should never happen unless you choose
                    // to ignore the SSL error dialog for a very long time),
                    // we wake up the thread and abort the request. This is
                    // to prevent us from stalling the network if things go
                    // very bad.
                    mSuspendLock.wait(10 * 60 * 1000);
                    if (mSuspended) {
                        // mSuspended is true if we have not had a chance to
                        // restart the connection yet (ie, the wait timeout
                        // has expired)
                        mSuspended = false;
                        mAborted = true;
                        if (HttpLog.LOGV) {
                            HttpLog.v("HttpsConnection.openConnection():"
                                    + " SSL timeout expired and request was cancelled!!!");
                        }
                    }
                } catch (InterruptedException e) {
                    // ignore
                }
            }
            if (mAborted) {
                // The user decided not to use this unverified connection
                // so close it immediately.
                sslSock.close();
                throw new SSLConnectionClosedByUserException("connection closed by the user");
            }
        }
    }

    // All went well, we have an open, verified connection.
    AndroidHttpClientConnection conn = new AndroidHttpClientConnection();
    BasicHttpParams params = new BasicHttpParams();
    params.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8192);
    conn.bind(sslSock, params);

    return conn;
}

From source file:android.net.http.HttpsConnection.java

/**
 * Opens the connection to a http server or proxy.
 *
 * @return the opened low level connection
 * @throws IOException if the connection fails for any reason.
 *///from w  w  w. j  a v a  2s. c  o  m
@Override
AndroidHttpClientConnection openConnection(Request req) throws IOException {
    SSLSocket sslSock = null;

    if (mProxyHost != null) {
        // If we have a proxy set, we first send a CONNECT request
        // to the proxy; if the proxy returns 200 OK, we negotiate
        // a secure connection to the target server via the proxy.
        // If the request fails, we drop it, but provide the event
        // handler with the response status and headers. The event
        // handler is then responsible for cancelling the load or
        // issueing a new request.
        AndroidHttpClientConnection proxyConnection = null;
        Socket proxySock = null;
        try {
            proxySock = new Socket(mProxyHost.getHostName(), mProxyHost.getPort());

            proxySock.setSoTimeout(60 * 1000);

            proxyConnection = new AndroidHttpClientConnection();
            HttpParams params = new BasicHttpParams();
            HttpConnectionParams.setSocketBufferSize(params, 8192);

            proxyConnection.bind(proxySock, params);
        } catch (IOException e) {
            if (proxyConnection != null) {
                proxyConnection.close();
            }

            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to establish a connection to the proxy";
            }

            throw new IOException(errorMessage);
        }

        StatusLine statusLine = null;
        int statusCode = 0;
        Headers headers = new Headers();
        try {
            BasicHttpRequest proxyReq = new BasicHttpRequest("CONNECT", mHost.toHostString());

            // add all 'proxy' headers from the original request, we also need
            // to add 'host' header unless we want proxy to answer us with a
            // 400 Bad Request
            for (Header h : req.mHttpRequest.getAllHeaders()) {
                String headerName = h.getName().toLowerCase(Locale.ROOT);
                if (headerName.startsWith("proxy") || headerName.equals("keep-alive")
                        || headerName.equals("host")) {
                    proxyReq.addHeader(h);
                }
            }

            proxyConnection.sendRequestHeader(proxyReq);
            proxyConnection.flush();

            // it is possible to receive informational status
            // codes prior to receiving actual headers;
            // all those status codes are smaller than OK 200
            // a loop is a standard way of dealing with them
            do {
                statusLine = proxyConnection.parseResponseHeader(headers);
                statusCode = statusLine.getStatusCode();
            } while (statusCode < HttpStatus.SC_OK);
        } catch (ParseException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        } catch (HttpException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        } catch (IOException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        }

        if (statusCode == HttpStatus.SC_OK) {
            try {
                sslSock = (SSLSocket) getSocketFactory().createSocket(proxySock, mHost.getHostName(),
                        mHost.getPort(), true);
            } catch (IOException e) {
                if (sslSock != null) {
                    sslSock.close();
                }

                String errorMessage = e.getMessage();
                if (errorMessage == null) {
                    errorMessage = "failed to create an SSL socket";
                }
                throw new IOException(errorMessage);
            }
        } else {
            // if the code is not OK, inform the event handler
            ProtocolVersion version = statusLine.getProtocolVersion();

            req.mEventHandler.status(version.getMajor(), version.getMinor(), statusCode,
                    statusLine.getReasonPhrase());
            req.mEventHandler.headers(headers);
            req.mEventHandler.endData();

            proxyConnection.close();

            // here, we return null to indicate that the original
            // request needs to be dropped
            return null;
        }
    } else {
        // if we do not have a proxy, we simply connect to the host
        try {
            sslSock = (SSLSocket) getSocketFactory().createSocket(mHost.getHostName(), mHost.getPort());
            sslSock.setSoTimeout(SOCKET_TIMEOUT);
        } catch (IOException e) {
            if (sslSock != null) {
                sslSock.close();
            }

            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to create an SSL socket";
            }

            throw new IOException(errorMessage);
        }
    }

    // do handshake and validate server certificates
    SslError error = CertificateChainValidator.getInstance().doHandshakeAndValidateServerCertificates(this,
            sslSock, mHost.getHostName());

    // Inform the user if there is a problem
    if (error != null) {
        // handleSslErrorRequest may immediately unsuspend if it wants to
        // allow the certificate anyway.
        // So we mark the connection as suspended, call handleSslErrorRequest
        // then check if we're still suspended and only wait if we actually
        // need to.
        synchronized (mSuspendLock) {
            mSuspended = true;
        }
        // don't hold the lock while calling out to the event handler
        boolean canHandle = req.getEventHandler().handleSslErrorRequest(error);
        if (!canHandle) {
            throw new IOException("failed to handle " + error);
        }
        synchronized (mSuspendLock) {
            if (mSuspended) {
                try {
                    // Put a limit on how long we are waiting; if the timeout
                    // expires (which should never happen unless you choose
                    // to ignore the SSL error dialog for a very long time),
                    // we wake up the thread and abort the request. This is
                    // to prevent us from stalling the network if things go
                    // very bad.
                    mSuspendLock.wait(10 * 60 * 1000);
                    if (mSuspended) {
                        // mSuspended is true if we have not had a chance to
                        // restart the connection yet (ie, the wait timeout
                        // has expired)
                        mSuspended = false;
                        mAborted = true;
                        if (HttpLog.LOGV) {
                            HttpLog.v("HttpsConnection.openConnection():"
                                    + " SSL timeout expired and request was cancelled!!!");
                        }
                    }
                } catch (InterruptedException e) {
                    // ignore
                }
            }
            if (mAborted) {
                // The user decided not to use this unverified connection
                // so close it immediately.
                sslSock.close();
                throw new SSLConnectionClosedByUserException("connection closed by the user");
            }
        }
    }

    // All went well, we have an open, verified connection.
    AndroidHttpClientConnection conn = new AndroidHttpClientConnection();
    BasicHttpParams params = new BasicHttpParams();
    params.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8192);
    conn.bind(sslSock, params);

    return conn;
}

From source file:org.sandrob.android.net.http.HttpsConnection.java

/**
 * Opens the connection to a http server or proxy.
 *
 * @return the opened low level connection
 * @throws IOException if the connection fails for any reason.
 *//*from  ww  w  .j  a va2s . co m*/
@Override
AndroidHttpClientConnection openConnection(Request req) throws IOException {
    SSLSocket sslSock = null;

    synchronized (HttpsConnection.class) {
        initializeEngine(null, req);
    }
    if (mProxyHost != null) {
        // If we have a proxy set, we first send a CONNECT request
        // to the proxy; if the proxy returns 200 OK, we negotiate
        // a secure connection to the target server via the proxy.
        // If the request fails, we drop it, but provide the event
        // handler with the response status and headers. The event
        // handler is then responsible for cancelling the load or
        // issueing a new request.
        AndroidHttpClientConnection proxyConnection = null;
        Socket proxySock = null;
        try {
            proxySock = new Socket(mProxyHost.getHostName(), mProxyHost.getPort());

            proxySock.setSoTimeout(60 * 1000);

            proxyConnection = new AndroidHttpClientConnection();
            HttpParams params = new BasicHttpParams();
            HttpConnectionParams.setSocketBufferSize(params, 8192);

            proxyConnection.bind(proxySock, params);
        } catch (IOException e) {
            if (proxyConnection != null) {
                proxyConnection.close();
            }

            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to establish a connection to the proxy";
            }

            throw new IOException(errorMessage);
        }

        StatusLine statusLine = null;
        int statusCode = 0;
        Headers headers = new Headers();
        try {
            BasicHttpRequest proxyReq = new BasicHttpRequest("CONNECT", mHost.toHostString());

            // add all 'proxy' headers from the original request
            for (Header h : req.mHttpRequest.getAllHeaders()) {
                String headerName = h.getName().toLowerCase();
                if (headerName.startsWith("proxy") || headerName.equals("keep-alive")) {
                    proxyReq.addHeader(h);
                }
            }

            proxyConnection.sendRequestHeader(proxyReq);
            proxyConnection.flush();

            // it is possible to receive informational status
            // codes prior to receiving actual headers;
            // all those status codes are smaller than OK 200
            // a loop is a standard way of dealing with them
            do {
                statusLine = proxyConnection.parseResponseHeader(headers);
                statusCode = statusLine.getStatusCode();
            } while (statusCode < HttpStatus.SC_OK);
        } catch (ParseException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        } catch (HttpException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        } catch (IOException e) {
            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to send a CONNECT request";
            }

            throw new IOException(errorMessage);
        }

        if (statusCode == HttpStatus.SC_OK) {
            try {
                sslSock = (SSLSocket) getSocketFactory().createSocket(proxySock, mHost.getHostName(),
                        mHost.getPort(), true);
            } catch (IOException e) {
                if (sslSock != null) {
                    sslSock.close();
                }

                String errorMessage = e.getMessage();
                if (errorMessage == null) {
                    errorMessage = "failed to create an SSL socket";
                }
                throw new IOException(errorMessage);
            }
        } else {
            // if the code is not OK, inform the event handler
            ProtocolVersion version = statusLine.getProtocolVersion();

            req.mEventHandler.status(version.getMajor(), version.getMinor(), statusCode,
                    statusLine.getReasonPhrase());
            req.mEventHandler.headers(headers);
            req.mEventHandler.endData();

            proxyConnection.close();

            // here, we return null to indicate that the original
            // request needs to be dropped
            return null;
        }
    } else {
        // if we do not have a proxy, we simply connect to the host
        try {
            sslSock = (SSLSocket) getSocketFactory().createSocket();

            sslSock.setSoTimeout(SOCKET_TIMEOUT);
            sslSock.connect(new InetSocketAddress(mHost.getHostName(), mHost.getPort()));
        } catch (IOException e) {
            if (sslSock != null) {
                sslSock.close();
            }

            String errorMessage = e.getMessage();
            if (errorMessage == null) {
                errorMessage = "failed to create an SSL socket";
            }

            throw new IOException(errorMessage);
        }
    }

    // do handshake and validate server certificates
    SslError error = CertificateChainValidator.getInstance().doHandshakeAndValidateServerCertificates(this,
            sslSock, mHost.getHostName());

    // Inform the user if there is a problem
    if (error != null) {
        // handleSslErrorRequest may immediately unsuspend if it wants to
        // allow the certificate anyway.
        // So we mark the connection as suspended, call handleSslErrorRequest
        // then check if we're still suspended and only wait if we actually
        // need to.
        synchronized (mSuspendLock) {
            mSuspended = true;
        }
        // don't hold the lock while calling out to the event handler
        boolean canHandle = req.getEventHandler().handleSslErrorRequest(error);
        if (!canHandle) {
            throw new IOException("failed to handle " + error);
        }
        synchronized (mSuspendLock) {
            if (mSuspended) {
                try {
                    // Put a limit on how long we are waiting; if the timeout
                    // expires (which should never happen unless you choose
                    // to ignore the SSL error dialog for a very long time),
                    // we wake up the thread and abort the request. This is
                    // to prevent us from stalling the network if things go
                    // very bad.
                    mSuspendLock.wait(10 * 60 * 1000);
                    if (mSuspended) {
                        // mSuspended is true if we have not had a chance to
                        // restart the connection yet (ie, the wait timeout
                        // has expired)
                        mSuspended = false;
                        mAborted = true;
                        if (HttpLog.LOGV) {
                            HttpLog.v("HttpsConnection.openConnection():"
                                    + " SSL timeout expired and request was cancelled!!!");
                        }
                    }
                } catch (InterruptedException e) {
                    // ignore
                }
            }
            if (mAborted) {
                // The user decided not to use this unverified connection
                // so close it immediately.
                sslSock.close();
                throw new SSLConnectionClosedByUserException("connection closed by the user");
            }
        }
    }

    // All went well, we have an open, verified connection.
    AndroidHttpClientConnection conn = new AndroidHttpClientConnection();
    BasicHttpParams params = new BasicHttpParams();
    params.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8192);
    conn.bind(sslSock, params);

    return conn;
}