Revert ALPN and java 8 changes to move to another branch

Reverts e9ecd8c,2f22a10,addc49f,f4e4b09,cf1c245
Disabled unit test from commit 47e7583
This commit is contained in:
Greg Wilkins 2014-03-19 12:54:04 +11:00
parent e9ecd8c966
commit a85b855921
46 changed files with 919 additions and 1762 deletions

View File

@ -72,7 +72,7 @@ public class SpdyConnector
new HTTPSPDYServerConnectionFactory(3,https_config,new ReferrerPushStrategy());
// NPN Factory
SPDYServerConnectionFactory.checkProtocolNegotiationAvailable();
SPDYServerConnectionFactory.checkNPNAvailable();
NPNServerConnectionFactory npn =
new NPNServerConnectionFactory(spdy3.getProtocol(),spdy2.getProtocol(),http.getDefaultProtocol());
npn.setDefaultProtocol(http.getDefaultProtocol());

View File

@ -110,7 +110,7 @@ public class SpdyServer
// Spdy Connector
// Make sure that the required NPN implementations are available.
SPDYServerConnectionFactory.checkProtocolNegotiationAvailable();
SPDYServerConnectionFactory.checkNPNAvailable();
// A ReferrerPushStrategy is being initialized.
// See: http://www.eclipse.org/jetty/documentation/current/spdy-configuring-push.html for more details.

View File

@ -20,7 +20,6 @@
<module>spdy-http-common</module>
<module>spdy-http-server</module>
<module>spdy-http-client-transport</module>
<module>spdy-alpn-tests</module>
<module>spdy-example-webapp</module>
</modules>
@ -71,16 +70,4 @@
</plugins>
</build>
<profiles>
<profile>
<id>jdk7-npn</id>
<activation>
<jdk>[1.7,1.8)</jdk>
</activation>
<modules>
<module>spdy-npn-tests</module>
</modules>
</profile>
</profiles>
</project>

View File

@ -1,89 +0,0 @@
<?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.spdy</groupId>
<artifactId>spdy-parent</artifactId>
<version>9.1.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spdy-alpn-tests</artifactId>
<name>Jetty :: SPDY :: ALPN Tests</name>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.mortbay.jetty.alpn</groupId>
<artifactId>alpn-boot</artifactId>
<version>${alpn.version}</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/alpn</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar</argLine>
</configuration>
</plugin>
</plugins>
</build>
<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-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-http-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-http-server</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,216 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Test;
public class ALPNNegotiationTest extends AbstractALPNTest
{
@Test
public void testClientAdvertisingHTTPServerSpeaksHTTP() throws Exception
{
InetSocketAddress address = prepare();
connector.addConnectionFactory(new HttpConnectionFactory());
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLContext sslContext = sslContextFactory.getSslContext();
try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort()))
{
client.setUseClientMode(true);
client.setSoTimeout(5000);
ALPN.put(client, new ALPN.ClientProvider()
{
@Override
public boolean supports()
{
return true;
}
@Override
public void unsupported()
{
}
@Override
public List<String> protocols()
{
return Arrays.asList("http/1.1");
}
@Override
public void selected(String protocol)
{
Assert.assertEquals("http/1.1", 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(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
}
}
@Test
public void testClientAdvertisingMultipleProtocolsServerSpeaksHTTPWhenNegotiated() throws Exception
{
InetSocketAddress address = prepare();
connector.addConnectionFactory(new HttpConnectionFactory());
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLContext sslContext = sslContextFactory.getSslContext();
try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort()))
{
client.setUseClientMode(true);
client.setSoTimeout(5000);
ALPN.put(client, new ALPN.ClientProvider()
{
@Override
public boolean supports()
{
return true;
}
@Override
public void unsupported()
{
}
@Override
public List<String> protocols()
{
return Arrays.asList("unknown/1.0", "http/1.1");
}
@Override
public void selected(String protocol)
{
Assert.assertEquals("http/1.1", 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(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
}
}
@Test
public void testClientNotSupportingALPNServerSpeaksDefaultProtocol() throws Exception
{
InetSocketAddress address = prepare();
connector.addConnectionFactory(new HttpConnectionFactory());
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLContext sslContext = sslContextFactory.getSslContext();
try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort()))
{
client.setUseClientMode(true);
client.setSoTimeout(5000);
ALPN.put(client, new ALPN.ClientProvider()
{
@Override
public boolean supports()
{
return false;
}
@Override
public void unsupported()
{
}
@Override
public List<String> protocols()
{
return null;
}
@Override
public void selected(String s)
{
}
});
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(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
}
}
}

View File

@ -1,160 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.List;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Test;
public class ALPNSynReplyTest extends AbstractALPNTest
{
@Test
public void testGentleCloseDuringHandshake() throws Exception
{
InetSocketAddress address = prepare();
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLEngine sslEngine = sslContextFactory.newSSLEngine(address);
sslEngine.setUseClientMode(true);
ALPN.put(sslEngine, new ALPN.ClientProvider()
{
@Override
public boolean supports()
{
return true;
}
@Override
public void unsupported()
{
}
@Override
public List<String> protocols()
{
return null;
}
@Override
public void selected(String protocol)
{
}
});
sslEngine.beginHandshake();
ByteBuffer encrypted = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize());
sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted);
encrypted.flip();
try (SocketChannel channel = SocketChannel.open(address))
{
// Send ClientHello, immediately followed by TLS Close Alert and then by FIN
channel.write(encrypted);
sslEngine.closeOutbound();
encrypted.clear();
sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted);
encrypted.flip();
channel.write(encrypted);
channel.shutdownOutput();
// Read ServerHello from server
encrypted.clear();
int read = channel.read(encrypted);
encrypted.flip();
Assert.assertTrue(read > 0);
// Cannot decrypt, as the SSLEngine has been already closed
// Now if we read more, we should either read the TLS Close Alert, or directly -1
encrypted.clear();
read = channel.read(encrypted);
// Sending a TLS Close Alert during handshake results in an exception when
// unwrapping that the server react to by closing the connection abruptly.
Assert.assertTrue(read < 0);
}
}
@Test
public void testAbruptCloseDuringHandshake() throws Exception
{
InetSocketAddress address = prepare();
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLEngine sslEngine = sslContextFactory.newSSLEngine(address);
sslEngine.setUseClientMode(true);
ALPN.put(sslEngine, new ALPN.ClientProvider()
{
@Override
public boolean supports()
{
return true;
}
@Override
public void unsupported()
{
}
@Override
public List<String> protocols()
{
return null;
}
@Override
public void selected(String s)
{
}
});
sslEngine.beginHandshake();
ByteBuffer encrypted = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize());
sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted);
encrypted.flip();
try (SocketChannel channel = SocketChannel.open(address))
{
// Send ClientHello, immediately followed by FIN (no TLS Close Alert)
channel.write(encrypted);
channel.shutdownOutput();
// Read ServerHello from server
encrypted.clear();
int read = channel.read(encrypted);
encrypted.flip();
Assert.assertTrue(read > 0);
ByteBuffer decrypted = ByteBuffer.allocate(sslEngine.getSession().getApplicationBufferSize());
sslEngine.unwrap(encrypted, decrypted);
// Now if we read more, we should either read the TLS Close Alert, or directly -1
encrypted.clear();
read = channel.read(encrypted);
// Since we have close the connection abruptly, the server also does so
Assert.assertTrue(read < 0);
}
}
}

