Added SSL support.

This commit is contained in:
Simone Bordet 2012-01-27 22:02:39 +01:00
parent 298605aebd
commit ffe10f3cf8
9 changed files with 143 additions and 76992 deletions

View File

@ -14,6 +14,8 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.ConnectedEndPoint;
@ -21,6 +23,7 @@ import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.io.nio.SelectorManager;
import org.eclipse.jetty.io.nio.SslConnection;
import org.eclipse.jetty.spdy.CompressionFactory;
import org.eclipse.jetty.spdy.CompressionFactory.Compressor;
import org.eclipse.jetty.spdy.CompressionFactory.Decompressor;
@ -32,6 +35,7 @@ import org.eclipse.jetty.spdy.api.Session.FrameListener;
import org.eclipse.jetty.spdy.generator.Generator;
import org.eclipse.jetty.spdy.parser.Parser;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
@ -93,6 +97,23 @@ public class SPDYClient
this.maxIdleTime = maxIdleTime;
}
protected SSLEngine newSSLEngine(SslContextFactory sslContextFactory, SocketChannel channel)
{
try
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
int peerPort = channel.socket().getPort();
SSLEngine engine = sslContextFactory.newSslEngine(peerHost, peerPort);
engine.setUseClientMode(true);
engine.beginHandshake();
return engine;
}
catch (SSLException x)
{
throw new RuntimeException(x);
}
}
protected CompressionFactory newCompressionFactory()
{
return new StandardCompressionFactory();
@ -118,19 +139,34 @@ public class SPDYClient
public static class Factory extends AggregateLifeCycle
{
private final ThreadPool threadPool;
private final SslContextFactory sslContextFactory;
private final SelectorManager selector;
public Factory()
{
this(null);
this(null, null);
}
public Factory(SslContextFactory sslContextFactory)
{
this(null, sslContextFactory);
}
public Factory(ThreadPool threadPool)
{
this(threadPool, null);
}
public Factory(ThreadPool threadPool, SslContextFactory sslContextFactory)
{
if (threadPool == null)
threadPool = new QueuedThreadPool();
this.threadPool = threadPool;
addBean(this.threadPool);
addBean(threadPool);
this.sslContextFactory = sslContextFactory;
if (sslContextFactory != null)
addBean(sslContextFactory);
selector = new ClientSelectorManager();
addBean(selector);
@ -164,10 +200,9 @@ public class SPDYClient
maxIdleTime = getMaxIdleTime();
SelectChannelEndPoint result = new SelectChannelEndPoint(channel, selectSet, key, (int)maxIdleTime);
// TODO: handle SSL
AsyncConnection connection = newConnection(channel, result, attachment);
result.setConnection(connection);
return result;
}
@ -193,13 +228,24 @@ public class SPDYClient
SessionFuture sessionFuture = (SessionFuture)attachment;
SPDYClient client = sessionFuture.client;
if (sslContextFactory != null)
{
SSLEngine engine = client.newSSLEngine(sslContextFactory, channel);
SslConnection sslConnection = new SslConnection(engine, endPoint);
endPoint.setConnection(sslConnection);
endPoint = sslConnection.getSslEndPoint();
}
CompressionFactory compressionFactory = client.newCompressionFactory();
Parser parser = client.newParser(compressionFactory.newDecompressor());
Generator generator = client.newGenerator(compressionFactory.newCompressor());
AsyncSPDYConnection connection = new AsyncSPDYConnection(endPoint, parser);
endPoint.setConnection(connection);
Session session = client.newSession(connection, sessionFuture.listener, parser, generator);
sessionFuture.connected(session);
return connection;
}
}

View File

