private void beginHandshakeInternal() throws SSLException {
        switch (state) {
            case STATE_NEW: {
                throw new IllegalStateException("Client/server mode must be set before handshake");
            }
            case STATE_MODE_SET: {
                // We know what mode to handshake in but have not started the handshake, proceed
                break;
            }
            case STATE_CLOSED_INBOUND:
            case STATE_CLOSED_OUTBOUND:
            case STATE_CLOSED:
                throw new SSLHandshakeException("Engine has already been closed");
            default:
                // We've already started the handshake, just return
                return;
        }

        transitionTo(STATE_HANDSHAKE_STARTED);

        boolean releaseResources = true;
        try {
            // Prepare the SSL object for the handshake.
            ssl.initialize(getHostname(), channelIdPrivateKey);

            // For clients, offer to resume a previously cached session to avoid the
            // full TLS handshake.
            if (getUseClientMode()) {
                NativeSslSession cachedSession = clientSessionContext().getCachedSession(
                        getHostname(), getPeerPort(), sslParameters);
                if (cachedSession != null) {
                    cachedSession.offerToResume(ssl);
                }
            }

            maxSealOverhead = ssl.getMaxSealOverhead();
            handshake();
            releaseResources = false;
        } catch (IOException e) {
            closeAll();
            throw SSLUtils.toSSLHandshakeException(e);
        } finally {
            if (releaseResources) {
                closeAndFreeResources();
            }
        }
    }
Returns the hostname from {@link #setHostname(String)} or supplied by the
{@link PeerInfoProvider} upon creation. No DNS resolution is attempted before
returning the hostname.
common/src/main/java/org/conscrypt/ConscryptEngine.java