View File

@ -1,77 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.net.InetSocketAddress;
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.spdy.client.SPDYClient;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.After;
import org.junit.Rule;
public class AbstractALPNTest
{
@Rule
public final TestTracker tracker = new TestTracker();
protected Server server;
protected SPDYServerConnector connector;
protected SPDYClient.Factory clientFactory;
protected InetSocketAddress prepare() throws Exception
{
server = new Server();
connector = new SPDYServerConnector(server, newSslContextFactory(), null, new ALPNServerConnectionFactory("spdy/3", "spdy/2", "http/1.1"));
connector.setPort(0);
connector.setIdleTimeout(30000);
server.addConnector(connector);
server.start();
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setName(threadPool.getName() + "-client");
clientFactory = new SPDYClient.Factory(threadPool);
clientFactory.start();
ALPN.debug = true;
return new InetSocketAddress("localhost", connector.getLocalPort());
}
protected SslContextFactory newSslContextFactory()
{
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks");
sslContextFactory.setTrustStorePassword("storepwd");
sslContextFactory.setProtocol("TLSv1");
sslContextFactory.setIncludeProtocols("TLSv1");
return sslContextFactory;
}
@After
public void dispose() throws Exception
{
clientFactory.stop();
server.stop();
}
}

View File

@ -1,2 +0,0 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
#org.eclipse.jetty.spdy.LEVEL=DEBUG

View File

@ -17,6 +17,36 @@
<url>http://www.eclipse.org/jetty</url>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.mortbay.jetty.npn</groupId>
<artifactId>npn-boot</artifactId>
<version>${npn.version}</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/npn</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xbootclasspath/p:${project.build.directory}/npn/npn-boot-${npn.version}.jar</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>

View File

@ -16,6 +16,36 @@
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.mortbay.jetty.npn</groupId>
<artifactId>npn-boot</artifactId>
<version>${npn.version}</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/npn</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xbootclasspath/p:${project.build.directory}/npn/npn-boot-${npn.version}.jar</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>

View File

@ -33,18 +33,35 @@
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>artifact-jars</id>
<id>copy</id>
<phase>generate-resources</phase>
<goals>
<goal>jar</goal>
<goal>test-jar</goal>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.mortbay.jetty.npn</groupId>
<artifactId>npn-boot</artifactId>
<version>${npn.version}</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/npn</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xbootclasspath/p:${project.build.directory}/npn/npn-boot-${npn.version}.jar</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
@ -110,6 +127,12 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-start</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>

View File

@ -19,14 +19,12 @@
package org.eclipse.jetty.spdy.server.proxy;
import java.util.Objects;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.server.NPNServerConnectionFactory;
import org.eclipse.jetty.spdy.server.NegotiatingServerConnectionFactory;
import org.eclipse.jetty.spdy.server.SPDYServerConnectionFactory;
import org.eclipse.jetty.util.ssl.SslContextFactory;
@ -39,7 +37,7 @@ public class HTTPSPDYProxyServerConnector extends ServerConnector
public HTTPSPDYProxyServerConnector(Server server, HttpConfiguration config, ProxyEngineSelector proxyEngineSelector)
{
super(server, (SslContextFactory)null, new ProxyHTTPConnectionFactory(config, SPDY.V2, proxyEngineSelector));
this(server, null, config, proxyEngineSelector);
}
public HTTPSPDYProxyServerConnector(Server server, SslContextFactory sslContextFactory, ProxyEngineSelector proxyEngineSelector)
@ -49,15 +47,16 @@ public class HTTPSPDYProxyServerConnector extends ServerConnector
public HTTPSPDYProxyServerConnector(Server server, SslContextFactory sslContextFactory, HttpConfiguration config, ProxyEngineSelector proxyEngineSelector)
{
this(server, sslContextFactory, config, proxyEngineSelector, new NPNServerConnectionFactory("spdy/3", "spdy/2", "http/1.1"));
}
public HTTPSPDYProxyServerConnector(Server server, SslContextFactory sslContextFactory, HttpConfiguration config, ProxyEngineSelector proxyEngineSelector, NegotiatingServerConnectionFactory negotiatingFactory)
{
super(server, Objects.requireNonNull(sslContextFactory), negotiatingFactory,
new SPDYServerConnectionFactory(SPDY.V3, proxyEngineSelector),
new SPDYServerConnectionFactory(SPDY.V2, proxyEngineSelector),
new ProxyHTTPConnectionFactory(config, SPDY.V2, proxyEngineSelector));
negotiatingFactory.setDefaultProtocol("http/1.1");
super(server,
sslContextFactory,
sslContextFactory == null
? new ConnectionFactory[]{new ProxyHTTPConnectionFactory(config, SPDY.V2, proxyEngineSelector)}
: new ConnectionFactory[]{new NPNServerConnectionFactory("spdy/3", "spdy/2", "http/1.1"),
new SPDYServerConnectionFactory(SPDY.V3, proxyEngineSelector),
new SPDYServerConnectionFactory(SPDY.V2, proxyEngineSelector),
new ProxyHTTPConnectionFactory(config, SPDY.V2, proxyEngineSelector)});
NPNServerConnectionFactory npnConnectionFactory = getConnectionFactory(NPNServerConnectionFactory.class);
if (npnConnectionFactory != null)
npnConnectionFactory.setDefaultProtocol("http/1.1");
}
}

View File

