From 883eb62de423ab3cfab3c8a05421e7ce8e508d97 Mon Sep 17 00:00:00 2001 From: Xudong Ma Date: Sat, 11 Apr 2015 10:59:00 +0800 Subject: [PATCH] OkHttp: Temporally support multiple h2-xx protocol on client side. Since the user provided SSLSocketFactory (especially in Android) may already do the handshake when creates the SSLSocket, and it may choose a different protocol name other than the one OkHttp is using. Resolves #293 --- .../grpc/transport/netty/Http2Negotiator.java | 3 +- .../squareup/okhttp/OkHttpTlsUpgrader.java | 33 ++++++++++++------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/netty/src/main/java/io/grpc/transport/netty/Http2Negotiator.java b/netty/src/main/java/io/grpc/transport/netty/Http2Negotiator.java index d982b09872..fa5d070537 100644 --- a/netty/src/main/java/io/grpc/transport/netty/Http2Negotiator.java +++ b/netty/src/main/java/io/grpc/transport/netty/Http2Negotiator.java @@ -68,10 +68,11 @@ import javax.net.ssl.SSLEngine; * endpoint. */ public class Http2Negotiator { - // TODO(madongfly): Remove "h2-15" and "h2-16" at a right time. + // TODO(madongfly): Remove "h2-xx" at a right time. private static final List SUPPORTED_PROTOCOLS = Collections.unmodifiableList( Arrays.asList( Http2OrHttpChooser.SelectedProtocol.HTTP_2.protocolName(), + "h2-14", "h2-15", "h2-16")); diff --git a/okhttp/src/main/java/com/squareup/okhttp/OkHttpTlsUpgrader.java b/okhttp/src/main/java/com/squareup/okhttp/OkHttpTlsUpgrader.java index a41223ee4d..3dc00b493c 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/OkHttpTlsUpgrader.java +++ b/okhttp/src/main/java/com/squareup/okhttp/OkHttpTlsUpgrader.java @@ -42,6 +42,7 @@ import java.net.ProxySelector; import java.net.Socket; import java.util.Arrays; import java.util.Collections; +import java.util.List; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; @@ -52,6 +53,10 @@ import javax.net.ssl.SSLSocketFactory; */ public final class OkHttpTlsUpgrader { + // TODO(madongfly): We should only support "h2" at a right time. + private static final List SUPPORTED_HTTP2_PROTOCOLS = Collections.unmodifiableList( + Arrays.asList("h2", "h2-14", "h2-15", "h2-16")); + // A dummy address used to bypass null check. private static final InetSocketAddress DUMMY_INET_SOCKET_ADDRESS = InetSocketAddress.createUnresolved("fake", 73); @@ -69,21 +74,27 @@ public final class OkHttpTlsUpgrader { spec.apply(sslSocket, getOkHttpRoute(host, port, spec)); Platform platform = Platform.get(); - try { - // Force handshake. - sslSocket.startHandshake(); + // It's possible that the user provided SSLSocketFactory has already done the handshake + // when creates the SSLSocket. + String negotiatedProtocol = platform.getSelectedProtocol(sslSocket); + if (negotiatedProtocol == null) { - String negotiatedProtocol = platform.getSelectedProtocol(sslSocket); - if (negotiatedProtocol == null) { - throw new RuntimeException("protocol negotiation failed"); + try { + // Force handshake. + sslSocket.startHandshake(); + + negotiatedProtocol = platform.getSelectedProtocol(sslSocket); + if (negotiatedProtocol == null) { + throw new RuntimeException("protocol negotiation failed"); + } + } finally { + platform.afterHandshake(sslSocket); } - Preconditions.checkState(Protocol.HTTP_2.equals(Protocol.get(negotiatedProtocol)), - "negotiated protocol is %s instead of %s.", - negotiatedProtocol, Protocol.HTTP_2.toString()); - } finally { - platform.afterHandshake(sslSocket); } + Preconditions.checkState(SUPPORTED_HTTP2_PROTOCOLS.contains(negotiatedProtocol), + "negotiated protocol %s is unsupported", negotiatedProtocol); + return sslSocket; }