diff --git a/.travis.yml b/.travis.yml index bc088e91b..5ad8e9825 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,3 +8,4 @@ before_install: jdk: - oraclejdk7 + - oraclejdk8 diff --git a/README.md b/README.md index 186f99b15..67eecc945 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,8 @@ Testing ### On the Desktop -Run OkHttp tests on the desktop with Maven. Running SPDY tests on the desktop uses -[Jetty-NPN][3] which requires OpenJDK 7. +Run OkHttp tests on the desktop with Maven. Running HTTP/2 and SPDY tests on the desktop uses +[Jetty-NPN][3] when running OpenJDK 7 or [Jetty-ALPN][4] when OpenJDK 8. ``` mvn clean test @@ -46,7 +46,7 @@ mvn clean test OkHttp's test suite creates an in-process HTTPS server. Prior to Android 2.3, SSL server sockets were broken, and so HTTPS tests will time out when run on such devices. -Test on a USB-attached Android using [Vogar][4]. Unfortunately `dx` requires that you build with +Test on a USB-attached Android using [Vogar][5]. Unfortunately `dx` requires that you build with Java 6, otherwise the test class will be silently omitted from the `.dex` file. ``` @@ -69,7 +69,7 @@ MockWebServer coupling with OkHttp is essential for proper testing of SPDY and H ### Download -Download [the latest JAR][5] or grab via Maven: +Download [the latest JAR][6] or grab via Maven: ```xml @@ -102,5 +102,6 @@ License [1]: http://square.github.io/okhttp [2]: http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.squareup.okhttp&a=okhttp&v=LATEST [3]: https://github.com/jetty-project/jetty-npn - [4]: https://code.google.com/p/vogar/ - [5]: http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.squareup.okhttp&a=mockwebserver&v=LATEST + [4]: https://github.com/jetty-project/jetty-alpn + [5]: https://code.google.com/p/vogar/ + [6]: http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.squareup.okhttp&a=mockwebserver&v=LATEST diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml index 6425e64f1..82ac3e873 100644 --- a/benchmarks/pom.xml +++ b/benchmarks/pom.xml @@ -38,11 +38,6 @@ org.bouncycastle bcprov-jdk15on - - org.mortbay.jetty.npn - npn-boot - provided - org.apache.httpcomponents httpclient @@ -71,28 +66,70 @@ - - org.codehaus.mojo - exec-maven-plugin - - - - java - - - - - java - - -Xms512m - -Xmx512m - -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn.version}/npn-boot-${npn.version}.jar - -classpath - - com.squareup.okhttp.benchmarks.Benchmark - - - + + org.codehaus.mojo + exec-maven-plugin + + + + java + + + + + java + + -Xms512m + -Xmx512m + -Xbootclasspath/p:${bootclasspath} + -classpath + + com.squareup.okhttp.benchmarks.Benchmark + + + + + + npn-when-jdk7 + + 1.7 + + + + org.mortbay.jetty.npn + npn-boot + provided + + + + + alpn-when-jdk8 + + 1.8 + + + + org.mortbay.jetty.alpn + alpn-boot + provided + + + + + + + org.codehaus.mojo + animal-sniffer-maven-plugin + + + none + + + + + + + diff --git a/mockwebserver/pom.xml b/mockwebserver/pom.xml index e02945c93..63ea9e6e5 100644 --- a/mockwebserver/pom.xml +++ b/mockwebserver/pom.xml @@ -22,11 +22,6 @@ org.bouncycastle bcprov-jdk15on - - org.mortbay.jetty.npn - npn-boot - true - junit junit diff --git a/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockWebServer.java b/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockWebServer.java index d7a9064be..988a8ff4c 100644 --- a/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockWebServer.java +++ b/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockWebServer.java @@ -110,7 +110,7 @@ public final class MockWebServer { private int port = -1; private boolean protocolNegotiationEnabled = true; - private List npnProtocols + private List protocols = Util.immutableList(Protocol.HTTP_2, Protocol.SPDY_3, Protocol.HTTP_1_1); public int getPort() { @@ -209,7 +209,7 @@ public final class MockWebServer { if (protocols.contains(null)) { throw new IllegalArgumentException("protocols must not contain null"); } - this.npnProtocols = protocols; + this.protocols = protocols; } /** @@ -351,7 +351,7 @@ public final class MockWebServer { openClientSockets.put(socket, true); if (protocolNegotiationEnabled) { - Platform.get().setProtocols(sslSocket, npnProtocols); + Platform.get().setProtocols(sslSocket, protocols); } sslSocket.startHandshake(); diff --git a/okhttp-tests/pom.xml b/okhttp-tests/pom.xml index ed270e2ac..6ce9c20f8 100644 --- a/okhttp-tests/pom.xml +++ b/okhttp-tests/pom.xml @@ -22,11 +22,6 @@ okhttp ${project.version} - - org.mortbay.jetty.npn - npn-boot - provided - junit diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/CallTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/CallTest.java index 5f273dfe6..0e278700d 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/CallTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/CallTest.java @@ -92,12 +92,12 @@ public final class CallTest { } @Test public void get_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); get(); } @Test public void get_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); get(); } @@ -123,12 +123,12 @@ public final class CallTest { } @Test public void head_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); head(); } @Test public void head_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); head(); } @@ -153,12 +153,12 @@ public final class CallTest { } @Test public void post_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); post(); } @Test public void post_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); post(); } @@ -183,12 +183,12 @@ public final class CallTest { } @Test public void postZeroLength_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); postZeroLength(); } @Test public void postZerolength_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); postZeroLength(); } @@ -213,12 +213,12 @@ public final class CallTest { } @Test public void delete_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); delete(); } @Test public void delete_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); delete(); } @@ -243,12 +243,12 @@ public final class CallTest { } @Test public void put_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); put(); } @Test public void put_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); put(); } @@ -273,12 +273,12 @@ public final class CallTest { } @Test public void patch_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); patch(); } @Test public void patch_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); patch(); } @@ -914,12 +914,12 @@ public final class CallTest { } @Test public void canceledBeforeIOSignalsOnFailure_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); canceledBeforeIOSignalsOnFailure(); } @Test public void canceledBeforeIOSignalsOnFailure_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); canceledBeforeIOSignalsOnFailure(); } @@ -940,12 +940,12 @@ public final class CallTest { } @Test public void canceledBeforeResponseReadSignalsOnFailure_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); canceledBeforeResponseReadSignalsOnFailure(); } @Test public void canceledBeforeResponseReadSignalsOnFailure_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); canceledBeforeResponseReadSignalsOnFailure(); } @@ -989,13 +989,13 @@ public final class CallTest { @Test public void canceledAfterResponseIsDeliveredBreaksStreamButSignalsOnce_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); canceledAfterResponseIsDeliveredBreaksStreamButSignalsOnce(); } @Test public void canceledAfterResponseIsDeliveredBreaksStreamButSignalsOnce_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); canceledAfterResponseIsDeliveredBreaksStreamButSignalsOnce(); } @@ -1006,9 +1006,9 @@ public final class CallTest { /** * Tests that use this will fail unless boot classpath is set. Ex. {@code - * -Xbootclasspath/p:/tmp/npn-boot-1.1.7.v20140316.jar} + * -Xbootclasspath/p:/tmp/alpn-boot-8.0.0.v20140317} */ - private void enableNpn(Protocol protocol) { + private void enableProtocol(Protocol protocol) { client.setSslSocketFactory(sslContext.getSocketFactory()); client.setHostnameVerifier(new RecordingHostnameVerifier()); client.setProtocols(Arrays.asList(protocol, Protocol.HTTP_1_1)); diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java index 197672dc9..42039fae3 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java @@ -647,10 +647,10 @@ public final class URLConnectionTest { assertContent("def", client.open(server.getUrl("/"))); RecordedRequest request1 = server.takeRequest(); - assertEquals("TLSv1", request1.getSslProtocol()); // OkHttp's current best TLS version. + assertTrue(request1.getSslProtocol().startsWith("TLSv1")); // v1.2 on OpenJDK 8. RecordedRequest request2 = server.takeRequest(); - assertEquals("TLSv1", request2.getSslProtocol()); // OkHttp's current best TLS version. + assertTrue(request2.getSslProtocol().startsWith("TLSv1")); // v1.2 on OpenJDK 8. } /** @@ -2745,19 +2745,19 @@ public final class URLConnectionTest { assertTrue(call, call.contains("challenges=[Bearer realm=\"oauthed\"]")); } - @Test public void npnSetsProtocolHeader_SPDY_3() throws Exception { - npnSetsProtocolHeader(Protocol.SPDY_3); + @Test public void setsNegotiatedProtocolHeader_SPDY_3() throws Exception { + setsNegotiatedProtocolHeader(Protocol.SPDY_3); } - @Test public void npnSetsProtocolHeader_HTTP_2() throws Exception { - npnSetsProtocolHeader(Protocol.HTTP_2); + @Test public void setsNegotiatedProtocolHeader_HTTP_2() throws Exception { + setsNegotiatedProtocolHeader(Protocol.HTTP_2); } - private void npnSetsProtocolHeader(Protocol protocol) throws IOException { - enableNpn(protocol); + private void setsNegotiatedProtocolHeader(Protocol protocol) throws IOException { + enableProtocol(protocol); server.enqueue(new MockResponse().setBody("A")); server.play(); - client.setProtocols(Arrays.asList(Protocol.HTTP_1_1, protocol)); + client.setProtocols(Arrays.asList(protocol, Protocol.HTTP_1_1)); connection = client.open(server.getUrl("/")); List protocolValues = connection.getHeaderFields().get(SELECTED_PROTOCOL); assertEquals(Arrays.asList(protocol.toString()), protocolValues); @@ -2786,12 +2786,12 @@ public final class URLConnectionTest { } @Test public void zeroLengthPost_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); zeroLengthPost(); } @Test public void zeroLengthPost_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); zeroLengthPost(); } @@ -2801,12 +2801,12 @@ public final class URLConnectionTest { } @Test public void zeroLengthPut_SPDY_3() throws Exception { - enableNpn(Protocol.SPDY_3); + enableProtocol(Protocol.SPDY_3); zeroLengthPut(); } @Test public void zeroLengthPut_HTTP_2() throws Exception { - enableNpn(Protocol.HTTP_2); + enableProtocol(Protocol.HTTP_2); zeroLengthPut(); } @@ -3113,9 +3113,9 @@ public final class URLConnectionTest { /** * Tests that use this will fail unless boot classpath is set. Ex. {@code - * -Xbootclasspath/p:/tmp/npn-boot-1.1.7.v20140316.jar} + * -Xbootclasspath/p:/tmp/alpn-boot-8.0.0.v20140317} */ - private void enableNpn(Protocol protocol) { + private void enableProtocol(Protocol protocol) { client.setSslSocketFactory(sslContext.getSocketFactory()); client.setHostnameVerifier(new RecordingHostnameVerifier()); client.setProtocols(Arrays.asList(protocol, Protocol.HTTP_1_1)); diff --git a/okhttp/src/main/java/com/squareup/okhttp/Connection.java b/okhttp/src/main/java/com/squareup/okhttp/Connection.java index 5af99e989..e092c2c6e 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/Connection.java +++ b/okhttp/src/main/java/com/squareup/okhttp/Connection.java @@ -51,8 +51,8 @@ import static java.net.HttpURLConnection.HTTP_PROXY_AUTH; * * Unfortunately, older HTTPS servers refuse to connect when such options are * presented. Rather than avoiding these options entirely, this class allows a diff --git a/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java b/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java index 038af2edf..a619be3bb 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java +++ b/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java @@ -321,19 +321,17 @@ public final class OkHttpClient implements URLStreamHandlerFactory, Cloneable { * * *

