public void afterConnect() throws IOException, UnknownHostException {
    if (!isCachedConnection()) {
      SSLSocket s = null;
      SSLSocketFactory factory;
      factory = sslSocketFactory;
      try {
        if (!(serverSocket instanceof SSLSocket)) {
          s = (SSLSocket) factory.createSocket(serverSocket, host, port, true);
        } else {
          s = (SSLSocket) serverSocket;
        }
      } catch (IOException ex) {
        // If we fail to connect through the tunnel, try it
        // locally, as a last resort.  If this doesn't work,
        // throw the original exception.
        try {
          s = (SSLSocket) factory.createSocket(host, port);
        } catch (IOException ignored) {
          throw ex;
        }
      }

      SSLSocketFactoryImpl.checkCreate(s);

      //
      // Force handshaking, so that we get any authentication.
      // Register a handshake callback so our session state tracks any
      // later session renegotiations.
      //
      String[] protocols = getProtocols();
      String[] ciphers = getCipherSuites();
      if (protocols != null) s.setEnabledProtocols(protocols);
      if (ciphers != null) s.setEnabledCipherSuites(ciphers);
      s.addHandshakeCompletedListener(this);
      s.startHandshake();
      session = s.getSession();
      // change the serverSocket and serverOutput
      serverSocket = s;
      try {
        serverOutput =
            new PrintStream(
                new BufferedOutputStream(serverSocket.getOutputStream()), false, encoding);
      } catch (UnsupportedEncodingException e) {
        throw new InternalError(encoding + " encoding not found");
      }

      // check URL spoofing
      checkURLSpoofing(hv);
    } else {
      // if we are reusing a cached https session,
      // we don't need to do handshaking etc. But we do need to
      // set the ssl session
      session = ((SSLSocket) serverSocket).getSession();
    }
  }
  /**
   * Overrides HTTP protocol handler method so that we return an SSL socket, not a TCP socket. This
   * establishes a secure tunnel if appropriate.
   *
   * @param host the host to connect to
   * @param port the port on that host.
   * @exception IOException on errors including a host doesn't authenicate corectly.
   * @exception UnknownHostException if "host" is unknown
   */
  protected Socket doConnect(String host, int port) throws IOException, UnknownHostException {
    // doConnect() ends up getting called from the
    // HttpClient constructor, so our constructor can't do any
    // meaningful initialization.  This could be made nicer
    // by refactoring HttpClient and HttpsClient so that they
    // have a common base class.
    instTunnelHost = ((instTunnelHost != null) ? instTunnelHost : getProxyHost());
    instTunnelPort = ((instTunnelPort != 0) ? instTunnelPort : getProxyPort());

    Socket s = null;
    SSLSocketFactory factory;
    factory = sslSocketFactory;

    if (instTunnelHost == null || isNonProxyHost()) {
      s = factory.createSocket(host, port);
    } else {
      try {
        s =
            (Socket)
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedExceptionAction() {
                      public Object run() throws IOException {
                        return new Socket(instTunnelHost, instTunnelPort);
                      }
                    });
      } catch (java.security.PrivilegedActionException pae) {
        throw (IOException) pae.getException();
      } catch (IOException ex) {
        // If we fail to connect through the tunnel, try it
        // locally, as a last resort.  If this doesn't work,
        // throw the original exception.
        try {
          s = (SSLSocket) factory.createSocket(host, port);
        } catch (IOException ignored) {
          throw ex;
        }
      }
    }
    return s;
  }