Skip to content

Commit

Permalink
Merge pull request #4678 from eclipse/jetty-9.4.x-4443-alpn-backport-…
Browse files Browse the repository at this point in the history
…8u252

Issue #4443 - Track backport of ALPN APIs to Java 8.
  • Loading branch information
sbordet authored Mar 18, 2020
2 parents 785b640 + 1be2f47 commit 91c1b52
Show file tree
Hide file tree
Showing 97 changed files with 289 additions and 634 deletions.
2 changes: 1 addition & 1 deletion examples/embedded/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@
<profile>
<id>jdk9</id>
<activation>
<jdk>[1.9,)</jdk>
<jdk>[9,)</jdk>
</activation>
<dependencies>
<dependency>
Expand Down
4 changes: 2 additions & 2 deletions jetty-alpn/jetty-alpn-java-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.9</source>
<target>1.9</target>
<source>9</source>
<target>9</target>
<release>9</release>
</configuration>
</plugin>
Expand Down
9 changes: 2 additions & 7 deletions jetty-alpn/jetty-alpn-java-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.9</source>
<target>1.9</target>
<source>9</source>
<target>9</target>
<release>9</release>
</configuration>
</plugin>
Expand All @@ -46,11 +46,6 @@
<artifactId>jetty-io</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.alpn</groupId>
<artifactId>alpn-api</artifactId>
<version>${alpn.api.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-server</artifactId>
Expand Down
1 change: 1 addition & 0 deletions jetty-alpn/jetty-alpn-openjdk8-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<groupId>org.eclipse.jetty.alpn</groupId>
<artifactId>alpn-api</artifactId>
<version>${alpn.api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,20 @@

package org.eclipse.jetty.alpn.openjdk8.client;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLParameters;

import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.alpn.client.ALPNClientConnection;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.ssl.ALPNProcessor;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.io.ssl.SslHandshakeListener;
import org.eclipse.jetty.util.JavaVersion;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
Expand All @@ -33,11 +40,31 @@ public class OpenJDK8ClientALPNProcessor implements ALPNProcessor.Client
{
private static final Logger LOG = Log.getLogger(OpenJDK8ClientALPNProcessor.class);

private Method alpnProtocols;
private Method alpnProtocol;

@Override
public void init()
{
if (JavaVersion.VERSION.getPlatform() != 8)
throw new IllegalStateException(this + " not applicable for java " + JavaVersion.VERSION);

try
{
// JDK 8u252 has the JDK 9 ALPN API backported.
// Use reflection so we can build with a JDK version less than 8u252.
alpnProtocols = SSLParameters.class.getMethod("setApplicationProtocols", String[].class);
alpnProtocol = SSLEngine.class.getMethod("getApplicationProtocol");
if (LOG.isDebugEnabled())
LOG.debug("Using OpenJDK ALPN APIs instead of Jetty ALPN APIs");
return;
}
catch (NoSuchMethodException x)
{
LOG.ignore(x);
}

// Backported ALPN APIs not available.
if (ALPN.class.getClassLoader() != null)
throw new IllegalStateException(ALPN.class.getName() + " must be on JVM boot classpath");
if (LOG.isDebugEnabled())
Expand All @@ -53,14 +80,34 @@ public boolean appliesTo(SSLEngine sslEngine)
@Override
public void configure(SSLEngine sslEngine, Connection connection)
{
connection.addListener(new ALPNListener((ALPNClientConnection)connection));
ALPNClientConnection alpnConnection = (ALPNClientConnection)connection;
if (alpnProtocols == null)
{
connection.addListener(new ALPNConnectionListener(alpnConnection));
}
else
{
try
{
Object protocols = alpnConnection.getProtocols().toArray(new String[0]);
SSLParameters sslParameters = sslEngine.getSSLParameters();
alpnProtocols.invoke(sslParameters, protocols);
sslEngine.setSSLParameters(sslParameters);
((SslConnection.DecryptedEndPoint)connection.getEndPoint()).getSslConnection()
.addHandshakeListener(new ALPNSSLListener(alpnConnection));
}
catch (IllegalAccessException | InvocationTargetException x)
{
throw new IllegalStateException(this + " unable to set ALPN protocols", x);
}
}
}

private final class ALPNListener implements ALPN.ClientProvider, Connection.Listener
private static final class ALPNConnectionListener implements ALPN.ClientProvider, Connection.Listener
{
private final ALPNClientConnection alpnConnection;

private ALPNListener(ALPNClientConnection connection)
private ALPNConnectionListener(ALPNClientConnection connection)
{
alpnConnection = connection;
}
Expand Down Expand Up @@ -102,4 +149,32 @@ public void selected(String protocol)
alpnConnection.selected(protocol);
}
}

private final class ALPNSSLListener implements SslHandshakeListener
{
private final ALPNClientConnection alpnConnection;

private ALPNSSLListener(ALPNClientConnection connection)
{
alpnConnection = connection;
}

@Override
public void handshakeSucceeded(Event event) throws SSLException
{
try
{
SSLEngine sslEngine = alpnConnection.getSSLEngine();
String protocol = (String)alpnProtocol.invoke(sslEngine);
if (LOG.isDebugEnabled())
LOG.debug("selected protocol {}", protocol);
alpnConnection.selected(protocol);
}
catch (IllegalAccessException | InvocationTargetException x)
{
SSLHandshakeException failure = new SSLHandshakeException(this + " unable to get ALPN protocol");
throw (SSLHandshakeException)failure.initCause(x);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@

package org.eclipse.jetty.alpn.openjdk8.server;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.function.BiFunction;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;

import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.alpn.server.ALPNServerConnection;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.ssl.ALPNProcessor;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.io.ssl.SslHandshakeListener;
import org.eclipse.jetty.util.JavaVersion;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
Expand All @@ -35,11 +39,29 @@ public class OpenJDK8ServerALPNProcessor implements ALPNProcessor.Server
{
private static final Logger LOG = Log.getLogger(OpenJDK8ServerALPNProcessor.class);

private Method alpnSelector;

@Override
public void init()
{
if (JavaVersion.VERSION.getPlatform() != 8)
throw new IllegalStateException(this + " not applicable for java " + JavaVersion.VERSION);

try
{
// JDK 8u252 has the JDK 9 ALPN API backported.
// Use reflection so we can build with a JDK version less than 8u252.
alpnSelector = SSLEngine.class.getMethod("setHandshakeApplicationProtocolSelector", BiFunction.class);
if (LOG.isDebugEnabled())
LOG.debug("Using OpenJDK ALPN APIs instead of Jetty ALPN APIs");
return;
}
catch (NoSuchMethodException x)
{
LOG.ignore(x);
}

// Backported ALPN APIs not available.
if (ALPN.class.getClassLoader() != null)
throw new IllegalStateException(ALPN.class.getName() + " must be on JVM boot classpath");
if (LOG.isDebugEnabled())
Expand All @@ -55,10 +77,26 @@ public boolean appliesTo(SSLEngine sslEngine)
@Override
public void configure(SSLEngine sslEngine, Connection connection)
{
connection.addListener(new ALPNListener((ALPNServerConnection)connection));
if (alpnSelector == null)
{
ALPNListener listener = new ALPNListener((ALPNServerConnection)connection);
connection.addListener(listener);
}
else
{
try
{
ALPNCallback callback = new ALPNCallback((ALPNServerConnection)connection);
alpnSelector.invoke(sslEngine, callback);
}
catch (IllegalAccessException | InvocationTargetException x)
{
throw new IllegalStateException(this + " unable to set ALPN selector", x);
}
}
}

private final class ALPNListener implements ALPN.ServerProvider, Connection.Listener
private static final class ALPNListener implements ALPN.ServerProvider, Connection.Listener
{
private final ALPNServerConnection alpnConnection;

Expand Down Expand Up @@ -92,12 +130,58 @@ public void unsupported()
}

@Override
public String select(List<String> protocols) throws SSLException
public String select(List<String> protocols)
{
if (LOG.isDebugEnabled())
LOG.debug("select {} {}", alpnConnection, protocols);
alpnConnection.select(protocols);
return alpnConnection.getProtocol();
}
}

private static class ALPNCallback implements BiFunction<SSLEngine, List<String>, String>, SslHandshakeListener
{
private final ALPNServerConnection alpnConnection;

private ALPNCallback(ALPNServerConnection connection)
{
alpnConnection = connection;
((SslConnection.DecryptedEndPoint)alpnConnection.getEndPoint()).getSslConnection().addHandshakeListener(this);
}

@Override
public String apply(SSLEngine engine, List<String> protocols)
{
try
{
if (LOG.isDebugEnabled())
LOG.debug("apply {} {}", alpnConnection, protocols);
alpnConnection.select(protocols);
return alpnConnection.getProtocol();
}
catch (Throwable x)
{
// Cannot negotiate the protocol, return null to have
// JSSE send Alert.NO_APPLICATION_PROTOCOL to the client.
return null;
}
}

@Override
public void handshakeSucceeded(Event event)
{
String protocol = alpnConnection.getProtocol();
if (LOG.isDebugEnabled())
LOG.debug("TLS handshake succeeded, protocol={} for {}", protocol, alpnConnection);
if (protocol == null)
alpnConnection.unsupported();
}

@Override
public void handshakeFailed(Event event, Throwable failure)
{
if (LOG.isDebugEnabled())
LOG.debug("TLS handshake failed " + alpnConnection, failure);
}
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit 91c1b52

Please sign in to comment.