This is an evolving set. Future releases may drop - * support for transitional protocols (like spdy/3.1), in favor of their - * successors (spdy/4 or hTTP/2). The http/1.1 transport will never be - * dropped. + * support for transitional protocols (like h2-10), in favor of their + * successors (h2). The http/1.1 transport will never be dropped. * *

If multiple protocols are specified, NPN will - * be used to negotiate a transport. Future releases may use another mechanism - * (such as ALPN) - * to negotiate a transport. + * href="https://technotes.googlecode.com/git/nextprotoneg.html">NPN or + * ALPN + * will be used to negotiate a transport. * * @param protocols the protocols to use, in order of preference. The list * must contain {@link Protocol#HTTP_1_1}. It must not contain null. diff --git a/okhttp/src/main/java/com/squareup/okhttp/Protocol.java b/okhttp/src/main/java/com/squareup/okhttp/Protocol.java index 10cf5f461..354d825f8 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/Protocol.java +++ b/okhttp/src/main/java/com/squareup/okhttp/Protocol.java @@ -20,7 +20,8 @@ import java.io.IOException; /** * Protocols that OkHttp implements for NPN and - * ALPN. + * ALPN + * selection. * *

Protocol vs Scheme

* Despite its name, {@link java.net.URL#getProtocol()} returns the diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/Platform.java b/okhttp/src/main/java/com/squareup/okhttp/internal/Platform.java index b411f6a21..c4518fa39 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/Platform.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/Platform.java @@ -45,12 +45,13 @@ import okio.Buffer; * *

NPN (Next Protocol Negotiation) was developed for SPDY. It is widely * available and we support it on both Android (4.1+) and OpenJDK 7 (via the - * Jetty NPN-boot library). NPN is not yet available on Java 8. + * Jetty Alpn-boot library). NPN is not yet available on OpenJDK 8. * *

ALPN (Application Layer Protocol Negotiation) is the successor to NPN. It * has some technical advantages over NPN. ALPN first arrived in Android 4.4, * but that release suffers a concurrency bug - * so we don't use it. ALPN will be supported in the future. + * so we don't use it. ALPN is supported on OpenJDK 7 and 8 (via the Jetty + * ALPN-boot library). * *

On platforms that support both extensions, OkHttp will use both, * preferring ALPN's result. Future versions of OkHttp will drop support for @@ -148,21 +149,24 @@ public class Platform { // This isn't Android 2.3 or better. } - // Attempt to find the Jetty's NPN extension for OpenJDK. - try { - String npnClassName = "org.eclipse.jetty.npn.NextProtoNego"; - Class nextProtoNegoClass = Class.forName(npnClassName); - Class providerClass = Class.forName(npnClassName + "$Provider"); - Class clientProviderClass = Class.forName(npnClassName + "$ClientProvider"); - Class serverProviderClass = Class.forName(npnClassName + "$ServerProvider"); - Method putMethod = nextProtoNegoClass.getMethod("put", SSLSocket.class, providerClass); - Method getMethod = nextProtoNegoClass.getMethod("get", SSLSocket.class); - return new JdkWithJettyNpnPlatform( + try { // to find the Jetty's ALPN or NPN extension for OpenJDK. + String negoClassName = "org.eclipse.jetty.alpn.ALPN"; + Class negoClass; + try { + negoClass = Class.forName(negoClassName); + } catch (ClassNotFoundException ignored) { // ALPN isn't on the classpath. + negoClassName = "org.eclipse.jetty.npn.NextProtoNego"; + negoClass = Class.forName(negoClassName); + } + Class providerClass = Class.forName(negoClassName + "$Provider"); + Class clientProviderClass = Class.forName(negoClassName + "$ClientProvider"); + Class serverProviderClass = Class.forName(negoClassName + "$ServerProvider"); + Method putMethod = negoClass.getMethod("put", SSLSocket.class, providerClass); + Method getMethod = negoClass.getMethod("get", SSLSocket.class); + return new JdkWithJettyBootPlatform( putMethod, getMethod, clientProviderClass, serverProviderClass); - } catch (ClassNotFoundException ignored) { - // NPN isn't on the classpath. - } catch (NoSuchMethodException ignored) { - // The NPN version isn't what we expect. + } catch (ClassNotFoundException ignored) { // NPN isn't on the classpath. + } catch (NoSuchMethodException ignored) { // The ALPN or NPN version isn't what we expect. } return new Platform(); @@ -247,15 +251,18 @@ public class Platform { } } - /** OpenJDK 7 plus {@code org.mortbay.jetty.npn/npn-boot} on the boot class path. */ - private static class JdkWithJettyNpnPlatform extends Platform { + /** + * OpenJDK 7+ with {@code org.mortbay.jetty.npn/npn-boot} or + * {@code org.mortbay.jetty.alpn/alpn-boot} in the boot class path. + */ + private static class JdkWithJettyBootPlatform extends Platform { private final Method getMethod; private final Method putMethod; private final Class clientProviderClass; private final Class serverProviderClass; - public JdkWithJettyNpnPlatform(Method putMethod, Method getMethod, Class clientProviderClass, - Class serverProviderClass) { + public JdkWithJettyBootPlatform(Method putMethod, Method getMethod, + Class clientProviderClass, Class serverProviderClass) { this.putMethod = putMethod; this.getMethod = getMethod; this.clientProviderClass = clientProviderClass; @@ -267,11 +274,11 @@ public class Platform { List names = new ArrayList(protocols.size()); for (int i = 0, size = protocols.size(); i < size; i++) { Protocol protocol = protocols.get(i); - if (protocol == Protocol.HTTP_1_0) continue; // No HTTP/1.0 for NPN. + if (protocol == Protocol.HTTP_1_0) continue; // No HTTP/1.0 for NPN or ALPN. names.add(protocol.toString()); } Object provider = Proxy.newProxyInstance(Platform.class.getClassLoader(), - new Class[] { clientProviderClass, serverProviderClass }, new JettyNpnProvider(names)); + new Class[] { clientProviderClass, serverProviderClass }, new JettyNegoProvider(names)); putMethod.invoke(null, socket, provider); } catch (InvocationTargetException e) { throw new AssertionError(e); @@ -282,12 +289,12 @@ public class Platform { @Override public String getSelectedProtocol(SSLSocket socket) { try { - JettyNpnProvider provider = - (JettyNpnProvider) Proxy.getInvocationHandler(getMethod.invoke(null, socket)); + JettyNegoProvider provider = + (JettyNegoProvider) Proxy.getInvocationHandler(getMethod.invoke(null, socket)); if (!provider.unsupported && provider.selected == null) { Logger logger = Logger.getLogger("com.squareup.okhttp.OkHttpClient"); - logger.log(Level.INFO, - "NPN callback dropped so SPDY is disabled. Is npn-boot on the boot class path?"); + logger.log(Level.INFO, "NPN/ALPN callback dropped: SPDY and HTTP/2 are disabled. " + + "Is npn-boot or alpn-boot on the boot class path?"); return null; } return provider.unsupported ? null : provider.selected; @@ -300,18 +307,18 @@ public class Platform { } /** - * Handle the methods of NextProtoNego's ClientProvider and ServerProvider + * Handle the methods of NPN or ALPN's ClientProvider and ServerProvider * without a compile-time dependency on those interfaces. */ - private static class JettyNpnProvider implements InvocationHandler { + private static class JettyNegoProvider implements InvocationHandler { /** This peer's supported protocols. */ private final List protocols; - /** Set when remote peer notifies NPN is unsupported. */ + /** Set when remote peer notifies NPN or ALPN is unsupported. */ private boolean unsupported; - /** The protocol the client selected. */ + /** The protocol the client (NPN) or server (ALPN) selected. */ private String selected; - public JettyNpnProvider(List protocols) { + public JettyNegoProvider(List protocols) { this.protocols = protocols; } @@ -322,27 +329,25 @@ public class Platform { args = Util.EMPTY_STRING_ARRAY; } if (methodName.equals("supports") && boolean.class == returnType) { - return true; // Client supports NPN. + return true; // NPN or ALPN is supported. } else if (methodName.equals("unsupported") && void.class == returnType) { - this.unsupported = true; // Remote peer doesn't support NPN. + this.unsupported = true; // Peer doesn't support NPN or ALPN. return null; } else if (methodName.equals("protocols") && args.length == 0) { - return protocols; // Server advertises these protocols. - } else if (methodName.equals("selectProtocol") // Called when client. - && String.class == returnType - && args.length == 1 - && (args[0] == null || args[0] instanceof List)) { - List serverProtocols = (List) args[0]; - // Pick the first protocol the server advertises and client knows. - for (int i = 0, size = serverProtocols.size(); i < size; i++) { - if (protocols.contains(serverProtocols.get(i))) { - return selected = serverProtocols.get(i); + return protocols; // Server (NPN) or Client (ALPN) advertises these protocols. + } else if ((methodName.equals("selectProtocol") || methodName.equals("select")) + && String.class == returnType && args.length == 1 && args[0] instanceof List) { + List peerProtocols = (List) args[0]; + // Pick the first known protocol the peer advertises. + for (int i = 0, size = peerProtocols.size(); i < size; i++) { + if (protocols.contains(peerProtocols.get(i))) { + return selected = peerProtocols.get(i); } } - // On no intersection, try client's first protocol. - return selected = protocols.get(0); - } else if (methodName.equals("protocolSelected") && args.length == 1) { - this.selected = (String) args[0]; // Client selected this protocol. + return selected = protocols.get(0); // On no intersection, try peer's first protocol. + } else if ((methodName.equals("protocolSelected") || methodName.equals("selected")) + && args.length == 1) { + this.selected = (String) args[0]; // Client (NPN) or Server (ALPN) selected this protocol. return null; } else { return method.invoke(this, args); diff --git a/pom.xml b/pom.xml index 32c29ed0a..96155c9b5 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,8 @@ 0.8.0 1.1.7.v20140316 + + 8.0.0.v20140317 1.48 2.2.3 4.2.2 @@ -72,15 +74,20 @@ okio ${okio.version} + + junit + junit + ${junit.version} + org.mortbay.jetty.npn npn-boot ${npn.version} - junit - junit - ${junit.version} + org.mortbay.jetty.alpn + alpn-boot + ${alpn.version} org.bouncycastle @@ -126,15 +133,12 @@ org.apache.maven.plugins maven-surefire-plugin - 2.16 - - -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn.version}/npn-boot-${npn.version}.jar - + 2.17 org.apache.maven.surefire surefire-junit47 - 2.16 + 2.17 @@ -185,7 +189,7 @@ org.codehaus.mojo animal-sniffer-maven-plugin - 1.10 + 1.11 test @@ -204,5 +208,66 @@ + + + + npn-when-jdk7 + + 1.7 + + + ${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn.version}/npn-boot-${npn.version}.jar + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Xbootclasspath/p:${bootclasspath} + + + + org.mortbay.jetty.npn + npn-boot + ${npn.version} + + + + + + + + + alpn-when-jdk8 + + 1.8 + + + ${settings.localRepository}/org/mortbay/jetty/alpn/alpn-boot/${alpn.version}/alpn-boot-${alpn.version}.jar + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Xbootclasspath/p:${bootclasspath} + + + + org.mortbay.jetty.alpn + alpn-boot + ${alpn.version} + + + + + + + + diff --git a/website/index.html b/website/index.html index ee1e55c06..e9ccd189b 100644 --- a/website/index.html +++ b/website/index.html @@ -58,7 +58,7 @@ common connection problems. If your service has multiple IP addresses OkHttp will attempt alternate addresses if the first connect fails. This is necessary for IPv4+IPv6 and for services hosted in redundant data centers. OkHttp initiates new connections - with modern TLS features (SNI, NPN), and falls back to SSLv3 if the handshake + with modern TLS features (SNI, ALPN), and falls back to SSLv3 if the handshake fails.

You can try OkHttp without rewriting your network code. The core module implements