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;
*
* - Server Name Indication (SNI) enables one IP address to negotiate secure
* connections for multiple domain names.
- *
- Next Protocol Negotiation (NPN) enables the HTTPS port (443) to be used
- * for both HTTP and SPDY protocols.
+ *
- Application Layer Protocol Negotiation (ALPN) enables the HTTPS port
+ * (443) to be used for different HTTP and SPDY protocols.
*
* 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