@ -1,9 +1,12 @@
package org.eclipse.jetty.spdy.nio;
import java.nio.channels.SocketChannel;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.io.nio.SslConnection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.spdy.CompressionFactory;
import org.eclipse.jetty.spdy.ISession;
@ -13,26 +16,47 @@ import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.generator.Generator;
import org.eclipse.jetty.spdy.parser.Parser;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public class SPDYServerConnector extends SelectChannelConnector
{
private final ServerSessionFrameListener listener;
private final SslContextFactory sslContextFactory;
public SPDYServerConnector(ServerSessionFrameListener listener)
{
this(listener, null);
}
public SPDYServerConnector(ServerSessionFrameListener listener, SslContextFactory sslContextFactory)
{
this.listener = listener;
this.sslContextFactory = sslContextFactory;
if (sslContextFactory != null)
addBean(sslContextFactory);
}
@Override
protected AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endPoint)
{
if (sslContextFactory != null)
{
SSLEngine engine = newSSLEngine(sslContextFactory, channel);
SslConnection sslConnection = new SslConnection(engine, endPoint);
endPoint.setConnection(sslConnection);
endPoint = sslConnection.getSslEndPoint();
}
CompressionFactory compressionFactory = newCompressionFactory();
Parser parser = newParser(compressionFactory.newDecompressor());
Generator generator = newGenerator(compressionFactory.newCompressor());
AsyncSPDYConnection connection = new AsyncSPDYConnection(endPoint, parser);
endPoint.setConnection(connection);
Session session = newSession(connection, listener, parser, generator);
// TODO: this is called in the selector thread, which is not good
// NPE guard to support tests
if (listener != null)
listener.onConnect(session);
@ -40,6 +64,23 @@ public class SPDYServerConnector extends SelectChannelConnector
return connection;
}
protected SSLEngine newSSLEngine(SslContextFactory sslContextFactory, SocketChannel channel)
{
try
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
int peerPort = channel.socket().getPort();
SSLEngine engine = sslContextFactory.newSslEngine(peerHost, peerPort);
engine.setUseClientMode(false);
engine.beginHandshake();
return engine;
}
catch (SSLException x)
{
throw new RuntimeException(x);
}
}
protected CompressionFactory newCompressionFactory()
{
return new StandardCompressionFactory();

View File

@ -8,10 +8,12 @@ import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.nio.SPDYClient;
import org.eclipse.jetty.spdy.nio.SPDYServerConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.junit.After;
public class SPDYTest
public abstract class SPDYTest
{
private Server server;
private SPDYClient.Factory clientFactory;
@ -19,24 +21,45 @@ public class SPDYTest
protected InetSocketAddress startServer(ServerSessionFrameListener listener) throws Exception
{
server = new Server();
Connector connector = new SPDYServerConnector(listener);
Connector connector = newSPDYServerConnector(listener);
server.addConnector(connector);
server.start();
return new InetSocketAddress(connector.getLocalPort());
}
protected Connector newSPDYServerConnector(ServerSessionFrameListener listener)
{
return new SPDYServerConnector(listener);
}
protected Session startClient(InetSocketAddress socketAddress, Session.FrameListener frameListener) throws Exception
{
if (clientFactory == null)
{
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setName(threadPool.getName() + "-client");
clientFactory = new SPDYClient.Factory(threadPool);
clientFactory = newSPDYClientFactory(threadPool);
clientFactory.start();
}
return clientFactory.newSPDYClient().connect(socketAddress, frameListener).get();
}
protected SPDYClient.Factory newSPDYClientFactory(ThreadPool threadPool)
{
return new SPDYClient.Factory(threadPool);
}
protected SslContextFactory newSslContextFactory()
{
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setTrustStore("src/test/resources/truststore.jks");
sslContextFactory.setTrustStorePassword("storepwd");
sslContextFactory.setProtocol("TLSv1");
return sslContextFactory;
}
@After
public void destroy() throws Exception
{

View File

@ -0,0 +1,25 @@
package org.eclipse.jetty.spdy;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.nio.SPDYClient;
import org.eclipse.jetty.spdy.nio.SPDYServerConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.ThreadPool;
public class SSLSPDYSynReplyTest extends SPDYSynReplyTest
{
@Override
protected Connector newSPDYServerConnector(ServerSessionFrameListener listener)
{
SslContextFactory sslContextFactory = newSslContextFactory();
return new SPDYServerConnector(listener, sslContextFactory);
}
@Override
protected SPDYClient.Factory newSPDYClientFactory(ThreadPool threadPool)
{
SslContextFactory sslContextFactory = newSslContextFactory();
return new SPDYClient.Factory(threadPool, sslContextFactory);
}
}

View File

@ -1,13 +0,0 @@
package org.eclipse.jetty.spdy;
import org.junit.Ignore;
import org.junit.Test;
public class SSLWithNPNTest
{
@Ignore
@Test
public void testSSLWithNPN()
{
}
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -11,3 +11,4 @@ log4j.appender.CONSOLE.target=System.err
# Level tuning
log4j.logger.org.eclipse.jetty=INFO
#log4j.logger.org.eclipse.jetty.spdy=DEBUG

Binary file not shown.