@ -18,6 +18,9 @@
package org.eclipse.jetty.spdy.server;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@ -42,14 +45,8 @@ import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@RunWith(Parameterized.class)
public class NPNModuleTest
public class NpnModuleTest
{
/** This is here to prevent pointless download attempts */
private static final List<String> KNOWN_GOOD_NPN_URLS = new ArrayList<>();
@ -69,7 +66,7 @@ public class NPNModuleTest
@Parameters(name = "{index}: mod:{0}")
public static List<Object[]> data()
{
File npnBootModDir = MavenTestingUtils.getProjectDir("../spdy-http-server/src/main/config/modules/npn");
File npnBootModDir = MavenTestingUtils.getProjectDir("src/main/config/modules/npn");
List<Object[]> data = new ArrayList<>();
for (File file : npnBootModDir.listFiles())
{
@ -89,8 +86,8 @@ public class NPNModuleTest
@BeforeClass
public static void initBaseHome()
{
File homeDir = MavenTestingUtils.getProjectDir("../spdy-http-server/src/main/config");
File baseDir = MavenTestingUtils.getTargetTestingDir(NPNModuleTest.class.getName());
File homeDir = MavenTestingUtils.getProjectDir("src/main/config");
File baseDir = MavenTestingUtils.getTargetTestingDir(NpnModuleTest.class.getName());
FS.ensureEmpty(baseDir);
basehome = new BaseHome(homeDir,baseDir);
}
@ -142,7 +139,7 @@ public class NPNModuleTest
public static void main(String[] args)
{
File outputDir = MavenTestingUtils.getTargetTestingDir(NPNModuleTest.class.getSimpleName() + "-main");
File outputDir = MavenTestingUtils.getTargetTestingDir(NpnModuleTest.class.getSimpleName() + "-main");
FS.ensureEmpty(outputDir);
for (String ref : KNOWN_GOOD_NPN_URLS)
{

View File

@ -73,6 +73,11 @@ public abstract class AbstractHTTPSPDYTest
this.version = version;
}
protected InetSocketAddress startHTTPServer(Handler handler) throws Exception
{
return startHTTPServer(SPDY.V2, handler, 30000);
}
protected InetSocketAddress startHTTPServer(short version, Handler handler, long idleTimeout) throws Exception
{
QueuedThreadPool threadPool = new QueuedThreadPool(256);
@ -84,6 +89,7 @@ public abstract class AbstractHTTPSPDYTest
server.addConnector(connector);
server.setHandler(handler);
server.start();
server.dumpStdErr();
return new InetSocketAddress("localhost", connector.getLocalPort());
}
@ -98,7 +104,13 @@ public abstract class AbstractHTTPSPDYTest
HttpConfiguration httpConfiguration = new HttpConfiguration();
httpConfiguration.setSendServerVersion(true);
httpConfiguration.setSendXPoweredBy(true);
return new HTTPSPDYServerConnector(server, version, httpConfiguration, new PushStrategy.None());
HTTPSPDYServerConnector connector = new HTTPSPDYServerConnector(server,version, httpConfiguration, new PushStrategy.None());
return connector;
}
protected Session startClient(InetSocketAddress socketAddress, SessionFrameListener listener) throws Exception
{
return startClient(SPDY.V2, socketAddress, listener);
}
protected Session startClient(short version, InetSocketAddress socketAddress, SessionFrameListener listener) throws Exception

View File

@ -0,0 +1,255 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server.http;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
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.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.spdy.server.SPDYServerConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
public class ProtocolNegotiationTest
{
@Rule
public final TestWatcher testName = new TestWatcher()
{
@Override
public void starting(Description description)
{
super.starting(description);
System.err.printf("Running %s.%s()%n",
description.getClassName(),
description.getMethodName());
}
};
protected Server server;
protected SPDYServerConnector connector;
protected InetSocketAddress startServer(SPDYServerConnector connector) throws Exception
{
server = new Server();
if (connector == null)
connector = new SPDYServerConnector(server, newSslContextFactory(), null);
connector.setPort(0);
connector.setIdleTimeout(30000);
this.connector = connector;
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.setTrustStorePath("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.addConnectionFactory(new HttpConnectionFactory());
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);
String protocol = "http/1.1";
Assert.assertTrue(strings.contains(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(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
client.close();
}
@Test
public void testServerAdvertisingSPDYAndHTTPSpeaksHTTPWhenNegotiated() throws Exception
{
InetSocketAddress address = startServer(null);
connector.addConnectionFactory(new HttpConnectionFactory());
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);
String spdyProtocol = "spdy/2";
Assert.assertTrue(strings.contains(spdyProtocol));
String httpProtocol = "http/1.1";
Assert.assertTrue(strings.contains(httpProtocol));
Assert.assertTrue(strings.indexOf(spdyProtocol) < strings.indexOf(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(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
client.close();
}
@Test
public void testServerAdvertisingSPDYAndHTTPSpeaksDefaultProtocolWhenNPNMissing() throws Exception
{
InetSocketAddress address = startServer(null);
connector.addConnectionFactory(new HttpConnectionFactory());
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(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
client.close();
}
}

View File

@ -18,6 +18,9 @@
package org.eclipse.jetty.spdy.server.proxy;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@ -50,35 +53,49 @@ import org.eclipse.jetty.spdy.client.SPDYClient;
import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
import org.eclipse.jetty.spdy.server.SPDYServerConnectionFactory;
import org.eclipse.jetty.spdy.server.SPDYServerConnector;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@RunWith(Parameterized.class)
public class ProxyHTTPToSPDYTest
{
private static final Logger LOG = Log.getLogger(ProxyHTTPToSPDYTest.class);
@Rule
public final TestWatcher testName = new TestWatcher()
{
@Override
public void starting(Description description)
{
super.starting(description);
System.err.printf("Running %s.%s()%n",
description.getClassName(),
description.getMethodName());
}
};
private final short version;
private HttpClient httpClient;
private HttpClient httpClient2;
@Parameterized.Parameters
public static Collection<Short[]> parameters()
{
return Arrays.asList(new Short[]{SPDY.V2}, new Short[]{SPDY.V3});
}
@Rule
public final TestTracker tracker = new TestTracker();
private final short version;
private HttpClient httpClient;
private HttpClient httpClient2;
private SPDYClient.Factory factory;
private Server server;
private Server proxy;

View File

@ -18,6 +18,11 @@
package org.eclipse.jetty.spdy.server.proxy;
import static junit.framework.Assert.fail;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
@ -33,13 +38,13 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
@ -53,9 +58,7 @@ import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.client.SPDYClient;
import org.eclipse.jetty.spdy.server.NegotiatingServerConnectionFactory;
import org.eclipse.jetty.spdy.server.http.SPDYTestUtils;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.IO;
@ -68,19 +71,33 @@ import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import static junit.framework.Assert.fail;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
@Ignore
@RunWith(value = Parameterized.class)
public abstract class ProxySPDYToHTTPLoadTest
public class ProxySPDYToHTTPLoadTest
{
private static final Logger LOG = Log.getLogger(ProxySPDYToHTTPLoadTest.class);
@Rule
public final TestWatcher testName = new TestWatcher()
{
@Override
public void starting(Description description)
{
super.starting(description);
System.err.printf("Running %s.%s()%n",
description.getClassName(),
description.getMethodName());
}
};
private final short version;
private final String server1String = "server1";
private final String server2String = "server2";
@Parameterized.Parameters
public static Collection<Short[]> parameters()
@ -88,12 +105,6 @@ public abstract class ProxySPDYToHTTPLoadTest
return Arrays.asList(new Short[]{SPDY.V2}, new Short[]{SPDY.V3});
}
@Rule
public final TestTracker tracker = new TestTracker();
private final short version;
private final NegotiatingServerConnectionFactory negotiator;
private final String server1String = "server1";
private final String server2String = "server2";
private SPDYClient.Factory factory;
private Server server1;
private Server server2;
@ -101,10 +112,9 @@ public abstract class ProxySPDYToHTTPLoadTest
private ServerConnector proxyConnector;
private SslContextFactory sslContextFactory = SPDYTestUtils.newSslContextFactory();
public ProxySPDYToHTTPLoadTest(short version, NegotiatingServerConnectionFactory negotiator)
public ProxySPDYToHTTPLoadTest(short version)
{
this.version = version;
this.negotiator = negotiator;
}
@Before
@ -178,7 +188,7 @@ public abstract class ProxySPDYToHTTPLoadTest
proxyEngineSelector.putProxyServerInfo("127.0.0.2", new ProxyEngineSelector.ProxyServerInfo("http/1.1",
server2.getHostName(), server2.getPort()));
proxyConnector = new HTTPSPDYProxyServerConnector(proxy, sslContextFactory, new HttpConfiguration(), proxyEngineSelector, negotiator);
proxyConnector = new HTTPSPDYProxyServerConnector(proxy, sslContextFactory, proxyEngineSelector);
proxyConnector.setPort(0);
proxyConnector.setIdleTimeout(proxyConnectorTimeout);
proxy.addConnector(proxyConnector);

View File

@ -18,6 +18,11 @@
package org.eclipse.jetty.spdy.server.proxy;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -27,6 +32,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -55,7 +61,6 @@ import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.client.SPDYClient;
import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
import org.eclipse.jetty.spdy.server.http.SPDYTestUtils;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.log.Log;
@ -66,19 +71,28 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
@RunWith(value = Parameterized.class)
public abstract class ProxySPDYToHTTPTest
public class ProxySPDYToHTTPTest
{
@Rule
public final TestTracker tracker = new TestTracker();
public final TestWatcher testName = new TestWatcher()
{
@Override
public void starting(Description description)
{
super.starting(description);
System.err.printf("Running %s.%s()%n",
description.getClassName(),
description.getMethodName());
}
};
private final short version;
@Parameterized.Parameters

View File

@ -18,6 +18,10 @@
package org.eclipse.jetty.spdy.server.proxy;
import static junit.framework.Assert.fail;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.io.ByteArrayOutputStream;
import java.net.InetSocketAddress;
import java.util.ArrayList;
@ -48,7 +52,6 @@ import org.eclipse.jetty.spdy.client.SPDYClient;
import org.eclipse.jetty.spdy.server.SPDYServerConnectionFactory;
import org.eclipse.jetty.spdy.server.SPDYServerConnector;
import org.eclipse.jetty.spdy.server.http.SPDYTestUtils;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.ssl.SslContextFactory;
@ -57,18 +60,28 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import static junit.framework.Assert.fail;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
@RunWith(value = Parameterized.class)
public abstract class ProxySPDYToSPDYLoadTest
public class ProxySPDYToSPDYLoadTest
{
@Rule
public final TestTracker tracker = new TestTracker();
public final TestWatcher testName = new TestWatcher()
{
@Override
public void starting(Description description)
{
super.starting(description);
System.err.printf("Running %s.%s()%n",
description.getClassName(),
description.getMethodName());
}
};
private final short version;
@Parameterized.Parameters

View File

@ -18,6 +18,9 @@
package org.eclipse.jetty.spdy.server.proxy;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import java.io.ByteArrayOutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
@ -49,7 +52,6 @@ import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
import org.eclipse.jetty.spdy.server.SPDYServerConnectionFactory;
import org.eclipse.jetty.spdy.server.SPDYServerConnector;
import org.eclipse.jetty.spdy.server.http.SPDYTestUtils;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.Promise;
@ -59,17 +61,27 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
@RunWith(value = Parameterized.class)
public abstract class ProxySPDYToSPDYTest
public class ProxySPDYToSPDYTest
{
@Rule
public final TestTracker tracker = new TestTracker();
public final TestWatcher testName = new TestWatcher()
{
@Override
public void starting(Description description)
{
super.starting(description);
System.err.printf("Running %s.%s()%n",
description.getClassName(),
description.getMethodName());
}
};
private final short version;
@Parameterized.Parameters

View File

@ -1,95 +0,0 @@
<?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.spdy</groupId>
<artifactId>spdy-parent</artifactId>
<version>9.1.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spdy-npn-tests</artifactId>
<name>Jetty :: SPDY :: NPN Tests</name>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.mortbay.jetty.npn</groupId>
<artifactId>npn-boot</artifactId>
<version>${npn.version}</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/npn</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xbootclasspath/p:${project.build.directory}/npn/npn-boot-${npn.version}.jar</argLine>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.npn</groupId>
<artifactId>npn-api</artifactId>
<version>${npn.api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-start</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-http-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-http-server</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,77 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.net.InetSocketAddress;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.spdy.client.SPDYClient;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.After;
import org.junit.Rule;
public class AbstractNPNTest
{
@Rule
public final TestTracker tracker = new TestTracker();
protected Server server;
protected SPDYServerConnector connector;
protected SPDYClient.Factory clientFactory;
protected InetSocketAddress prepare() throws Exception
{
server = new Server();
connector = new SPDYServerConnector(server, newSslContextFactory(), null);
connector.setPort(0);
connector.setIdleTimeout(30000);
server.addConnector(connector);
server.start();
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setName(threadPool.getName() + "-client");
clientFactory = new SPDYClient.Factory(threadPool);
clientFactory.start();
NextProtoNego.debug = true;
return new InetSocketAddress("localhost", connector.getLocalPort());
}
protected SslContextFactory newSslContextFactory()
{
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks");
sslContextFactory.setTrustStorePassword("storepwd");
sslContextFactory.setProtocol("TLSv1");
sslContextFactory.setIncludeProtocols("TLSv1");
return sslContextFactory;
}
@After
public void dispose() throws Exception
{
clientFactory.stop();
server.stop();
}
}

View File

@ -1,207 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
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.HttpConnectionFactory;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Test;
public class NPNNegotiationTest extends AbstractNPNTest
{
@Test
public void testServerAdvertisingHTTPSpeaksHTTP() throws Exception
{
InetSocketAddress address = prepare();
connector.addConnectionFactory(new HttpConnectionFactory());
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLContext sslContext = sslContextFactory.getSslContext();
try (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);
String protocol = "http/1.1";
Assert.assertTrue(strings.contains(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(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
}
}
@Test
public void testServerAdvertisingSPDYAndHTTPSpeaksHTTPWhenNegotiated() throws Exception
{
InetSocketAddress address = prepare();
connector.addConnectionFactory(new HttpConnectionFactory());
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLContext sslContext = sslContextFactory.getSslContext();
try (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);
String spdyProtocol = "spdy/2";
Assert.assertTrue(strings.contains(spdyProtocol));
String httpProtocol = "http/1.1";
Assert.assertTrue(strings.contains(httpProtocol));
Assert.assertTrue(strings.indexOf(spdyProtocol) < strings.indexOf(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(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
}
}
@Test
public void testServerAdvertisingSPDYAndHTTPSpeaksDefaultProtocolWhenNPNMissing() throws Exception
{
InetSocketAddress address = prepare();
connector.addConnectionFactory(new HttpConnectionFactory());
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLContext sslContext = sslContextFactory.getSslContext();
try (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(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
}
}
}

View File

@ -1,29 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server.proxy;
import org.eclipse.jetty.spdy.server.NPNServerConnectionFactory;
public class NPNProxySPDYToHTTPLoadTest extends ProxySPDYToHTTPLoadTest
{
public NPNProxySPDYToHTTPLoadTest(short version)
{
super(version, new NPNServerConnectionFactory("spdy/3", "spdy/2", "http/1.1"));
}
}

View File

@ -1,27 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server.proxy;
public class NPNProxySPDYToHTTPTest extends ProxySPDYToHTTPTest
{
public NPNProxySPDYToHTTPTest(short version)
{
super(version);
}
}

View File

@ -1,27 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server.proxy;
public class NPNProxySPDYToSPDYLoadTest extends ProxySPDYToSPDYLoadTest
{
public NPNProxySPDYToSPDYLoadTest(short version)
{
super(version);
}
}

View File

@ -1,27 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server.proxy;
public class NPNProxySPDYToSPDYTest extends ProxySPDYToSPDYTest
{
public NPNProxySPDYToSPDYTest(short version)
{
super(version);
}
}

View File

@ -1,2 +0,0 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
#org.eclipse.jetty.spdy.LEVEL=DEBUG

View File

@ -17,6 +17,36 @@
<url>http://www.eclipse.org/jetty</url>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.mortbay.jetty.npn</groupId>
<artifactId>npn-boot</artifactId>
<version>${npn.version}</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/npn</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xbootclasspath/p:${project.build.directory}/npn/npn-boot-${npn.version}.jar</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
@ -61,12 +91,6 @@
<version>${npn.api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.alpn</groupId>
<artifactId>alpn-api</artifactId>
<version>${alpn.api.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,76 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.util.Collections;
import java.util.List;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class ALPNServerConnection extends NegotiatingServerConnection implements ALPN.ServerProvider
{
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.<String>emptyList());
}
@Override
public String select(List<String> clientProtocols)
{
List<String> serverProtocols = getProtocols();
String negotiated = null;
for (String clientProtocol : clientProtocols)
{
if (serverProtocols.contains(clientProtocol))
{
negotiated = clientProtocol;
break;
}
}
if (negotiated == null)
{
negotiated = getDefaultProtocol();
}
LOG.debug("{} protocol selected {}", this, negotiated);
setProtocol(negotiated);
ALPN.remove(getSSLEngine());
return negotiated;
}
@Override
public void close()
{
ALPN.remove(getSSLEngine());
super.close();
}
}

View File

@ -1,60 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.util.List;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Connector;
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
{
private static final Logger LOG = Log.getLogger(ALPNServerConnectionFactory.class);
public ALPNServerConnectionFactory(@Name("protocols") String... protocols)
{
super("alpn", protocols);
try
{
ClassLoader alpnClassLoader = ALPN.class.getClassLoader();
if (alpnClassLoader != null)
{
LOG.warn("ALPN must be in the boot classloader, not in: " + alpnClassLoader);
throw new IllegalStateException("ALPN must be in the boot classloader");
}
}
catch (Throwable x)
{
LOG.warn("ALPN not available", x);
throw new IllegalStateException("ALPN not available", x);
}
}
@Override
protected AbstractConnection newServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol)
{
return new ALPNServerConnection(connector, endPoint, engine, protocols, defaultProtocol);
}
}

View File

@ -18,49 +18,146 @@
package org.eclipse.jetty.spdy.server;
import java.io.IOException;
import java.util.List;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class NPNServerConnection extends NegotiatingServerConnection implements NextProtoNego.ServerProvider
public class NPNServerConnection extends AbstractConnection implements NextProtoNego.ServerProvider
{
private static final Logger LOG = Log.getLogger(NPNServerConnection.class);
private final Logger LOG = Log.getLogger(getClass());
private final Connector connector;
private final SSLEngine engine;
private final List<String> protocols;
private final String defaultProtocol;
private String nextProtocol; // No need to be volatile: it is modified and read by the same thread
public NPNServerConnection(EndPoint endPoint, SSLEngine engine, Connector connector, List<String> protocols, String defaultProtocol)
{
super(connector, endPoint, engine, protocols, defaultProtocol);
super(endPoint, connector.getExecutor());
this.connector = connector;
this.protocols = protocols;
this.defaultProtocol = defaultProtocol;
this.engine = engine;
NextProtoNego.put(engine, this);
}
@Override
public void onOpen()
{
super.onOpen();
fillInterested();
}
@Override
public void onFillable()
{
int filled = fill();
if (filled == 0)
{
if (nextProtocol == null)
{
if (engine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
{
// Here the SSL handshake is finished, but while the client sent
// the NPN extension, the server application did not select the
// protocol; we need to close as the protocol cannot be negotiated.
LOG.debug("{} missing next protocol. SSLEngine: {}", this, engine);
close();
}
else
{
// Here the SSL handshake is not finished yet but we filled 0 bytes,
// so we need to read more.
fillInterested();
}
}
else
{
ConnectionFactory connectionFactory = connector.getConnectionFactory(nextProtocol);
if (connectionFactory == null)
{
LOG.debug("{} application selected protocol '{}', but no correspondent {} has been configured",
this, nextProtocol, ConnectionFactory.class.getName());
close();
}
else
{
EndPoint endPoint = getEndPoint();
Connection oldConnection = endPoint.getConnection();
Connection newConnection = connectionFactory.newConnection(connector, endPoint);
LOG.debug("{} switching from {} to {}", this, oldConnection, newConnection);
oldConnection.onClose();
endPoint.setConnection(newConnection);
getEndPoint().getConnection().onOpen();
}
}
}
else if (filled < 0)
{
// Something went bad, we need to close.
LOG.debug("{} closing on client close", this);
close();
}
else
{
// Must never happen, since we fill using an empty buffer
throw new IllegalStateException();
}
}
private int fill()
{
try
{
return getEndPoint().fill(BufferUtil.EMPTY_BUFFER);
}
catch (IOException x)
{
LOG.debug(x);
close();
return -1;
}
}
@Override
public void unsupported()
{
protocolSelected(getDefaultProtocol());
protocolSelected(defaultProtocol);
}
@Override
public List<String> protocols()
{
return getProtocols();
return protocols;
}
@Override
public void protocolSelected(String protocol)
{
LOG.debug("{} protocol selected {}", this, protocol);
setProtocol(protocol != null ? protocol : getDefaultProtocol());
NextProtoNego.remove(getSSLEngine());
nextProtocol = protocol != null ? protocol : defaultProtocol;
NextProtoNego.remove(engine);
}
@Override
public void close()
{
NextProtoNego.remove(getSSLEngine());
super.close();
NextProtoNego.remove(engine);
EndPoint endPoint = getEndPoint();
endPoint.shutdownOutput();
endPoint.close();
}
}

View File

@ -16,45 +16,106 @@
// ========================================================================
//
package org.eclipse.jetty.spdy.server;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.AbstractConnectionFactory;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class NPNServerConnectionFactory extends NegotiatingServerConnectionFactory
public class NPNServerConnectionFactory extends AbstractConnectionFactory
{
private static final Logger LOG = Log.getLogger(NPNServerConnectionFactory.class);
private final List<String> _protocols;
private String _defaultProtocol;
public NPNServerConnectionFactory(@Name("protocols") String... protocols)
/* ------------------------------------------------------------ */
/**
* @param protocols List of supported protocols in priority order
*/
public NPNServerConnectionFactory(@Name("protocols")String... protocols)
{
super("npn", protocols);
super("npn");
_protocols=Arrays.asList(protocols);
try
{
ClassLoader npnClassLoader = NextProtoNego.class.getClassLoader();
if (npnClassLoader != null)
if (NextProtoNego.class.getClassLoader()!=null)
{
LOG.warn("NPN must be in the boot classloader, not in: " + npnClassLoader);
throw new IllegalStateException("NPN must be in the boot classloader");
LOG.warn("NextProtoNego not from bootloader classloader: "+NextProtoNego.class.getClassLoader());
throw new IllegalStateException("NextProtoNego not on bootloader");
}
}
catch (Throwable x)
catch(Throwable th)
{
LOG.warn("NPN not available: " + x);
throw new IllegalStateException("NPN not available", x);
LOG.warn("NextProtoNego not available: "+th);
throw new IllegalStateException("NextProtoNego not available",th);
}
}
public String getDefaultProtocol()
{
return _defaultProtocol;
}
public void setDefaultProtocol(String defaultProtocol)
{
_defaultProtocol = defaultProtocol;
}
public List<String> getProtocols()
{
return _protocols;
}
@Override
protected AbstractConnection newServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol)
public Connection newConnection(Connector connector, EndPoint endPoint)
{
return new NPNServerConnection(endPoint, engine, connector, protocols, defaultProtocol);
List<String> protocols=_protocols;
if (protocols==null || protocols.size()==0)
{
protocols=connector.getProtocols();
for (Iterator<String> i=protocols.iterator();i.hasNext();)
{
String protocol=i.next();
if (protocol.startsWith("SSL-")||protocol.equals("NPN"))
i.remove();
}
}
String dft=_defaultProtocol;
if (dft==null)
dft=_protocols.get(0);
SSLEngine engine=null;
EndPoint ep=endPoint;
while(engine==null && ep!=null)
{
// TODO make more generic
if (ep instanceof SslConnection.DecryptedEndPoint)
engine=((SslConnection.DecryptedEndPoint)ep).getSslConnection().getSSLEngine();
else
ep=null;
}
return configure(new NPNServerConnection(endPoint, engine, connector,protocols,_defaultProtocol),connector,endPoint);
}
@Override
public String toString()
{
return String.format("%s@%x{%s,%s,%s}",this.getClass().getSimpleName(),hashCode(),getProtocol(),getDefaultProtocol(),getProtocols());
}
}

View File

@ -1,163 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.io.IOException;
import java.util.List;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public abstract class NegotiatingServerConnection extends AbstractConnection
{
private static final Logger LOG = Log.getLogger(NegotiatingServerConnection.class);
private final Connector connector;
private final SSLEngine engine;
private final List<String> protocols;
private final String defaultProtocol;
private String protocol; // No need to be volatile: it is modified and read by the same thread
public NegotiatingServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol)
{
super(endPoint, connector.getExecutor());
this.connector = connector;
this.protocols = protocols;
this.defaultProtocol = defaultProtocol;
this.engine = engine;
}
protected List<String> getProtocols()
{
return protocols;
}
protected String getDefaultProtocol()
{
return defaultProtocol;
}
protected SSLEngine getSSLEngine()
{
return engine;
}
protected String getProtocol()
{
return protocol;
}
protected void setProtocol(String protocol)
{
this.protocol = protocol;
}
@Override
public void onOpen()
{
super.onOpen();
fillInterested();
}
@Override
public void onFillable()
{
int filled = fill();
if (filled == 0)
{
if (protocol == null)
{
if (engine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
{
// Here the SSL handshake is finished, but the protocol has not been negotiated.
LOG.debug("{} could not negotiate protocol, SSLEngine: {}", this, engine);
close();
}
else
{
// Here the SSL handshake is not finished yet but we filled 0 bytes,
// so we need to read more.
fillInterested();
}
}
else
{
ConnectionFactory connectionFactory = connector.getConnectionFactory(protocol);
if (connectionFactory == null)
{
LOG.debug("{} application selected protocol '{}', but no correspondent {} has been configured",
this, protocol, ConnectionFactory.class.getName());
close();
}
else
{
EndPoint endPoint = getEndPoint();
Connection oldConnection = endPoint.getConnection();
Connection newConnection = connectionFactory.newConnection(connector, endPoint);
LOG.debug("{} switching from {} to {}", this, oldConnection, newConnection);
oldConnection.onClose();
endPoint.setConnection(newConnection);
getEndPoint().getConnection().onOpen();
}
}
}
else if (filled < 0)
{
// Something went bad, we need to close.
LOG.debug("{} closing on client close", this);
close();
}
else
{
// Must never happen, since we fill using an empty buffer
throw new IllegalStateException();
}
}
private int fill()
{
try
{
return getEndPoint().fill(BufferUtil.EMPTY_BUFFER);
}
catch (IOException x)
{
LOG.debug(x);
close();
return -1;
}
}
@Override
public void close()
{
// Gentler close for SSL.
getEndPoint().shutdownOutput();
super.close();
}
}

View File

@ -1,103 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.server.AbstractConnectionFactory;
import org.eclipse.jetty.server.Connector;
public abstract class NegotiatingServerConnectionFactory extends AbstractConnectionFactory
{
private final List<String> protocols;
private String defaultProtocol;
public NegotiatingServerConnectionFactory(String protocol, String... protocols)
{
super(protocol);
this.protocols = Arrays.asList(protocols);
}
public String getDefaultProtocol()
{
return defaultProtocol;
}
public void setDefaultProtocol(String defaultProtocol)
{
this.defaultProtocol = defaultProtocol;
}
public List<String> getProtocols()
{
return protocols;
}
@Override
public Connection newConnection(Connector connector, EndPoint endPoint)
{
List<String> protocols = this.protocols;
if (protocols.isEmpty())
{
protocols = connector.getProtocols();
Iterator<String> i = protocols.iterator();
while (i.hasNext())
{
String protocol = i.next();
String prefix = "ssl-";
if (protocol.regionMatches(true, 0, prefix, 0, prefix.length()) || protocol.equalsIgnoreCase("alpn"))
{
i.remove();
}
}
}
String dft = defaultProtocol;
if (dft == null && !protocols.isEmpty())
dft = protocols.get(0);
SSLEngine engine = null;
EndPoint ep = endPoint;
while (engine == null && ep != null)
{
// TODO make more generic
if (ep instanceof SslConnection.DecryptedEndPoint)
engine = ((SslConnection.DecryptedEndPoint)ep).getSslConnection().getSSLEngine();
else
ep = null;
}
return configure(newServerConnection(connector, endPoint, engine, protocols, dft), connector, endPoint);
}
protected abstract AbstractConnection newServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol);
@Override
public String toString()
{
return String.format("%s@%x{%s,%s,%s}", getClass().getSimpleName(), hashCode(), getProtocol(), getDefaultProtocol(), getProtocols());
}
}

View File

@ -47,34 +47,19 @@ import org.eclipse.jetty.util.annotation.ManagedObject;
@ManagedObject("SPDY Server Connection Factory")
public class SPDYServerConnectionFactory extends AbstractConnectionFactory
{
/**
* @deprecated use {@link #checkProtocolNegotiationAvailable()} instead.
*/
@Deprecated
// This method is placed here so as to provide a check for NPN before attempting to load any
// NPN classes.
public static void checkNPNAvailable()
{
checkProtocolNegotiationAvailable();
}
public static void checkProtocolNegotiationAvailable()
{
if (!isAvailableInBootClassPath("org.eclipse.jetty.alpn.ALPN") &&
!isAvailableInBootClassPath("org.eclipse.jetty.npn.NextProtoNego"))
throw new IllegalStateException("No ALPN nor NPN classes available");
}
private static boolean isAvailableInBootClassPath(String className)
{
try
{
Class<?> klass = ClassLoader.getSystemClassLoader().loadClass(className);
if (klass.getClassLoader() != null)
throw new IllegalStateException(className + " must be on JVM boot classpath");
return true;
Class<?> npn = ClassLoader.getSystemClassLoader().loadClass("org.eclipse.jetty.npn.NextProtoNego");
if (npn.getClassLoader() != null)
throw new IllegalStateException("NextProtoNego must be on JVM boot path");
}
catch (ClassNotFoundException x)
catch (ClassNotFoundException e)
{
return false;
throw new IllegalStateException("No NextProtoNego on boot path", e);
}
}

View File

@ -18,8 +18,7 @@
package org.eclipse.jetty.spdy.server;
import java.util.Objects;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
@ -31,21 +30,23 @@ public class SPDYServerConnector extends ServerConnector
{
public SPDYServerConnector(Server server, ServerSessionFrameListener listener)
{
super(server, (SslContextFactory)null, new SPDYServerConnectionFactory(SPDY.V2, listener));
this(server, null, listener);
}
public SPDYServerConnector(Server server, SslContextFactory sslContextFactory, ServerSessionFrameListener listener)
{
this(server, sslContextFactory, listener, new NPNServerConnectionFactory("spdy/3", "spdy/2", "http/1.1"));
super(server,
sslContextFactory,
sslContextFactory==null
?new ConnectionFactory[]{new SPDYServerConnectionFactory(SPDY.V2, listener)}
:new ConnectionFactory[]{
new NPNServerConnectionFactory("spdy/3","spdy/2","http/1.1"),
new HttpConnectionFactory(),
new SPDYServerConnectionFactory(SPDY.V2, listener),
new SPDYServerConnectionFactory(SPDY.V3, listener)});
if (getConnectionFactory(NPNServerConnectionFactory.class)!=null)
getConnectionFactory(NPNServerConnectionFactory.class).setDefaultProtocol("http/1.1");
}
public SPDYServerConnector(Server server, SslContextFactory sslContextFactory, ServerSessionFrameListener listener, NegotiatingServerConnectionFactory negotiator)
{
super(server, Objects.requireNonNull(sslContextFactory),
negotiator,
new SPDYServerConnectionFactory(SPDY.V3, listener),
new SPDYServerConnectionFactory(SPDY.V2, listener),
new HttpConnectionFactory());
negotiator.setDefaultProtocol("http/1.1");
}
}

View File

@ -19,20 +19,39 @@
package org.eclipse.jetty.spdy.server;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.client.SPDYClient;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
public class SSLEngineLeakTest extends AbstractNPNTest
public class SSLEngineLeakTest extends AbstractTest
{
@Override
protected SPDYServerConnector newSPDYServerConnector(Server server, ServerSessionFrameListener listener)
{
SslContextFactory sslContextFactory = newSslContextFactory();
return new SPDYServerConnector(server, sslContextFactory, listener);
}
@Override
protected SPDYClient.Factory newSPDYClientFactory(Executor threadPool)
{
SslContextFactory sslContextFactory = newSslContextFactory();
return new SPDYClient.Factory(threadPool, null, sslContextFactory);
}
@Test
@Ignore
public void testSSLEngineLeak() throws Exception
{
System.gc();
@ -48,12 +67,12 @@ public class SSLEngineLeakTest extends AbstractNPNTest
// Allow the close to arrive to the server and the selector to process it
Thread.sleep(1000);
// Perform GC to be sure that the map is cleared
System.gc();
// Perform GC to be sure that the WeakHashMap is cleared
Thread.sleep(1000);
System.gc();
// Check that the map is empty
if (objects.size() != initialSize)
// Check that the WeakHashMap is empty
if (objects.size()!=initialSize)
{
System.err.println(objects);
server.dumpStdErr();
@ -64,8 +83,7 @@ public class SSLEngineLeakTest extends AbstractNPNTest
private void avoidStackLocalVariables() throws Exception
{
InetSocketAddress address = prepare();
Session session = clientFactory.newSPDYClient(SPDY.V3).connect(address, null);
Session session = startClient(startServer(null), null);
session.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
}
}

View File

@ -23,20 +23,48 @@ import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.List;
import java.util.concurrent.Executor;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.client.SPDYClient;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class SSLSynReplyTest extends AbstractNPNTest
public class SSLSynReplyTest extends SynReplyTest
{
@Override
protected SPDYServerConnector newSPDYServerConnector(Server server, ServerSessionFrameListener listener)
{
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.setEndpointIdentificationAlgorithm("");
return new SPDYServerConnector(server, sslContextFactory, listener);
}
@Override
protected SPDYClient.Factory newSPDYClientFactory(Executor threadPool)
{
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.setEndpointIdentificationAlgorithm("");
return new SPDYClient.Factory(threadPool, null, sslContextFactory);
}
@Before
public void init()
{
NextProtoNego.debug = true;
}
@Test
public void testGentleCloseDuringHandshake() throws Exception
{
InetSocketAddress address = prepare();
InetSocketAddress address = startServer(version, null);
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLEngine sslEngine = sslContextFactory.newSSLEngine(address);
@ -96,7 +124,7 @@ public class SSLSynReplyTest extends AbstractNPNTest
@Test
public void testAbruptCloseDuringHandshake() throws Exception
{
InetSocketAddress address = prepare();
InetSocketAddress address = startServer(version, null);
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLEngine sslEngine = sslContextFactory.newSSLEngine(address);

View File

@ -20,6 +20,8 @@ package org.eclipse.jetty.websocket.jsr356;
import static org.hamcrest.Matchers.*;
import org.junit.Ignore;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
@ -57,6 +59,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@Ignore
public class DecoderReaderTest
{
public static class Quotes

286
pom.xml
View File

@ -17,7 +17,6 @@
<slf4j-version>1.6.1</slf4j-version>
<jetty-test-policy-version>1.2</jetty-test-policy-version>
<npn.api.version>1.1.0.v20120525</npn.api.version>
<alpn.api.version>1.0.0</alpn.api.version>
</properties>
<scm>
<connection>scm:git:http://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git</connection>
@ -434,6 +433,7 @@
<module>jetty-client</module>
<module>jetty-proxy</module>
<module>jetty-jaspi</module>
<module>jetty-osgi</module>
<module>jetty-rewrite</module>
<module>jetty-nosql</module>
<module>jetty-quickstart</module>
@ -814,159 +814,137 @@
</build>
</profile>
<profile>
<id>osgi</id>
<activation>
<jdk>[1.7,1.8)</jdk>
</activation>
<modules>
<module>jetty-osgi</module>
</modules>
</profile>
<profile>
<id>7u9</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_9</value>
</property>
</activation>
<properties>
<npn.version>1.1.3.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u10</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_10</value>
</property>
</activation>
<properties>
<npn.version>1.1.3.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u11</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_11</value>
</property>
</activation>
<properties>
<npn.version>1.1.3.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u13</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_13</value>
</property>
</activation>
<properties>
<npn.version>1.1.4.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u15</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_15</value>
</property>
</activation>
<properties>
<npn.version>1.1.5.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u17</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_17</value>
</property>
</activation>
<properties>
<npn.version>1.1.5.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u21</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_21</value>
</property>
</activation>
<properties>
<npn.version>1.1.5.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u25</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_25</value>
</property>
</activation>
<properties>
<npn.version>1.1.5.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u40</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_40</value>
</property>
</activation>
<properties>
<npn.version>1.1.6.v20130911</npn.version>
</properties>
</profile>
<profile>
<id>7u45</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_45</value>
</property>
</activation>
<properties>
<npn.version>1.1.6.v20130911</npn.version>
</properties>
</profile>
<profile>
<id>7u51</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_51</value>
</property>
</activation>
<properties>
<npn.version>1.1.6.v20130911</npn.version>
<alpn.version>7.0.0</alpn.version>
</properties>
</profile>
<profile>
<id>8u00</id>
<activation>
<property>
<name>java.version</name>
<value>1.8.0</value>
</property>
</activation>
<properties>
<alpn.version>8.0.0</alpn.version>
</properties>
</profile>
<id>7u9</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_9</value>
</property>
</activation>
<properties>
<npn.version>1.1.3.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u10</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_10</value>
</property>
</activation>
<properties>
<npn.version>1.1.3.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u11</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_11</value>
</property>
</activation>
<properties>
<npn.version>1.1.3.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u13</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_13</value>
</property>
</activation>
<properties>
<npn.version>1.1.4.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u15</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_15</value>
</property>
</activation>
<properties>
<npn.version>1.1.5.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u17</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_17</value>
</property>
</activation>
<properties>
<npn.version>1.1.5.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u21</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_21</value>
</property>
</activation>
<properties>
<npn.version>1.1.5.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u25</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_25</value>
</property>
</activation>
<properties>
<npn.version>1.1.5.v20130313</npn.version>
</properties>
</profile>
<profile>
<id>7u40</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_40</value>
</property>
</activation>
<properties>
<npn.version>1.1.6.v20130911</npn.version>
</properties>
</profile>
<profile>
<id>7u45</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_45</value>
</property>
</activation>
<properties>
<npn.version>1.1.6.v20130911</npn.version>
</properties>
</profile>
<profile>
<id>7u51</id>
<activation>
<property>
<name>java.version</name>
<value>1.7.0_51</value>
</property>
</activation>
<properties>
<npn.version>1.1.6.v20130911</npn.version>
</properties>
</profile>
</profiles>
</project>

View File

@ -102,7 +102,7 @@ public class TestTransparentProxyServer
// Spdy Connector
SPDYServerConnectionFactory.checkProtocolNegotiationAvailable();
SPDYServerConnectionFactory.checkNPNAvailable();
PushStrategy push = new ReferrerPushStrategy();
HTTPSPDYServerConnectionFactory spdy2 = new HTTPSPDYServerConnectionFactory(2,config,push);
spdy2.setInputBufferSize(8192);