Updated to correct version of NPN artifact.
Implemented plain HTTP AsyncConnectionFactory and tested protocol negotiation.
This commit is contained in:
parent
7be63d7f76
commit
cb1be263c4
|
@ -25,5 +25,6 @@ public class HTTPSPDYServerConnector extends SPDYServerConnector
|
|||
{
|
||||
super(null);
|
||||
putAsyncConnectionFactory("spdy/2", new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V2, this));
|
||||
setDefaultProtocol("http/1.1");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.eclipse.jetty.spdy.http;
|
||||
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.nio.AsyncConnection;
|
||||
import org.eclipse.jetty.server.AsyncHttpConnection;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.spdy.AsyncConnectionFactory;
|
||||
|
||||
public class ServerHTTPAsyncConnectionFactory implements AsyncConnectionFactory
|
||||
{
|
||||
private final Connector connector;
|
||||
|
||||
public ServerHTTPAsyncConnectionFactory(Connector connector)
|
||||
{
|
||||
this.connector = connector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncConnection newAsyncConnection(SocketChannel channel, AsyncEndPoint endPoint, Object attachment)
|
||||
{
|
||||
return new AsyncHttpConnection(connector, endPoint, connector.getServer());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Copyright (c) 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.eclipse.jetty.spdy.http;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
import org.eclipse.jetty.npn.NextProtoNego;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.spdy.SPDYServerConnector;
|
||||
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestWatchman;
|
||||
import org.junit.runners.model.FrameworkMethod;
|
||||
|
||||
public class ProtocolNegotiationTest
|
||||
{
|
||||
@Rule
|
||||
public final TestWatchman testName = new TestWatchman()
|
||||
{
|
||||
@Override
|
||||
public void starting(FrameworkMethod method)
|
||||
{
|
||||
super.starting(method);
|
||||
System.err.printf("Running %s.%s()%n",
|
||||
method.getMethod().getDeclaringClass().getName(),
|
||||
method.getName());
|
||||
}
|
||||
};
|
||||
|
||||
protected Server server;
|
||||
protected SPDYServerConnector connector;
|
||||
|
||||
protected InetSocketAddress startServer(ServerSessionFrameListener listener) throws Exception
|
||||
{
|
||||
server = new Server();
|
||||
SslContextFactory sslContextFactory = newSslContextFactory();
|
||||
connector = new SPDYServerConnector(listener, sslContextFactory);
|
||||
connector.setPort(0);
|
||||
server.addConnector(connector);
|
||||
server.start();
|
||||
return new InetSocketAddress("localhost", connector.getLocalPort());
|
||||
}
|
||||
|
||||
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");
|
||||
sslContextFactory.setIncludeProtocols("TLSv1");
|
||||
return sslContextFactory;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerAdvertisingHTTPSpeaksHTTP() throws Exception
|
||||
{
|
||||
InetSocketAddress address = startServer(null);
|
||||
connector.removeAsyncConnectionFactory("spdy/2");
|
||||
connector.putAsyncConnectionFactory("http/1.1", new ServerHTTPAsyncConnectionFactory(connector));
|
||||
|
||||
SslContextFactory sslContextFactory = newSslContextFactory();
|
||||
sslContextFactory.start();
|
||||
SSLContext sslContext = sslContextFactory.getSslContext();
|
||||
SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort());
|
||||
client.setUseClientMode(true);
|
||||
client.setSoTimeout(5000);
|
||||
|
||||
NextProtoNego.put(client, new NextProtoNego.ClientProvider()
|
||||
{
|
||||
@Override
|
||||
public boolean supports()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String selectProtocol(List<String> strings)
|
||||
{
|
||||
Assert.assertNotNull(strings);
|
||||
Assert.assertEquals(1, strings.size());
|
||||
String protocol = strings.get(0);
|
||||
Assert.assertEquals("http/1.1", protocol);
|
||||
return protocol;
|
||||
}
|
||||
});
|
||||
|
||||
client.startHandshake();
|
||||
|
||||
// Verify that the server really speaks http/1.1
|
||||
|
||||
OutputStream output = client.getOutputStream();
|
||||
output.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost:" + address.getPort() + "\r\n" +
|
||||
"\r\n" +
|
||||
"").getBytes("UTF-8"));
|
||||
output.flush();
|
||||
|
||||
InputStream input = client.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
|
||||
String line = reader.readLine();
|
||||
Assert.assertTrue(line.contains(" 404 "));
|
||||
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerAdvertisingSPDYAndHTTPSpeaksHTTPWhenNegotiated() throws Exception
|
||||
{
|
||||
InetSocketAddress address = startServer(null);
|
||||
connector.putAsyncConnectionFactory("http/1.1", new ServerHTTPAsyncConnectionFactory(connector));
|
||||
|
||||
SslContextFactory sslContextFactory = newSslContextFactory();
|
||||
sslContextFactory.start();
|
||||
SSLContext sslContext = sslContextFactory.getSslContext();
|
||||
SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort());
|
||||
client.setUseClientMode(true);
|
||||
client.setSoTimeout(5000);
|
||||
|
||||
NextProtoNego.put(client, new NextProtoNego.ClientProvider()
|
||||
{
|
||||
@Override
|
||||
public boolean supports()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String selectProtocol(List<String> strings)
|
||||
{
|
||||
Assert.assertNotNull(strings);
|
||||
Assert.assertEquals(2, strings.size());
|
||||
String spdyProtocol = strings.get(0);
|
||||
Assert.assertEquals("spdy/2", spdyProtocol);
|
||||
String httpProtocol = strings.get(1);
|
||||
Assert.assertEquals("http/1.1", httpProtocol);
|
||||
return httpProtocol;
|
||||
}
|
||||
});
|
||||
|
||||
client.startHandshake();
|
||||
|
||||
// Verify that the server really speaks http/1.1
|
||||
|
||||
OutputStream output = client.getOutputStream();
|
||||
output.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost:" + address.getPort() + "\r\n" +
|
||||
"\r\n" +
|
||||
"").getBytes("UTF-8"));
|
||||
output.flush();
|
||||
|
||||
InputStream input = client.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
|
||||
String line = reader.readLine();
|
||||
Assert.assertTrue(line.contains(" 404 "));
|
||||
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerAdvertisingSPDYAndHTTPSpeaksDefaultProtocolWhenNPNMissing() throws Exception
|
||||
{
|
||||
InetSocketAddress address = startServer(null);
|
||||
connector.putAsyncConnectionFactory("http/1.1", new ServerHTTPAsyncConnectionFactory(connector));
|
||||
connector.setDefaultProtocol("http/1.1");
|
||||
|
||||
SslContextFactory sslContextFactory = newSslContextFactory();
|
||||
sslContextFactory.start();
|
||||
SSLContext sslContext = sslContextFactory.getSslContext();
|
||||
SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort());
|
||||
client.setUseClientMode(true);
|
||||
client.setSoTimeout(5000);
|
||||
|
||||
NextProtoNego.put(client, new NextProtoNego.ClientProvider()
|
||||
{
|
||||
@Override
|
||||
public boolean supports()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String selectProtocol(List<String> strings)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
client.startHandshake();
|
||||
|
||||
// Verify that the server really speaks http/1.1
|
||||
|
||||
OutputStream output = client.getOutputStream();
|
||||
output.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost:" + address.getPort() + "\r\n" +
|
||||
"\r\n" +
|
||||
"").getBytes("UTF-8"));
|
||||
output.flush();
|
||||
|
||||
InputStream input = client.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
|
||||
String line = reader.readLine();
|
||||
Assert.assertTrue(line.contains(" 404 "));
|
||||
|
||||
client.close();
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -39,7 +39,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-npn-boot</artifactId>
|
||||
<artifactId>npn-boot</artifactId>
|
||||
<version>${npn.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -290,6 +290,15 @@ public class SPDYClient
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported()
|
||||
{
|
||||
// Server does not support NPN, but this is a SPDY client, so hardcode SPDY
|
||||
ClientSPDYAsyncConnectionFactory connectionFactory = new ClientSPDYAsyncConnectionFactory();
|
||||
AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, attachment);
|
||||
sslEndPoint.setConnection(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String selectProtocol(List<String> protocols)
|
||||
{
|
||||
|
|
|
@ -38,6 +38,7 @@ public class SPDYServerConnector extends SelectChannelConnector
|
|||
// Order is important on server side, so we use a LinkedHashMap
|
||||
private final Map<String, AsyncConnectionFactory> factories = new LinkedHashMap<>();
|
||||
private final SslContextFactory sslContextFactory;
|
||||
private volatile String defaultProtocol = "spdy/2";
|
||||
|
||||
public SPDYServerConnector(ServerSessionFrameListener listener)
|
||||
{
|
||||
|
@ -92,6 +93,16 @@ public class SPDYServerConnector extends SelectChannelConnector
|
|||
}
|
||||
}
|
||||
|
||||
public String getDefaultProtocol()
|
||||
{
|
||||
return defaultProtocol;
|
||||
}
|
||||
|
||||
public void setDefaultProtocol(String defaultProtocol)
|
||||
{
|
||||
this.defaultProtocol = defaultProtocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AsyncConnection newConnection(final SocketChannel channel, AsyncEndPoint endPoint)
|
||||
{
|
||||
|
@ -104,6 +115,12 @@ public class SPDYServerConnector extends SelectChannelConnector
|
|||
|
||||
NextProtoNego.put(engine, new NextProtoNego.ServerProvider()
|
||||
{
|
||||
@Override
|
||||
public void unsupported()
|
||||
{
|
||||
protocolSelected(getDefaultProtocol());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> protocols()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue