/** Create an {@code SSLSocket} and perform the TLS handshake and certificate validation. */ private void upgradeToTls(TunnelRequest tunnelRequest) throws IOException { Platform platform = Platform.get(); // Make an SSL Tunnel on the first message pair of each SSL + proxy connection. if (requiresTunnel()) { makeTunnel(tunnelRequest); } // Create the wrapper over connected socket. socket = route.address.sslSocketFactory.createSocket( socket, route.address.uriHost, route.address.uriPort, true /* autoClose */); SSLSocket sslSocket = (SSLSocket) socket; if (route.modernTls) { platform.enableTlsExtensions(sslSocket, route.address.uriHost); } else { platform.supportTlsIntolerantServer(sslSocket); } boolean useNpn = route.modernTls && route.address.transports.contains("spdy/3"); if (useNpn) { platform.setNpnProtocols(sslSocket, NPN_PROTOCOLS); } // Force handshake. This can throw! sslSocket.startHandshake(); // Verify that the socket's certificates are acceptable for the target host. if (!route.address.hostnameVerifier.verify(route.address.uriHost, sslSocket.getSession())) { throw new IOException("Hostname '" + route.address.uriHost + "' was not verified"); } out = sslSocket.getOutputStream(); in = sslSocket.getInputStream(); byte[] selectedProtocol; if (useNpn && (selectedProtocol = platform.getNpnSelectedProtocol(sslSocket)) != null) { if (Arrays.equals(selectedProtocol, SPDY3)) { sslSocket.setSoTimeout(0); // SPDY timeouts are set per-stream. spdyConnection = new SpdyConnection.Builder(route.address.getUriHost(), true, in, out).build(); spdyConnection.sendConnectionHeader(); } else if (!Arrays.equals(selectedProtocol, HTTP_11)) { throw new IOException( "Unexpected NPN transport " + new String(selectedProtocol, "ISO-8859-1")); } } }
/** Create an {@code SSLSocket} and perform the TLS handshake and certificate validation. */ private void upgradeToTls(TunnelRequest tunnelRequest) throws IOException { Platform platform = Platform.get(); // Make an SSL Tunnel on the first message pair of each SSL + proxy connection. if (requiresTunnel()) { makeTunnel(tunnelRequest); } // Create the wrapper over connected socket. socket = route.address.sslSocketFactory.createSocket( socket, route.address.uriHost, route.address.uriPort, true /* autoClose */); SSLSocket sslSocket = (SSLSocket) socket; if (route.modernTls) { platform.enableTlsExtensions(sslSocket, route.address.uriHost); } else { platform.supportTlsIntolerantServer(sslSocket); } boolean useNpn = route.modernTls && ( // Contains a spdy variant. route.address.protocols.contains(Protocol.HTTP_2) || route.address.protocols.contains(Protocol.SPDY_3)); if (useNpn) { if (route.address.protocols.contains(Protocol.HTTP_2) // Contains both spdy variants. && route.address.protocols.contains(Protocol.SPDY_3)) { platform.setNpnProtocols(sslSocket, Protocol.HTTP2_SPDY3_AND_HTTP); } else if (route.address.protocols.contains(Protocol.HTTP_2)) { platform.setNpnProtocols(sslSocket, Protocol.HTTP2_AND_HTTP_11); } else { platform.setNpnProtocols(sslSocket, Protocol.SPDY3_AND_HTTP11); } } // Force handshake. This can throw! sslSocket.startHandshake(); // Verify that the socket's certificates are acceptable for the target host. if (!route.address.hostnameVerifier.verify(route.address.uriHost, sslSocket.getSession())) { throw new IOException("Hostname '" + route.address.uriHost + "' was not verified"); } out = sslSocket.getOutputStream(); in = sslSocket.getInputStream(); handshake = Handshake.get(sslSocket.getSession()); streamWrapper(); ByteString maybeProtocol; if (useNpn && (maybeProtocol = platform.getNpnSelectedProtocol(sslSocket)) != null) { Protocol selectedProtocol = Protocol.find(maybeProtocol); // Throws IOE on unknown. if (selectedProtocol.spdyVariant) { sslSocket.setSoTimeout(0); // SPDY timeouts are set per-stream. spdyConnection = new SpdyConnection.Builder(route.address.getUriHost(), true, in, out) .protocol(selectedProtocol) .build(); spdyConnection.sendConnectionHeader(); } } }