mirror of
https://github.com/jetty/jetty.project.git
synced 2025-02-24 00:17:18 +00:00
Introduced NPN support in the client.
This commit is contained in:
parent
000b635a12
commit
233c32e9f3
16
pom.xml
16
pom.xml
@ -13,6 +13,7 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<jetty.version>7.6.0.RC5</jetty.version>
|
||||
<jetty.npn.version>1.0.0-SNAPSHOT</jetty.npn.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
@ -44,6 +45,16 @@
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.9</version>
|
||||
<configuration>
|
||||
<argLine>
|
||||
-Xbootclasspath/a:${settings.localRepository}/org/eclipse/jetty/jetty-npn-boot/${jetty.npn.version}/jetty-npn-boot-${jetty.npn.version}.jar
|
||||
-javaagent:${settings.localRepository}/org/eclipse/jetty/jetty-npn-agent/${jetty.npn.version}/jetty-npn-agent-${jetty.npn.version}.jar
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
@ -53,6 +64,11 @@
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${jetty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-npn-boot</artifactId>
|
||||
<version>${jetty.npn.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
|
@ -0,0 +1,13 @@
|
||||
package org.eclipse.jetty.spdy.nio;
|
||||
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.nio.AsyncConnection;
|
||||
|
||||
public interface AsyncConnectionFactory
|
||||
{
|
||||
public String getProtocol();
|
||||
|
||||
public AsyncConnection newAsyncConnection(SocketChannel channel, AsyncEndPoint endPoint, Object attachment);
|
||||
}
|
@ -19,8 +19,8 @@ import org.eclipse.jetty.spdy.parser.Parser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AsyncSPDYConnection extends AbstractConnection implements AsyncConnection, Controller {
|
||||
|
||||
public class AsyncSPDYConnection extends AbstractConnection implements AsyncConnection, Controller
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(AsyncSPDYConnection.class);
|
||||
private final Parser parser;
|
||||
private ByteBuffer buffer;
|
||||
|
@ -0,0 +1,51 @@
|
||||
package org.eclipse.jetty.spdy.nio;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.nio.AsyncConnection;
|
||||
|
||||
public class NoProtocolConnection extends AbstractConnection implements AsyncConnection
|
||||
{
|
||||
public NoProtocolConnection(AsyncEndPoint endPoint)
|
||||
{
|
||||
super(endPoint);
|
||||
}
|
||||
|
||||
public Connection handle() throws IOException
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncEndPoint getEndPoint()
|
||||
{
|
||||
return (AsyncEndPoint)super.getEndPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdle()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuspended()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputShutdown() throws IOException
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package org.eclipse.jetty.spdy.nio;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -9,6 +10,7 @@ import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
@ -24,10 +26,8 @@ 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.npn.NextProtoNego;
|
||||
import org.eclipse.jetty.spdy.CompressionFactory;
|
||||
import org.eclipse.jetty.spdy.CompressionFactory.Compressor;
|
||||
import org.eclipse.jetty.spdy.CompressionFactory.Decompressor;
|
||||
import org.eclipse.jetty.spdy.ISession;
|
||||
import org.eclipse.jetty.spdy.StandardCompressionFactory;
|
||||
import org.eclipse.jetty.spdy.StandardSession;
|
||||
import org.eclipse.jetty.spdy.api.Session;
|
||||
@ -97,43 +97,24 @@ public class SPDYClient
|
||||
this.maxIdleTime = maxIdleTime;
|
||||
}
|
||||
|
||||
protected AsyncConnectionFactory selectAsyncConnectionFactory(List<String> serverProtocols)
|
||||
{
|
||||
if (serverProtocols == null)
|
||||
return new ClientSPDY2AsyncConnectionFactory();
|
||||
|
||||
// TODO: for each server protocol, lookup a connection factory in SPDYClient.Factory;
|
||||
// TODO: if that's null, lookup a connection factory in SPDYClient; if that's null, return null.
|
||||
|
||||
return new ClientSPDY2AsyncConnectionFactory();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
protected Parser newParser(Decompressor decompressor)
|
||||
{
|
||||
return new Parser(decompressor);
|
||||
}
|
||||
|
||||
protected Generator newGenerator(Compressor compressor)
|
||||
{
|
||||
return new Generator(compressor);
|
||||
}
|
||||
|
||||
private Session newSession(ISession.Controller controller, FrameListener listener, Parser parser, Generator generator)
|
||||
{
|
||||
StandardSession session = new StandardSession(controller, 1, listener, generator);
|
||||
parser.addListener(session);
|
||||
return session;
|
||||
String peerHost = channel.socket().getInetAddress().getHostAddress();
|
||||
int peerPort = channel.socket().getPort();
|
||||
SSLEngine engine = sslContextFactory.newSslEngine(peerHost, peerPort);
|
||||
engine.setUseClientMode(true);
|
||||
return engine;
|
||||
}
|
||||
|
||||
public static class Factory extends AggregateLifeCycle
|
||||
@ -223,45 +204,72 @@ public class SPDYClient
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endPoint, Object attachment)
|
||||
public AsyncConnection newConnection(final SocketChannel channel, AsyncEndPoint endPoint, final Object attachment)
|
||||
{
|
||||
SessionFuture sessionFuture = (SessionFuture)attachment;
|
||||
SPDYClient client = sessionFuture.client;
|
||||
final SPDYClient client = sessionFuture.client;
|
||||
|
||||
CompressionFactory compressionFactory = client.newCompressionFactory();
|
||||
Parser parser = client.newParser(compressionFactory.newDecompressor());
|
||||
Generator generator = client.newGenerator(compressionFactory.newCompressor());
|
||||
|
||||
AsyncConnection result;
|
||||
ISession.Controller controller;
|
||||
if (sslContextFactory != null)
|
||||
{
|
||||
SSLEngine engine = client.newSSLEngine(sslContextFactory, channel);
|
||||
SslConnection sslConnection = new SslConnection(engine, endPoint);
|
||||
endPoint.setConnection(sslConnection);
|
||||
AsyncEndPoint sslEndPoint = sslConnection.getSslEndPoint();
|
||||
AsyncSPDYConnection connection = new AsyncSPDYConnection(sslEndPoint, parser);
|
||||
final AsyncEndPoint sslEndPoint = sslConnection.getSslEndPoint();
|
||||
|
||||
NextProtoNego.put(engine, new NextProtoNego.ClientProvider()
|
||||
{
|
||||
@Override
|
||||
public boolean supports()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String selectProtocol(List<String> protocols)
|
||||
{
|
||||
AsyncConnectionFactory connectionFactory = client.selectAsyncConnectionFactory(protocols);
|
||||
if (connectionFactory == null)
|
||||
return null;
|
||||
|
||||
AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, attachment);
|
||||
sslEndPoint.setConnection(connection);
|
||||
|
||||
return connectionFactory.getProtocol();
|
||||
// return protocols == null ? null : connectionFactory.getProtocol();
|
||||
}
|
||||
});
|
||||
|
||||
AsyncConnection connection = new NoProtocolConnection(sslEndPoint);
|
||||
sslEndPoint.setConnection(connection);
|
||||
result = sslConnection;
|
||||
controller = connection;
|
||||
|
||||
startHandshake(engine);
|
||||
|
||||
return sslConnection;
|
||||
}
|
||||
else
|
||||
{
|
||||
AsyncSPDYConnection connection = new AsyncSPDYConnection(endPoint, parser);
|
||||
AsyncConnectionFactory connectionFactory = new ClientSPDY2AsyncConnectionFactory();
|
||||
AsyncConnection connection = connectionFactory.newAsyncConnection(channel, endPoint, attachment);
|
||||
endPoint.setConnection(connection);
|
||||
result = connection;
|
||||
controller = connection;
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
|
||||
Session session = client.newSession(controller, sessionFuture.listener, parser, generator);
|
||||
sessionFuture.connected(session);
|
||||
|
||||
return result;
|
||||
private void startHandshake(SSLEngine engine)
|
||||
{
|
||||
try
|
||||
{
|
||||
engine.beginHandshake();
|
||||
}
|
||||
catch (SSLException x)
|
||||
{
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SessionFuture implements Future<Session>
|
||||
private static class SessionFuture implements Future<Session>
|
||||
{
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
private final SPDYClient client;
|
||||
@ -330,4 +338,32 @@ public class SPDYClient
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClientSPDY2AsyncConnectionFactory implements AsyncConnectionFactory
|
||||
{
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return "spdy/2";
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncConnection newAsyncConnection(SocketChannel channel, AsyncEndPoint endPoint, Object attachment)
|
||||
{
|
||||
SessionFuture sessionFuture = (SessionFuture)attachment;
|
||||
|
||||
CompressionFactory compressionFactory = new StandardCompressionFactory();
|
||||
Parser parser = new Parser(compressionFactory.newDecompressor());
|
||||
Generator generator = new Generator(compressionFactory.newCompressor());
|
||||
|
||||
AsyncSPDYConnection connection = new AsyncSPDYConnection(endPoint, parser);
|
||||
endPoint.setConnection(connection);
|
||||
|
||||
StandardSession session = new StandardSession(connection, 1, sessionFuture.listener, generator);
|
||||
parser.addListener(session);
|
||||
sessionFuture.connected(session);
|
||||
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ 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;
|
||||
@ -66,7 +65,7 @@ public class SPDYServerConnector extends SelectChannelConnector
|
||||
|
||||
Session session = newSession(controller, listener, parser, generator);
|
||||
|
||||
// TODO: this is called in the selector thread, which is not good
|
||||
// TODO: this is called in the selector thread, which is not optimal
|
||||
// NPE guard to support tests
|
||||
if (listener != null)
|
||||
listener.onConnect(session);
|
||||
@ -76,19 +75,11 @@ public class SPDYServerConnector extends SelectChannelConnector
|
||||
|
||||
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);
|
||||
}
|
||||
String peerHost = channel.socket().getInetAddress().getHostAddress();
|
||||
int peerPort = channel.socket().getPort();
|
||||
SSLEngine engine = sslContextFactory.newSslEngine(peerHost, peerPort);
|
||||
engine.setUseClientMode(false);
|
||||
return engine;
|
||||
}
|
||||
|
||||
protected CompressionFactory newCompressionFactory()
|
||||
|
@ -22,6 +22,7 @@ public abstract class SPDYTest
|
||||
{
|
||||
server = new Server();
|
||||
Connector connector = newSPDYServerConnector(listener);
|
||||
connector.setPort(47443);
|
||||
server.addConnector(connector);
|
||||
server.start();
|
||||
return new InetSocketAddress(connector.getLocalPort());
|
||||
@ -57,6 +58,7 @@ public abstract class SPDYTest
|
||||
sslContextFactory.setTrustStore("src/test/resources/truststore.jks");
|
||||
sslContextFactory.setTrustStorePassword("storepwd");
|
||||
sslContextFactory.setProtocol("TLSv1");
|
||||
sslContextFactory.setIncludeProtocols("TLSv1");
|
||||
return sslContextFactory;
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
package org.eclipse.jetty.spdy;
|
||||
|
||||
import org.eclipse.jetty.npn.NextProtoNego;
|
||||
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;
|
||||
import org.junit.Before;
|
||||
|
||||
public class SSLSPDYSynReplyTest extends SPDYSynReplyTest
|
||||
{
|
||||
@ -22,4 +24,10 @@ public class SSLSPDYSynReplyTest extends SPDYSynReplyTest
|
||||
SslContextFactory sslContextFactory = newSslContextFactory();
|
||||
return new SPDYClient.Factory(threadPool, sslContextFactory);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void init()
|
||||
{
|
||||
NextProtoNego.debug = true;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user