Skip to content

Commit

Permalink
Issue #4443 - Track backport of ALPN APIs to Java 8.
Browse files Browse the repository at this point in the history
Modified jetty-alpn-openjdk8-* classes to support both
pre 8u252 (via alpn-boot) and post 8u252 (via standard API).

Replaced usages of -Xbootclasspath with -javaagent, and
using Jetty ALPN Agent jar rather than Jetty ALPN boot jar.

Removed all alpn-1.8.0*.mod files since now it is
possible to use a fixed version of the ALPN Agent
to cover all the versions.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
  • Loading branch information
sbordet committed Mar 17, 2020
1 parent 32c9981 commit 9bb92f8
Show file tree
Hide file tree
Showing 97 changed files with 286 additions and 1,189 deletions.
2 changes: 1 addition & 1 deletion examples/embedded/pom.xml
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
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
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
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
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,28 @@ 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");
return;
}
catch (NoSuchMethodException ignored)
{
}

// 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 +77,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 +146,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);
}
}
}
}
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,26 @@ 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);
return;
}
catch (NoSuchMethodException ignored)
{
}

// 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 +74,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 +127,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.

This file was deleted.

0 comments on commit 9bb92f8

Please sign in to comment.