Issue #215 Conscrypt module for SSL and ALPN
Squash of the following commits: commit 53e503b48d290e2ff83b214fd81572bf4cacd9ab Merge: cc4ed73d77ba82
Author: Greg Wilkins <gregw@webtide.com> Date: Thu Sep 21 07:27:45 2017 +1000 Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-9.4.x-215-conscrypt-alpn commit cc4ed73ae45e69addbb31221a860dd0984d92ac5 Author: Greg Wilkins <gregw@webtide.com> Date: Thu Sep 21 07:26:45 2017 +1000 Issue #215 Conscrypt module debug commit f640693f7ef61f8012d1454b2ed364740b330a6e Author: Simone Bordet <simone.bordet@gmail.com> Date: Wed Sep 20 18:23:51 2017 +0200 Issue #215 - Consider native ALPN/SSL provider. Fixed server-side ALPN negotiation for Conscrypt. commit 669e992624a0f8f23103c70ba895b877dcec2404 Author: Simone Bordet <simone.bordet@gmail.com> Date: Wed Sep 20 16:56:20 2017 +0200 Issue #215 - Consider native ALPN/SSL provider. Fixed client-side ALPN negotiation for Conscrypt. commit aa873263d73c19461890bd1f9a417c796412b3d2 Author: Simone Bordet <simone.bordet@gmail.com> Date: Wed Sep 20 15:26:45 2017 +0200 Issue #215 - Consider native ALPN/SSL provider. Code cleanups. Changed ALPNProcessor.init(boolean) to init(). Removed unnecessary try/catches and simplified exception handling. commit db9b169c35da956bcc42013f9bb8acddd7238d14 Author: Greg Wilkins <gregw@webtide.com> Date: Wed Sep 20 18:07:30 2017 +1000 Issue #215 Conscrypt SSL pom cleanups commit 096572e029352428275e86a964fa92dbeee19a65 Author: Greg Wilkins <gregw@webtide.com> Date: Wed Sep 20 15:57:20 2017 +1000 Issue #215 Conscrypt SSL ALPN cleanups commit b3c1bcb1fa9a7e15517a348270738e24c7b0a820 Merge: c836708effec06
Author: Greg Wilkins <gregw@webtide.com> Date: Wed Sep 20 15:46:13 2017 +1000 Merge branch 'jetty-9.4.x' into jetty-9.4.x-215-conscrypt-alpn commit c836708a9bcd5fb61ed26302eb7d71b618cce329 Merge: de039d4d9ecd5e
Author: Greg Wilkins <gregw@webtide.com> Date: Wed Sep 20 14:56:06 2017 +1000 Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-9.4.x-215-conscrypt-alpn commit de039d42f23f9caa239e5ddee0242b9a83a45441 Author: Greg Wilkins <gregw@webtide.com> Date: Tue Sep 19 17:19:49 2017 +1000 Fix #1823 MimeTypes for ResourceHandler mp4 commit ff1e08434415cd6d909715547c2a54dbd0fc5dee Author: Greg Wilkins <gregw@webtide.com> Date: Tue Sep 19 14:21:39 2017 +1000 Issue #215 commit 3bb63147ebf4967698f51a65f009d80010038b20 Author: Greg Wilkins <gregw@webtide.com> Date: Tue Sep 19 14:08:05 2017 +1000 Issue #215 Use conscrypt 1.0.0.RC10 uber jar commit 8b18099fde67f12d0e98d0b414568c9b76835459 Merge: 06f6530eee4117
Author: Greg Wilkins <gregw@webtide.com> Date: Tue Sep 19 10:35:43 2017 +1000 Merge branch 'jetty-9.4.x' into jetty-9.4.x-conscrypt-alpn commit 06f65305d536250c5dfa2aaa84ffacdac113c8fc Author: Greg Wilkins <gregw@webtide.com> Date: Thu Sep 14 16:04:05 2017 +1000 Issue #215 Conscrypt ALPN provider First attempt at client support commit 32d77461935263da86fb363233af0aa5a159d1fc Author: Greg Wilkins <gregw@webtide.com> Date: Thu Sep 14 09:48:43 2017 +1000 Issue #215 Conscrypt ALPN provider commit bc051dca5e3ea7fed6ddb3a25ba5cecbd1c5b18b Merge: 573c9f06c47126
Author: Greg Wilkins <gregw@webtide.com> Date: Thu Sep 14 08:49:10 2017 +1000 Merge branch 'jetty-9.4.x' into jetty-9.4.x-conscrypt-alpn commit 573c9f060172b2863b0b0a94c1ec2fb9a8762fa2 Merge: 47e22fe3399fd3
Author: Greg Wilkins <gregw@webtide.com> Date: Wed Sep 13 15:24:27 2017 +1000 Merge branch 'jetty-9.4.x' into jetty-9.4.x-conscrypt-alpn commit 47e22fe2e4f8e3cc71f3117ad7d789dc3ea56675 Merge: 63ffa2b187f37d
Author: Greg Wilkins <gregw@webtide.com> Date: Wed Sep 13 11:04:24 2017 +1000 Merge branch 'jetty-9.4.x' into jetty-9.4.x-conscrypt-alpn commit 63ffa2bdc13fa85d02459855a3f8e0de4f4b4f1b Merge: cf1443da0cb424
Author: Greg Wilkins <gregw@webtide.com> Date: Tue Sep 12 09:04:45 2017 +1000 Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-9.4.x-conscrypt-alpn commit cf1443d3ab71ac1aec7f153c233e869a3d6f783f Author: Greg Wilkins <gregw@webtide.com> Date: Tue Sep 12 09:03:52 2017 +1000 Issue #215 Conscrypt ALPN provider commit a37aec327274042e1007f4146a3c3ec06fb424d9 Author: Greg Wilkins <gregw@webtide.com> Date: Thu Sep 7 21:19:28 2017 +1000 Issue #215 Conscrypt ALPN provider commit 6d7f39b2b0e53570afa61be5abfef2a352f80cf3 Author: Greg Wilkins <gregw@webtide.com> Date: Thu Sep 7 18:22:19 2017 +1000 Issue #215 Conscrypt ALPN provider commit a7d0f46b57091550724242693559d786180896ff Author: Greg Wilkins <gregw@webtide.com> Date: Thu Sep 7 18:16:35 2017 +1000 Issue #215 Conscrypt ALPN provider
This commit is contained in:
parent
d77ba8203a
commit
31a9b6f2e8
|
@ -75,6 +75,16 @@
|
|||
<artifactId>jetty-alpn-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-openjdk8-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-conscrypt-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-annotations</artifactId>
|
||||
|
@ -131,4 +141,20 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>jdk9</id>
|
||||
<activation>
|
||||
<jdk>[1.9,)</jdk>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-java-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
|
||||
package org.eclipse.jetty.embedded;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Date;
|
||||
import java.util.EnumSet;
|
||||
|
||||
|
@ -72,7 +74,10 @@ public class Http2Server
|
|||
server.addBean(mbContainer);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler(server, "/",ServletContextHandler.SESSIONS);
|
||||
context.setResourceBase("src/main/resources/docroot");
|
||||
String docroot = "src/main/resources/docroot";
|
||||
if (!new File(docroot).exists())
|
||||
docroot = "examples/embedded/src/main/resources/docroot";
|
||||
context.setResourceBase(docroot);
|
||||
context.addFilter(PushCacheFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST));
|
||||
// context.addFilter(PushSessionCacheFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST));
|
||||
context.addFilter(PushedTilesFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST));
|
||||
|
@ -94,11 +99,14 @@ public class Http2Server
|
|||
|
||||
// SSL Context Factory for HTTPS and HTTP/2
|
||||
String jetty_distro = System.getProperty("jetty.distro","../../jetty-distribution/target/distribution");
|
||||
if (!new File(jetty_distro).exists())
|
||||
jetty_distro = "jetty-distribution/target/distribution";
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
sslContextFactory.setKeyStorePath(jetty_distro + "/demo-base/etc/keystore");
|
||||
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
|
||||
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
|
||||
sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR);
|
||||
// sslContextFactory.setProvider("Conscrypt");
|
||||
|
||||
// HTTPS Configuration
|
||||
HttpConfiguration https_config = new HttpConfiguration(http_config);
|
||||
|
|
|
@ -8,3 +8,4 @@
|
|||
#org.eclipse.jetty.io.ssl.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.server.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.servlets.LEVEL=DEBUG
|
||||
org.eclipse.jetty.alpn.LEVEL=DEBUG
|
||||
|
|
|
@ -50,12 +50,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>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -24,14 +24,13 @@ import java.util.concurrent.Executor;
|
|||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import org.eclipse.jetty.alpn.ALPN;
|
||||
import org.eclipse.jetty.io.ClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.NegotiatingClientConnection;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
public class ALPNClientConnection extends NegotiatingClientConnection implements ALPN.ClientProvider
|
||||
public class ALPNClientConnection extends NegotiatingClientConnection
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ALPNClientConnection.class);
|
||||
|
||||
|
@ -41,41 +40,18 @@ public class ALPNClientConnection extends NegotiatingClientConnection implements
|
|||
{
|
||||
super(endPoint, executor, sslEngine, connectionFactory, context);
|
||||
this.protocols = protocols;
|
||||
ALPN.put(sslEngine, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported()
|
||||
{
|
||||
ALPN.remove(getSSLEngine());
|
||||
completed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> protocols()
|
||||
public List<String> getProtocols()
|
||||
{
|
||||
return protocols;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selected(String protocol)
|
||||
{
|
||||
if (protocols.contains(protocol))
|
||||
{
|
||||
ALPN.remove(getSSLEngine());
|
||||
completed();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.info("Could not negotiate protocol: server [{}] - client {}", protocol, protocols);
|
||||
if (protocol==null || !protocols.contains(protocol))
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
ALPN.remove(getSSLEngine());
|
||||
super.close();
|
||||
else
|
||||
super.completed();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
package org.eclipse.jetty.alpn.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
@ -31,17 +31,19 @@ import org.eclipse.jetty.io.ClientConnectionFactory;
|
|||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.NegotiatingClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.ssl.ALPNProcessor;
|
||||
import org.eclipse.jetty.io.ssl.ALPNProcessor.Client;
|
||||
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.ssl.SslHandshakeListener;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
public class ALPNClientConnectionFactory extends NegotiatingClientConnectionFactory implements SslHandshakeListener
|
||||
{
|
||||
private final SslHandshakeListener alpnListener = new ALPNListener();
|
||||
private static final Logger LOG = Log.getLogger(ALPNClientConnectionFactory.class);
|
||||
|
||||
private final List<Client> processors = new ArrayList<>();
|
||||
private final Executor executor;
|
||||
private final List<String> protocols;
|
||||
private final ALPNProcessor.Client alpnProcessor;
|
||||
|
||||
public ALPNClientConnectionFactory(Executor executor, ClientConnectionFactory connectionFactory, List<String> protocols)
|
||||
{
|
||||
|
@ -50,39 +52,49 @@ public class ALPNClientConnectionFactory extends NegotiatingClientConnectionFact
|
|||
throw new IllegalArgumentException("ALPN protocol list cannot be empty");
|
||||
this.executor = executor;
|
||||
this.protocols = protocols;
|
||||
Iterator<ALPNProcessor.Client> processors = ServiceLoader.load(ALPNProcessor.Client.class).iterator();
|
||||
alpnProcessor = processors.hasNext() ? processors.next() : ALPNProcessor.Client.NOOP;
|
||||
|
||||
IllegalStateException failure = new IllegalStateException("No Client ALPNProcessors!");
|
||||
for (Client processor : ServiceLoader.load(Client.class))
|
||||
{
|
||||
try
|
||||
{
|
||||
processor.init();
|
||||
processors.add(processor);
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Could not initialize " + processor, x);
|
||||
failure.addSuppressed(x);
|
||||
}
|
||||
}
|
||||
|
||||
public ALPNProcessor.Client getALPNProcessor()
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
return alpnProcessor;
|
||||
LOG.debug("protocols: {}", protocols);
|
||||
LOG.debug("processors: {}", processors);
|
||||
}
|
||||
|
||||
if (processors.isEmpty())
|
||||
throw failure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException
|
||||
{
|
||||
SSLEngine sslEngine = (SSLEngine)context.get(SslClientConnectionFactory.SSL_ENGINE_CONTEXT_KEY);
|
||||
getALPNProcessor().configure(sslEngine, protocols);
|
||||
ContainerLifeCycle connector = (ContainerLifeCycle)context.get(ClientConnectionFactory.CONNECTOR_CONTEXT_KEY);
|
||||
// Method addBean() has set semantic, so the listener is added only once.
|
||||
connector.addBean(alpnListener);
|
||||
SSLEngine engine = (SSLEngine)context.get(SslClientConnectionFactory.SSL_ENGINE_CONTEXT_KEY);
|
||||
for (Client processor : processors)
|
||||
{
|
||||
if (processor.appliesTo(engine))
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} for {} on {}", processor, engine, endPoint);
|
||||
ALPNClientConnection connection = new ALPNClientConnection(endPoint, executor, getClientConnectionFactory(),
|
||||
sslEngine, context, protocols);
|
||||
engine, context, protocols);
|
||||
processor.configure(engine, connection);
|
||||
return customize(connection, context);
|
||||
}
|
||||
|
||||
private class ALPNListener implements SslHandshakeListener
|
||||
{
|
||||
@Override
|
||||
public void handshakeSucceeded(Event event)
|
||||
{
|
||||
getALPNProcessor().process(event.getSSLEngine());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeFailed(Event event, Throwable failure)
|
||||
{
|
||||
}
|
||||
throw new IllegalStateException("No ALPNProcessor for " + engine);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-alpn-conscrypt-client</artifactId>
|
||||
<name>Jetty :: ALPN :: Conscrypt Client Implementation</name>
|
||||
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.alpn.java.client</bundle-symbolic-name>
|
||||
<conscrypt.version>1.0.0.RC10</conscrypt.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.conscrypt</groupId>
|
||||
<artifactId>conscrypt-openjdk-uber</artifactId>
|
||||
<version>${conscrypt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,107 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.alpn.conscrypt.client;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Security;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import org.conscrypt.OpenSSLProvider;
|
||||
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.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
public class ConscryptClientALPNProcessor implements ALPNProcessor.Client
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ConscryptClientALPNProcessor.class);
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
if (Security.getProvider("Conscrypt")==null)
|
||||
{
|
||||
Security.addProvider(new OpenSSLProvider());
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Added Conscrypt provider");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appliesTo(SSLEngine sslEngine)
|
||||
{
|
||||
return sslEngine.getClass().getName().startsWith("org.conscrypt.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(SSLEngine sslEngine, Connection connection)
|
||||
{
|
||||
try
|
||||
{
|
||||
Method setAlpnProtocols = sslEngine.getClass().getDeclaredMethod("setAlpnProtocols", String[].class);
|
||||
setAlpnProtocols.setAccessible(true);
|
||||
ALPNClientConnection alpn = (ALPNClientConnection)connection;
|
||||
String[] protocols = alpn.getProtocols().toArray(new String[0]);
|
||||
setAlpnProtocols.invoke(sslEngine, (Object)protocols);
|
||||
((SslConnection.DecryptedEndPoint)connection.getEndPoint()).getSslConnection()
|
||||
.addHandshakeListener(new ALPNListener(alpn));
|
||||
}
|
||||
catch (RuntimeException x)
|
||||
{
|
||||
throw x;
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
}
|
||||
|
||||
private final class ALPNListener implements SslHandshakeListener
|
||||
{
|
||||
private final ALPNClientConnection alpnConnection;
|
||||
|
||||
private ALPNListener(ALPNClientConnection connection)
|
||||
{
|
||||
alpnConnection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeSucceeded(Event event)
|
||||
{
|
||||
try
|
||||
{
|
||||
SSLEngine sslEngine = alpnConnection.getSSLEngine();
|
||||
Method method = sslEngine.getClass().getDeclaredMethod("getAlpnSelectedProtocol");
|
||||
method.setAccessible(true);
|
||||
String protocol = new String((byte[])method.invoke(sslEngine), StandardCharsets.US_ASCII);
|
||||
alpnConnection.selected(protocol);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
alpnConnection.selected(null);
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.eclipse.jetty.alpn.conscrypt.client.ConscryptClientALPNProcessor
|
|
@ -0,0 +1,89 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.alpn.java.client;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.Security;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.conscrypt.OpenSSLProvider;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.api.Session;
|
||||
import org.eclipse.jetty.http2.api.Stream;
|
||||
import org.eclipse.jetty.http2.client.HTTP2Client;
|
||||
import org.eclipse.jetty.http2.frames.DataFrame;
|
||||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.FuturePromise;
|
||||
import org.eclipse.jetty.util.Jetty;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
public class ConscryptHTTP2Client
|
||||
{
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
Security.addProvider(new OpenSSLProvider());
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
sslContextFactory.setProvider("Conscrypt");
|
||||
HTTP2Client client = new HTTP2Client();
|
||||
client.addBean(sslContextFactory);
|
||||
client.start();
|
||||
|
||||
String host = "webtide.com";
|
||||
int port = 443;
|
||||
|
||||
FuturePromise<Session> sessionPromise = new FuturePromise<>();
|
||||
client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise);
|
||||
Session session = sessionPromise.get(5, TimeUnit.SECONDS);
|
||||
|
||||
HttpFields requestFields = new HttpFields();
|
||||
requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION);
|
||||
MetaData.Request metaData = new MetaData.Request("GET", new HttpURI("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields);
|
||||
HeadersFrame headersFrame = new HeadersFrame(metaData, null, true);
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
session.newStream(headersFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
System.err.println(frame);
|
||||
if (frame.isEndStream())
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onData(Stream stream, DataFrame frame, Callback callback)
|
||||
{
|
||||
System.err.println(frame);
|
||||
callback.succeeded();
|
||||
if (frame.isEndStream())
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
latch.await(5, TimeUnit.SECONDS);
|
||||
|
||||
client.stop();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
#org.eclipse.jetty.LEVEL=DEBUG
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-alpn-conscrypt-server</artifactId>
|
||||
<name>Jetty :: ALPN :: Conscrypt Server Implementation</name>
|
||||
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.alpn.conscrypt.server</bundle-symbolic-name>
|
||||
<conscrypt.version>1.0.0.RC10</conscrypt.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.conscrypt</groupId>
|
||||
<artifactId>conscrypt-openjdk-uber</artifactId>
|
||||
<version>${conscrypt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.alpn.conscrypt.server;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.Security;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import org.conscrypt.OpenSSLProvider;
|
||||
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.DecryptedEndPoint;
|
||||
import org.eclipse.jetty.io.ssl.SslHandshakeListener;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
public class ConscryptServerALPNProcessor implements ALPNProcessor.Server
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ConscryptServerALPNProcessor.class);
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
if (Security.getProvider("Conscrypt")==null)
|
||||
{
|
||||
Security.addProvider(new OpenSSLProvider());
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Added Conscrypt provider");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appliesTo(SSLEngine sslEngine)
|
||||
{
|
||||
return sslEngine.getClass().getName().startsWith("org.conscrypt.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(SSLEngine sslEngine,Connection connection)
|
||||
{
|
||||
try
|
||||
{
|
||||
Method method = sslEngine.getClass().getMethod("setHandshakeApplicationProtocolSelector", BiFunction.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(sslEngine,new ALPNCallback((ALPNServerConnection)connection));
|
||||
}
|
||||
catch (RuntimeException x)
|
||||
{
|
||||
throw x;
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
}
|
||||
|
||||
private final class ALPNCallback implements BiFunction<SSLEngine,List<String>,String>, SslHandshakeListener
|
||||
{
|
||||
private final ALPNServerConnection alpnConnection;
|
||||
|
||||
private ALPNCallback(ALPNServerConnection connection)
|
||||
{
|
||||
alpnConnection = connection;
|
||||
((DecryptedEndPoint)alpnConnection.getEndPoint()).getSslConnection().addHandshakeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(SSLEngine engine, List<String> protocols)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("apply {} {}", alpnConnection, protocols);
|
||||
alpnConnection.select(protocols);
|
||||
return alpnConnection.getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeSucceeded(Event event)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("handshakeSucceeded {} {}", alpnConnection, event);
|
||||
if (alpnConnection.getProtocol()==null)
|
||||
{
|
||||
LOG.warn("No ALPN callback! {} {}",alpnConnection, event);
|
||||
alpnConnection.unsupported();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeFailed(Event event, Throwable failure)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("handshakeFailed {} {} {}", alpnConnection, event, failure);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.eclipse.jetty.alpn.conscrypt.server.ConscryptServerALPNProcessor
|
|
@ -0,0 +1,72 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.alpn.conscrypt.server;
|
||||
|
||||
import java.security.Security;
|
||||
|
||||
import org.conscrypt.OpenSSLProvider;
|
||||
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
|
||||
import org.eclipse.jetty.http2.HTTP2Cipher;
|
||||
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.SslConnectionFactory;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
/**
|
||||
* Test server that verifies that the Conscrypt ALPN mechanism works.
|
||||
*/
|
||||
public class ConscryptHTTP2Server
|
||||
{
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
Security.addProvider(new OpenSSLProvider());
|
||||
|
||||
Server server = new Server();
|
||||
|
||||
HttpConfiguration httpsConfig = new HttpConfiguration();
|
||||
httpsConfig.setSecureScheme("https");
|
||||
httpsConfig.setSecurePort(8443);
|
||||
httpsConfig.setSendXPoweredBy(true);
|
||||
httpsConfig.setSendServerVersion(true);
|
||||
httpsConfig.addCustomizer(new SecureRequestCustomizer());
|
||||
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
sslContextFactory.setProvider("Conscrypt");
|
||||
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
|
||||
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
|
||||
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
|
||||
sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR);
|
||||
|
||||
HttpConnectionFactory http = new HttpConnectionFactory(httpsConfig);
|
||||
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig);
|
||||
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
|
||||
alpn.setDefaultProtocol(http.getProtocol());
|
||||
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol());
|
||||
|
||||
ServerConnector http2Connector = new ServerConnector(server, ssl, alpn, h2, http);
|
||||
http2Connector.setPort(8443);
|
||||
server.addConnector(http2Connector);
|
||||
|
||||
server.start();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
#org.eclipse.jetty.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.alpn.LEVEL=DEBUG
|
Binary file not shown.
|
@ -33,22 +33,15 @@
|
|||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
<artifactId>jetty-alpn-client</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.http2</groupId>
|
||||
<artifactId>http2-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -18,38 +18,66 @@
|
|||
|
||||
package org.eclipse.jetty.alpn.java.client;
|
||||
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
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.DecryptedEndPoint;
|
||||
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;
|
||||
|
||||
public class JDK9ClientALPNProcessor implements ALPNProcessor.Client
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(JDK9ClientALPNProcessor.class);
|
||||
|
||||
@Override
|
||||
public void configure(SSLEngine sslEngine, List<String> protocols)
|
||||
public void init()
|
||||
{
|
||||
SSLParameters sslParameters = sslEngine.getSSLParameters();
|
||||
sslParameters.setApplicationProtocols(protocols.toArray(new String[0]));
|
||||
sslEngine.setSSLParameters(sslParameters);
|
||||
if (JavaVersion.VERSION.getPlatform()<9)
|
||||
throw new IllegalStateException(this + " not applicable for java "+JavaVersion.VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(SSLEngine sslEngine)
|
||||
public boolean appliesTo(SSLEngine sslEngine)
|
||||
{
|
||||
try
|
||||
Module module = sslEngine.getClass().getModule();
|
||||
return module!=null && "java.base".equals(module.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(SSLEngine sslEngine, Connection connection)
|
||||
{
|
||||
ALPN.ClientProvider provider = (ALPN.ClientProvider)ALPN.get(sslEngine);
|
||||
if (provider != null)
|
||||
provider.selected(sslEngine.getApplicationProtocol());
|
||||
ALPNClientConnection alpn = (ALPNClientConnection)connection;
|
||||
SSLParameters sslParameters = sslEngine.getSSLParameters();
|
||||
List<String> protocols = alpn.getProtocols();
|
||||
sslParameters.setApplicationProtocols(protocols.toArray(new String[protocols.size()]));
|
||||
sslEngine.setSSLParameters(sslParameters);
|
||||
((DecryptedEndPoint)connection.getEndPoint()).getSslConnection()
|
||||
.addHandshakeListener(new ALPNListener(alpn));
|
||||
}
|
||||
catch (SSLException x)
|
||||
|
||||
private final class ALPNListener implements SslHandshakeListener
|
||||
{
|
||||
throw new UncheckedIOException(x);
|
||||
private final ALPNClientConnection alpnConnection;
|
||||
|
||||
private ALPNListener(ALPNClientConnection connection)
|
||||
{
|
||||
alpnConnection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeSucceeded(Event event)
|
||||
{
|
||||
String protocol = alpnConnection.getSSLEngine().getApplicationProtocol();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("selected protocol {}", protocol);
|
||||
alpnConnection.selected(protocol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,16 +42,16 @@ public class JDK9HTTP2Client
|
|||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
HTTP2Client client = new HTTP2Client();
|
||||
SslContextFactory sslContextFactory = new SslContextFactory(true);
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
client.addBean(sslContextFactory);
|
||||
client.start();
|
||||
|
||||
String host = "localhost";
|
||||
int port = 8443;
|
||||
String host = "webtide.com";
|
||||
int port = 443;
|
||||
|
||||
FuturePromise<Session> sessionPromise = new FuturePromise<>();
|
||||
client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise);
|
||||
Session session = sessionPromise.get(555, TimeUnit.SECONDS);
|
||||
Session session = sessionPromise.get(5, TimeUnit.SECONDS);
|
||||
|
||||
HttpFields requestFields = new HttpFields();
|
||||
requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION);
|
||||
|
|
|
@ -40,12 +40,10 @@
|
|||
<artifactId>alpn-api</artifactId>
|
||||
<version>${alpn.api.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<artifactId>jetty-alpn-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
|
@ -53,12 +51,6 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
|
|
@ -19,13 +19,16 @@
|
|||
package org.eclipse.jetty.alpn.java.server;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -34,40 +37,61 @@ public class JDK9ServerALPNProcessor implements ALPNProcessor.Server, SslHandsha
|
|||
private static final Logger LOG = Log.getLogger(JDK9ServerALPNProcessor.class);
|
||||
|
||||
@Override
|
||||
public void configure(SSLEngine sslEngine)
|
||||
public void init()
|
||||
{
|
||||
sslEngine.setHandshakeApplicationProtocolSelector(this::process);
|
||||
if (JavaVersion.VERSION.getPlatform()<9)
|
||||
throw new IllegalStateException(this + " not applicable for java "+JavaVersion.VERSION);
|
||||
}
|
||||
|
||||
private String process(SSLEngine sslEngine, List<String> protocols)
|
||||
@Override
|
||||
public boolean appliesTo(SSLEngine sslEngine)
|
||||
{
|
||||
try
|
||||
Module module = sslEngine.getClass().getModule();
|
||||
return module!=null && "java.base".equals(module.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(SSLEngine sslEngine, Connection connection)
|
||||
{
|
||||
sslEngine.setHandshakeApplicationProtocolSelector(new ALPNCallback((ALPNServerConnection)connection));
|
||||
}
|
||||
|
||||
private final 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)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("ALPN selecting among client{}", protocols);
|
||||
ALPN.ServerProvider provider = (ALPN.ServerProvider)ALPN.remove(sslEngine);
|
||||
return provider == null ? "" : provider.select(protocols);
|
||||
}
|
||||
catch (SSLException x)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
LOG.debug("apply {} {}", alpnConnection, protocols);
|
||||
alpnConnection.select(protocols);
|
||||
return alpnConnection.getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeSucceeded(Event event)
|
||||
{
|
||||
ALPN.ServerProvider provider = (ALPN.ServerProvider)ALPN.remove(event.getSSLEngine());
|
||||
if (provider != null)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("ALPN unsupported by client");
|
||||
provider.unsupported();
|
||||
LOG.debug("handshakeSucceeded {} {}", alpnConnection, event);
|
||||
if (alpnConnection.getProtocol()==null)
|
||||
{
|
||||
LOG.warn("No ALPN callback! {} {}",alpnConnection, event);
|
||||
alpnConnection.unsupported();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeFailed(Event event, Throwable failure)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("handshakeFailed {} {} {}", alpnConnection, event, failure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-alpn-openjdk8-client</artifactId>
|
||||
<name>Jetty :: ALPN :: OpenJDK8 Client Implementation</name>
|
||||
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.alpn.java.client</bundle-symbolic-name>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-client</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.http2</groupId>
|
||||
<artifactId>http2-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,104 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.alpn.java.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
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.util.JavaVersion;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
public class OpenJDK8ClientALPNProcessor implements ALPNProcessor.Client
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(OpenJDK8ClientALPNProcessor.class);
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
if (JavaVersion.VERSION.getPlatform()!=8)
|
||||
throw new IllegalStateException(this + " not applicable for java "+JavaVersion.VERSION);
|
||||
if (ALPN.class.getClassLoader()!=null)
|
||||
throw new IllegalStateException(this + " must be on JVM boot classpath");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appliesTo(SSLEngine sslEngine)
|
||||
{
|
||||
return sslEngine.getClass().getName().startsWith("sun.security.ssl.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(SSLEngine sslEngine, Connection connection)
|
||||
{
|
||||
connection.addListener(new ALPNListener((ALPNClientConnection)connection));
|
||||
}
|
||||
|
||||
private final class ALPNListener implements ALPN.ClientProvider, Connection.Listener
|
||||
{
|
||||
private final ALPNClientConnection alpnConnection;
|
||||
|
||||
private ALPNListener(ALPNClientConnection connection)
|
||||
{
|
||||
alpnConnection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpened(Connection connection)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("onOpened {}", alpnConnection);
|
||||
ALPN.put(alpnConnection.getSSLEngine(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosed(Connection connection)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("onClosed {}", alpnConnection);
|
||||
ALPN.remove(alpnConnection.getSSLEngine());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> protocols()
|
||||
{
|
||||
return alpnConnection.getProtocols();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported()
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("unsupported {}", alpnConnection);
|
||||
ALPN.remove(alpnConnection.getSSLEngine());
|
||||
alpnConnection.selected(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selected(String protocol)
|
||||
{
|
||||
alpnConnection.selected(protocol);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.eclipse.jetty.alpn.java.client.OpenJDK8ClientALPNProcessor
|
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.alpn.java.client;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.api.Session;
|
||||
import org.eclipse.jetty.http2.api.Stream;
|
||||
import org.eclipse.jetty.http2.client.HTTP2Client;
|
||||
import org.eclipse.jetty.http2.frames.DataFrame;
|
||||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.FuturePromise;
|
||||
import org.eclipse.jetty.util.Jetty;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
public class OpenJDK8HTTP2Client
|
||||
{
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
HTTP2Client client = new HTTP2Client();
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
client.addBean(sslContextFactory);
|
||||
client.start();
|
||||
|
||||
String host = "webtide.com";
|
||||
int port = 443;
|
||||
|
||||
FuturePromise<Session> sessionPromise = new FuturePromise<>();
|
||||
client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise);
|
||||
Session session = sessionPromise.get(5, TimeUnit.SECONDS);
|
||||
|
||||
HttpFields requestFields = new HttpFields();
|
||||
requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION);
|
||||
MetaData.Request metaData = new MetaData.Request("GET", new HttpURI("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields);
|
||||
HeadersFrame headersFrame = new HeadersFrame(metaData, null, true);
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
session.newStream(headersFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
System.err.println(frame);
|
||||
if (frame.isEndStream())
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onData(Stream stream, DataFrame frame, Callback callback)
|
||||
{
|
||||
System.err.println(frame);
|
||||
callback.succeeded();
|
||||
if (frame.isEndStream())
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
latch.await(5, TimeUnit.SECONDS);
|
||||
|
||||
client.stop();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
#org.eclipse.jetty.LEVEL=DEBUG
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-alpn-openjdk8-server</artifactId>
|
||||
<name>Jetty :: ALPN :: OpenJDK8 Server Implementation</name>
|
||||
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.alpn.conscrypt.server</bundle-symbolic-name>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.alpn</groupId>
|
||||
<artifactId>alpn-api</artifactId>
|
||||
<version>${alpn.api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,104 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.alpn.openjdk8.server;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
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.util.JavaVersion;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
public class OpenJDK8ServerALPNProcessor implements ALPNProcessor.Server
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(OpenJDK8ServerALPNProcessor.class);
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
if (JavaVersion.VERSION.getPlatform()!=8)
|
||||
throw new IllegalStateException(this + " not applicable for java "+JavaVersion.VERSION);
|
||||
if (ALPN.class.getClassLoader()!=null)
|
||||
throw new IllegalStateException(ALPN.class.getName() + " must be on JVM boot classpath");
|
||||
if (LOG.isDebugEnabled())
|
||||
ALPN.debug = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appliesTo(SSLEngine sslEngine)
|
||||
{
|
||||
return sslEngine.getClass().getName().startsWith("sun.security.ssl.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(SSLEngine sslEngine, Connection connection)
|
||||
{
|
||||
connection.addListener(new ALPNListener((ALPNServerConnection)connection));
|
||||
}
|
||||
|
||||
private final class ALPNListener implements ALPN.ServerProvider, Connection.Listener
|
||||
{
|
||||
private final ALPNServerConnection alpnConnection;
|
||||
|
||||
private ALPNListener(ALPNServerConnection connection)
|
||||
{
|
||||
alpnConnection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpened(Connection connection)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("onOpened {}", alpnConnection);
|
||||
ALPN.put(alpnConnection.getSSLEngine(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosed(Connection connection)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("onClosed {}", alpnConnection);
|
||||
ALPN.remove(alpnConnection.getSSLEngine());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported()
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("unsupported {}", alpnConnection);
|
||||
alpnConnection.select(Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String select(List<String> protocols) throws SSLException
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("select {} {}", alpnConnection, protocols);
|
||||
alpnConnection.select(protocols);
|
||||
return alpnConnection.getProtocol();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.eclipse.jetty.alpn.openjdk8.server.OpenJDK8ServerALPNProcessor
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.alpn.openjdk8.server;
|
||||
|
||||
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
|
||||
import org.eclipse.jetty.http2.HTTP2Cipher;
|
||||
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.SslConnectionFactory;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
/**
|
||||
* Test server that verifies that the JDK 8 ALPN mechanism works.
|
||||
*/
|
||||
public class OpenJDK8HTTP2Server
|
||||
{
|
||||
public static void main(String... args) throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
|
||||
HttpConfiguration httpsConfig = new HttpConfiguration();
|
||||
httpsConfig.setSecureScheme("https");
|
||||
httpsConfig.setSecurePort(8443);
|
||||
httpsConfig.setSendXPoweredBy(true);
|
||||
httpsConfig.setSendServerVersion(true);
|
||||
httpsConfig.addCustomizer(new SecureRequestCustomizer());
|
||||
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
|
||||
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
|
||||
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
|
||||
sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR);
|
||||
|
||||
HttpConnectionFactory http = new HttpConnectionFactory(httpsConfig);
|
||||
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig);
|
||||
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
|
||||
alpn.setDefaultProtocol(http.getProtocol());
|
||||
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol());
|
||||
|
||||
ServerConnector http2Connector = new ServerConnector(server, ssl, alpn, h2, http);
|
||||
http2Connector.setPort(8443);
|
||||
server.addConnector(http2Connector);
|
||||
|
||||
server.start();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
#org.eclipse.jetty.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.alpn.LEVEL=DEBUG
|
Binary file not shown.
|
@ -59,12 +59,6 @@
|
|||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.alpn</groupId>
|
||||
<artifactId>alpn-api</artifactId>
|
||||
<version>${alpn.api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -15,18 +15,9 @@
|
|||
<Call name="addConnectionFactory">
|
||||
<Arg>
|
||||
<New id="alpn" class="org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory">
|
||||
<Arg type="String">
|
||||
<Property name="jetty.alpn.protocols" deprecated="alpn.protocols" default="" />
|
||||
</Arg>
|
||||
<Set name="defaultProtocol">
|
||||
<Property name="jetty.alpn.defaultProtocol" deprecated="alpn.defaultProtocol" />
|
||||
</Set>
|
||||
<Arg name="protocols" type="String"><Property name="jetty.alpn.protocols" deprecated="alpn.protocols" default="" /></Arg>
|
||||
<Set name="defaultProtocol"><Property name="jetty.alpn.defaultProtocol" deprecated="alpn.defaultProtocol" /></Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
<!-- ALPN debugging on System.err -->
|
||||
<Set class="org.eclipse.jetty.alpn.ALPN" name="debug" type="boolean"><Property name="jetty.alpn.debug" default="false" /></Set>
|
||||
|
||||
</Configure>
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[description]
|
||||
Selects an ALPN (Application Layer Protocol Negotiation) implementation by java version.
|
||||
|
||||
[depend]
|
||||
alpn-impl/alpn-${java.version.platform}
|
|
@ -17,6 +17,9 @@ specific version of Java.
|
|||
[depend]
|
||||
alpn-impl/alpn-${java.version}
|
||||
|
||||
[lib]
|
||||
lib/jetty-alpn-openjdk8-server-${jetty.version}.jar
|
||||
|
||||
[files]
|
||||
lib/
|
||||
lib/alpn/
|
||||
|
|
|
@ -3,7 +3,7 @@ Enables the ALPN (Application Layer Protocol Negotiation) TLS extension.
|
|||
|
||||
[depend]
|
||||
ssl
|
||||
alpn-impl/alpn-${java.version.platform}
|
||||
alpn-impl
|
||||
|
||||
[lib]
|
||||
lib/jetty-alpn-client-${jetty.version}.jar
|
||||
|
@ -21,6 +21,3 @@ etc/jetty-alpn.xml
|
|||
## Specifies what protocol to use when negotiation fails.
|
||||
# jetty.alpn.defaultProtocol=http/1.1
|
||||
|
||||
## ALPN debug logging on System.err
|
||||
# jetty.alpn.debug=false
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ import java.util.List;
|
|||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
import org.eclipse.jetty.alpn.ALPN;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.server.ConnectionFactory;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
|
@ -32,24 +31,21 @@ import org.eclipse.jetty.server.NegotiatingServerConnection;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
public class ALPNServerConnection extends NegotiatingServerConnection implements ALPN.ServerProvider
|
||||
public class ALPNServerConnection extends NegotiatingServerConnection
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ALPNServerConnection.class);
|
||||
|
||||
public ALPNServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol)
|
||||
{
|
||||
super(connector, endPoint, engine, protocols, defaultProtocol);
|
||||
ALPN.put(engine, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported()
|
||||
{
|
||||
select(Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String select(List<String> clientProtocols)
|
||||
public void select(List<String> clientProtocols)
|
||||
{
|
||||
SSLEngine sslEngine = getSSLEngine();
|
||||
List<String> serverProtocols = getProtocols();
|
||||
|
@ -70,7 +66,7 @@ public class ALPNServerConnection extends NegotiatingServerConnection implements
|
|||
if (factory instanceof CipherDiscriminator && !((CipherDiscriminator)factory).isAcceptable(serverProtocol, tlsProtocol, tlsCipher))
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} protocol {} not acceptable to {} for {}/{}", this, serverProtocol, factory, tlsProtocol, tlsCipher);
|
||||
LOG.debug("Protocol {} not acceptable to {} for {}/{} on {}", serverProtocol, factory, tlsProtocol, tlsCipher, getEndPoint());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -87,21 +83,12 @@ public class ALPNServerConnection extends NegotiatingServerConnection implements
|
|||
else
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} could not negotiate protocol among client{} and server{}", this, clientProtocols, serverProtocols);
|
||||
LOG.debug("Could not negotiate protocol from client{} and server{} on {}", clientProtocols, serverProtocols, getEndPoint());
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} protocol selected {} among client{} and server{}", this, negotiated, clientProtocols, serverProtocols);
|
||||
LOG.debug("Protocol selected {} from client{} and server{} on {}", negotiated, clientProtocols, serverProtocols, getEndPoint());
|
||||
setProtocol(negotiated);
|
||||
ALPN.remove(sslEngine);
|
||||
return negotiated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
ALPN.remove(getSSLEngine());
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
|
||||
package org.eclipse.jetty.alpn.server;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
|
@ -26,17 +27,20 @@ import javax.net.ssl.SSLEngine;
|
|||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.ssl.ALPNProcessor;
|
||||
import org.eclipse.jetty.io.ssl.SslHandshakeListener;
|
||||
import org.eclipse.jetty.io.ssl.ALPNProcessor.Server;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
public class ALPNServerConnectionFactory extends NegotiatingServerConnectionFactory implements SslHandshakeListener
|
||||
public class ALPNServerConnectionFactory extends NegotiatingServerConnectionFactory
|
||||
{
|
||||
private final ALPNProcessor.Server alpnProcessor;
|
||||
private static final Logger LOG = Log.getLogger(ALPNServerConnectionFactory.class);
|
||||
|
||||
public ALPNServerConnectionFactory(String protocols)
|
||||
private final List<Server> processors = new ArrayList<>();
|
||||
|
||||
public ALPNServerConnectionFactory(@Name("protocols") String protocols)
|
||||
{
|
||||
this(protocols.trim().split(",", 0));
|
||||
}
|
||||
|
@ -44,34 +48,47 @@ public class ALPNServerConnectionFactory extends NegotiatingServerConnectionFact
|
|||
public ALPNServerConnectionFactory(@Name("protocols") String... protocols)
|
||||
{
|
||||
super("alpn", protocols);
|
||||
checkProtocolNegotiationAvailable();
|
||||
Iterator<ALPNProcessor.Server> processors = ServiceLoader.load(ALPNProcessor.Server.class).iterator();
|
||||
alpnProcessor = processors.hasNext() ? processors.next() : ALPNProcessor.Server.NOOP;
|
||||
|
||||
IllegalStateException failure = new IllegalStateException("No Server ALPNProcessors!");
|
||||
for (Server processor : ServiceLoader.load(Server.class))
|
||||
{
|
||||
try
|
||||
{
|
||||
processor.init();
|
||||
processors.add(processor);
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Could not initialize " + processor, x);
|
||||
failure.addSuppressed(x);
|
||||
}
|
||||
}
|
||||
|
||||
public ALPNProcessor.Server getALPNProcessor()
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
return alpnProcessor;
|
||||
LOG.debug("protocols: {}", Arrays.asList(protocols));
|
||||
LOG.debug("processors: {}", processors);
|
||||
}
|
||||
|
||||
if (processors.isEmpty())
|
||||
throw failure;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractConnection newServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol)
|
||||
{
|
||||
getALPNProcessor().configure(engine);
|
||||
return new ALPNServerConnection(connector, endPoint, engine, protocols, defaultProtocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeSucceeded(Event event)
|
||||
for (Server processor : processors)
|
||||
{
|
||||
if (alpnProcessor instanceof SslHandshakeListener)
|
||||
((SslHandshakeListener)alpnProcessor).handshakeSucceeded(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeFailed(Event event, Throwable failure)
|
||||
if (processor.appliesTo(engine))
|
||||
{
|
||||
if (alpnProcessor instanceof SslHandshakeListener)
|
||||
((SslHandshakeListener)alpnProcessor).handshakeFailed(event, failure);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} for {} on {}", processor, engine, endPoint);
|
||||
ALPNServerConnection connection = new ALPNServerConnection(connector, endPoint, engine, protocols, defaultProtocol);
|
||||
processor.configure(engine, connection);
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("No ALPNProcessor for " + engine);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
<modules>
|
||||
<module>jetty-alpn-server</module>
|
||||
<module>jetty-alpn-client</module>
|
||||
<module>jetty-alpn-openjdk8-server</module>
|
||||
<module>jetty-alpn-openjdk8-client</module>
|
||||
<module>jetty-alpn-conscrypt-server</module>
|
||||
<module>jetty-alpn-conscrypt-client</module>
|
||||
</modules>
|
||||
<profiles>
|
||||
<profile>
|
||||
|
|
|
@ -499,6 +499,16 @@
|
|||
<artifactId>jetty-alpn-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-openjdk8-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-conscrypt-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jaspi</artifactId>
|
||||
|
|
|
@ -7,21 +7,26 @@ Installs the Conscrypt JSSE provider
|
|||
[depend]
|
||||
ssl
|
||||
|
||||
[provides]
|
||||
alpn-impl
|
||||
|
||||
[files]
|
||||
maven://org.conscrypt/conscrypt-openjdk-uber/${conscrypt.version}|lib/conscrypt/conscrypt-uber-${conscrypt.version}.jar
|
||||
#maven://org.conscrypt/conscrypt-openjdk/${conscrypt.version}/jar/linux-x86_64|lib/conscrypt/conscrypt-${conscrypt.version}-linux-x86_64.jar
|
||||
basehome:modules/conscrypt/conscrypt.xml|etc/conscrypt.xml
|
||||
|
||||
[lib]
|
||||
lib/conscrypt/**.jar
|
||||
|
||||
[xml]
|
||||
etc/conscrypt.xml
|
||||
|
||||
[lib]
|
||||
lib/conscrypt/**.jar
|
||||
lib/jetty-alpn-conscrypt-server-${jetty.version}.jar
|
||||
|
||||
[license]
|
||||
Conscrypt is distributed under the Apache Licence 2.0
|
||||
https://github.com/google/conscrypt/blob/master/LICENSE
|
||||
|
||||
[ini]
|
||||
conscrypt.version?=1.0.0.RC9
|
||||
jetty.sslContext.provider?=AndroidOpenSSL
|
||||
conscrypt.version?=1.0.0.RC10
|
||||
jetty.sslContext.provider?=Conscrypt
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ mov=video/quicktime
|
|||
movie=video/x-sgi-movie
|
||||
mp2=audio/mpeg
|
||||
mp3=audio/mpeg
|
||||
mp4=video/mp4
|
||||
mpe=video/mpeg
|
||||
mpeg=video/mpeg
|
||||
mpg=video/mpeg
|
||||
|
|
|
@ -45,7 +45,7 @@ public abstract class NegotiatingClientConnection extends AbstractConnection
|
|||
this.context = context;
|
||||
}
|
||||
|
||||
protected SSLEngine getSSLEngine()
|
||||
public SSLEngine getSSLEngine()
|
||||
{
|
||||
return engine;
|
||||
}
|
||||
|
|
|
@ -18,35 +18,54 @@
|
|||
|
||||
package org.eclipse.jetty.io.ssl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
|
||||
public interface ALPNProcessor
|
||||
{
|
||||
public interface Server
|
||||
{
|
||||
public static final ALPNProcessor.Server NOOP = new ALPNProcessor.Server()
|
||||
{
|
||||
};
|
||||
|
||||
public default void configure(SSLEngine sslEngine)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public interface Client
|
||||
{
|
||||
public static final Client NOOP = new Client()
|
||||
{
|
||||
};
|
||||
|
||||
public default void configure(SSLEngine sslEngine, List<String> protocols)
|
||||
/**
|
||||
* Initializes this ALPNProcessor
|
||||
*
|
||||
* @throws RuntimeException if this processor is unavailable (e.g. missing dependencies or wrong JVM)
|
||||
*/
|
||||
public default void init()
|
||||
{
|
||||
}
|
||||
|
||||
public default void process(SSLEngine sslEngine)
|
||||
/**
|
||||
* Tests if this processor can be applied to the given SSLEngine.
|
||||
*
|
||||
* @param sslEngine the SSLEngine to check
|
||||
* @return true if the processor can be applied to the given SSLEngine
|
||||
*/
|
||||
public default boolean appliesTo(SSLEngine sslEngine)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the given SSLEngine and the given Connection for ALPN.
|
||||
*
|
||||
* @param sslEngine the SSLEngine to configure
|
||||
* @param connection the Connection to configure
|
||||
* @throws RuntimeException if this processor cannot be configured
|
||||
*/
|
||||
public default void configure(SSLEngine sslEngine, Connection connection)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-side interface used by ServiceLoader.
|
||||
*/
|
||||
public interface Server extends ALPNProcessor
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Client-side interface used by ServiceLoader.
|
||||
*/
|
||||
public interface Client extends ALPNProcessor
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,27 +55,27 @@ public abstract class NegotiatingServerConnection extends AbstractConnection
|
|||
this.engine = engine;
|
||||
}
|
||||
|
||||
protected List<String> getProtocols()
|
||||
public List<String> getProtocols()
|
||||
{
|
||||
return protocols;
|
||||
}
|
||||
|
||||
protected String getDefaultProtocol()
|
||||
public String getDefaultProtocol()
|
||||
{
|
||||
return defaultProtocol;
|
||||
}
|
||||
|
||||
protected Connector getConnector()
|
||||
public Connector getConnector()
|
||||
{
|
||||
return connector;
|
||||
}
|
||||
|
||||
protected SSLEngine getSSLEngine()
|
||||
public SSLEngine getSSLEngine()
|
||||
{
|
||||
return engine;
|
||||
}
|
||||
|
||||
protected String getProtocol()
|
||||
public String getProtocol()
|
||||
{
|
||||
return protocol;
|
||||
}
|
||||
|
|
|
@ -32,28 +32,6 @@ import org.eclipse.jetty.io.ssl.SslConnection;
|
|||
|
||||
public abstract class NegotiatingServerConnectionFactory extends AbstractConnectionFactory
|
||||
{
|
||||
public static void checkProtocolNegotiationAvailable()
|
||||
{
|
||||
try
|
||||
{
|
||||
String javaVersion = System.getProperty("java.version");
|
||||
String alpnClassName = "org.eclipse.jetty.alpn.ALPN";
|
||||
if (javaVersion.startsWith("1."))
|
||||
{
|
||||
Class<?> klass = ClassLoader.getSystemClassLoader().loadClass(alpnClassName);
|
||||
if (klass.getClassLoader() != null)
|
||||
throw new IllegalStateException(alpnClassName + " must be on JVM boot classpath");
|
||||
}
|
||||
else
|
||||
{
|
||||
NegotiatingServerConnectionFactory.class.getClassLoader().loadClass(alpnClassName);
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException x)
|
||||
{
|
||||
throw new IllegalStateException("No ALPN classes available");
|
||||
}
|
||||
}
|
||||
|
||||
private final List<String> negotiatedProtocols;
|
||||
private String defaultProtocol;
|
||||
|
|
|
@ -109,6 +109,7 @@ public class ResourceHandler extends HandlerWrapper implements ResourceFactory,W
|
|||
{
|
||||
Context scontext = ContextHandler.getCurrentContext();
|
||||
_context = (scontext == null?null:scontext.getContextHandler());
|
||||
if (_mimeTypes==null)
|
||||
_mimeTypes = _context == null?new MimeTypes():_context.getMimeTypes();
|
||||
|
||||
_resourceService.setContentFactory(new ResourceContentFactory(this,_mimeTypes,_resourceService.getPrecompressedFormats()));
|
||||
|
|
Loading…
Reference in New Issue