diff --git a/README.txt b/README.txt
index 3412f8ff169..412eb3a4426 100644
--- a/README.txt
+++ b/README.txt
@@ -3,8 +3,8 @@ This is a source checkout of the Jetty webserver.
To build, use:
- mvn install
-
+ mvn clean install
+
The jetty distribution will be built in
jetty-distribution/target/distribution
@@ -12,8 +12,11 @@ The jetty distribution will be built in
The first build may take a long time as Maven downloads all the
dependencies.
-The tests do a lot of stress testing, and on some machines it is
+The tests do a lot of stress testing, and on some machines it is
necessary to set the file descriptor limit to greater than 2048
-for the tests to all pass successfully.
+for the tests to all pass successfully.
+
+Bypass tests by building with -Dmaven.test.skip=true but note
+that this will not produce some test jars that are leveraged
+in other places in the build.
-Bypass tests by building with -Dmaven.test.skip=true but note that this will not produce some test jars that are leveraged in other places in the build.
diff --git a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/FileServerXml.java b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/FileServerXml.java
index 428a1dbbf6b..4c2429e68d1 100644
--- a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/FileServerXml.java
+++ b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/FileServerXml.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.embedded;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.resource.Resource;
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java
index 7a02031352a..4042ccaec0a 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java
@@ -79,7 +79,7 @@ public class MultiPartConfigAnnotationHandler extends AbstractIntrospectableAnno
{
for (ServletHolder h : holders)
{
- if (h.getClassName().equals(clazz.getName()))
+ if (h.getClassName() != null && h.getClassName().equals(clazz.getName()))
{
holder = h;
}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java
index 1e4e25d42d2..02cae551d07 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java
@@ -102,7 +102,7 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
{
for (ServletHolder h : holders)
{
- if (h.getClassName().equals(clazz.getName()))
+ if (h.getClassName() != null && h.getClassName().equals(clazz.getName()))
{
holder = h;
}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java
index e3cac47aaa3..7e0529026aa 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java
@@ -105,9 +105,9 @@ public class ServletContainerInitializerListener implements ServletContextListen
}
}
- //TODO Email from Jan Luehe 18 August: after all ServletContainerInitializers have been
+ //Email from Jan Luehe 18 August: after all ServletContainerInitializers have been
//called, need to check to see if there are any ServletRegistrations remaining
- //that are "preliminary" and fail the deployment if so.
+ //that are "preliminary" and fail the deployment if so. Implemented in ServletHolder.doStart().
}
}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java
index a439f0df9bc..83be6bf93c4 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java
@@ -245,7 +245,7 @@ public class ServletSecurityAnnotationHandler extends AbstractIntrospectableAnno
{
//Check the name of the servlet that this mapping applies to, and then find the ServletHolder for it to find it's class
ServletHolder holder = _context.getServletHandler().getServlet(mapping.getServletName());
- if (holder.getClassName().equals(className))
+ if (holder.getClassName() != null && holder.getClassName().equals(className))
results.add(mapping);
}
return results;
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
index b3cd7acd4dc..8cdc0840cb5 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
@@ -92,7 +92,7 @@ public class WebServletAnnotation extends DiscoveredAnnotation
MetaData metaData = _context.getMetaData();
- //Find out if a of this type already exists with this name
+ //Find out if a already exists with this name
ServletHolder[] holders = _context.getServletHandler().getServlets();
boolean isNew = true;
ServletHolder holder = null;
@@ -100,7 +100,7 @@ public class WebServletAnnotation extends DiscoveredAnnotation
{
for (ServletHolder h : holders)
{
- if (h.getClassName().equals(clazz.getName()) && h.getName() != null && servletName.equals(h.getName()))
+ if (h.getName() != null && servletName.equals(h.getName()))
{
holder = h;
isNew = false;
@@ -142,11 +142,19 @@ public class WebServletAnnotation extends DiscoveredAnnotation
}
else
{
+ //set the class according to the servlet that is annotated, if it wasn't already
+ //NOTE: this may be considered as "completing" an incomplete servlet registration, and it is
+ //not clear from servlet 3.0 spec whether this is intended, or if only a ServletContext.addServlet() call
+ //can complete it, see http://java.net/jira/browse/SERVLET_SPEC-42
+ if (holder.getClassName() == null)
+ holder.setClassName(clazz.getName());
+ if (holder.getHeldClass() == null)
+ holder.setHeldClass(clazz);
+
//check if the existing servlet has each init-param from the annotation
//if not, add it
for (WebInitParam ip:annotation.initParams())
{
- //if (holder.getInitParameter(ip.name()) == null)
if (metaData.getOrigin(servletName+".servlet.init-param"+ip.name())==Origin.NotSet)
{
holder.setInitParameter(ip.name(), ip.value());
@@ -154,17 +162,53 @@ public class WebServletAnnotation extends DiscoveredAnnotation
}
}
- //check the url-patterns, if there annotation has a new one, add it
- ServletMapping[] mappings = _context.getServletHandler().getServletMappings();
-
+ //check the url-patterns
//ServletSpec 3.0 p81 If a servlet already has url mappings from a
- //descriptor the annotation is ignored
- if (mappings == null && metaData.getOriginDescriptor(servletName+".servlet.mappings") != null)
+ //webxml or fragment descriptor the annotation is ignored. However, we want to be able to
+ //replace mappings that were given in webdefault.xml
+ boolean mappingsExist = false;
+ boolean anyNonDefaults = false;
+ ServletMapping[] allMappings = _context.getServletHandler().getServletMappings();
+ if (allMappings != null)
{
- ServletMapping mapping = new ServletMapping();
- mapping.setServletName(servletName);
- mapping.setPathSpecs(LazyList.toStringArray(urlPatternList));
- _context.getServletHandler().addServletMapping(mapping);
+ for (ServletMapping m:allMappings)
+ {
+ if (m.getServletName() != null && servletName.equals(m.getServletName()))
+ {
+ mappingsExist = true;
+ if (!m.isDefault())
+ {
+ anyNonDefaults = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (anyNonDefaults)
+ return; //if any mappings already set by a descriptor that is not webdefault.xml, we're done
+
+ boolean clash = false;
+ if (mappingsExist)
+ {
+ for (String p:urlPatternList)
+ {
+ ServletMapping m = _context.getServletHandler().getServletMapping(p);
+ if (m != null && !m.isDefault())
+ {
+ //trying to override a servlet-mapping that was added not by webdefault.xml
+ clash = true;
+ break;
+ }
+ }
+ }
+
+ if (!mappingsExist || !clash)
+ {
+ ServletMapping m = new ServletMapping();
+ m.setServletName(servletName);
+ m.setPathSpecs(LazyList.toStringArray(urlPatternList));
+ _context.getServletHandler().addServletMapping(m);
}
}
}
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/Multi.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/Multi.java
index 36cbe8e24d2..790d2702cd1 100644
--- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/Multi.java
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/Multi.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.annotations;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/TestResourceAnnotations.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/TestResourceAnnotations.java
index 451e899b95f..66ebc5a20fc 100644
--- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/TestResourceAnnotations.java
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/TestResourceAnnotations.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.annotations.resources;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
import java.lang.reflect.Field;
import java.util.List;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/CachedHeadersIsolationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/CachedHeadersIsolationTest.java
index 8a599808386..0cfdecb680e 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/CachedHeadersIsolationTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/CachedHeadersIsolationTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
import static org.junit.Assert.assertEquals;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java b/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java
index 6c4d5102709..5f44036c08f 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ExpirationWithLimitedConnectionsTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ExpirationWithLimitedConnectionsTest.java
new file mode 100644
index 00000000000..3db4a5e72b3
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ExpirationWithLimitedConnectionsTest.java
@@ -0,0 +1,191 @@
+// ========================================================================
+// Copyright 2012-2012 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.client;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ExpirationWithLimitedConnectionsTest
+{
+ @Test
+ public void testExpirationWithMaxConnectionPerAddressReached() throws Exception
+ {
+ final Logger logger = Log.getLogger("org.eclipse.jetty.client");
+ logger.setDebugEnabled(true);
+
+ HttpClient client = new HttpClient();
+ int maxConnectionsPerAddress = 10;
+ client.setMaxConnectionsPerAddress(maxConnectionsPerAddress);
+ long timeout = 1000;
+ client.setTimeout(timeout);
+ client.start();
+
+ final List sockets = new CopyOnWriteArrayList();
+ final List failures = new CopyOnWriteArrayList();
+ final AtomicLong processingDelay = new AtomicLong(200);
+
+ final ExecutorService threadPool = Executors.newCachedThreadPool();
+ final ServerSocket server = new ServerSocket(0);
+ threadPool.submit(new Runnable()
+ {
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ final Socket socket = server.accept();
+ sockets.add(socket);
+ logger.debug("CONNECTION {}", socket.getRemoteSocketAddress());
+ threadPool.submit(new Runnable()
+ {
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
+ String firstLine = reader.readLine();
+ String line = firstLine;
+ while (line != null)
+ {
+ if (line.length() == 0)
+ break;
+ line = reader.readLine();
+ }
+
+ if (line == null)
+ break;
+
+ long sleep = processingDelay.get();
+ logger.debug("{} {} {} ms", firstLine, socket.getRemoteSocketAddress(), sleep);
+ TimeUnit.MILLISECONDS.sleep(sleep);
+
+ String response = "" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-Length: 0\r\n" +
+ "\r\n";
+ OutputStream output = socket.getOutputStream();
+ output.write(response.getBytes("UTF-8"));
+ output.flush();
+ }
+ catch (Exception x)
+ {
+ failures.add(x);
+ break;
+ }
+ }
+ }
+ });
+ }
+ catch (Exception x)
+ {
+ failures.add(x);
+ break;
+ }
+ }
+ }
+ });
+
+ List exchanges = new ArrayList();
+
+ final AtomicBoolean firstExpired = new AtomicBoolean();
+ int count = 0;
+ int maxAdditionalRequest = 100;
+ int additionalRequests = 0;
+ while (true)
+ {
+ TimeUnit.MILLISECONDS.sleep(1); // Just avoid being too fast
+ ContentExchange exchange = new ContentExchange(true)
+ {
+ @Override
+ protected void onResponseComplete() throws IOException
+ {
+ logger.debug("{} {} OK", getMethod(), getRequestURI());
+ }
+
+ @Override
+ protected void onExpire()
+ {
+ logger.debug("{} {} EXPIRED {}", getMethod(), getRequestURI(), this);
+ firstExpired.compareAndSet(false, true);
+ }
+ };
+ exchanges.add(exchange);
+ Address address = new Address("localhost", server.getLocalPort());
+ exchange.setAddress(address);
+ exchange.setMethod("GET");
+ exchange.setRequestURI("/" + count);
+ exchange.setVersion("HTTP/1.1");
+ exchange.setRequestHeader("Host", address.toString());
+ logger.debug("{} {} SENT", exchange.getMethod(), exchange.getRequestURI());
+ client.send(exchange);
+ ++count;
+
+ if (processingDelay.get() > 0)
+ {
+ if (client.getDestination(address, false).getConnections() == maxConnectionsPerAddress)
+ {
+ if (firstExpired.get())
+ {
+ ++additionalRequests;
+ if (additionalRequests == maxAdditionalRequest)
+ processingDelay.set(0);
+ }
+ }
+ }
+ else
+ {
+ ++additionalRequests;
+ if (additionalRequests == 2 * maxAdditionalRequest)
+ break;
+ }
+ }
+
+ for (ContentExchange exchange : exchanges)
+ {
+ int status = exchange.waitForDone();
+ Assert.assertTrue(status == HttpExchange.STATUS_COMPLETED || status == HttpExchange.STATUS_EXPIRED);
+ }
+
+ client.stop();
+
+ Assert.assertTrue(failures.isEmpty());
+
+ for (Socket socket : sockets)
+ socket.close();
+ server.close();
+
+ threadPool.shutdown();
+ threadPool.awaitTermination(5, TimeUnit.SECONDS);
+ }
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java
index e0410057571..bd1e9d37412 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.util.Collections;
import java.util.List;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpDestinationQueueTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpDestinationQueueTest.java
index 4f3b970a62c..d292a8961b1 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpDestinationQueueTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpDestinationQueueTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.net.ServerSocket;
import java.net.Socket;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java
index 1d09edc80ad..6071f5ef1ae 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.io.InputStream;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java
index 89a55f510e0..b85fb5041e4 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java
@@ -1,7 +1,18 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import java.io.IOException;
import java.net.URLEncoder;
@@ -229,7 +240,7 @@ public class ProxyTunnellingTest
exchange.setURL("https://localhost:" + serverPort + "/echo?body=" + URLEncoder.encode(body, "UTF-8"));
httpClient.send(exchange);
- assertTrue(latch.await(serverConnectTimeout * 2, TimeUnit.MILLISECONDS));
+ assertTrue("Server connect exception should have occurred", latch.await(serverConnectTimeout * 2, TimeUnit.MILLISECONDS));
}
finally
{
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java b/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java
index bc476c27fc7..00c24dc3dfd 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.util.ArrayList;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SluggishServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SluggishServerTest.java
index 65252038b7c..edc358ad5ff 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SluggishServerTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SluggishServerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.io.InputStream;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesClientTest.java
index a2f041b7d0e..7c2e57cccd2 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesClientTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesClientTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.BufferedReader;
import java.io.File;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java
index be41f47bb96..fc046614b8a 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.hamcrest.Matchers.*;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java
index 9b13bc30e02..db3762fd7c4 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.EOFException;
import java.io.IOException;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslSelectChannelValidationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslSelectChannelValidationTest.java
index ffba50d0586..a6bfd2fa7b4 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslSelectChannelValidationTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslSelectChannelValidationTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslSocketValidationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslSocketValidationTest.java
index eef2f2914d0..82380187937 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslSocketValidationTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslSocketValidationTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import org.eclipse.jetty.server.ssl.SslSocketConnector;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslValidationTestBase.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslValidationTestBase.java
index 50a733c4927..2ed12f43902 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslValidationTestBase.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslValidationTestBase.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.InputStream;
import java.lang.reflect.Constructor;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutTest.java
index 4aefca55148..2c90a802660 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.hamcrest.Matchers.*;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/UnexpectedDataTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/UnexpectedDataTest.java
index 74dd69d43d4..5812ff8e041 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/UnexpectedDataTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/UnexpectedDataTest.java
@@ -1,16 +1,15 @@
-// ========================================================================
-// Copyright 2006-2007 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.
-// ========================================================================
+//========================================================================
+//Copyright 2011-2012 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.client;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java
index b9627e47dba..c5424b83c44 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java
index 584f4b1a64b..c8442bc1e8c 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.FileInputStream;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java
index cc9ac055454..4694bfff130 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.ByteArrayOutputStream;
import java.io.IOException;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java
index d9a2f1d3eef..6f18ac85b30 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Connector;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java
index 015006f6802..98c063968c4 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Server;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java
index d0e0ad0a115..f1c30f030dc 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import org.eclipse.jetty.client.HttpClient;
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationFilter.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationFilter.java
index e5bd75144a5..c10ae1292c1 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationFilter.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationFilter.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.continuation;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationListener.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationListener.java
index 54581a8f5b1..a3f3ee1ceba 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationListener.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationListener.java
@@ -1,5 +1,16 @@
-
package org.eclipse.jetty.continuation;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.util.EventListener;
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Jetty6Continuation.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Jetty6Continuation.java
index 142b675ec2d..db43a22f7bd 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Jetty6Continuation.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Jetty6Continuation.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.continuation;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.util.ArrayList;
import java.util.List;
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
index 26323372c49..5e509b007f4 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.continuation;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.util.ArrayList;
diff --git a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/jmx/DeploymentManagerMBean.java b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/jmx/DeploymentManagerMBean.java
index 3bd53624942..447fb7bd7d0 100644
--- a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/jmx/DeploymentManagerMBean.java
+++ b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/jmx/DeploymentManagerMBean.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy.jmx;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.util.ArrayList;
import java.util.Collection;
diff --git a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java
index 323f836bf9a..2685b82fdcc 100644
--- a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java
+++ b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy.providers;
+//========================================================================
+//Copyright 2009-2012 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.
+//========================================================================
import java.io.File;
import java.io.FilenameFilter;
diff --git a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java
index c924b455a94..557edc0de94 100644
--- a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java
+++ b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy.providers;
+//========================================================================
+//Copyright 2009-2012 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.
+//========================================================================
import java.io.File;
import java.io.FilenameFilter;
diff --git a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java
index 99d619444fa..b29dc8fc694 100644
--- a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java
+++ b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.util.Collection;
import java.util.Set;
diff --git a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/graph/GraphTest.java b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/graph/GraphTest.java
index cc284e1f4dc..c067569a739 100644
--- a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/graph/GraphTest.java
+++ b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/graph/GraphTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy.graph;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import junit.framework.Assert;
diff --git a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/WebAppProviderTest.java b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/WebAppProviderTest.java
index 8e6357bd437..0685d889096 100644
--- a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/WebAppProviderTest.java
+++ b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/WebAppProviderTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy.providers;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.File;
import java.util.Arrays;
diff --git a/jetty-http-spi/src/test/java/org/eclipse/jetty/http/spi/TestSPIServer.java b/jetty-http-spi/src/test/java/org/eclipse/jetty/http/spi/TestSPIServer.java
index 20ad8e97bee..f0d2327510e 100644
--- a/jetty-http-spi/src/test/java/org/eclipse/jetty/http/spi/TestSPIServer.java
+++ b/jetty-http-spi/src/test/java/org/eclipse/jetty/http/spi/TestSPIServer.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.http.spi;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.io.OutputStream;
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java b/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java
index 39aaa995167..2b136cec6ab 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java
@@ -234,8 +234,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
if (_response.isCommitted())
throw new IllegalStateException();
- setHeader("Content-Encoding", _encoding);
-
+ setHeader("Content-Encoding", _encoding);
if (_response.containsHeader("Content-Encoding"))
{
_out=_compressedOutputStream=createStream();
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java b/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java
index 7a5d156f0e1..fc1ab558af1 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.http.ssl;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
/* ------------------------------------------------------------ */
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java
index e3ea2973793..f95e6b0f10d 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.http;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import org.eclipse.jetty.io.Buffer;
import org.junit.Assert;
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffers.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffers.java
index b94710af5ca..9bc63cd1deb 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffers.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffers.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
index ef80cccb2ff..e3da77460e4 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//Copyright (c) 2006-2009 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.
+//========================================================================
import java.io.IOException;
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/BuffersFactory.java b/jetty-io/src/main/java/org/eclipse/jetty/io/BuffersFactory.java
index 693976a3d8b..db23f962326 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/BuffersFactory.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/BuffersFactory.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
public class BuffersFactory
{
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectedEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectedEndPoint.java
index a7e66dd2842..ea550ce4090 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectedEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectedEndPoint.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
public interface ConnectedEndPoint extends EndPoint
{
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/PooledBuffers.java b/jetty-io/src/main/java/org/eclipse/jetty/io/PooledBuffers.java
index 194eb9bf71b..f8356bab814 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/PooledBuffers.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/PooledBuffers.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
index a8db4ec100b..3ba70b035b2 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
@@ -333,9 +333,10 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
if (l==0 && ( header!=null && header.hasContent() || buffer!=null && buffer.hasContent() || trailer!=null && trailer.hasContent()))
{
synchronized (this)
- {
- if (_dispatched)
- _writable=false;
+ {
+ _writable=false;
+ if (!_dispatched)
+ updateKey();
}
}
else if (l>0)
@@ -358,9 +359,10 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
if (l==0 && buffer!=null && buffer.hasContent())
{
synchronized (this)
- {
- if (_dispatched)
- _writable=false;
+ {
+ _writable=false;
+ if (!_dispatched)
+ updateKey();
}
}
else if (l>0)
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/EndPointTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/EndPointTest.java
index 51be3cd751f..62183eb1860 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/EndPointTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/EndPointTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/bio/SocketEndPointTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/bio/SocketEndPointTest.java
index 277c6c7ccba..c412b427364 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/bio/SocketEndPointTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/bio/SocketEndPointTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io.bio;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.net.ServerSocket;
import java.net.Socket;
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/ChannelEndPointTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/ChannelEndPointTest.java
index 1d8d5b2c7eb..2803722a0d9 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/ChannelEndPointTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/ChannelEndPointTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io.nio;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java
index fbf3eae1ac7..e279f5cfa30 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io.nio;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.File;
import java.io.IOException;
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointTest.java
index 47e5f7daf54..5399f7fe414 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io.nio;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.greaterThan;
diff --git a/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/DataSourceCloser.java b/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/DataSourceCloser.java
index 352b745fccb..e0a46e9848f 100644
--- a/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/DataSourceCloser.java
+++ b/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/DataSourceCloser.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.jndi;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.lang.reflect.Method;
import java.sql.Statement;
diff --git a/jetty-monitor/src/main/config/etc/jetty-monitor.xml b/jetty-monitor/src/main/config/etc/jetty-monitor.xml
index 6a866dda28c..dc97f88a495 100644
--- a/jetty-monitor/src/main/config/etc/jetty-monitor.xml
+++ b/jetty-monitor/src/main/config/etc/jetty-monitor.xml
@@ -8,14 +8,14 @@
200090
- 3
+ 52
diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java
index bb41ac918bb..646fad620c3 100644
--- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java
+++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.nosql.mongodb.jmx;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import org.eclipse.jetty.nosql.mongodb.MongoSessionManager;
import org.eclipse.jetty.server.handler.AbstractHandlerContainer;
diff --git a/jetty-npn/pom.xml b/jetty-npn/pom.xml
index 063dffda7a0..f7bd5872e8a 100644
--- a/jetty-npn/pom.xml
+++ b/jetty-npn/pom.xml
@@ -9,7 +9,7 @@
4.0.0org.eclipse.jetty.npnnpn-api
- 1.0.1-SNAPSHOT
+ 1.1.1-SNAPSHOTJetty :: Next Protocol Negotiation :: API
diff --git a/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java b/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java
index 3db7950ef86..c6ff784c77f 100644
--- a/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java
+++ b/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.npn;
@@ -87,7 +85,8 @@ import javax.net.ssl.SSLSocket;
*
*
There is no need to unregister {@link SSLSocket} or {@link SSLEngine} instances, as they
* are kept in a {@link WeakHashMap} and will be garbage collected when the application does not
- * hard reference them anymore.
+ * hard reference them anymore. However, methods to explicitly unregister {@link SSLSocket} or
+ * {@link SSLEngine} instances are provided.
*
In order to help application development, you can set the {@link NextProtoNego#debug} field
* to {@code true} to have debug code printed to {@link System#err}.
*/
@@ -109,6 +108,7 @@ public class NextProtoNego
*
* @param socket the socket to register with the provider
* @param provider the provider to register with the socket
+ * @see #remove(SSLSocket)
*/
public static void put(SSLSocket socket, Provider provider)
{
@@ -124,11 +124,24 @@ public class NextProtoNego
return objects.get(socket);
}
+ /**
+ *
Unregisters the given SSLSocket.
+ *
+ * @param socket the socket to unregister
+ * @return the provider registered with the socket
+ * @see #put(SSLSocket, Provider)
+ */
+ public static Provider remove(SSLSocket socket)
+ {
+ return objects.remove(socket);
+ }
+
/**
*
Registers a SSLEngine with a provider.
*
* @param engine the engine to register with the provider
* @param provider the provider to register with the engine
+ * @see #remove(SSLEngine)
*/
public static void put(SSLEngine engine, Provider provider)
{
@@ -145,6 +158,18 @@ public class NextProtoNego
return objects.get(engine);
}
+ /**
+ *
Unregisters the given SSLEngine.
+ *
+ * @param engine the engine to unregister
+ * @return the provider registered with the engine
+ * @see #put(SSLEngine, Provider)
+ */
+ public static Provider remove(SSLEngine engine)
+ {
+ return objects.remove(engine);
+ }
+
/**
*
Base, empty, interface for providers.
*/
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java
index 5f7401724af..a939937e665 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java
@@ -327,6 +327,7 @@ public class LdapLoginModule extends AbstractLoginModule
SearchControls ctls = new SearchControls();
ctls.setDerefLinkFlag(true);
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+ ctls.setReturningAttributes(new String[]{_roleNameAttribute});
String filter = "(&(objectClass={0})({1}={2}))";
Object[] filterArguments = {_roleObjectClass, _roleMemberAttribute, userDn};
diff --git a/jetty-policy/src/main/java/org/eclipse/jetty/policy/PolicyMonitor.java b/jetty-policy/src/main/java/org/eclipse/jetty/policy/PolicyMonitor.java
index 64a1755fecf..092ce5e0453 100644
--- a/jetty-policy/src/main/java/org/eclipse/jetty/policy/PolicyMonitor.java
+++ b/jetty-policy/src/main/java/org/eclipse/jetty/policy/PolicyMonitor.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.policy;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.File;
import java.io.FileInputStream;
diff --git a/jetty-policy/src/test/java/org/eclipse/jetty/policy/PolicyMonitorTest.java b/jetty-policy/src/test/java/org/eclipse/jetty/policy/PolicyMonitorTest.java
index 06008534282..48315130486 100644
--- a/jetty-policy/src/test/java/org/eclipse/jetty/policy/PolicyMonitorTest.java
+++ b/jetty-policy/src/test/java/org/eclipse/jetty/policy/PolicyMonitorTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.policy;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.File;
import java.util.HashMap;
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthenticatorFactory.java b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthenticatorFactory.java
index 6c243a3a873..4dee1d083ba 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthenticatorFactory.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthenticatorFactory.java
@@ -62,6 +62,8 @@ public class DefaultAuthenticatorFactory implements Authenticator.Factory
authenticator=new FormAuthenticator();
else if ( Constraint.__SPNEGO_AUTH.equalsIgnoreCase(auth) )
authenticator = new SpnegoAuthenticator();
+ else if ( Constraint.__NEGOTIATE_AUTH.equalsIgnoreCase(auth) ) // see Bug #377076
+ authenticator = new SpnegoAuthenticator(Constraint.__NEGOTIATE_AUTH);
if (Constraint.__CERT_AUTH.equalsIgnoreCase(auth)||Constraint.__CERT_AUTH2.equalsIgnoreCase(auth))
authenticator=new ClientCertAuthenticator();
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java b/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
index d3921bcab0a..1c95cc1a238 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.security;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.File;
import java.io.FilenameFilter;
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/SpnegoUserPrincipal.java b/jetty-security/src/main/java/org/eclipse/jetty/security/SpnegoUserPrincipal.java
index a30f60996f5..26de9c2c20c 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/SpnegoUserPrincipal.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/SpnegoUserPrincipal.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.security;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.security.Principal;
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticator.java
index 9df7448468a..412d3fd30cb 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticator.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticator.java
@@ -36,9 +36,25 @@ public class SpnegoAuthenticator extends LoginAuthenticator
{
private static final Logger LOG = Log.getLogger(SpnegoAuthenticator.class);
+ private String _authMethod = Constraint.__SPNEGO_AUTH;
+
+ public SpnegoAuthenticator()
+ {
+
+ }
+
+ /**
+ * Allow for a custom authMethod value to be set for instances where SPENGO may not be appropriate
+ * @param authMethod
+ */
+ public SpnegoAuthenticator( String authMethod )
+ {
+ _authMethod = authMethod;
+ }
+
public String getAuthMethod()
{
- return Constraint.__SPNEGO_AUTH;
+ return _authMethod;
}
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java
index 2e24c178c4d..3e70b3efbbf 100644
--- a/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.security;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.BufferedWriter;
import java.io.File;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java b/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java
index 67ca6db2898..8beb127508d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java
@@ -312,7 +312,6 @@ public class CookieCutter
}
catch (Exception e)
{
- LOG.warn(e.toString());
LOG.debug(e);
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
index 5c9c2076efd..f477da9c174 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
@@ -137,11 +137,21 @@ public class Server extends HandlerWrapper implements Attributes
/* ------------------------------------------------------------ */
public void setStopAtShutdown(boolean stop)
{
- _stopAtShutdown=stop;
+ //if we now want to stop
if (stop)
- ShutdownThread.register(this);
+ {
+ //and we weren't stopping before
+ if (!_stopAtShutdown)
+ {
+ //only register to stop if we're already started (otherwise we'll do it in doStart())
+ if (isStarted())
+ ShutdownThread.register(this);
+ }
+ }
else
ShutdownThread.deregister(this);
+
+ _stopAtShutdown=stop;
}
/* ------------------------------------------------------------ */
@@ -344,7 +354,7 @@ public class Server extends HandlerWrapper implements Attributes
{
LOG.debug("REQUEST "+target+" on "+connection);
handle(target, request, request, response);
- LOG.debug("RESPONSE "+target+" "+connection.getResponse().getStatus());
+ LOG.debug("RESPONSE "+target+" "+connection.getResponse().getStatus()+" handled="+request.isHandled());
}
else
handle(target, request, request, response);
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java
index 12595c594ad..fc710143f58 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.util.Collection;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java
index cef2c5cc978..cc79dc2aa78 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java
@@ -1,7 +1,21 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.net.InetSocketAddress;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
@@ -223,7 +237,33 @@ public class ConnectHandler extends HandlerWrapper
return;
}
- SocketChannel channel = connectToServer(request, host, port);
+ SocketChannel channel;
+
+ try
+ {
+ channel = connectToServer(request,host,port);
+ }
+ catch (SocketException se)
+ {
+ LOG.info("ConnectHandler: SocketException " + se.getMessage());
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ baseRequest.setHandled(true);
+ return;
+ }
+ catch (SocketTimeoutException ste)
+ {
+ LOG.info("ConnectHandler: SocketTimeoutException" + ste.getMessage());
+ response.setStatus(HttpServletResponse.SC_GATEWAY_TIMEOUT);
+ baseRequest.setHandled(true);
+ return;
+ }
+ catch (IOException ioe)
+ {
+ LOG.info("ConnectHandler: IOException" + ioe.getMessage());
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ baseRequest.setHandled(true);
+ return;
+ }
// Transfer unread data from old connection to new connection
// We need to copy the data to avoid races:
@@ -304,9 +344,10 @@ public class ConnectHandler extends HandlerWrapper
return new ProxyToServerConnection(context, buffer);
}
+ // may return null
private SocketChannel connectToServer(HttpServletRequest request, String host, int port) throws IOException
{
- SocketChannel channel = connect(request, host, port);
+ SocketChannel channel = connect(request, host, port);
channel.configureBlocking(false);
return channel;
}
@@ -323,6 +364,12 @@ public class ConnectHandler extends HandlerWrapper
protected SocketChannel connect(HttpServletRequest request, String host, int port) throws IOException
{
SocketChannel channel = SocketChannel.open();
+
+ if (channel == null)
+ {
+ throw new IOException("unable to connect to " + host + ":" + port);
+ }
+
try
{
// Connect to remote server
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
index 812ef3013aa..6b1e9cfebb4 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
@@ -68,6 +68,7 @@ import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.Loader;
+import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
@@ -143,6 +144,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
private Object _requestListeners;
private Object _requestAttributeListeners;
private Map _managedAttributes;
+ private String[] _protectedTargets;
private boolean _shutdown = false;
private boolean _available = true;
@@ -1131,13 +1133,49 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/* ------------------------------------------------------------ */
/**
* Check the target. Called by {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)} when a target within a context is determined. If
- * the target is protected, 404 is returned. The default implementation always returns false.
+ * the target is protected, 404 is returned.
*/
/* ------------------------------------------------------------ */
- protected boolean isProtectedTarget(String target)
+ public boolean isProtectedTarget(String target)
{
- return false;
+ if (target == null || _protectedTargets == null)
+ return false;
+
+ while (target.startsWith("//"))
+ target=URIUtil.compactPath(target);
+
+ boolean isProtected = false;
+ int i=0;
+ while (!isProtected && i<_protectedTargets.length)
+ {
+ isProtected = StringUtil.startsWithIgnoreCase(target, _protectedTargets[i++]);
+ }
+ return isProtected;
}
+
+
+ public void setProtectedTargets (String[] targets)
+ {
+ if (targets == null)
+ {
+ _protectedTargets = null;
+ return;
+ }
+
+ _protectedTargets = new String[targets.length];
+ System.arraycopy(targets, 0, _protectedTargets, 0, targets.length);
+ }
+
+ public String[] getProtectedTargets ()
+ {
+ if (_protectedTargets == null)
+ return null;
+
+ String[] tmp = new String[_protectedTargets.length];
+ System.arraycopy(_protectedTargets, 0, tmp, 0, _protectedTargets.length);
+ return tmp;
+ }
+
/* ------------------------------------------------------------ */
/*
@@ -1793,8 +1831,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
query = uriInContext.substring(q + 1);
uriInContext = uriInContext.substring(0,q);
}
- if ((q = uriInContext.indexOf(';')) > 0)
- uriInContext = uriInContext.substring(0,q);
+ // if ((q = uriInContext.indexOf(';')) > 0)
+ // uriInContext = uriInContext.substring(0,q);
String pathInContext = URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
String uri = URIUtil.addPaths(getContextPath(),uriInContext);
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java
index d224474e3a8..dd463edb78e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java
@@ -1,15 +1,14 @@
//========================================================================
-//Copyright 2009 Mort Bay Consulting Pty. Ltd.
+//Copyright 2011-2012 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
-//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.
+//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.server.handler;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java
index 96b4dfd8544..bf8c556b887 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import org.eclipse.jetty.server.Handler;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java
index d4ff318c7a3..674c780d7e3 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
index 690c917393b..c22dbf82476 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.session;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.util.ArrayList;
import java.util.Collections;
@@ -77,6 +89,7 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
_accessed=accessed;
_lastAccessed=accessed;
_requests=1;
+ _maxIdleMs=_manager._dftMaxIdleSecs>0?_manager._dftMaxIdleSecs*1000L:-1;
if (LOG.isDebugEnabled())
LOG.debug("new session "+_nodeId+" "+_clusterId);
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java
index 5db2550a132..20ead438926 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.session;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.DataOutputStream;
import java.io.File;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java
index 7fcd9f8d111..f0e047b8d15 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.ssl;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.ByteArrayInputStream;
import java.io.IOException;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java
index fb04d57d61c..ae45de39fe6 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.ssl;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.File;
import java.security.SecureRandom;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java
index 49d6cf0cadb..614204e9b16 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java
@@ -21,9 +21,11 @@ import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.net.Socket;
+import java.net.SocketException;
import java.net.URL;
import java.util.Arrays;
import java.util.Random;
+import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.Exchanger;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
@@ -131,6 +133,11 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
Assert.assertThat(response, Matchers.containsString("HTTP/1.1 413 "));
}
+ catch(SocketException e)
+ {
+ // TODO looks like a close is overtaking the 413 in SSL
+ System.err.println("Investigate this "+e);
+ }
finally
{
client.close();
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java
index 607c271abe7..0fa1972d51d 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.BufferedReader;
import java.io.IOException;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java
index 3d21c413757..6edd05115f1 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java
index 3bd3cf3920e..6e13a24622c 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.net.Socket;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java
index 833e5ff97b0..db9782dbb1b 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.io.InputStream;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java
index 4cde042e98c..553886aef28 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.io.InputStream;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java
index eb07c09aade..aa78cd69fc5 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.BufferedReader;
import java.io.EOFException;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java
index 25284911cae..2af503aee68 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java
index da1f5c57075..8a5ac5b5d2c 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java
@@ -1,4 +1,19 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
+
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
@@ -6,9 +21,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.net.InetAddress;
import java.net.Socket;
+import java.net.UnknownHostException;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ConcurrentMap;
+
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
@@ -19,13 +37,10 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.toolchain.test.OS;
-import org.eclipse.jetty.util.log.Log;
+import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assume.assumeTrue;
-
/**
* @version $Revision$ $Date$
*/
@@ -104,6 +119,53 @@ public class ConnectHandlerTest extends AbstractConnectHandlerTest
}
}
+
+ @Test
+ public void testCONNECTBadHostPort() throws Exception
+ {
+ String invalidHostname = "AMAZEBALLS_BADHOST.webtide.com";
+
+ try
+ {
+ InetAddress addr = InetAddress.getByName(invalidHostname);
+ StringBuilder err = new StringBuilder();
+ err.append("DNS Hijacking detected: ");
+ err.append(invalidHostname).append(" should have not returned a valid IP address [");
+ err.append(addr.getHostAddress()).append("]. ");
+ err.append("Fix your DNS provider to have this test pass.");
+ err.append("\nFor more info see https://en.wikipedia.org/wiki/DNS_hijacking");
+ Assert.assertNull(err.toString(), addr);
+ }
+ catch (UnknownHostException e)
+ {
+ // expected path
+ }
+
+ String hostPort = String.format("%s:%d",invalidHostname,serverConnector.getLocalPort());
+ String request = "" +
+ "CONNECT " + hostPort + " HTTP/1.1\r\n" +
+ "Host: " + hostPort + "\r\n" +
+ "\r\n";
+ Socket socket = newSocket();
+ socket.setSoTimeout(30000);
+ try
+ {
+ OutputStream output = socket.getOutputStream();
+ BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ // Expect 500 OK from the CONNECT request
+ Response response = readResponse(input);
+ assertEquals("Response Code", "500", response.getCode());
+ }
+ finally
+ {
+ socket.close();
+ }
+ }
+
@Test
public void testCONNECT10AndGET() throws Exception
{
@@ -355,6 +417,14 @@ public class ConnectHandlerTest extends AbstractConnectHandlerTest
@Test
public void testCONNECTAndPOSTWithBigBody() throws Exception
{
+ // fails under windows and occasionally on mac due to OOME
+ boolean stress = Boolean.getBoolean( "STRESS" );
+
+ if (!stress)
+ {
+ return;
+ }
+
// Log.getLogger(ConnectHandler.class).setDebugEnabled(true);
String hostPort = "localhost:" + serverConnector.getLocalPort();
String request = "" +
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java
index 0ca3fba82fc..183dc57ee25 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java
@@ -1,5 +1,4 @@
// ========================================================================
-// $Id$
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
@@ -292,6 +291,34 @@ public class ContextHandlerTest
assertEquals("333",handler.getServletContext().getAttribute("ccc"));
assertEquals(null,handler.getServletContext().getAttribute("ddd"));
}
+
+ @Test
+ public void testProtected() throws Exception
+ {
+ ContextHandler handler = new ContextHandler();
+ String[] protectedTargets = {"/foo-inf", "/bar-inf"};
+ handler.setProtectedTargets(protectedTargets);
+
+ assertTrue(handler.isProtectedTarget("/foo-inf/x/y/z"));
+ assertFalse(handler.isProtectedTarget("/foo/x/y/z"));
+ assertTrue(handler.isProtectedTarget("/foo-inf?x=y&z=1"));
+
+ protectedTargets = new String[4];
+ System.arraycopy(handler.getProtectedTargets(), 0, protectedTargets, 0, 2);
+ protectedTargets[2] = "/abc";
+ protectedTargets[3] = "/def";
+ handler.setProtectedTargets(protectedTargets);
+
+ assertTrue(handler.isProtectedTarget("/foo-inf/x/y/z"));
+ assertFalse(handler.isProtectedTarget("/foo/x/y/z"));
+ assertTrue(handler.isProtectedTarget("/foo-inf?x=y&z=1"));
+ assertTrue(handler.isProtectedTarget("/abc/124"));
+ assertTrue(handler.isProtectedTarget("//def"));
+
+ assertTrue(handler.isProtectedTarget("/ABC/7777"));
+ }
+
+
private void checkResourcePathsForExampleWebApp(String root) throws IOException
{
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java
index 0fa811db0b2..b74e9fc9e40 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.junit.Assert.assertEquals;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java
index c413a1a7be0..f5728f4d697 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.session;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java
index eb927154972..321122e0a67 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java
@@ -1,15 +1,14 @@
//========================================================================
-//Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
+//Copyright 2011-2012 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
-//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.
+//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.
//========================================================================
// JettyTest.java --
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java
index 79ef7d32f21..67efa218849 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.ssl;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.BufferedReader;
import java.io.FileInputStream;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslRenegotiateTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslRenegotiateTest.java
index a38967f164c..65864527f80 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslRenegotiateTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslRenegotiateTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.ssl;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
index 2ee07da5d14..31643879753 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
@@ -421,6 +421,9 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
boolean gzip=false;
if (!included.booleanValue() && _gzip && reqRanges==null && !endsWithSlash )
{
+ // Tell caches that response may vary by accept-encoding
+ response.setHeader(HttpHeaders.VARY,HttpHeaders.ACCEPT_ENCODING);
+ // Should we vary this response according to accept-encoding?
String accept=request.getHeader(HttpHeaders.ACCEPT_ENCODING);
if (accept!=null && accept.indexOf("gzip")>=0)
gzip=true;
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java
index c1fe3526a7a..eea5ac42feb 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java
@@ -82,7 +82,7 @@ public class Holder extends AbstractLifeCycle implements Dumpable
{
//if no class already loaded and no classname, make servlet permanently unavailable
if (_class==null && (_className==null || _className.equals("")))
- throw new UnavailableException("No class for Servlet or Filter", -1);
+ throw new UnavailableException("No class for Servlet or Filter for "+_name, -1);
//try to load class
if (_class==null)
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
index cc5fd070c21..91cefb05ee0 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
@@ -815,11 +815,24 @@ public class ServletContextHandler extends ContextHandler
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final FilterHolder holder= handler.newFilterHolder(Holder.Source.JAVAX_API);
- holder.setName(filterName);
- holder.setHeldClass(filterClass);
- handler.addFilter(holder);
- return holder.getRegistration();
+ FilterHolder holder = handler.getFilter(filterName);
+ if (holder == null)
+ {
+ //new filter
+ holder = handler.newFilterHolder(Holder.Source.JAVAX_API);
+ holder.setName(filterName);
+ holder.setHeldClass(filterClass);
+ handler.addFilter(holder);
+ return holder.getRegistration();
+ }
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ //preliminary filter registration completion
+ holder.setHeldClass(filterClass);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing filter
}
/* ------------------------------------------------------------ */
@@ -836,11 +849,24 @@ public class ServletContextHandler extends ContextHandler
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final FilterHolder holder= handler.newFilterHolder(Holder.Source.JAVAX_API);
- holder.setName(filterName);
- holder.setClassName(className);
- handler.addFilter(holder);
- return holder.getRegistration();
+ FilterHolder holder = handler.getFilter(filterName);
+ if (holder == null)
+ {
+ //new filter
+ holder = handler.newFilterHolder(Holder.Source.JAVAX_API);
+ holder.setName(filterName);
+ holder.setClassName(className);
+ handler.addFilter(holder);
+ return holder.getRegistration();
+ }
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ //preliminary filter registration completion
+ holder.setClassName(className);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing filter
}
@@ -858,11 +884,25 @@ public class ServletContextHandler extends ContextHandler
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final FilterHolder holder= handler.newFilterHolder(Holder.Source.JAVAX_API);
- holder.setName(filterName);
- holder.setFilter(filter);
- handler.addFilter(holder);
- return holder.getRegistration();
+ FilterHolder holder = handler.getFilter(filterName);
+ if (holder == null)
+ {
+ //new filter
+ holder = handler.newFilterHolder(Holder.Source.JAVAX_API);
+ holder.setName(filterName);
+ holder.setFilter(filter);
+ handler.addFilter(holder);
+ return holder.getRegistration();
+ }
+
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ //preliminary filter registration completion
+ holder.setFilter(filter);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing filter
}
/* ------------------------------------------------------------ */
@@ -877,13 +917,27 @@ public class ServletContextHandler extends ContextHandler
if (!_enabled)
throw new UnsupportedOperationException();
-
+
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final ServletHolder holder= handler.newServletHolder(Holder.Source.JAVAX_API);
- holder.setName(servletName);
- holder.setHeldClass(servletClass);
- handler.addServlet(holder);
- return dynamicHolderAdded(holder);
+ ServletHolder holder = handler.getServlet(servletName);
+ if (holder == null)
+ {
+ //new servlet
+ holder = handler.newServletHolder(Holder.Source.JAVAX_API);
+ holder.setName(servletName);
+ holder.setHeldClass(servletClass);
+ handler.addServlet(holder);
+ return dynamicHolderAdded(holder);
+ }
+
+ //complete a partial registration
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ holder.setHeldClass(servletClass);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing completed registration for servlet name
}
/* ------------------------------------------------------------ */
@@ -899,12 +953,27 @@ public class ServletContextHandler extends ContextHandler
if (!_enabled)
throw new UnsupportedOperationException();
- final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final ServletHolder holder= handler.newServletHolder(Holder.Source.JAVAX_API);
- holder.setName(servletName);
- holder.setClassName(className);
- handler.addServlet(holder);
- return dynamicHolderAdded(holder);
+
+ final ServletHandler handler = ServletContextHandler.this.getServletHandler();
+ ServletHolder holder = handler.getServlet(servletName);
+ if (holder == null)
+ {
+ //new servlet
+ holder = handler.newServletHolder(Holder.Source.JAVAX_API);
+ holder.setName(servletName);
+ holder.setClassName(className);
+ handler.addServlet(holder);
+ return dynamicHolderAdded(holder);
+ }
+
+ //complete a partial registration
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ holder.setClassName(className);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing completed registration for servlet name
}
/* ------------------------------------------------------------ */
@@ -919,13 +988,28 @@ public class ServletContextHandler extends ContextHandler
if (!_enabled)
throw new UnsupportedOperationException();
+
+ //TODO handle partial registrations
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final ServletHolder holder= handler.newServletHolder(Holder.Source.JAVAX_API);
- holder.setName(servletName);
- holder.setServlet(servlet);
- handler.addServlet(holder);
- return dynamicHolderAdded(holder);
+ ServletHolder holder = handler.getServlet(servletName);
+ if (holder == null)
+ {
+ holder = handler.newServletHolder(Holder.Source.JAVAX_API);
+ holder.setName(servletName);
+ holder.setServlet(servlet);
+ handler.addServlet(holder);
+ return dynamicHolderAdded(holder);
+ }
+
+ //complete a partial registration
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ holder.setServlet(servlet);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing completed registration for servlet name
}
/* ------------------------------------------------------------ */
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
index 708099437c2..8084896bb03 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
@@ -259,44 +259,7 @@ public class ServletHandler extends ScopedHandler
return null;
return _servletPathMap.getMatch(pathInContext);
}
-
- /* ------------------------------------------------------------ */
- /**
- * @param uriInContext uri to get dispatcher for
- * @return A {@link RequestDispatcher dispatcher} wrapping the resource at uriInContext,
- * or null if the specified uri cannot be dispatched to.
- */
- public RequestDispatcher getRequestDispatcher(String uriInContext)
- {
- if (uriInContext == null || _contextHandler==null)
- return null;
-
- if (!uriInContext.startsWith("/"))
- return null;
-
- try
- {
- String query=null;
- int q;
- if ((q=uriInContext.indexOf('?'))>0)
- {
- query=uriInContext.substring(q+1);
- uriInContext=uriInContext.substring(0,q);
- }
- if ((q=uriInContext.indexOf(';'))>0)
- uriInContext=uriInContext.substring(0,q);
-
- String pathInContext=URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
- String uri=URIUtil.addPaths(_contextHandler.getContextPath(), uriInContext);
- return new Dispatcher(_contextHandler, uri, pathInContext, query);
- }
- catch(Exception e)
- {
- LOG.ignore(e);
- }
- return null;
- }
-
+
/* ------------------------------------------------------------ */
public ServletContext getServletContext()
{
@@ -318,6 +281,7 @@ public class ServletHandler extends ScopedHandler
*/
public ServletMapping getServletMapping(String pattern)
{
+ ServletMapping theMapping = null;
if (_servletMappings!=null)
{
for (ServletMapping m:_servletMappings)
@@ -328,12 +292,12 @@ public class ServletHandler extends ScopedHandler
for (String path:paths)
{
if (pattern.equals(path))
- return m;
+ theMapping = m;
}
}
}
}
- return null;
+ return theMapping;
}
/* ------------------------------------------------------------ */
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
index e34b1d40a42..6d20a1d94e0 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
@@ -41,6 +41,8 @@ import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.RunAsToken;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -285,16 +287,28 @@ public class ServletHolder extends Holder implements UserIdentity.Scope
_unavailable=0;
if (!_enabled)
return;
-
+ //check servlet has a class (ie is not a preliminary registration). If preliminary, fail startup.
try
{
super.doStart();
+ }
+ catch (UnavailableException ue)
+ {
+ makeUnavailable(ue);
+ throw ue;
+ }
+
+ try
+ {
checkServletType();
}
catch (UnavailableException ue)
{
makeUnavailable(ue);
+ if (!_servletHandler.isStartWithUnavailable())
+ throw ue; //servlet is not an instance of javax.servlet.Servlet
}
+
_identityService = _servletHandler.getIdentityService();
if (_identityService!=null && _runAsRole!=null)
@@ -488,6 +502,12 @@ public class ServletHolder extends Holder implements UserIdentity.Scope
{
old_run_as=_identityService.setRunAs(_identityService.getSystemUserIdentity(),_runAsToken);
}
+
+ // Handle configuring servlets that implement org.apache.jasper.servlet.JspServlet
+ if (isJspServlet())
+ {
+ initJspServlet();
+ }
_servlet.init(_config);
}
@@ -521,6 +541,31 @@ public class ServletHolder extends Holder implements UserIdentity.Scope
}
+ /* ------------------------------------------------------------ */
+ /**
+ * @throws Exception
+ */
+ protected void initJspServlet () throws Exception
+ {
+ ContextHandler ch = ((ContextHandler.Context)getServletHandler().getServletContext()).getContextHandler();
+
+ /* Set the webapp's classpath for Jasper */
+ ch.setAttribute("org.apache.catalina.jsp_classpath", ch.getClassPath());
+
+ /* Set the system classpath for Jasper */
+ setInitParameter("com.sun.appserv.jsp.classpath", Loader.getClassPath(ch.getClassLoader().getParent()));
+
+ /* Set up other classpath attribute */
+ if ("?".equals(getInitParameter("classpath")))
+ {
+ String classpath = ch.getClassPath();
+ LOG.debug("classpath=" + classpath);
+ if (classpath != null)
+ setInitParameter("classpath", classpath);
+ }
+ }
+
+
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.UserIdentity.Scope#getContextPath()
@@ -616,6 +661,34 @@ public class ServletHolder extends Holder implements UserIdentity.Scope
request.setAttribute("javax.servlet.error.servlet_name",getName());
}
}
+
+
+ /* ------------------------------------------------------------ */
+ private boolean isJspServlet ()
+ {
+ if (_servlet == null)
+ return false;
+
+ Class c = _servlet.getClass();
+
+ boolean result = false;
+ while (c != null && !result)
+ {
+ result = isJspServlet(c.getName());
+ c = c.getSuperclass();
+ }
+
+ return result;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ private boolean isJspServlet (String classname)
+ {
+ if (classname == null)
+ return false;
+ return ("org.apache.jasper.servlet.JspServlet".equals(classname));
+ }
/* ------------------------------------------------------------ */
@@ -644,17 +717,24 @@ public class ServletHolder extends Holder implements UserIdentity.Scope
Set clash=null;
for (String pattern : urlPatterns)
{
- if (_servletHandler.getServletMapping(pattern)!=null)
+ ServletMapping mapping = _servletHandler.getServletMapping(pattern);
+ if (mapping!=null)
{
- if (clash==null)
- clash=new HashSet();
- clash.add(pattern);
+ //if the servlet mapping was from a default descriptor, then allow it to be overridden
+ if (!mapping.isDefault())
+ {
+ if (clash==null)
+ clash=new HashSet();
+ clash.add(pattern);
+ }
}
}
+ //if there were any clashes amongst the urls, return them
if (clash!=null)
return clash;
+ //otherwise apply all of them
ServletMapping mapping = new ServletMapping();
mapping.setServletName(ServletHolder.this.getName());
mapping.setPathSpecs(urlPatterns);
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java
index e8e133d541d..27af5fa4001 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java
@@ -21,6 +21,8 @@ public class ServletMapping
{
private String[] _pathSpecs;
private String _servletName;
+ private boolean _default;
+
/* ------------------------------------------------------------ */
public ServletMapping()
@@ -72,6 +74,25 @@ public class ServletMapping
_servletName = servletName;
}
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return
+ */
+ public boolean isDefault()
+ {
+ return _default;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param default1
+ */
+ public void setDefault(boolean fromDefault)
+ {
+ _default = fromDefault;
+ }
/* ------------------------------------------------------------ */
public String toString()
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextDispatchWithQueryStrings.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextDispatchWithQueryStrings.java
index 27497fa0854..27d1a5502f9 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextDispatchWithQueryStrings.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextDispatchWithQueryStrings.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlet;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java
index 925c409493a..3da4254bf14 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlet;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
index 3164aaab4e3..96a9a73733b 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlet;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.junit.Assert.assertTrue;
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
index 9925340ee66..9d1f9e5b98b 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
@@ -108,6 +108,27 @@ public class DispatcherTest
assertEquals(expected, responses);
}
+
+ @Test
+ public void testForwardWithParam() throws Exception
+ {
+ _contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*");
+ _contextHandler.addServlet(EchoURIServlet.class, "/EchoURI/*");
+
+ String expected=
+ "HTTP/1.1 200 OK\r\n"+
+ "Content-Type: text/plain\r\n"+
+ "Content-Length: 54\r\n"+
+ "\r\n"+
+ "/context\r\n"+
+ "/EchoURI\r\n"+
+ "/x x\r\n"+
+ "/context/EchoURI/x%20x;a=1\r\n";
+
+ String responses = _connector.getResponses("GET /context/ForwardServlet;ignore=true?do=req.echo&uri=EchoURI%2Fx%2520x%3Ba=1%3Fb=2 HTTP/1.1\n" + "Host: localhost\n\n");
+
+ assertEquals(expected, responses);
+ }
@Test
public void testInclude() throws Exception
@@ -282,6 +303,10 @@ public class DispatcherTest
dispatcher = getServletContext().getRequestDispatcher("/AssertIncludeForwardServlet/assertpath?do=end");
else if(request.getParameter("do").equals("assertforward"))
dispatcher = getServletContext().getRequestDispatcher("/AssertForwardServlet?do=end&do=the");
+ else if(request.getParameter("do").equals("ctx.echo"))
+ dispatcher = getServletContext().getRequestDispatcher(request.getParameter("uri"));
+ else if(request.getParameter("do").equals("req.echo"))
+ dispatcher = request.getRequestDispatcher(request.getParameter("uri"));
dispatcher.forward(request, response);
}
}
@@ -465,6 +490,19 @@ public class DispatcherTest
}
}
+ public static class EchoURIServlet extends HttpServlet implements Servlet
+ {
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ response.setContentType("text/plain");
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.getOutputStream().println(request.getContextPath());
+ response.getOutputStream().println(request.getServletPath());
+ response.getOutputStream().println(request.getPathInfo());
+ response.getOutputStream().println(request.getRequestURI());
+ }
+ }
+
public static class AssertForwardServlet extends HttpServlet implements Servlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
index 522643605ff..820c5805a09 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlet;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.junit.Assert.assertEquals;
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/BalancerServlet.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/BalancerServlet.java
new file mode 100644
index 00000000000..f7ef7db0097
--- /dev/null
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/BalancerServlet.java
@@ -0,0 +1,417 @@
+// ========================================================================
+// Copyright (c) 2012 Intalio, Inc.
+// ------------------------------------------------------------------------
+// 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.servlets;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.UnavailableException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.jetty.http.HttpURI;
+import org.eclipse.jetty.server.Request;
+
+/**
+ * 6
+ */
+public class BalancerServlet extends ProxyServlet
+{
+
+ private static final class BalancerMember
+ {
+
+ private String _name;
+
+ private String _proxyTo;
+
+ private HttpURI _backendURI;
+
+ public BalancerMember(String name, String proxyTo)
+ {
+ super();
+ _name = name;
+ _proxyTo = proxyTo;
+ _backendURI = new HttpURI(_proxyTo);
+ }
+
+ public String getProxyTo()
+ {
+ return _proxyTo;
+ }
+
+ public HttpURI getBackendURI()
+ {
+ return _backendURI;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "BalancerMember [_name=" + _name + ", _proxyTo=" + _proxyTo + "]";
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_name == null)?0:_name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BalancerMember other = (BalancerMember)obj;
+ if (_name == null)
+ {
+ if (other._name != null)
+ return false;
+ }
+ else if (!_name.equals(other._name))
+ return false;
+ return true;
+ }
+
+ }
+
+ private static final class RoundRobinIterator implements Iterator
+ {
+
+ private BalancerMember[] _balancerMembers;
+
+ private AtomicInteger _index;
+
+ public RoundRobinIterator(Collection balancerMembers)
+ {
+ _balancerMembers = (BalancerMember[])balancerMembers.toArray(new BalancerMember[balancerMembers.size()]);
+ _index = new AtomicInteger(-1);
+ }
+
+ public boolean hasNext()
+ {
+ return true;
+ }
+
+ public BalancerMember next()
+ {
+ BalancerMember balancerMember = null;
+ while (balancerMember == null)
+ {
+ int currentIndex = _index.get();
+ int nextIndex = (currentIndex + 1) % _balancerMembers.length;
+ if (_index.compareAndSet(currentIndex,nextIndex))
+ {
+ balancerMember = _balancerMembers[nextIndex];
+ }
+ }
+ return balancerMember;
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ private static final String BALANCER_MEMBER_PREFIX = "BalancerMember.";
+
+ private static final List FORBIDDEN_CONFIG_PARAMETERS;
+ static
+ {
+ List params = new LinkedList();
+ params.add("HostHeader");
+ params.add("whiteList");
+ params.add("blackList");
+ FORBIDDEN_CONFIG_PARAMETERS = Collections.unmodifiableList(params);
+ }
+
+ private static final List REVERSE_PROXY_HEADERS;
+ static
+ {
+ List params = new LinkedList();
+ params.add("Location");
+ params.add("Content-Location");
+ params.add("URI");
+ REVERSE_PROXY_HEADERS = Collections.unmodifiableList(params);
+ }
+
+ private static final String JSESSIONID = "jsessionid";
+
+ private static final String JSESSIONID_URL_PREFIX = JSESSIONID + "=";
+
+ private boolean _stickySessions;
+
+ private Set _balancerMembers = new HashSet();
+
+ private boolean _proxyPassReverse;
+
+ private RoundRobinIterator _roundRobinIterator;
+
+ @Override
+ public void init(ServletConfig config) throws ServletException
+ {
+ validateConfig(config);
+ super.init(config);
+ initStickySessions(config);
+ initBalancers(config);
+ initProxyPassReverse(config);
+ postInit();
+ }
+
+ private void validateConfig(ServletConfig config) throws ServletException
+ {
+ @SuppressWarnings("unchecked")
+ List initParameterNames = Collections.list(config.getInitParameterNames());
+ for (String initParameterName : initParameterNames)
+ {
+ if (FORBIDDEN_CONFIG_PARAMETERS.contains(initParameterName))
+ {
+ throw new UnavailableException(initParameterName + " not supported in " + getClass().getName());
+ }
+ }
+ }
+
+ private void initStickySessions(ServletConfig config) throws ServletException
+ {
+ _stickySessions = "true".equalsIgnoreCase(config.getInitParameter("StickySessions"));
+ }
+
+ private void initBalancers(ServletConfig config) throws ServletException
+ {
+ Set balancerNames = getBalancerNames(config);
+ for (String balancerName : balancerNames)
+ {
+ String memberProxyToParam = BALANCER_MEMBER_PREFIX + balancerName + ".ProxyTo";
+ String proxyTo = config.getInitParameter(memberProxyToParam);
+ if (proxyTo == null || proxyTo.trim().length() == 0)
+ {
+ throw new UnavailableException(memberProxyToParam + " parameter is empty.");
+ }
+ _balancerMembers.add(new BalancerMember(balancerName,proxyTo));
+ }
+ }
+
+ private void initProxyPassReverse(ServletConfig config)
+ {
+ _proxyPassReverse = "true".equalsIgnoreCase(config.getInitParameter("ProxyPassReverse"));
+ }
+
+ private void postInit()
+ {
+ _roundRobinIterator = new RoundRobinIterator(_balancerMembers);
+ }
+
+ private Set getBalancerNames(ServletConfig config) throws ServletException
+ {
+ Set names = new HashSet();
+ @SuppressWarnings("unchecked")
+ List initParameterNames = Collections.list(config.getInitParameterNames());
+ for (String initParameterName : initParameterNames)
+ {
+ if (!initParameterName.startsWith(BALANCER_MEMBER_PREFIX))
+ {
+ continue;
+ }
+ int endOfNameIndex = initParameterName.lastIndexOf(".");
+ if (endOfNameIndex <= BALANCER_MEMBER_PREFIX.length())
+ {
+ throw new UnavailableException(initParameterName + " parameter does not provide a balancer member name");
+ }
+ names.add(initParameterName.substring(BALANCER_MEMBER_PREFIX.length(),endOfNameIndex));
+ }
+ return names;
+ }
+
+ @Override
+ protected HttpURI proxyHttpURI(HttpServletRequest request, String uri) throws MalformedURLException
+ {
+ BalancerMember balancerMember = selectBalancerMember(request);
+ try
+ {
+ URI dstUri = new URI(balancerMember.getProxyTo() + "/" + uri).normalize();
+ return new HttpURI(dstUri.toString());
+ }
+ catch (URISyntaxException e)
+ {
+ throw new MalformedURLException(e.getMessage());
+ }
+ }
+
+ private BalancerMember selectBalancerMember(HttpServletRequest request)
+ {
+ BalancerMember balancerMember = null;
+ if (_stickySessions)
+ {
+ String name = getBalancerMemberNameFromSessionId(request);
+ if (name != null)
+ {
+ balancerMember = findBalancerMemberByName(name);
+ if (balancerMember != null)
+ {
+ return balancerMember;
+ }
+ }
+ }
+ return _roundRobinIterator.next();
+ }
+
+ private BalancerMember findBalancerMemberByName(String name)
+ {
+ BalancerMember example = new BalancerMember(name,"");
+ for (BalancerMember balancerMember : _balancerMembers)
+ {
+ if (balancerMember.equals(example))
+ {
+ return balancerMember;
+ }
+ }
+ return null;
+ }
+
+ private String getBalancerMemberNameFromSessionId(HttpServletRequest request)
+ {
+ String name = getBalancerMemberNameFromSessionCookie(request);
+ if (name == null)
+ {
+ name = getBalancerMemberNameFromURL(request);
+ }
+ return name;
+ }
+
+ private String getBalancerMemberNameFromSessionCookie(HttpServletRequest request)
+ {
+ Cookie[] cookies = request.getCookies();
+ String name = null;
+ for (Cookie cookie : cookies)
+ {
+ if (JSESSIONID.equalsIgnoreCase(cookie.getName()))
+ {
+ name = extractBalancerMemberNameFromSessionId(cookie.getValue());
+ break;
+ }
+ }
+ return name;
+ }
+
+ private String getBalancerMemberNameFromURL(HttpServletRequest request)
+ {
+ String name = null;
+ String requestURI = request.getRequestURI();
+ int idx = requestURI.lastIndexOf(";");
+ if (idx != -1)
+ {
+ String requestURISuffix = requestURI.substring(idx);
+ if (requestURISuffix.startsWith(JSESSIONID_URL_PREFIX))
+ {
+ name = extractBalancerMemberNameFromSessionId(requestURISuffix.substring(JSESSIONID_URL_PREFIX.length()));
+ }
+ }
+ return name;
+ }
+
+ private String extractBalancerMemberNameFromSessionId(String sessionId)
+ {
+ String name = null;
+ int idx = sessionId.lastIndexOf(".");
+ if (idx != -1)
+ {
+ String sessionIdSuffix = sessionId.substring(idx + 1);
+ name = (sessionIdSuffix.length() > 0)?sessionIdSuffix:null;
+ }
+ return name;
+ }
+
+ @Override
+ protected String filterResponseHeaderValue(String headerName, String headerValue, HttpServletRequest request)
+ {
+ if (_proxyPassReverse && REVERSE_PROXY_HEADERS.contains(headerName))
+ {
+ HttpURI locationURI = new HttpURI(headerValue);
+ if (isAbsoluteLocation(locationURI) && isBackendLocation(locationURI))
+ {
+ Request jettyRequest = (Request)request;
+ URI reverseUri;
+ try
+ {
+ reverseUri = new URI(jettyRequest.getRootURL().append(locationURI.getCompletePath()).toString()).normalize();
+ return reverseUri.toURL().toString();
+ }
+ catch (Exception e)
+ {
+ _log.warn("Not filtering header response",e);
+ return headerValue;
+ }
+ }
+ }
+ return headerValue;
+ }
+
+ private boolean isBackendLocation(HttpURI locationURI)
+ {
+ for (BalancerMember balancerMember : _balancerMembers)
+ {
+ HttpURI backendURI = balancerMember.getBackendURI();
+ if (backendURI.getHost().equals(locationURI.getHost()) && backendURI.getScheme().equals(locationURI.getScheme())
+ && backendURI.getPort() == locationURI.getPort())
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isAbsoluteLocation(HttpURI locationURI)
+ {
+ return locationURI.getHost() != null;
+ }
+
+ @Override
+ public String getHostHeader()
+ {
+ throw new UnsupportedOperationException("HostHeader not supported in " + getClass().getName());
+ }
+
+ @Override
+ public void setHostHeader(String hostHeader)
+ {
+ throw new UnsupportedOperationException("HostHeader not supported in " + getClass().getName());
+ }
+
+ @Override
+ public boolean validateDestination(String host, String path)
+ {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java
index bb57608c4b4..6561166a18c 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java
@@ -54,15 +54,18 @@ import org.eclipse.jetty.util.log.Logger;
* and any 3 letter top-level domain (.com, .net, .org, etc.).
*
allowedMethods, a comma separated list of HTTP methods that
* are allowed to be used when accessing the resources. Default value is
- * GET,POST
+ * GET,POST,HEAD
*
allowedHeaders, a comma separated list of HTTP headers that
* are allowed to be specified when accessing the resources. Default value
- * is X-Requested-With
+ * is X-Requested-With,Content-Type,Accept,Origin
*
preflightMaxAge, the number of seconds that preflight requests
* can be cached by the client. Default value is 1800 seconds, or 30
* minutes
*
allowCredentials, a boolean indicating if the resource allows
* requests with credentials. Default value is false
+ *
exposeHeaders, a comma separated list of HTTP headers that
+ * are allowed to be exposed on the client. Default value is the
+ * empty list
- *
- * @version $Revision$ $Date$
*/
public class CrossOriginFilter implements Filter
{
@@ -96,12 +97,15 @@ public class CrossOriginFilter implements Filter
public static final String ACCESS_CONTROL_ALLOW_HEADERS_HEADER = "Access-Control-Allow-Headers";
public static final String ACCESS_CONTROL_MAX_AGE_HEADER = "Access-Control-Max-Age";
public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER = "Access-Control-Allow-Credentials";
+ public static final String ACCESS_CONTROL_EXPOSE_HEADERS_HEADER = "Access-Control-Expose-Headers";
// Implementation constants
public static final String ALLOWED_ORIGINS_PARAM = "allowedOrigins";
public static final String ALLOWED_METHODS_PARAM = "allowedMethods";
public static final String ALLOWED_HEADERS_PARAM = "allowedHeaders";
public static final String PREFLIGHT_MAX_AGE_PARAM = "preflightMaxAge";
public static final String ALLOW_CREDENTIALS_PARAM = "allowCredentials";
+ public static final String EXPOSED_HEADERS_PARAM = "exposedHeaders";
+ public static final String FORWARD_PREFLIGHT_PARAM = "forwardPreflight";
private static final String ANY_ORIGIN = "*";
private static final List SIMPLE_HTTP_METHODS = Arrays.asList("GET", "POST", "HEAD");
@@ -109,8 +113,10 @@ public class CrossOriginFilter implements Filter
private List allowedOrigins = new ArrayList();
private List allowedMethods = new ArrayList();
private List allowedHeaders = new ArrayList();
- private int preflightMaxAge = 0;
+ private List exposedHeaders = new ArrayList();
+ private int preflightMaxAge;
private boolean allowCredentials;
+ private boolean forwardPreflight;
public void init(FilterConfig config) throws ServletException
{
@@ -163,6 +169,16 @@ public class CrossOriginFilter implements Filter
allowedCredentialsConfig = "true";
allowCredentials = Boolean.parseBoolean(allowedCredentialsConfig);
+ String exposedHeadersConfig = config.getInitParameter(EXPOSED_HEADERS_PARAM);
+ if (exposedHeadersConfig == null)
+ exposedHeadersConfig = "";
+ exposedHeaders.addAll(Arrays.asList(exposedHeadersConfig.split(",")));
+
+ String forwardPreflightConfig = config.getInitParameter(FORWARD_PREFLIGHT_PARAM);
+ if (forwardPreflightConfig == null)
+ forwardPreflightConfig = "true";
+ forwardPreflight = Boolean.parseBoolean(forwardPreflightConfig);
+
if (LOG.isDebugEnabled())
{
LOG.debug("Cross-origin filter configuration: " +
@@ -170,7 +186,10 @@ public class CrossOriginFilter implements Filter
ALLOWED_METHODS_PARAM + " = " + allowedMethodsConfig + ", " +
ALLOWED_HEADERS_PARAM + " = " + allowedHeadersConfig + ", " +
PREFLIGHT_MAX_AGE_PARAM + " = " + preflightMaxAgeConfig + ", " +
- ALLOW_CREDENTIALS_PARAM + " = " + allowedCredentialsConfig);
+ ALLOW_CREDENTIALS_PARAM + " = " + allowedCredentialsConfig + "," +
+ EXPOSED_HEADERS_PARAM + " = " + exposedHeadersConfig + "," +
+ FORWARD_PREFLIGHT_PARAM + " = " + forwardPreflightConfig
+ );
}
}
@@ -196,6 +215,10 @@ public class CrossOriginFilter implements Filter
{
LOG.debug("Cross-origin request to {} is a preflight cross-origin request", request.getRequestURI());
handlePreflightResponse(request, response, origin);
+ if (forwardPreflight)
+ LOG.debug("Preflight cross-origin request to {} forwarded to application", request.getRequestURI());
+ else
+ return;
}
else
{
@@ -305,6 +328,8 @@ public class CrossOriginFilter implements Filter
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, origin);
if (allowCredentials)
response.setHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
+ if (!exposedHeaders.isEmpty())
+ response.setHeader(ACCESS_CONTROL_EXPOSE_HEADERS_HEADER, commify(exposedHeaders));
}
private void handlePreflightResponse(HttpServletRequest request, HttpServletResponse response, String origin)
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java
index 8b9a9c76d3f..2837be9c97a 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java
@@ -201,7 +201,11 @@ public class GzipFilter extends UserAgentFilter
{
HttpServletRequest request=(HttpServletRequest)req;
HttpServletResponse response=(HttpServletResponse)res;
+
+ // Inform caches that responses may vary according to Accept-Encoding
+ response.setHeader("Vary","Accept-Encoding");
+ // Should we vary this response according to Accept-Encoding
String compressionType = selectCompression(request.getHeader("accept-encoding"));
if (compressionType!=null && !response.containsHeader("Content-Encoding") && !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
{
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java
index 7fa971838a5..6687903a6a5 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java
@@ -483,13 +483,20 @@ public class ProxyServlet implements Servlet
@Override
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
- String s = name.toString().toLowerCase();
+ String nameString = name.toString();
+ String s = nameString.toLowerCase();
if (!_DontProxyHeaders.contains(s) || (HttpHeaders.CONNECTION_BUFFER.equals(name) && HttpHeaderValues.CLOSE_BUFFER.equals(value)))
{
if (debug != 0)
_log.debug(debug + " " + name + ": " + value);
- response.addHeader(name.toString(),value.toString());
+ String filteredHeaderValue = filterResponseHeaderValue(nameString,value.toString(),request);
+ if (filteredHeaderValue != null && filteredHeaderValue.trim().length() > 0)
+ {
+ if (debug != 0)
+ _log.debug(debug + " " + name + ": (filtered): " + filteredHeaderValue);
+ response.addHeader(nameString,filteredHeaderValue);
+ }
}
else if (debug != 0)
_log.debug(debug + " " + name + "! " + value);
@@ -785,9 +792,23 @@ public class ProxyServlet implements Servlet
}
}
+ /**
+ * Extension point for remote server response header filtering. The default implementation returns the header value as is. If null is returned, this header
+ * won't be forwarded back to the client.
+ *
+ * @param headerName
+ * @param headerValue
+ * @param request
+ * @return filteredHeaderValue
+ */
+ protected String filterResponseHeaderValue(String headerName, String headerValue, HttpServletRequest request)
+ {
+ return headerValue;
+ }
+
/**
* Transparent Proxy.
- *
+ *
* This convenience extension to ProxyServlet configures the servlet as a transparent proxy. The servlet is configured with init parameters:
*
*
ProxyTo - a URI like http://host:80/context to which the request is proxied.
@@ -795,7 +816,7 @@ public class ProxyServlet implements Servlet
*
* For example, if a request was received at /foo/bar and the ProxyTo was http://host:80/context and the Prefix was /foo, then the request would be proxied
* to http://host:80/context/bar
- *
+ *
*/
public static class Transparent extends ProxyServlet
{
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractBalancerServletTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractBalancerServletTest.java
new file mode 100644
index 00000000000..e798396adc8
--- /dev/null
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractBalancerServletTest.java
@@ -0,0 +1,157 @@
+package org.eclipse.jetty.servlets;
+
+//========================================================================
+//Copyright (c) 2012 Intalio, Inc.
+//------------------------------------------------------------------------
+//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.
+//========================================================================
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServlet;
+
+import org.eclipse.jetty.client.ContentExchange;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.http.HttpCookie;
+import org.eclipse.jetty.http.HttpMethods;
+import org.eclipse.jetty.io.Buffer;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.server.session.HashSessionIdManager;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.After;
+import org.junit.Before;
+
+
+public abstract class AbstractBalancerServletTest
+{
+
+ private boolean _stickySessions;
+
+ private Server _node1;
+
+ private Server _node2;
+
+ private Server _balancerServer;
+
+ private HttpClient _httpClient;
+
+ @Before
+ public void setUp() throws Exception
+ {
+ _httpClient = new HttpClient();
+ _httpClient.registerListener("org.eclipse.jetty.client.RedirectListener");
+ _httpClient.start();
+ }
+
+ @After
+ public void tearDown() throws Exception
+ {
+ stopServer(_node1);
+ stopServer(_node2);
+ stopServer(_balancerServer);
+ _httpClient.stop();
+ }
+
+ private void stopServer(Server server)
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Exception e)
+ {
+ // Do nothing
+ }
+ }
+
+ protected void setStickySessions(boolean stickySessions)
+ {
+ _stickySessions = stickySessions;
+ }
+
+ protected void startBalancer(Class extends HttpServlet> httpServletClass) throws Exception
+ {
+ _node1 = createServer(new ServletHolder(httpServletClass.newInstance()),"/pipo","/molo/*");
+ setSessionIdManager(_node1,"node1");
+ _node1.start();
+
+ _node2 = createServer(new ServletHolder(httpServletClass.newInstance()),"/pipo","/molo/*");
+ setSessionIdManager(_node2,"node2");
+ _node2.start();
+
+ BalancerServlet balancerServlet = new BalancerServlet();
+ ServletHolder balancerServletHolder = new ServletHolder(balancerServlet);
+ balancerServletHolder.setInitParameter("StickySessions",String.valueOf(_stickySessions));
+ balancerServletHolder.setInitParameter("ProxyPassReverse","true");
+ balancerServletHolder.setInitParameter("BalancerMember." + "node1" + ".ProxyTo","http://localhost:" + getServerPort(_node1));
+ balancerServletHolder.setInitParameter("BalancerMember." + "node2" + ".ProxyTo","http://localhost:" + getServerPort(_node2));
+
+ _balancerServer = createServer(balancerServletHolder,"/pipo","/molo/*");
+ _balancerServer.start();
+ }
+
+ private Server createServer(ServletHolder servletHolder, String appContext, String servletUrlPattern)
+ {
+ Server server = new Server();
+ SelectChannelConnector httpConnector = new SelectChannelConnector();
+ server.addConnector(httpConnector);
+
+ ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ context.setContextPath(appContext);
+ server.setHandler(context);
+
+ context.addServlet(servletHolder,servletUrlPattern);
+
+ return server;
+ }
+
+ private void setSessionIdManager(Server node, String nodeName)
+ {
+ HashSessionIdManager sessionIdManager = new HashSessionIdManager();
+ sessionIdManager.setWorkerName(nodeName);
+ node.setSessionIdManager(sessionIdManager);
+ }
+
+ private int getServerPort(Server node)
+ {
+ return node.getConnectors()[0].getLocalPort();
+ }
+
+ protected byte[] sendRequestToBalancer(String requestUri) throws IOException, InterruptedException
+ {
+ ContentExchange exchange = new ContentExchange()
+ {
+ @Override
+ protected void onResponseHeader(Buffer name, Buffer value) throws IOException
+ {
+ // Cookie persistence
+ if (name.toString().equals("Set-Cookie"))
+ {
+ String cookieVal = value.toString();
+ if (cookieVal.startsWith("JSESSIONID="))
+ {
+ String jsessionid = cookieVal.split(";")[0].substring("JSESSIONID=".length());
+ _httpClient.getDestination(getAddress(),false).addCookie(new HttpCookie("JSESSIONID",jsessionid));
+ }
+ }
+ }
+ };
+ exchange.setURL("http://localhost:" + getServerPort(_balancerServer) + "/pipo/molo/" + requestUri);
+ exchange.setMethod(HttpMethods.GET);
+
+ _httpClient.send(exchange);
+ exchange.waitForDone();
+
+ return exchange.getResponseContentBytes();
+ }
+
+}
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java
index c2b09772b7c..5d09cf114d1 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/BalancerServletTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/BalancerServletTest.java
new file mode 100644
index 00000000000..9513895fc61
--- /dev/null
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/BalancerServletTest.java
@@ -0,0 +1,129 @@
+package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright (c) 2012 Intalio, Inc.
+//------------------------------------------------------------------------
+//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.
+//========================================================================
+
+import static org.junit.Assert.*;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Test;
+
+/**
+ *
+ */
+public class BalancerServletTest extends AbstractBalancerServletTest
+{
+
+ @Test
+ public void testRoundRobinBalancer() throws Exception
+ {
+ setStickySessions(false);
+ startBalancer(CounterServlet.class);
+
+ for (int i = 0; i < 10; i++)
+ {
+ byte[] responseBytes = sendRequestToBalancer("/");
+ String returnedCounter = readFirstLine(responseBytes);
+ // RR : response should increment every other request
+ String expectedCounter = String.valueOf(i / 2);
+ assertEquals(expectedCounter,returnedCounter);
+ }
+ }
+
+ @Test
+ public void testStickySessionsBalancer() throws Exception
+ {
+ setStickySessions(true);
+ startBalancer(CounterServlet.class);
+
+ for (int i = 0; i < 10; i++)
+ {
+ byte[] responseBytes = sendRequestToBalancer("/");
+ String returnedCounter = readFirstLine(responseBytes);
+ // RR : response should increment on each request
+ String expectedCounter = String.valueOf(i);
+ assertEquals(expectedCounter,returnedCounter);
+ }
+ }
+
+ @Test
+ public void testProxyPassReverse() throws Exception
+ {
+ setStickySessions(false);
+ startBalancer(RelocationServlet.class);
+
+ byte[] responseBytes = sendRequestToBalancer("index.html");
+ String msg = readFirstLine(responseBytes);
+ assertEquals("success",msg);
+ }
+
+ private String readFirstLine(byte[] responseBytes) throws IOException
+ {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(responseBytes)));
+ return reader.readLine();
+ }
+
+ @SuppressWarnings("serial")
+ public static final class CounterServlet extends HttpServlet
+ {
+
+ private int counter;
+
+ @Override
+ public void init() throws ServletException
+ {
+ counter = 0;
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ // Force session creation
+ req.getSession();
+ resp.setContentType("text/plain");
+ resp.getWriter().println(counter++);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static final class RelocationServlet extends HttpServlet
+ {
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ if (req.getRequestURI().endsWith("/index.html"))
+ {
+ resp.sendRedirect("http://localhost:" + req.getLocalPort() + req.getContextPath() + req.getServletPath() + "/other.html?secret=pipo%20molo");
+ return;
+ }
+ resp.setContentType("text/plain");
+ if ("pipo molo".equals(req.getParameter("secret")))
+ {
+ resp.getWriter().println("success");
+ }
+ else
+ {
+ resp.getWriter().println("failure");
+ }
+ }
+ }
+
+}
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
index ff78a629ff0..c250165550f 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
@@ -1,3 +1,16 @@
+// ========================================================================
+// Copyright 2011-2012 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.servlets;
import java.io.IOException;
@@ -374,6 +387,51 @@ public class CrossOriginFilterTest
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
}
+ @Test
+ public void testSimpleRequestWithExposedHeaders() throws Exception
+ {
+ FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
+ filterHolder.setInitParameter("exposedHeaders", "Content-Length");
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
+
+ CountDownLatch latch = new CountDownLatch(1);
+ tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ "Origin: http://localhost\r\n" +
+ "\r\n";
+ String response = tester.getResponses(request);
+ Assert.assertTrue(response.contains("HTTP/1.1 200"));
+ Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_EXPOSE_HEADERS_HEADER));
+ Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testForwardPreflightRequest() throws Exception
+ {
+ FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
+ filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "PUT");
+ filterHolder.setInitParameter(CrossOriginFilter.FORWARD_PREFLIGHT_PARAM, "false");
+ tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+
+ CountDownLatch latch = new CountDownLatch(1);
+ tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
+
+ // Preflight request
+ String request = "" +
+ "OPTIONS / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD_HEADER + ": PUT\r\n" +
+ "Origin: http://localhost\r\n" +
+ "\r\n";
+ String response = tester.getResponses(request);
+ Assert.assertTrue(response.contains("HTTP/1.1 200"));
+ Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_METHODS_HEADER));
+ Assert.assertFalse(latch.await(1, TimeUnit.SECONDS));
+ }
+
public static class ResourceServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java
index 6f89e0f0eb4..eee5518c3a2 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java
@@ -1,15 +1,14 @@
-// ========================================================================
-// Copyright 2009 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.
+//========================================================================
+//Copyright 2011-2012 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.servlets;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterContentLengthTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterContentLengthTest.java
index c752591bc25..60307270b4a 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterContentLengthTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterContentLengthTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.File;
import java.util.Arrays;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultNoRecompressTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultNoRecompressTest.java
index a890b96b628..8920bf08b6a 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultNoRecompressTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultNoRecompressTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.File;
import java.io.IOException;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java
index 8fd8a0336f9..38496601c69 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.util.Arrays;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java
index 631864af8d7..7a1242eb481 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.greaterThan;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PipelineHelper.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PipelineHelper.java
index ad58c1bad6e..3ea4641cf9b 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PipelineHelper.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PipelineHelper.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.io.InputStream;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java
index 80e1fe396fa..04f06623fb1 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.File;
import java.io.FileInputStream;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java
index aadaa20fa8e..7b096319d9e 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/Hex.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/Hex.java
index ee17583c92b..3d1608f7a9d 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/Hex.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/Hex.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
public final class Hex
{
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/NoOpOutputStream.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/NoOpOutputStream.java
index 0a3c857a0ab..bb457d7682e 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/NoOpOutputStream.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/NoOpOutputStream.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
import java.io.OutputStream;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestDirContentServlet.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestDirContentServlet.java
index 440528b332b..4b95545e996 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestDirContentServlet.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestDirContentServlet.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.ByteArrayOutputStream;
import java.io.File;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestMinGzipSizeServlet.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestMinGzipSizeServlet.java
index 3a3c9897f6c..7b071cf2e04 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestMinGzipSizeServlet.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestMinGzipSizeServlet.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthStreamTypeWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthStreamTypeWrite.java
index 5c5cd4810b3..01873fedcca 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthStreamTypeWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthStreamTypeWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthTypeStreamWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthTypeStreamWrite.java
index 4cf6a4acafe..aa7b0908890 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthTypeStreamWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthTypeStreamWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamLengthTypeWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamLengthTypeWrite.java
index f10d5305ce3..271f1432170 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamLengthTypeWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamLengthTypeWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamTypeLengthWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamTypeLengthWrite.java
index efd5bcdc12e..9c85cc139a1 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamTypeLengthWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamTypeLengthWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeLengthStreamWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeLengthStreamWrite.java
index 7551d4d4a6a..9185cd3e033 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeLengthStreamWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeLengthStreamWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeStreamLengthWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeStreamLengthWrite.java
index 9efc34d43ea..87f04c204d9 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeStreamLengthWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeStreamLengthWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestStaticMimeTypeServlet.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestStaticMimeTypeServlet.java
index 298fc0aa9be..fd85fc3b73b 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestStaticMimeTypeServlet.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestStaticMimeTypeServlet.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import java.io.IOException;
diff --git a/jetty-spdy/pom.xml b/jetty-spdy/pom.xml
index 7517551c119..d03be44993e 100644
--- a/jetty-spdy/pom.xml
+++ b/jetty-spdy/pom.xml
@@ -13,7 +13,7 @@
Jetty :: SPDY :: Parent
- 1.0.0.v20120402
+ 1.1.0.v20120525
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ByteBufferPool.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ByteBufferPool.java
index 68eac61ac04..e2964cc0f00 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ByteBufferPool.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ByteBufferPool.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2012 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;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionDictionary.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionDictionary.java
index 0aa024d30f7..8b8b83a134c 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionDictionary.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionDictionary.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionFactory.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionFactory.java
index f81a5b3f491..620c24ac100 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionFactory.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionFactory.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Controller.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Controller.java
index 998efd57749..75e26ef934c 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Controller.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Controller.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategy.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategy.java
new file mode 100644
index 00000000000..c08bc421218
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategy.java
@@ -0,0 +1,86 @@
+//========================================================================
+//Copyright 2011-2012 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;
+
+import org.eclipse.jetty.spdy.api.DataInfo;
+
+// TODO: add methods that tell how much written and whether we're TCP congested ?
+public interface FlowControlStrategy
+{
+ public int getWindowSize(ISession session);
+
+ public void setWindowSize(ISession session, int windowSize);
+
+ public void onNewStream(ISession session, IStream stream);
+
+ public void onWindowUpdate(ISession session, IStream stream, int delta);
+
+ public void updateWindow(ISession session, IStream stream, int delta);
+
+ public void onDataReceived(ISession session, IStream stream, DataInfo dataInfo);
+
+ public void onDataConsumed(ISession session, IStream stream, DataInfo dataInfo, int delta);
+
+ public static class None implements FlowControlStrategy
+ {
+ private volatile int windowSize;
+
+ public None()
+ {
+ this(65536);
+ }
+
+ public None(int windowSize)
+ {
+ this.windowSize = windowSize;
+ }
+
+ @Override
+ public int getWindowSize(ISession session)
+ {
+ return windowSize;
+ }
+
+ @Override
+ public void setWindowSize(ISession session, int windowSize)
+ {
+ this.windowSize = windowSize;
+ }
+
+ @Override
+ public void onNewStream(ISession session, IStream stream)
+ {
+ stream.updateWindowSize(windowSize);
+ }
+
+ @Override
+ public void onWindowUpdate(ISession session, IStream stream, int delta)
+ {
+ }
+
+ @Override
+ public void updateWindow(ISession session, IStream stream, int delta)
+ {
+ }
+
+ @Override
+ public void onDataReceived(ISession session, IStream stream, DataInfo dataInfo)
+ {
+ }
+
+ @Override
+ public void onDataConsumed(ISession session, IStream stream, DataInfo dataInfo, int delta)
+ {
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ISession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ISession.java
index c69af218385..41bbfd7da87 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ISession.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ISession.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java
index 07934c16e17..ad75f406a7f 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java
@@ -1,29 +1,24 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
-import java.nio.ByteBuffer;
-
+import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.SessionFrameListener;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.frames.ControlFrame;
-import org.eclipse.jetty.spdy.frames.DataFrame;
/**
*
The internal interface that represents a stream.
@@ -77,37 +72,36 @@ public interface IStream extends Stream
* for example by updating the stream's state or by calling listeners.
*
* @param frame the control frame to process
- * @see #process(DataFrame, ByteBuffer)
+ * @see #process(DataInfo)
*/
public void process(ControlFrame frame);
/**
- *
Processes the given data frame along with the given byte buffer,
+ *
Processes the given {@code dataInfo},
* for example by updating the stream's state or by calling listeners.
*
- * @param frame the data frame to process
- * @param data the byte buffer to process
+ * @param dataInfo the DataInfo to process
* @see #process(ControlFrame)
*/
- public void process(DataFrame frame, ByteBuffer data);
-
+ public void process(DataInfo dataInfo);
+
/**
*
Associate the given {@link IStream} to this {@link IStream}.
- *
+ *
* @param stream the stream to associate with this stream
*/
public void associate(IStream stream);
-
+
/**
*
remove the given associated {@link IStream} from this stream
- *
+ *
* @param stream the stream to be removed
*/
public void disassociate(IStream stream);
-
+
/**
*
Overrides Stream.getAssociatedStream() to return an instance of IStream instead of Stream
- *
+ *
* @see Stream#getAssociatedStream()
*/
@Override
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IdleListener.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IdleListener.java
index 8ca26add0d5..42e44496790 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IdleListener.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IdleListener.java
@@ -1,19 +1,15 @@
-/*
- * 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.
- */
-
+///========================================================================
+//Copyright 2011-2012 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;
public interface IdleListener
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Promise.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Promise.java
index d44da62dee8..b08cde8c498 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Promise.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Promise.java
@@ -1,21 +1,19 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -44,7 +42,8 @@ public class Promise implements Handler, Future
latch.countDown();
}
- public void failed(Throwable x)
+ @Override
+ public void failed(T context, Throwable x)
{
this.failure = x;
latch.countDown();
@@ -88,6 +87,8 @@ public class Promise implements Handler, Future
private T result() throws ExecutionException
{
+ if (isCancelled())
+ throw new CancellationException();
Throwable failure = this.failure;
if (failure != null)
throw new ExecutionException(failure);
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/PushSynInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/PushSynInfo.java
index a460d54d7d4..8befef43edb 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/PushSynInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/PushSynInfo.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.spdy;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
import org.eclipse.jetty.spdy.api.SynInfo;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SPDYv3FlowControlStrategy.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SPDYv3FlowControlStrategy.java
new file mode 100644
index 00000000000..8eb4b0ebdfe
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SPDYv3FlowControlStrategy.java
@@ -0,0 +1,84 @@
+//========================================================================
+//Copyright 2011-2012 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;
+
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.frames.WindowUpdateFrame;
+
+public class SPDYv3FlowControlStrategy implements FlowControlStrategy
+{
+ private volatile int windowSize;
+
+ @Override
+ public int getWindowSize(ISession session)
+ {
+ return windowSize;
+ }
+
+ @Override
+ public void setWindowSize(ISession session, int windowSize)
+ {
+ int prevWindowSize = this.windowSize;
+ this.windowSize = windowSize;
+ for (Stream stream : session.getStreams())
+ ((IStream)stream).updateWindowSize(windowSize - prevWindowSize);
+ }
+
+ @Override
+ public void onNewStream(ISession session, IStream stream)
+ {
+ stream.updateWindowSize(windowSize);
+ }
+
+ @Override
+ public void onWindowUpdate(ISession session, IStream stream, int delta)
+ {
+ if (stream != null)
+ stream.updateWindowSize(delta);
+ }
+
+ @Override
+ public void updateWindow(ISession session, IStream stream, int delta)
+ {
+ stream.updateWindowSize(delta);
+ }
+
+ @Override
+ public void onDataReceived(ISession session, IStream stream, DataInfo dataInfo)
+ {
+ // Do nothing
+ }
+
+ @Override
+ public void onDataConsumed(ISession session, IStream stream, DataInfo dataInfo, int delta)
+ {
+ // This is the algorithm for flow control.
+ // This method may be called multiple times with delta=1, but we only send a window
+ // update when the whole dataInfo has been consumed.
+ // Other policies may be to send window updates when consumed() is greater than
+ // a certain threshold, etc. but for now the policy is not pluggable for simplicity.
+ // Note that the frequency of window updates depends on the read buffer, that
+ // should not be too smaller than the window size to avoid frequent window updates.
+ // Therefore, a pluggable policy should be able to modify the read buffer capacity.
+ int length = dataInfo.length();
+ if (dataInfo.consumed() == length && !stream.isClosed() && length > 0)
+ {
+ WindowUpdateFrame windowUpdateFrame = new WindowUpdateFrame(session.getVersion(), stream.getId(), length);
+ session.control(stream, windowUpdateFrame, 0, TimeUnit.MILLISECONDS, null, null);
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SessionException.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SessionException.java
index 3e0c1950e58..65f375412d1 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SessionException.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SessionException.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
@@ -20,7 +17,6 @@ import org.eclipse.jetty.spdy.api.SessionStatus;
public class SessionException extends RuntimeException
{
-
private final SessionStatus sessionStatus;
public SessionException(SessionStatus sessionStatus)
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardByteBufferPool.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardByteBufferPool.java
index 3ecc001da7c..60b6190bf24 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardByteBufferPool.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardByteBufferPool.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardCompressionFactory.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardCompressionFactory.java
index f0a7eebbdff..1e7e6e084d3 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardCompressionFactory.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardCompressionFactory.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
index b77e9eb6afd..d5524e2f617 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
@@ -1,26 +1,27 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.InterruptedByTimeoutException;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -33,6 +34,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.Handler;
@@ -50,6 +52,7 @@ import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.frames.ControlFrame;
import org.eclipse.jetty.spdy.frames.ControlFrameType;
+import org.eclipse.jetty.spdy.frames.CredentialFrame;
import org.eclipse.jetty.spdy.frames.DataFrame;
import org.eclipse.jetty.spdy.frames.GoAwayFrame;
import org.eclipse.jetty.spdy.frames.HeadersFrame;
@@ -61,10 +64,13 @@ import org.eclipse.jetty.spdy.frames.SynStreamFrame;
import org.eclipse.jetty.spdy.frames.WindowUpdateFrame;
import org.eclipse.jetty.spdy.generator.Generator;
import org.eclipse.jetty.spdy.parser.Parser;
+import org.eclipse.jetty.util.Atomics;
+import org.eclipse.jetty.util.component.AggregateLifeCycle;
+import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
-public class StandardSession implements ISession, Parser.Listener, Handler
+public class StandardSession implements ISession, Parser.Listener, Handler, Dumpable
{
private static final Logger logger = Log.getLogger(Session.class);
private static final ThreadLocal handlerInvocations = new ThreadLocal()
@@ -76,6 +82,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler attributes = new ConcurrentHashMap<>();
private final List listeners = new CopyOnWriteArrayList<>();
private final ConcurrentMap streams = new ConcurrentHashMap<>();
private final LinkedList queue = new LinkedList<>();
@@ -92,11 +99,13 @@ public class StandardSession implements ISession, Parser.Listener, Handler controller, IdleListener idleListener, int initialStreamId, SessionFrameListener listener, Generator generator)
+ Controller controller, IdleListener idleListener, int initialStreamId, SessionFrameListener listener,
+ Generator generator, FlowControlStrategy flowControlStrategy)
{
this.version = version;
this.bufferPool = bufferPool;
@@ -108,6 +117,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler handler)
{
SettingsFrame frame = new SettingsFrame(version,settingsInfo.getFlags(),settingsInfo.getSettings());
- control(null,frame,timeout,unit,handler,null);
+ control(null, frame, timeout, unit, handler, null);
}
@Override
@@ -237,7 +248,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler handler)
{
- goAway(SessionStatus.OK,timeout,unit,handler);
+ goAway(SessionStatus.OK, timeout, unit, handler);
}
private void goAway(SessionStatus sessionStatus, long timeout, TimeUnit unit, Handler handler)
@@ -262,17 +273,41 @@ public class StandardSession implements ISession, Parser.Listener, Handler frameBytes = new ControlFrameBytes<>(stream,handler,context,frame,buffer);
+ logger.debug("Queuing {} on {}", frame, stream);
+ ControlFrameBytes frameBytes = new ControlFrameBytes<>(stream, handler, context, frame, buffer);
if (timeout > 0)
- frameBytes.task = scheduler.schedule(frameBytes,timeout,unit);
+ frameBytes.task = scheduler.schedule(frameBytes, timeout, unit);
// Special handling for PING frames, they must be sent as soon as possible
if (ControlFrameType.PING == frame.getType())
@@ -759,26 +847,17 @@ public class StandardSession implements ISession, Parser.Listener, Handler oldValue)
- {
- if (lastStreamId.compareAndSet(oldValue,streamId))
- break;
- oldValue = lastStreamId.get();
- }
- }
+ if (streamId % 2 != streamIds.get() % 2)
+ Atomics.updateMax(lastStreamId, streamId);
}
@Override
@@ -787,9 +866,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler frameBytes = new DataFrameBytes<>(stream,handler,context,dataInfo);
if (timeout > 0)
- {
frameBytes.task = scheduler.schedule(frameBytes,timeout,unit);
- }
append(frameBytes);
flush();
}
@@ -822,9 +899,11 @@ public class StandardSession implements ISession, Parser.Listener, Handler find a better solution
- if (stream != null && !streams.containsValue(stream) && !stream.isUnidirectional())
+ if (stream != null && stream.isReset())
+ {
frameBytes.fail(new StreamException(stream.getId(),StreamStatus.INVALID_STREAM));
+ return;
+ }
break;
}
@@ -847,34 +926,50 @@ public class StandardSession implements ISession, Parser.Listener, Handler 0)
+ failure = this.failure;
+ if (failure == null)
{
- FrameBytes element = queue.get(index - 1);
- if (element.compareTo(frameBytes) >= 0)
- break;
- --index;
+ int index = queue.size();
+ while (index > 0)
+ {
+ FrameBytes element = queue.get(index - 1);
+ if (element.compareTo(frameBytes) >= 0)
+ break;
+ --index;
+ }
+ queue.add(index,frameBytes);
}
- queue.add(index,frameBytes);
}
+
+ if (failure != null)
+ frameBytes.fail(new SPDYException(failure));
}
private void prepend(FrameBytes frameBytes)
{
+ Throwable failure;
synchronized (queue)
{
- int index = 0;
- while (index < queue.size())
+ failure = this.failure;
+ if (failure == null)
{
- FrameBytes element = queue.get(index);
- if (element.compareTo(frameBytes) <= 0)
- break;
- ++index;
+ int index = 0;
+ while (index < queue.size())
+ {
+ FrameBytes element = queue.get(index);
+ if (element.compareTo(frameBytes) <= 0)
+ break;
+ ++index;
+ }
+ queue.add(index,frameBytes);
}
- queue.add(index,frameBytes);
}
+
+ if (failure != null)
+ frameBytes.fail(new SPDYException(failure));
}
@Override
@@ -889,9 +984,23 @@ public class StandardSession implements ISession, Parser.Listener, Handler frameBytesToFail = new ArrayList<>();
+ frameBytesToFail.add(frameBytes);
+
+ synchronized (queue)
+ {
+ failure = x;
+ String logMessage = String.format("Failed write of %s, failing all %d frame(s) in queue",frameBytes,queue.size());
+ logger.debug(logMessage,x);
+ frameBytesToFail.addAll(queue);
+ queue.clear();
+ flushing = false;
+ }
+
+ for (FrameBytes fb : frameBytesToFail)
+ fb.fail(x);
}
protected void write(ByteBuffer buffer, Handler handler, FrameBytes frameBytes)
@@ -947,23 +1056,64 @@ public class StandardSession implements ISession, Parser.Listener, Handler void notifyHandlerFailed(Handler handler, Throwable x)
+ private void notifyHandlerFailed(Handler handler, C context, Throwable x)
{
try
{
if (handler != null)
- handler.failed(x);
+ handler.failed(context, x);
}
catch (Exception xx)
{
- logger.info("Exception while notifying handler " + handler,xx);
+ logger.info("Exception while notifying handler " + handler, xx);
+ }
+ catch (Error xx)
+ {
+ logger.info("Exception while notifying handler " + handler, xx);
+ throw xx;
}
}
+ public int getWindowSize()
+ {
+ return flowControlStrategy.getWindowSize(this);
+ }
+
+ public void setWindowSize(int initialWindowSize)
+ {
+ flowControlStrategy.setWindowSize(this, initialWindowSize);
+ }
+
+ public String toString()
+ {
+ return String.format("%s@%x{v%d,queuSize=%d,windowSize=%d,streams=%d}", getClass().getSimpleName(), hashCode(), version, queue.size(), getWindowSize(), streams.size());
+ }
+
+
+ @Override
+ public String dump()
+ {
+ return AggregateLifeCycle.dump(this);
+ }
+
+ @Override
+ public void dump(Appendable out, String indent) throws IOException
+ {
+ AggregateLifeCycle.dumpObject(out,this);
+ AggregateLifeCycle.dump(out,indent,Collections.singletonList(controller),streams.values());
+ }
+
+
+
public interface FrameBytes extends Comparable
{
public IStream getStream();
@@ -998,8 +1148,16 @@ public class StandardSession implements ISession, Parser.Listener, Handler that.stream.priority => -1 (this.stream has less priority than that.stream)
- return that.getStream().getPriority() - getStream().getPriority();
+ // FrameBytes may have or not have a related stream (for example, PING do not have a related stream)
+ // FrameBytes without related streams have higher priority
+ IStream thisStream = getStream();
+ IStream thatStream = that.getStream();
+ if (thisStream == null)
+ return thatStream == null ? 0 : -1;
+ if (thatStream == null)
+ return 1;
+ // If this.stream.priority > that.stream.priority => this.stream has less priority than that.stream
+ return thatStream.getPriority() - thisStream.getPriority();
}
@Override
@@ -1013,7 +1171,8 @@ public class StandardSession implements ISession, Parser.Listener, Handler 0)
{
// We have written a frame out of this DataInfo, but there is more to write.
// We need to keep the correct ordering of frames, to avoid that another
// DataInfo for the same stream is written before this one is finished.
prepend(this);
+ flush();
}
else
{
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java
index 4de901c74e2..360a6395919 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java
@@ -1,22 +1,18 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
-import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -25,23 +21,18 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.Handler;
import org.eclipse.jetty.spdy.api.HeadersInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
-import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.frames.ControlFrame;
-import org.eclipse.jetty.spdy.frames.DataFrame;
import org.eclipse.jetty.spdy.frames.HeadersFrame;
import org.eclipse.jetty.spdy.frames.SynReplyFrame;
-import org.eclipse.jetty.spdy.frames.SynStreamFrame;
-import org.eclipse.jetty.spdy.frames.WindowUpdateFrame;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -49,28 +40,29 @@ public class StandardStream implements IStream
{
private static final Logger logger = Log.getLogger(Stream.class);
private final Map attributes = new ConcurrentHashMap<>();
- private final IStream associatedStream;
- private final SynStreamFrame frame;
+ private final int id;
+ private final byte priority;
private final ISession session;
- private final AtomicInteger windowSize;
+ private final IStream associatedStream;
+ private final AtomicInteger windowSize = new AtomicInteger();
private final Set pushedStreams = Collections.newSetFromMap(new ConcurrentHashMap());
private volatile StreamFrameListener listener;
private volatile OpenState openState = OpenState.SYN_SENT;
private volatile CloseState closeState = CloseState.OPENED;
private volatile boolean reset = false;
- public StandardStream(SynStreamFrame frame, ISession session, int windowSize, IStream associatedStream)
+ public StandardStream(int id, byte priority, ISession session, IStream associatedStream)
{
- this.frame = frame;
+ this.id = id;
+ this.priority = priority;
this.session = session;
- this.windowSize = new AtomicInteger(windowSize);
this.associatedStream = associatedStream;
}
@Override
public int getId()
{
- return frame.getStreamId();
+ return id;
}
@Override
@@ -100,7 +92,7 @@ public class StandardStream implements IStream
@Override
public byte getPriority()
{
- return frame.getPriority();
+ return priority;
}
@Override
@@ -113,11 +105,11 @@ public class StandardStream implements IStream
public void updateWindowSize(int delta)
{
int size = windowSize.addAndGet(delta);
- logger.debug("Updated window size by {}, new window size {}",delta,size);
+ logger.debug("Updated window size {} -> {} for {}", size - delta, size, this);
}
@Override
- public Session getSession()
+ public ISession getSession()
{
return session;
}
@@ -146,6 +138,11 @@ public class StandardStream implements IStream
this.listener = listener;
}
+ public StreamFrameListener getStreamFrameListener()
+ {
+ return listener;
+ }
+
@Override
public void updateCloseState(boolean close, boolean local)
{
@@ -155,7 +152,7 @@ public class StandardStream implements IStream
{
case OPENED:
{
- closeState = local?CloseState.LOCALLY_CLOSED:CloseState.REMOTELY_CLOSED;
+ closeState = local ? CloseState.LOCALLY_CLOSED : CloseState.REMOTELY_CLOSED;
break;
}
case LOCALLY_CLOSED:
@@ -196,25 +193,19 @@ public class StandardStream implements IStream
{
openState = OpenState.REPLY_RECV;
SynReplyFrame synReply = (SynReplyFrame)frame;
- updateCloseState(synReply.isClose(),false);
- ReplyInfo replyInfo = new ReplyInfo(synReply.getHeaders(),synReply.isClose());
+ updateCloseState(synReply.isClose(), false);
+ ReplyInfo replyInfo = new ReplyInfo(synReply.getHeaders(), synReply.isClose());
notifyOnReply(replyInfo);
break;
}
case HEADERS:
{
HeadersFrame headers = (HeadersFrame)frame;
- updateCloseState(headers.isClose(),false);
- HeadersInfo headersInfo = new HeadersInfo(headers.getHeaders(),headers.isClose(),headers.isResetCompression());
+ updateCloseState(headers.isClose(), false);
+ HeadersInfo headersInfo = new HeadersInfo(headers.getHeaders(), headers.isClose(), headers.isResetCompression());
notifyOnHeaders(headersInfo);
break;
}
- case WINDOW_UPDATE:
- {
- WindowUpdateFrame windowUpdate = (WindowUpdateFrame)frame;
- updateWindowSize(windowUpdate.getWindowDelta());
- break;
- }
case RST_STREAM:
{
reset = true;
@@ -229,57 +220,28 @@ public class StandardStream implements IStream
}
@Override
- public void process(DataFrame frame, ByteBuffer data)
+ public void process(DataInfo dataInfo)
{
// TODO: in v3 we need to send a rst instead of just ignoring
// ignore data frame if this stream is remotelyClosed already
- if (isHalfClosed() && !isLocallyClosed())
+ if (isRemotelyClosed())
{
- logger.debug("Ignoring received dataFrame as this stream is remotely closed: " + frame);
+ logger.debug("Stream is remotely closed, ignoring {}", dataInfo);
return;
}
if (!canReceive())
{
- logger.debug("Can't receive. Sending rst: " + frame);
- session.rst(new RstInfo(getId(),StreamStatus.PROTOCOL_ERROR));
+ logger.debug("Protocol error receiving {}, resetting" + dataInfo);
+ session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
return;
}
- updateCloseState(frame.isClose(),false);
-
- ByteBufferDataInfo dataInfo = new ByteBufferDataInfo(data,frame.isClose(),frame.isCompress())
- {
- @Override
- public void consume(int delta)
- {
- super.consume(delta);
-
- // This is the algorithm for flow control.
- // This method may be called multiple times with delta=1, but we only send a window
- // update when the whole dataInfo has been consumed.
- // Other policies may be to send window updates when consumed() is greater than
- // a certain threshold, etc. but for now the policy is not pluggable for simplicity.
- // Note that the frequency of window updates depends on the read buffer, that
- // should not be too smaller than the window size to avoid frequent window updates.
- // Therefore, a pluggable policy should be able to modify the read buffer capacity.
- if (consumed() == length() && !isClosed())
- windowUpdate(length());
- }
- };
+ updateCloseState(dataInfo.isClose(), false);
notifyOnData(dataInfo);
session.flush();
}
- private void windowUpdate(int delta)
- {
- if (delta > 0)
- {
- WindowUpdateFrame windowUpdateFrame = new WindowUpdateFrame(session.getVersion(),getId(),delta);
- session.control(this,windowUpdateFrame,0,TimeUnit.MILLISECONDS,null,null);
- }
- }
-
private void notifyOnReply(ReplyInfo replyInfo)
{
final StreamFrameListener listener = this.listener;
@@ -287,13 +249,18 @@ public class StandardStream implements IStream
{
if (listener != null)
{
- logger.debug("Invoking reply callback with {} on listener {}",replyInfo,listener);
- listener.onReply(this,replyInfo);
+ logger.debug("Invoking reply callback with {} on listener {}", replyInfo, listener);
+ listener.onReply(this, replyInfo);
}
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
@@ -304,13 +271,18 @@ public class StandardStream implements IStream
{
if (listener != null)
{
- logger.debug("Invoking headers callback with {} on listener {}",frame,listener);
- listener.onHeaders(this,headersInfo);
+ logger.debug("Invoking headers callback with {} on listener {}", headersInfo, listener);
+ listener.onHeaders(this, headersInfo);
}
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
@@ -321,14 +293,19 @@ public class StandardStream implements IStream
{
if (listener != null)
{
- logger.debug("Invoking data callback with {} on listener {}",dataInfo,listener);
- listener.onData(this,dataInfo);
- logger.debug("Invoked data callback with {} on listener {}",dataInfo,listener);
+ logger.debug("Invoking data callback with {} on listener {}", dataInfo, listener);
+ listener.onData(this, dataInfo);
+ logger.debug("Invoked data callback with {} on listener {}", dataInfo, listener);
}
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
@@ -345,11 +322,11 @@ public class StandardStream implements IStream
{
if (isClosed() || isReset())
{
- handler.failed(new StreamException(getId(),StreamStatus.STREAM_ALREADY_CLOSED));
+ handler.failed(this, new StreamException(getId(), StreamStatus.STREAM_ALREADY_CLOSED));
return;
}
- PushSynInfo pushSynInfo = new PushSynInfo(getId(),synInfo);
- session.syn(pushSynInfo,null,timeout,unit,handler);
+ PushSynInfo pushSynInfo = new PushSynInfo(getId(), synInfo);
+ session.syn(pushSynInfo, null, timeout, unit, handler);
}
@Override
@@ -366,9 +343,9 @@ public class StandardStream implements IStream
if (isUnidirectional())
throw new IllegalStateException("Protocol violation: cannot send SYN_REPLY frames in unidirectional streams");
openState = OpenState.REPLY_SENT;
- updateCloseState(replyInfo.isClose(),true);
- SynReplyFrame frame = new SynReplyFrame(session.getVersion(),replyInfo.getFlags(),getId(),replyInfo.getHeaders());
- session.control(this,frame,timeout,unit,handler,null);
+ updateCloseState(replyInfo.isClose(), true);
+ SynReplyFrame frame = new SynReplyFrame(session.getVersion(), replyInfo.getFlags(), getId(), replyInfo.getHeaders());
+ session.control(this, frame, timeout, unit, handler, null);
}
@Override
@@ -384,18 +361,18 @@ public class StandardStream implements IStream
{
if (!canSend())
{
- session.rst(new RstInfo(getId(),StreamStatus.PROTOCOL_ERROR));
+ session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
throw new IllegalStateException("Protocol violation: cannot send a DATA frame before a SYN_REPLY frame");
}
if (isLocallyClosed())
{
- session.rst(new RstInfo(getId(),StreamStatus.PROTOCOL_ERROR));
+ session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
throw new IllegalStateException("Protocol violation: cannot send a DATA frame on a closed stream");
}
// Cannot update the close state here, because the data that we send may
// be flow controlled, so we need the stream to update the window size.
- session.data(this,dataInfo,timeout,unit,handler,null);
+ session.data(this, dataInfo, timeout, unit, handler, null);
}
@Override
@@ -411,18 +388,18 @@ public class StandardStream implements IStream
{
if (!canSend())
{
- session.rst(new RstInfo(getId(),StreamStatus.PROTOCOL_ERROR));
+ session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
throw new IllegalStateException("Protocol violation: cannot send a HEADERS frame before a SYN_REPLY frame");
}
if (isLocallyClosed())
{
- session.rst(new RstInfo(getId(),StreamStatus.PROTOCOL_ERROR));
+ session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
throw new IllegalStateException("Protocol violation: cannot send a HEADERS frame on a closed stream");
}
- updateCloseState(headersInfo.isClose(),true);
- HeadersFrame frame = new HeadersFrame(session.getVersion(),headersInfo.getFlags(),getId(),headersInfo.getHeaders());
- session.control(this,frame,timeout,unit,handler,null);
+ updateCloseState(headersInfo.isClose(), true);
+ HeadersFrame frame = new HeadersFrame(session.getVersion(), headersInfo.getFlags(), getId(), headersInfo.getHeaders());
+ session.control(this, frame, timeout, unit, handler, null);
}
@Override
@@ -456,10 +433,16 @@ public class StandardStream implements IStream
return closeState == CloseState.LOCALLY_CLOSED || closeState == CloseState.CLOSED;
}
+ private boolean isRemotelyClosed()
+ {
+ CloseState closeState = this.closeState;
+ return closeState == CloseState.REMOTELY_CLOSED || closeState == CloseState.CLOSED;
+ }
+
@Override
public String toString()
{
- return String.format("stream=%d v%d %s",getId(),session.getVersion(),closeState);
+ return String.format("stream=%d v%d windowSize=%db reset=%s %s %s", getId(), session.getVersion(), getWindowSize(), isReset(), openState, closeState);
}
private boolean canSend()
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StreamException.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StreamException.java
index 5b4bd7f4562..4a0a954918e 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StreamException.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StreamException.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ByteBufferDataInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ByteBufferDataInfo.java
index 678ff516e36..3b856f66192 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ByteBufferDataInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ByteBufferDataInfo.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
@@ -68,4 +65,10 @@ public class ByteBufferDataInfo extends DataInfo
}
return space;
}
+
+ @Override
+ protected ByteBuffer allocate(int size)
+ {
+ return buffer.isDirect() ? ByteBuffer.allocateDirect(size) : super.allocate(size);
+ }
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/BytesDataInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/BytesDataInfo.java
index f2150846ca5..9d2123b066f 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/BytesDataInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/BytesDataInfo.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
@@ -23,39 +20,44 @@ import java.nio.ByteBuffer;
*/
public class BytesDataInfo extends DataInfo
{
- private byte[] bytes;
- private int offset;
+ private final byte[] bytes;
+ private final int offset;
+ private final int length;
+ private int index;
public BytesDataInfo(byte[] bytes, boolean close)
{
- this(bytes, close, false);
+ this(bytes, 0, bytes.length, close);
}
- public BytesDataInfo(byte[] bytes, boolean close, boolean compress)
+ public BytesDataInfo(byte[] bytes, int offset, int length, boolean close)
{
- super(close, compress);
+ super(close, false);
this.bytes = bytes;
+ this.offset = offset;
+ this.length = length;
+ this.index = offset;
}
@Override
public int length()
{
- return bytes.length;
+ return length;
}
@Override
public int available()
{
- return length() - offset;
+ return length - index + offset;
}
@Override
public int readInto(ByteBuffer output)
{
int space = output.remaining();
- int length = Math.min(available(), space);
- output.put(bytes, offset, length);
- offset += length;
- return length;
+ int chunk = Math.min(available(), space);
+ output.put(bytes, index, chunk);
+ index += chunk;
+ return chunk;
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/DataInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/DataInfo.java
index 40364017f57..8253e40fc86 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/DataInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/DataInfo.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/GoAwayInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/GoAwayInfo.java
index 4ebc7262fc6..1e16e345348 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/GoAwayInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/GoAwayInfo.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Handler.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Handler.java
index 479d33fe09c..b69467e368d 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Handler.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Handler.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
@@ -28,16 +25,16 @@ public interface Handler
*
- *
+ * @param context the context
* @param x the reason for the operation failure
*/
- public void failed(Throwable x);
+ public void failed(C context, Throwable x);
/**
*
Empty implementation of {@link Handler}
@@ -52,9 +49,8 @@ public interface Handler
}
@Override
- public void failed(Throwable x)
+ public void failed(C context, Throwable x)
{
- throw new SPDYException(x);
}
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Headers.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Headers.java
index 31615006042..261a94f730d 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Headers.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Headers.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
@@ -219,13 +216,15 @@ public class Headers implements Iterable
if (obj == null || getClass() != obj.getClass())
return false;
Header that = (Header)obj;
- return name.equals(that.name) && Arrays.equals(values, that.values);
+ // Header names must be lowercase, thus we lowercase them before transmission, but keep them as is
+ // internally. That's why we've to compare them case insensitive.
+ return name.equalsIgnoreCase(that.name) && Arrays.equals(values, that.values);
}
@Override
public int hashCode()
{
- int result = name.hashCode();
+ int result = name.toLowerCase().hashCode();
result = 31 * result + Arrays.hashCode(values);
return result;
}
@@ -268,6 +267,21 @@ public class Headers implements Iterable
return values;
}
+ /**
+ * @return the values as a comma separated list
+ */
+ public String valuesAsString()
+ {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < values.length; ++i)
+ {
+ if (i > 0)
+ result.append(", ");
+ result.append(values[i]);
+ }
+ return result.toString();
+ }
+
/**
* @return whether the header has multiple values
*/
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/HeadersInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/HeadersInfo.java
index 62ae07f6091..97a6a7e59cb 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/HeadersInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/HeadersInfo.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/PingInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/PingInfo.java
index bbcd9a87d08..28bc7a7c993 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/PingInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/PingInfo.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ReplyInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ReplyInfo.java
index 9ce0ef6eb5d..9e511436e61 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ReplyInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ReplyInfo.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/RstInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/RstInfo.java
index f1f5ee482a0..101fd713967 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/RstInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/RstInfo.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDY.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDY.java
index 8ec2d8d6687..31d7620ad55 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDY.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDY.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDYException.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDYException.java
index a0585f7ad73..af21428e877 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDYException.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDYException.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Session.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Session.java
index 5e2e5e281d7..bbe17fc7295 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Session.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Session.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
@@ -75,7 +72,7 @@ public interface Session
* @see #syn(SynInfo, StreamFrameListener, long, TimeUnit, Handler)
*/
public Future syn(SynInfo synInfo, StreamFrameListener listener);
-
+
/**
*
Sends asynchronously a SYN_FRAME to create a new {@link Stream SPDY stream}.
*
Callers may pass a non-null completion handler to be notified of when the
@@ -90,7 +87,7 @@ public interface Session
*/
public void syn(SynInfo synInfo, StreamFrameListener listener, long timeout, TimeUnit unit, Handler handler);
-
+
/**
*
Sends asynchronously a RST_STREAM to abort a stream.
*
Callers may use the returned future to wait for the reset to be sent.
@@ -180,10 +177,40 @@ public interface Session
public void goAway(long timeout, TimeUnit unit, Handler handler);
/**
- * @return the streams currently active in this session
+ * @return a snapshot of the streams currently active in this session
+ * @see #getStream(int)
*/
public Set getStreams();
+ /**
+ * @param streamId the id of the stream to retrieve
+ * @return the stream with the given stream id
+ * @see #getStreams()
+ */
+ public Stream getStream(int streamId);
+
+ /**
+ * @param key the attribute key
+ * @return an arbitrary object associated with the given key to this session
+ * @see #setAttribute(String, Object)
+ */
+ public Object getAttribute(String key);
+
+ /**
+ * @param key the attribute key
+ * @param value an arbitrary object to associate with the given key to this session
+ * @see #getAttribute(String)
+ * @see #removeAttribute(String)
+ */
+ public void setAttribute(String key, Object value);
+
+ /**
+ * @param key the attribute key
+ * @return the arbitrary object associated with the given key to this session
+ * @see #setAttribute(String, Object)
+ */
+ public Object removeAttribute(String key);
+
/**
*
Super interface for listeners with callbacks that are invoked on specific session events.
*/
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java
index 467919c29cf..7e507e3fd84 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionStatus.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionStatus.java
index c9c40d137f5..56e9355ef15 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionStatus.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionStatus.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Settings.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Settings.java
index 6db03e814c8..6ed59a00dbb 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Settings.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Settings.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SettingsInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SettingsInfo.java
index 3823382d3d3..d622189797c 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SettingsInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SettingsInfo.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java
index c7f6e3537d8..092c7a35499 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java
index a279f38a01d..23b5b169439 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamStatus.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamStatus.java
index c9908c8a146..b3e48e0b489 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamStatus.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamStatus.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StringDataInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StringDataInfo.java
index 41e9e62330a..164c6fb4302 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StringDataInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StringDataInfo.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
@@ -25,11 +22,6 @@ public class StringDataInfo extends BytesDataInfo
{
public StringDataInfo(String string, boolean close)
{
- this(string, close, false);
- }
-
- public StringDataInfo(String string, boolean close, boolean compress)
- {
- super(string.getBytes(Charset.forName("UTF-8")), close, compress);
+ super(string.getBytes(Charset.forName("UTF-8")), close);
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SynInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SynInfo.java
index c51a0016dd0..3f8eb605df0 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SynInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SynInfo.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/server/ServerSessionFrameListener.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/server/ServerSessionFrameListener.java
index 79415505698..7b330a9ceae 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/server/ServerSessionFrameListener.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/server/ServerSessionFrameListener.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api.server;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrame.java
index afd554c67e8..a9c7b0a5af6 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrame.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrameType.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrameType.java
index bf638d3bf56..1fb28346d6d 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrameType.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrameType.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
@@ -29,7 +26,8 @@ public enum ControlFrameType
PING((short)6),
GO_AWAY((short)7),
HEADERS((short)8),
- WINDOW_UPDATE((short)9);
+ WINDOW_UPDATE((short)9),
+ CREDENTIAL((short)10);
public static ControlFrameType from(short code)
{
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/CredentialFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/CredentialFrame.java
new file mode 100644
index 00000000000..5bd882fb967
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/CredentialFrame.java
@@ -0,0 +1,46 @@
+//========================================================================
+//Copyright 2011-2012 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.frames;
+
+import java.security.cert.Certificate;
+
+public class CredentialFrame extends ControlFrame
+{
+ private final short slot;
+ private final byte[] proof;
+ private final Certificate[] certificateChain;
+
+ public CredentialFrame(short version, short slot, byte[] proof, Certificate[] certificateChain)
+ {
+ super(version, ControlFrameType.CREDENTIAL, (byte)0);
+ this.slot = slot;
+ this.proof = proof;
+ this.certificateChain = certificateChain;
+ }
+
+ public short getSlot()
+ {
+ return slot;
+ }
+
+ public byte[] getProof()
+ {
+ return proof;
+ }
+
+ public Certificate[] getCertificateChain()
+ {
+ return certificateChain;
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/DataFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/DataFrame.java
index 3ce17eeb9f7..e261bf8f5ee 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/DataFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/DataFrame.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/GoAwayFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/GoAwayFrame.java
index bda5755522f..15f04f1a4dc 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/GoAwayFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/GoAwayFrame.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/HeadersFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/HeadersFrame.java
index e0545b68703..ea88513075e 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/HeadersFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/HeadersFrame.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/NoOpFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/NoOpFrame.java
index bf9eac00f3f..e4cffcc3f77 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/NoOpFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/NoOpFrame.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/PingFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/PingFrame.java
index aa1ac543d27..3989a09ccc0 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/PingFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/PingFrame.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/RstStreamFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/RstStreamFrame.java
index 334b8166ac6..0877da45d52 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/RstStreamFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/RstStreamFrame.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SettingsFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SettingsFrame.java
index afddb371fa7..8b676cde732 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SettingsFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SettingsFrame.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynReplyFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynReplyFrame.java
index 91081686382..82888b14bf6 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynReplyFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynReplyFrame.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynStreamFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynStreamFrame.java
index 1b4089541c3..c5aa8d3bc5b 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynStreamFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynStreamFrame.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
@@ -25,14 +22,16 @@ public class SynStreamFrame extends ControlFrame
private final int streamId;
private final int associatedStreamId;
private final byte priority;
+ private final short slot;
private final Headers headers;
- public SynStreamFrame(short version, byte flags, int streamId, int associatedStreamId, byte priority, Headers headers)
+ public SynStreamFrame(short version, byte flags, int streamId, int associatedStreamId, byte priority, short slot, Headers headers)
{
super(version, ControlFrameType.SYN_STREAM, flags);
this.streamId = streamId;
this.associatedStreamId = associatedStreamId;
this.priority = priority;
+ this.slot = slot;
this.headers = headers;
}
@@ -51,6 +50,11 @@ public class SynStreamFrame extends ControlFrame
return priority;
}
+ public short getSlot()
+ {
+ return slot;
+ }
+
public Headers getHeaders()
{
return headers;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/WindowUpdateFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/WindowUpdateFrame.java
index 22a4129e769..8ed37d4784c 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/WindowUpdateFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/WindowUpdateFrame.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/ControlFrameGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/ControlFrameGenerator.java
index c872beddb67..ff7302cfc7a 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/ControlFrameGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/ControlFrameGenerator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/CredentialGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/CredentialGenerator.java
new file mode 100644
index 00000000000..f2064fb68fd
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/CredentialGenerator.java
@@ -0,0 +1,80 @@
+//========================================================================
+//Copyright 2011-2012 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.generator;
+
+import java.nio.ByteBuffer;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.spdy.ByteBufferPool;
+import org.eclipse.jetty.spdy.SessionException;
+import org.eclipse.jetty.spdy.api.SessionStatus;
+import org.eclipse.jetty.spdy.frames.ControlFrame;
+import org.eclipse.jetty.spdy.frames.CredentialFrame;
+
+public class CredentialGenerator extends ControlFrameGenerator
+{
+ public CredentialGenerator(ByteBufferPool bufferPool)
+ {
+ super(bufferPool);
+ }
+
+ @Override
+ public ByteBuffer generate(ControlFrame frame)
+ {
+ CredentialFrame credential = (CredentialFrame)frame;
+
+ byte[] proof = credential.getProof();
+
+ List certificates = serializeCertificates(credential.getCertificateChain());
+ int certificatesLength = 0;
+ for (byte[] certificate : certificates)
+ certificatesLength += certificate.length;
+
+ int frameBodyLength = 2 + 4 + proof.length + certificates.size() * 4 + certificatesLength;
+
+ int totalLength = ControlFrame.HEADER_LENGTH + frameBodyLength;
+ ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
+ generateControlFrameHeader(credential, frameBodyLength, buffer);
+
+ buffer.putShort(credential.getSlot());
+ buffer.putInt(proof.length);
+ buffer.put(proof);
+ for (byte[] certificate : certificates)
+ {
+ buffer.putInt(certificate.length);
+ buffer.put(certificate);
+ }
+
+ buffer.flip();
+ return buffer;
+ }
+
+ private List serializeCertificates(Certificate[] certificates)
+ {
+ try
+ {
+ List result = new ArrayList<>(certificates.length);
+ for (Certificate certificate : certificates)
+ result.add(certificate.getEncoded());
+ return result;
+ }
+ catch (CertificateEncodingException x)
+ {
+ throw new SessionException(SessionStatus.PROTOCOL_ERROR, x);
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/DataFrameGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/DataFrameGenerator.java
index 075cbc081f7..aed8fbc7583 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/DataFrameGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/DataFrameGenerator.java
@@ -1,19 +1,15 @@
-/*
- * 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.
- */
-
+//========================================================================
+//Copyright 2011-2012 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.generator;
import java.nio.ByteBuffer;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/Generator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/Generator.java
index 70462c6ddd8..cccbf15586c 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/Generator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/Generator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
@@ -42,6 +39,7 @@ public class Generator
generators.put(ControlFrameType.GO_AWAY, new GoAwayGenerator(bufferPool));
generators.put(ControlFrameType.HEADERS, new HeadersGenerator(bufferPool, headersBlockGenerator));
generators.put(ControlFrameType.WINDOW_UPDATE, new WindowUpdateGenerator(bufferPool));
+ generators.put(ControlFrameType.CREDENTIAL, new CredentialGenerator(bufferPool));
dataFrameGenerator = new DataFrameGenerator(bufferPool);
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/GoAwayGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/GoAwayGenerator.java
index 80c824f860a..dced42a64ee 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/GoAwayGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/GoAwayGenerator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java
index 93a2dd6210b..6290841b794 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
@@ -43,7 +40,7 @@ public class HeadersBlockGenerator
writeCount(version, buffer, headers.size());
for (Headers.Header header : headers)
{
- String name = header.name();
+ String name = header.name().toLowerCase();
byte[] nameBytes = name.getBytes(iso1);
writeNameLength(version, buffer, nameBytes.length);
buffer.write(nameBytes, 0, nameBytes.length);
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersGenerator.java
index e979330ff77..6f520d91ea0 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersGenerator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
@@ -20,6 +17,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.spdy.ByteBufferPool;
import org.eclipse.jetty.spdy.SessionException;
+import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.SessionStatus;
import org.eclipse.jetty.spdy.frames.ControlFrame;
import org.eclipse.jetty.spdy.frames.HeadersFrame;
@@ -43,6 +41,8 @@ public class HeadersGenerator extends ControlFrameGenerator
ByteBuffer headersBuffer = headersBlockGenerator.generate(version, headers.getHeaders());
int frameBodyLength = 4;
+ if (frame.getVersion() == SPDY.V2)
+ frameBodyLength += 2;
int frameLength = frameBodyLength + headersBuffer.remaining();
if (frameLength > 0xFF_FF_FF)
@@ -58,6 +58,8 @@ public class HeadersGenerator extends ControlFrameGenerator
generateControlFrameHeader(headers, frameLength, buffer);
buffer.putInt(headers.getStreamId() & 0x7F_FF_FF_FF);
+ if (frame.getVersion() == SPDY.V2)
+ buffer.putShort((short)0);
buffer.put(headersBuffer);
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/NoOpGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/NoOpGenerator.java
index 5678df329cb..86a2feb5c03 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/NoOpGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/NoOpGenerator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/PingGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/PingGenerator.java
index ae2a3e4ebc8..0ead892baa5 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/PingGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/PingGenerator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/RstStreamGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/RstStreamGenerator.java
index d7d1a21af6f..63a014250ee 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/RstStreamGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/RstStreamGenerator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java
index c61846ebd84..6004afa905a 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynReplyGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynReplyGenerator.java
index 4820086da20..fc8f3827007 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynReplyGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynReplyGenerator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynStreamGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynStreamGenerator.java
index cf432e14964..ff6ace8699e 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynStreamGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynStreamGenerator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
@@ -64,6 +61,7 @@ public class SynStreamGenerator extends ControlFrameGenerator
buffer.putInt(streamId & 0x7F_FF_FF_FF);
buffer.putInt(synStream.getAssociatedStreamId() & 0x7F_FF_FF_FF);
writePriority(streamId, version, synStream.getPriority(), buffer);
+ buffer.put((byte)synStream.getSlot());
buffer.put(headersBuffer);
@@ -85,6 +83,5 @@ public class SynStreamGenerator extends ControlFrameGenerator
throw new StreamException(streamId, StreamStatus.UNSUPPORTED_VERSION);
}
buffer.put(priority);
- buffer.put((byte)0);
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/WindowUpdateGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/WindowUpdateGenerator.java
index 329d058489a..38092803cf2 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/WindowUpdateGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/WindowUpdateGenerator.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameBodyParser.java
index a9499a8ad41..f820b599c87 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java
index af8b78f6548..73c01898664 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
@@ -46,6 +43,7 @@ public abstract class ControlFrameParser
parsers.put(ControlFrameType.GO_AWAY, new GoAwayBodyParser(this));
parsers.put(ControlFrameType.HEADERS, new HeadersBodyParser(decompressor, this));
parsers.put(ControlFrameType.WINDOW_UPDATE, new WindowUpdateBodyParser(this));
+ parsers.put(ControlFrameType.CREDENTIAL, new CredentialBodyParser(this));
}
public short getVersion()
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/CredentialBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/CredentialBodyParser.java
new file mode 100644
index 00000000000..0dbb3d6b8ea
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/CredentialBodyParser.java
@@ -0,0 +1,269 @@
+//========================================================================
+//Copyright 2011-2012 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.parser;
+
+import java.io.ByteArrayInputStream;
+import java.nio.ByteBuffer;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jetty.spdy.SessionException;
+import org.eclipse.jetty.spdy.api.SessionStatus;
+import org.eclipse.jetty.spdy.frames.ControlFrameType;
+import org.eclipse.jetty.spdy.frames.CredentialFrame;
+
+public class CredentialBodyParser extends ControlFrameBodyParser
+{
+ private final List certificates = new ArrayList<>();
+ private final ControlFrameParser controlFrameParser;
+ private State state = State.SLOT;
+ private int totalLength;
+ private int cursor;
+ private short slot;
+ private int proofLength;
+ private byte[] proof;
+ private int certificateLength;
+ private byte[] certificate;
+
+ public CredentialBodyParser(ControlFrameParser controlFrameParser)
+ {
+ this.controlFrameParser = controlFrameParser;
+ }
+
+ @Override
+ public boolean parse(ByteBuffer buffer)
+ {
+ while (buffer.hasRemaining())
+ {
+ switch (state)
+ {
+ case SLOT:
+ {
+ if (buffer.remaining() >= 2)
+ {
+ slot = buffer.getShort();
+ checkSlotValid();
+ state = State.PROOF_LENGTH;
+ }
+ else
+ {
+ state = State.SLOT_BYTES;
+ cursor = 2;
+ }
+ break;
+ }
+ case SLOT_BYTES:
+ {
+ byte currByte = buffer.get();
+ --cursor;
+ slot += (currByte & 0xFF) << 8 * cursor;
+ if (cursor == 0)
+ {
+ checkSlotValid();
+ state = State.PROOF_LENGTH;
+ }
+ break;
+ }
+ case PROOF_LENGTH:
+ {
+ if (buffer.remaining() >= 4)
+ {
+ proofLength = buffer.getInt() & 0x7F_FF_FF_FF;
+ state = State.PROOF;
+ }
+ else
+ {
+ state = State.PROOF_LENGTH_BYTES;
+ cursor = 4;
+ }
+ break;
+ }
+ case PROOF_LENGTH_BYTES:
+ {
+ byte currByte = buffer.get();
+ --cursor;
+ proofLength += (currByte & 0xFF) << 8 * cursor;
+ if (cursor == 0)
+ {
+ proofLength &= 0x7F_FF_FF_FF;
+ state = State.PROOF;
+ }
+ break;
+ }
+ case PROOF:
+ {
+ totalLength = controlFrameParser.getLength() - 2 - 4 - proofLength;
+ proof = new byte[proofLength];
+ if (buffer.remaining() >= proofLength)
+ {
+ buffer.get(proof);
+ state = State.CERTIFICATE_LENGTH;
+ if (totalLength == 0)
+ {
+ onCredential();
+ return true;
+ }
+ }
+ else
+ {
+ state = State.PROOF_BYTES;
+ cursor = proofLength;
+ }
+ break;
+ }
+ case PROOF_BYTES:
+ {
+ proof[proofLength - cursor] = buffer.get();
+ --cursor;
+ if (cursor == 0)
+ {
+ state = State.CERTIFICATE_LENGTH;
+ if (totalLength == 0)
+ {
+ onCredential();
+ return true;
+ }
+ }
+ break;
+ }
+ case CERTIFICATE_LENGTH:
+ {
+ if (buffer.remaining() >= 4)
+ {
+ certificateLength = buffer.getInt() & 0x7F_FF_FF_FF;
+ state = State.CERTIFICATE;
+ }
+ else
+ {
+ state = State.CERTIFICATE_LENGTH_BYTES;
+ cursor = 4;
+ }
+ break;
+ }
+ case CERTIFICATE_LENGTH_BYTES:
+ {
+ byte currByte = buffer.get();
+ --cursor;
+ certificateLength += (currByte & 0xFF) << 8 * cursor;
+ if (cursor == 0)
+ {
+ certificateLength &= 0x7F_FF_FF_FF;
+ state = State.CERTIFICATE;
+ }
+ break;
+ }
+ case CERTIFICATE:
+ {
+ totalLength -= 4 + certificateLength;
+ certificate = new byte[certificateLength];
+ if (buffer.remaining() >= certificateLength)
+ {
+ buffer.get(certificate);
+ if (onCertificate())
+ return true;
+ }
+ else
+ {
+ state = State.CERTIFICATE_BYTES;
+ cursor = certificateLength;
+ }
+ break;
+ }
+ case CERTIFICATE_BYTES:
+ {
+ certificate[certificateLength - cursor] = buffer.get();
+ --cursor;
+ if (cursor == 0)
+ {
+ if (onCertificate())
+ return true;
+ }
+ break;
+ }
+ default:
+ {
+ throw new IllegalStateException();
+ }
+ }
+ }
+ return false;
+ }
+
+ private void checkSlotValid()
+ {
+ if (slot <= 0)
+ throw new SessionException(SessionStatus.PROTOCOL_ERROR,
+ "Invalid slot " + slot + " for " + ControlFrameType.CREDENTIAL + " frame");
+ }
+
+ private boolean onCertificate()
+ {
+ certificates.add(deserializeCertificate(certificate));
+ if (totalLength == 0)
+ {
+ onCredential();
+ return true;
+ }
+ else
+ {
+ certificateLength = 0;
+ state = State.CERTIFICATE_LENGTH;
+ }
+ return false;
+ }
+
+ private Certificate deserializeCertificate(byte[] bytes)
+ {
+ try
+ {
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+ return certificateFactory.generateCertificate(new ByteArrayInputStream(bytes));
+ }
+ catch (CertificateException x)
+ {
+ throw new SessionException(SessionStatus.PROTOCOL_ERROR, x);
+ }
+ }
+
+ private void onCredential()
+ {
+ CredentialFrame frame = new CredentialFrame(controlFrameParser.getVersion(), slot,
+ Arrays.copyOf(proof, proof.length), certificates.toArray(new Certificate[certificates.size()]));
+ controlFrameParser.onControlFrame(frame);
+ reset();
+ }
+
+ private void reset()
+ {
+ state = State.SLOT;
+ totalLength = 0;
+ cursor = 0;
+ slot = 0;
+ proofLength = 0;
+ proof = null;
+ certificateLength = 0;
+ certificate = null;
+ certificates.clear();
+ }
+
+ public enum State
+ {
+ SLOT, SLOT_BYTES, PROOF_LENGTH, PROOF_LENGTH_BYTES, PROOF, PROOF_BYTES,
+ CERTIFICATE_LENGTH, CERTIFICATE_LENGTH_BYTES, CERTIFICATE, CERTIFICATE_BYTES
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/DataFrameParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/DataFrameParser.java
index 74ea686837f..1926ab7352e 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/DataFrameParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/DataFrameParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java
index 753ad804d4d..cb9fd37d93a 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
@@ -24,7 +21,7 @@ import org.eclipse.jetty.spdy.frames.GoAwayFrame;
public class GoAwayBodyParser extends ControlFrameBodyParser
{
private final ControlFrameParser controlFrameParser;
- private State state = State.LAST_STREAM_ID;
+ private State state = State.LAST_GOOD_STREAM_ID;
private int cursor;
private int lastStreamId;
private int statusCode;
@@ -41,7 +38,7 @@ public class GoAwayBodyParser extends ControlFrameBodyParser
{
switch (state)
{
- case LAST_STREAM_ID:
+ case LAST_GOOD_STREAM_ID:
{
if (buffer.remaining() >= 4)
{
@@ -66,12 +63,12 @@ public class GoAwayBodyParser extends ControlFrameBodyParser
}
else
{
- state = State.LAST_STREAM_ID_BYTES;
+ state = State.LAST_GOOD_STREAM_ID_BYTES;
cursor = 4;
}
break;
}
- case LAST_STREAM_ID_BYTES:
+ case LAST_GOOD_STREAM_ID_BYTES:
{
byte currByte = buffer.get();
--cursor;
@@ -144,7 +141,7 @@ public class GoAwayBodyParser extends ControlFrameBodyParser
private void reset()
{
- state = State.LAST_STREAM_ID;
+ state = State.LAST_GOOD_STREAM_ID;
cursor = 0;
lastStreamId = 0;
statusCode = 0;
@@ -152,6 +149,6 @@ public class GoAwayBodyParser extends ControlFrameBodyParser
private enum State
{
- LAST_STREAM_ID, LAST_STREAM_ID_BYTES, STATUS_CODE, STATUS_CODE_BYTES
+ LAST_GOOD_STREAM_ID, LAST_GOOD_STREAM_ID_BYTES, STATUS_CODE, STATUS_CODE_BYTES
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java
index 2b4b70bafb8..60725f821e3 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBodyParser.java
index 98bbc7ca258..a91a19c5c39 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
@@ -21,6 +18,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.spdy.CompressionFactory;
import org.eclipse.jetty.spdy.api.Headers;
import org.eclipse.jetty.spdy.api.HeadersInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.frames.ControlFrameType;
import org.eclipse.jetty.spdy.frames.HeadersFrame;
@@ -51,7 +49,7 @@ public class HeadersBodyParser extends ControlFrameBodyParser
if (buffer.remaining() >= 4)
{
streamId = buffer.getInt() & 0x7F_FF_FF_FF;
- state = State.HEADERS;
+ state = State.ADDITIONAL;
}
else
{
@@ -68,14 +66,55 @@ public class HeadersBodyParser extends ControlFrameBodyParser
if (cursor == 0)
{
streamId &= 0x7F_FF_FF_FF;
- state = State.HEADERS;
+ state = State.ADDITIONAL;
}
break;
}
+ case ADDITIONAL:
+ {
+ switch (controlFrameParser.getVersion())
+ {
+ case SPDY.V2:
+ {
+ if (buffer.remaining() >= 2)
+ {
+ buffer.getShort();
+ state = State.HEADERS;
+ }
+ else
+ {
+ state = State.ADDITIONAL_BYTES;
+ cursor = 2;
+ }
+ break;
+ }
+ case SPDY.V3:
+ {
+ state = State.HEADERS;
+ break;
+ }
+ default:
+ {
+ throw new IllegalStateException();
+ }
+ }
+ break;
+ }
+ case ADDITIONAL_BYTES:
+ {
+ assert controlFrameParser.getVersion() == SPDY.V2;
+ buffer.get();
+ --cursor;
+ if (cursor == 0)
+ state = State.HEADERS;
+ break;
+ }
case HEADERS:
{
short version = controlFrameParser.getVersion();
int length = controlFrameParser.getLength() - 4;
+ if (version == SPDY.V2)
+ length -= 2;
if (headersBlockParser.parse(streamId, version, length, buffer))
{
byte flags = controlFrameParser.getFlags();
@@ -109,7 +148,7 @@ public class HeadersBodyParser extends ControlFrameBodyParser
private enum State
{
- STREAM_ID, STREAM_ID_BYTES, HEADERS
+ STREAM_ID, STREAM_ID_BYTES, ADDITIONAL, ADDITIONAL_BYTES, HEADERS
}
private class HeadersHeadersBlockParser extends HeadersBlockParser
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/NoOpBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/NoOpBodyParser.java
index ac14c798b55..f0efe09dd49 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/NoOpBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/NoOpBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java
index 8cc42e18144..df897603b51 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/PingBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/PingBodyParser.java
index 3f078f6e640..0e8ed613343 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/PingBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/PingBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/RstStreamBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/RstStreamBodyParser.java
index 81c9b3ccf83..e05aea4906d 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/RstStreamBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/RstStreamBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SettingsBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SettingsBodyParser.java
index d76382ad0e3..e4fc7c76cec 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SettingsBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SettingsBodyParser.java
@@ -1,19 +1,15 @@
-/*
- * 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.
- */
-
+//========================================================================
+//Copyright 2011-2012 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.parser;
import java.nio.ByteBuffer;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynReplyBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynReplyBodyParser.java
index ec58478f290..4c93210d3f0 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynReplyBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynReplyBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java
index 14673b9e7d7..ba54e739f99 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
@@ -38,6 +35,7 @@ public class SynStreamBodyParser extends ControlFrameBodyParser
private int streamId;
private int associatedStreamId;
private byte priority;
+ private short slot;
public SynStreamBodyParser(CompressionFactory.Decompressor decompressor, ControlFrameParser controlFrameParser)
{
@@ -118,7 +116,9 @@ public class SynStreamBodyParser extends ControlFrameBodyParser
}
else
{
- // Unused byte after priority, skip it
+ slot = (short)(currByte & 0xFF);
+ if (slot < 0)
+ throw new StreamException(streamId, StreamStatus.INVALID_CREDENTIALS);
cursor = 0;
state = State.HEADERS;
}
@@ -134,7 +134,7 @@ public class SynStreamBodyParser extends ControlFrameBodyParser
if (flags > (SynInfo.FLAG_CLOSE | PushSynInfo.FLAG_UNIDIRECTIONAL))
throw new IllegalArgumentException("Invalid flag " + flags + " for frame " + ControlFrameType.SYN_STREAM);
- SynStreamFrame frame = new SynStreamFrame(version, flags, streamId, associatedStreamId, priority, new Headers(headers, true));
+ SynStreamFrame frame = new SynStreamFrame(version, flags, streamId, associatedStreamId, priority, slot, new Headers(headers, true));
controlFrameParser.onControlFrame(frame);
reset();
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameBodyParser.java
index ea5890ff6f0..0de0d37eeb9 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/WindowUpdateBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/WindowUpdateBodyParser.java
index 697b885308d..9010a346bc1 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/WindowUpdateBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/WindowUpdateBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java
index 85cea3452d7..16af7c7a51b 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
@@ -46,7 +43,7 @@ public class AsyncTimeoutTest
Executor threadPool = Executors.newCachedThreadPool();
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor());
- Session session = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler, new TestController(), null, 1, null, generator)
+ Session session = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler, new TestController(), null, 1, null, generator, new FlowControlStrategy.None())
{
@Override
public void flush()
@@ -72,7 +69,7 @@ public class AsyncTimeoutTest
}
@Override
- public void failed(Throwable x)
+ public void failed(Stream stream, Throwable x)
{
failedLatch.countDown();
}
@@ -91,7 +88,7 @@ public class AsyncTimeoutTest
Executor threadPool = Executors.newCachedThreadPool();
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor());
- Session session = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler, new TestController(), null, 1, null, generator)
+ Session session = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler, new TestController(), null, 1, null, generator, new FlowControlStrategy.None())
{
@Override
protected void write(ByteBuffer buffer, Handler handler, FrameBytes frameBytes)
@@ -120,7 +117,7 @@ public class AsyncTimeoutTest
}
@Override
- public void failed(Throwable x)
+ public void failed(Void context, Throwable x)
{
failedLatch.countDown();
}
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java
index c999c34c59b..6406f623aec 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java
@@ -1,31 +1,20 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-
import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
@@ -34,6 +23,8 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import org.eclipse.jetty.spdy.StandardSession.FrameBytes;
+import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.Handler;
import org.eclipse.jetty.spdy.api.Headers;
@@ -55,13 +46,25 @@ import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class StandardSessionTest
{
@Mock
- private ISession sessionMock;
+ private Controller controller;
+
private ByteBufferPool bufferPool;
private Executor threadPool;
private StandardSession session;
@@ -76,13 +79,36 @@ public class StandardSessionTest
threadPool = Executors.newCachedThreadPool();
scheduler = Executors.newSingleThreadScheduledExecutor();
generator = new Generator(new StandardByteBufferPool(),new StandardCompressionFactory.StandardCompressor());
- session = new StandardSession(SPDY.V2,bufferPool,threadPool,scheduler,new TestController(),null,1,null,generator);
+ session = new StandardSession(SPDY.V2,bufferPool,threadPool,scheduler,controller,null,1,null,generator,new FlowControlStrategy.None());
headers = new Headers();
}
+ @SuppressWarnings("unchecked")
+ private void setControllerWriteExpectationToFail(final boolean fail)
+ {
+ when(controller.write(any(ByteBuffer.class),any(Handler.class),any(StandardSession.FrameBytes.class))).thenAnswer(new Answer()
+ {
+ public Integer answer(InvocationOnMock invocation)
+ {
+ Object[] args = invocation.getArguments();
+
+ Handler handler = (Handler)args[1];
+ FrameBytes context = (FrameBytes)args[2];
+
+ if (fail)
+ handler.failed(context,new ClosedChannelException());
+ else
+ handler.completed(context);
+ return 0;
+ }
+ });
+ }
+
@Test
public void testStreamIsRemovedFromSessionWhenReset() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
assertThatStreamIsInSession(stream);
assertThat("stream is not reset",stream.isReset(),is(false));
@@ -94,6 +120,8 @@ public class StandardSessionTest
@Test
public void testStreamIsAddedAndRemovedFromSession() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
assertThatStreamIsInSession(stream);
stream.updateCloseState(true,true);
@@ -105,6 +133,8 @@ public class StandardSessionTest
@Test
public void testStreamIsRemovedWhenHeadersWithCloseFlagAreSent() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
assertThatStreamIsInSession(stream);
stream.updateCloseState(true,false);
@@ -116,6 +146,8 @@ public class StandardSessionTest
@Test
public void testStreamIsUnidirectional() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
assertThat("stream is not unidirectional",stream.isUnidirectional(),not(true));
Stream pushStream = createPushStream(stream);
@@ -125,6 +157,8 @@ public class StandardSessionTest
@Test
public void testPushStreamCreation() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
Stream stream = createStream();
IStream pushStream = createPushStream(stream);
assertThat("Push stream must be associated to the first stream created",pushStream.getAssociatedStream().getId(),is(stream.getId()));
@@ -134,6 +168,8 @@ public class StandardSessionTest
@Test
public void testPushStreamIsNotClosedWhenAssociatedStreamIsClosed() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
Stream pushStream = createPushStream(stream);
assertThatStreamIsNotHalfClosed(stream);
@@ -155,6 +191,8 @@ public class StandardSessionTest
@Test
public void testCreatePushStreamOnClosedStream() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
stream.updateCloseState(true,true);
assertThatStreamIsHalfClosed(stream);
@@ -167,15 +205,10 @@ public class StandardSessionTest
{
final CountDownLatch failedLatch = new CountDownLatch(1);
SynInfo synInfo = new SynInfo(headers,false,stream.getPriority());
- stream.syn(synInfo,5,TimeUnit.SECONDS,new Handler()
+ stream.syn(synInfo,5,TimeUnit.SECONDS,new Handler.Adapter()
{
@Override
- public void completed(Stream context)
- {
- }
-
- @Override
- public void failed(Throwable x)
+ public void failed(Stream stream, Throwable x)
{
failedLatch.countDown();
}
@@ -186,6 +219,8 @@ public class StandardSessionTest
@Test
public void testPushStreamIsAddedAndRemovedFromParentAndSessionWhenClosed() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
IStream pushStream = createPushStream(stream);
assertThatPushStreamIsHalfClosed(pushStream);
@@ -200,6 +235,8 @@ public class StandardSessionTest
@Test
public void testPushStreamIsRemovedWhenReset() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
IStream pushStream = (IStream)stream.syn(new SynInfo(false)).get();
assertThatPushStreamIsInSession(pushStream);
@@ -212,6 +249,8 @@ public class StandardSessionTest
@Test
public void testPushStreamWithSynInfoClosedTrue() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
SynInfo synInfo = new SynInfo(headers,true,stream.getPriority());
IStream pushStream = (IStream)stream.syn(synInfo).get(5,TimeUnit.SECONDS);
@@ -225,6 +264,8 @@ public class StandardSessionTest
public void testPushStreamSendHeadersWithCloseFlagIsRemovedFromSessionAndDisassociateFromParent() throws InterruptedException, ExecutionException,
TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
SynInfo synInfo = new SynInfo(headers,false,stream.getPriority());
IStream pushStream = (IStream)stream.syn(synInfo).get(5,TimeUnit.SECONDS);
@@ -240,6 +281,8 @@ public class StandardSessionTest
@Test
public void testCreatedAndClosedListenersAreCalledForNewStream() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
final CountDownLatch createdListenerCalledLatch = new CountDownLatch(1);
final CountDownLatch closedListenerCalledLatch = new CountDownLatch(1);
session.addListener(new TestStreamListener(createdListenerCalledLatch,closedListenerCalledLatch));
@@ -253,6 +296,8 @@ public class StandardSessionTest
@Test
public void testListenerIsCalledForResetStream() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
final CountDownLatch closedListenerCalledLatch = new CountDownLatch(1);
session.addListener(new TestStreamListener(null,closedListenerCalledLatch));
IStream stream = createStream();
@@ -263,6 +308,8 @@ public class StandardSessionTest
@Test
public void testCreatedAndClosedListenersAreCalledForNewPushStream() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
final CountDownLatch createdListenerCalledLatch = new CountDownLatch(2);
final CountDownLatch closedListenerCalledLatch = new CountDownLatch(1);
session.addListener(new TestStreamListener(createdListenerCalledLatch,closedListenerCalledLatch));
@@ -277,6 +324,8 @@ public class StandardSessionTest
@Test
public void testListenerIsCalledForResetPushStream() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
final CountDownLatch closedListenerCalledLatch = new CountDownLatch(1);
session.addListener(new TestStreamListener(null,closedListenerCalledLatch));
IStream stream = createStream();
@@ -313,31 +362,23 @@ public class StandardSessionTest
}
}
- @SuppressWarnings("unchecked")
- @Test(expected = IllegalStateException.class)
- public void testSendDataOnHalfClosedStream() throws InterruptedException, ExecutionException, TimeoutException
- {
- SynStreamFrame synStreamFrame = new SynStreamFrame(SPDY.V2,SynInfo.FLAG_CLOSE,1,0,(byte)0,null);
- IStream stream = new StandardStream(synStreamFrame,sessionMock,8184,null);
- stream.updateCloseState(synStreamFrame.isClose(),true);
- assertThat("stream is half closed",stream.isHalfClosed(),is(true));
- stream.data(new StringDataInfo("data on half closed stream",true));
- verify(sessionMock,never()).data(any(IStream.class),any(DataInfo.class),anyInt(),any(TimeUnit.class),any(Handler.class),any(void.class));
- }
-
@Test
@Ignore("In V3 we need to rst the stream if we receive data on a remotely half closed stream.")
public void receiveDataOnRemotelyHalfClosedStreamResetsStreamInV3() throws InterruptedException, ExecutionException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = (IStream)session.syn(new SynInfo(false),new StreamFrameListener.Adapter()).get();
stream.updateCloseState(true,false);
assertThat("stream is half closed from remote side",stream.isHalfClosed(),is(true));
- stream.process(new DataFrame(stream.getId(),(byte)0,256),ByteBuffer.allocate(256));
+ stream.process(new ByteBufferDataInfo(ByteBuffer.allocate(256), true));
}
@Test
public void testReceiveDataOnRemotelyClosedStreamIsIgnored() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
final CountDownLatch onDataCalledLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(false),new StreamFrameListener.Adapter()
{
@@ -353,10 +394,38 @@ public class StandardSessionTest
assertThat("onData is never called",onDataCalledLatch.await(1,TimeUnit.SECONDS),not(true));
}
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testControllerWriteFailsInEndPointFlush() throws InterruptedException
+ {
+ setControllerWriteExpectationToFail(true);
+
+ final CountDownLatch failedCalledLatch = new CountDownLatch(2);
+ SynStreamFrame synStreamFrame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, null);
+ IStream stream = new StandardStream(synStreamFrame.getStreamId(), synStreamFrame.getPriority(), session, null);
+ stream.updateWindowSize(8192);
+ Handler.Adapter handler = new Handler.Adapter()
+ {
+ @Override
+ public void failed(Void context, Throwable x)
+ {
+ failedCalledLatch.countDown();
+ }
+ };
+
+ // first data frame should fail on controller.write()
+ stream.data(new StringDataInfo("data", false), 5, TimeUnit.SECONDS, handler);
+ // second data frame should fail without controller.writer() as the connection is expected to be broken after first controller.write() call failed.
+ stream.data(new StringDataInfo("data", false), 5, TimeUnit.SECONDS, handler);
+
+ verify(controller, times(1)).write(any(ByteBuffer.class), any(Handler.class), any(FrameBytes.class));
+ assertThat("Handler.failed has been called twice", failedCalledLatch.await(5, TimeUnit.SECONDS), is(true));
+ }
+
private IStream createStream() throws InterruptedException, ExecutionException, TimeoutException
{
SynInfo synInfo = new SynInfo(headers,false,(byte)0);
- return (IStream)session.syn(synInfo,new StreamFrameListener.Adapter()).get(5,TimeUnit.SECONDS);
+ return (IStream)session.syn(synInfo,new StreamFrameListener.Adapter()).get(50,TimeUnit.SECONDS);
}
private IStream createPushStream(Stream stream) throws InterruptedException, ExecutionException, TimeoutException
@@ -365,21 +434,6 @@ public class StandardSessionTest
return (IStream)stream.syn(synInfo).get(5,TimeUnit.SECONDS);
}
- private static class TestController implements Controller
- {
- @Override
- public int write(ByteBuffer buffer, Handler handler, StandardSession.FrameBytes context)
- {
- handler.completed(context);
- return buffer.remaining();
- }
-
- @Override
- public void close(boolean onlyOutput)
- {
- }
- }
-
private void assertThatStreamIsClosed(IStream stream)
{
assertThat("stream is closed",stream.isClosed(),is(true));
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java
index 68a6a9576c6..f75c7237395 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java
@@ -1,36 +1,31 @@
-// ========================================================================
-// Copyright (c) 2009-2009 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.
-// ========================================================================
-
+//========================================================================
+//Copyright 2011-2012 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;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.Handler;
+import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Stream;
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.frames.SynStreamFrame;
import org.junit.Test;
@@ -39,16 +34,25 @@ import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
-/* ------------------------------------------------------------ */
-/**
- */
@RunWith(MockitoJUnitRunner.class)
public class StandardStreamTest
{
- @Mock private ISession session;
- @Mock private SynStreamFrame synStreamFrame;
-
+ @Mock
+ private ISession session;
+ @Mock
+ private SynStreamFrame synStreamFrame;
+
/**
* Test method for {@link org.eclipse.jetty.spdy.StandardStream#syn(org.eclipse.jetty.spdy.api.SynInfo)}.
*/
@@ -56,34 +60,38 @@ public class StandardStreamTest
@Test
public void testSyn()
{
- Stream stream = new StandardStream(synStreamFrame,session,0,null);
+ Stream stream = new StandardStream(synStreamFrame.getStreamId(), synStreamFrame.getPriority(), session, null);
Set streams = new HashSet<>();
streams.add(stream);
when(synStreamFrame.isClose()).thenReturn(false);
SynInfo synInfo = new SynInfo(false);
when(session.getStreams()).thenReturn(streams);
stream.syn(synInfo);
- verify(session).syn(argThat(new PushSynInfoMatcher(stream.getId(),synInfo)),any(StreamFrameListener.class),anyLong(),any(TimeUnit.class),any(Handler.class));
+ verify(session).syn(argThat(new PushSynInfoMatcher(stream.getId(), synInfo)), any(StreamFrameListener.class), anyLong(), any(TimeUnit.class), any(Handler.class));
}
-
- private class PushSynInfoMatcher extends ArgumentMatcher{
+
+ private class PushSynInfoMatcher extends ArgumentMatcher
+ {
int associatedStreamId;
SynInfo synInfo;
-
+
public PushSynInfoMatcher(int associatedStreamId, SynInfo synInfo)
{
this.associatedStreamId = associatedStreamId;
this.synInfo = synInfo;
}
+
@Override
public boolean matches(Object argument)
{
PushSynInfo pushSynInfo = (PushSynInfo)argument;
- if(pushSynInfo.getAssociatedStreamId() != associatedStreamId){
+ if (pushSynInfo.getAssociatedStreamId() != associatedStreamId)
+ {
System.out.println("streamIds do not match!");
return false;
}
- if(pushSynInfo.isClose() != synInfo.isClose()){
+ if (pushSynInfo.isClose() != synInfo.isClose())
+ {
System.out.println("isClose doesn't match");
return false;
}
@@ -92,16 +100,17 @@ public class StandardStreamTest
}
@Test
- public void testSynOnClosedStream(){
- IStream stream = new StandardStream(synStreamFrame,session,0,null);
- stream.updateCloseState(true,true);
- stream.updateCloseState(true,false);
- assertThat("stream expected to be closed",stream.isClosed(),is(true));
+ public void testSynOnClosedStream()
+ {
+ IStream stream = new StandardStream(synStreamFrame.getStreamId(), synStreamFrame.getPriority(), session, null);
+ stream.updateCloseState(true, true);
+ stream.updateCloseState(true, false);
+ assertThat("stream expected to be closed", stream.isClosed(), is(true));
final CountDownLatch failedLatch = new CountDownLatch(1);
- stream.syn(new SynInfo(false),1,TimeUnit.SECONDS,new Handler.Adapter()
+ stream.syn(new SynInfo(false), 1, TimeUnit.SECONDS, new Handler.Adapter()
{
@Override
- public void failed(Throwable x)
+ public void failed(Stream stream, Throwable x)
{
failedLatch.countDown();
}
@@ -109,4 +118,16 @@ public class StandardStreamTest
assertThat("PushStream creation failed", failedLatch.getCount(), equalTo(0L));
}
+ @SuppressWarnings("unchecked")
+ @Test(expected = IllegalStateException.class)
+ public void testSendDataOnHalfClosedStream() throws InterruptedException, ExecutionException, TimeoutException
+ {
+ SynStreamFrame synStreamFrame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, null);
+ IStream stream = new StandardStream(synStreamFrame.getStreamId(), synStreamFrame.getPriority(), session, null);
+ stream.updateWindowSize(8192);
+ stream.updateCloseState(synStreamFrame.isClose(), true);
+ assertThat("stream is half closed", stream.isHalfClosed(), is(true));
+ stream.data(new StringDataInfo("data on half closed stream", true));
+ verify(session, never()).data(any(IStream.class), any(DataInfo.class), anyInt(), any(TimeUnit.class), any(Handler.class), any(void.class));
+ }
}
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ClientUsageTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ClientUsageTest.java
index b1c40d54daf..9de7f49175a 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ClientUsageTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ClientUsageTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
@@ -29,7 +26,7 @@ public class ClientUsageTest
@Test
public void testClientRequestResponseNoBody() throws Exception
{
- Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null);
+ Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null, null);
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
{
@@ -48,7 +45,7 @@ public class ClientUsageTest
@Test
public void testClientRequestWithBodyResponseNoBody() throws Exception
{
- Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null);
+ Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null, null);
Stream stream = session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
{
@@ -69,7 +66,7 @@ public class ClientUsageTest
@Test
public void testAsyncClientRequestWithBodyResponseNoBody() throws Exception
{
- Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null);
+ Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null, null);
final String context = "context";
session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
@@ -104,7 +101,7 @@ public class ClientUsageTest
@Test
public void testAsyncClientRequestWithBodyAndResponseWithBody() throws Exception
{
- Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null);
+ Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null, null);
session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
{
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ServerUsageTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ServerUsageTest.java
index a8bff06d67b..b1a326fc17a 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ServerUsageTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ServerUsageTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.api;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/CredentialGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/CredentialGenerateParseTest.java
new file mode 100644
index 00000000000..e7db2c8c7a6
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/CredentialGenerateParseTest.java
@@ -0,0 +1,99 @@
+//========================================================================
+//Copyright 2011-2012 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.frames;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+
+import org.eclipse.jetty.spdy.StandardByteBufferPool;
+import org.eclipse.jetty.spdy.StandardCompressionFactory;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.generator.Generator;
+import org.eclipse.jetty.spdy.parser.Parser;
+import org.eclipse.jetty.util.resource.Resource;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CredentialGenerateParseTest
+{
+ @Test
+ public void testGenerateParse() throws Exception
+ {
+ short slot = 1;
+ byte[] proof = new byte[]{0, 1, 2};
+ Certificate[] temp = loadCertificates();
+ Certificate[] certificates = new Certificate[temp.length * 2];
+ System.arraycopy(temp, 0, certificates, 0, temp.length);
+ System.arraycopy(temp, 0, certificates, temp.length, temp.length);
+ CredentialFrame frame1 = new CredentialFrame(SPDY.V3, slot, proof, certificates);
+ Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
+ ByteBuffer buffer = generator.control(frame1);
+
+ Assert.assertNotNull(buffer);
+
+ TestSPDYParserListener listener = new TestSPDYParserListener();
+ Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
+ parser.addListener(listener);
+ parser.parse(buffer);
+ ControlFrame frame2 = listener.getControlFrame();
+
+ Assert.assertNotNull(frame2);
+ Assert.assertEquals(ControlFrameType.CREDENTIAL, frame2.getType());
+ CredentialFrame credential = (CredentialFrame)frame2;
+ Assert.assertEquals(SPDY.V3, credential.getVersion());
+ Assert.assertEquals(0, credential.getFlags());
+ Assert.assertEquals(slot, credential.getSlot());
+ Assert.assertArrayEquals(proof, credential.getProof());
+ Assert.assertArrayEquals(certificates, credential.getCertificateChain());
+ }
+
+ @Test
+ public void testGenerateParseOneByteAtATime() throws Exception
+ {
+ short slot = 1;
+ byte[] proof = new byte[]{0, 1, 2};
+ Certificate[] certificates = loadCertificates();
+ CredentialFrame frame1 = new CredentialFrame(SPDY.V3, slot, proof, certificates);
+ Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
+ ByteBuffer buffer = generator.control(frame1);
+
+ Assert.assertNotNull(buffer);
+
+ TestSPDYParserListener listener = new TestSPDYParserListener();
+ Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
+ parser.addListener(listener);
+ while (buffer.hasRemaining())
+ parser.parse(ByteBuffer.wrap(new byte[]{buffer.get()}));
+ ControlFrame frame2 = listener.getControlFrame();
+
+ Assert.assertNotNull(frame2);
+ Assert.assertEquals(ControlFrameType.CREDENTIAL, frame2.getType());
+ CredentialFrame credential = (CredentialFrame)frame2;
+ Assert.assertEquals(SPDY.V3, credential.getVersion());
+ Assert.assertEquals(0, credential.getFlags());
+ Assert.assertEquals(slot, credential.getSlot());
+ Assert.assertArrayEquals(proof, credential.getProof());
+ Assert.assertArrayEquals(certificates, credential.getCertificateChain());
+ }
+
+ private Certificate[] loadCertificates() throws Exception
+ {
+ KeyStore keyStore = KeyStore.getInstance("JKS");
+ InputStream keyStoreStream = Resource.newResource("src/test/resources/keystore.jks").getInputStream();
+ keyStore.load(keyStoreStream, "storepwd".toCharArray());
+ return keyStore.getCertificateChain("mykey");
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/DataGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/DataGenerateParseTest.java
index ea83e10dd93..6f53b64c09c 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/DataGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/DataGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/GoAwayGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/GoAwayGenerateParseTest.java
index c32df12ba02..c3ae26d4368 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/GoAwayGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/GoAwayGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/HeadersGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/HeadersGenerateParseTest.java
index 99bd4b37edd..fd5a36de3d8 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/HeadersGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/HeadersGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
@@ -25,65 +22,77 @@ import org.eclipse.jetty.spdy.api.HeadersInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.generator.Generator;
import org.eclipse.jetty.spdy.parser.Parser;
-import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
public class HeadersGenerateParseTest
{
- @Test
- public void testGenerateParse() throws Exception
+
+ private Headers headers = new Headers();
+ private int streamId = 13;
+ private byte flags = HeadersInfo.FLAG_RESET_COMPRESSION;
+ private final TestSPDYParserListener listener = new TestSPDYParserListener();
+ private final Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
+ private ByteBuffer buffer;
+
+ @Before
+ public void setUp()
{
- byte flags = HeadersInfo.FLAG_RESET_COMPRESSION;
- int streamId = 13;
- Headers headers = new Headers();
+ parser.addListener(listener);
headers.put("a", "b");
+ buffer = createHeadersFrameBuffer(headers);
+ }
+
+ private ByteBuffer createHeadersFrameBuffer(Headers headers)
+ {
HeadersFrame frame1 = new HeadersFrame(SPDY.V2, flags, streamId, headers);
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
ByteBuffer buffer = generator.control(frame1);
+ assertThat("Buffer is not null", buffer, notNullValue());
+ return buffer;
+ }
- Assert.assertNotNull(buffer);
-
- TestSPDYParserListener listener = new TestSPDYParserListener();
- Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
- parser.addListener(listener);
+ @Test
+ public void testGenerateParse() throws Exception
+ {
parser.parse(buffer);
- ControlFrame frame2 = listener.getControlFrame();
-
- Assert.assertNotNull(frame2);
- Assert.assertEquals(ControlFrameType.HEADERS, frame2.getType());
- HeadersFrame headersFrame = (HeadersFrame)frame2;
- Assert.assertEquals(SPDY.V2, headersFrame.getVersion());
- Assert.assertEquals(streamId, headersFrame.getStreamId());
- Assert.assertEquals(flags, headersFrame.getFlags());
- Assert.assertEquals(headers, headersFrame.getHeaders());
+ assertExpectationsAreMet(headers);
}
@Test
public void testGenerateParseOneByteAtATime() throws Exception
{
- byte flags = HeadersInfo.FLAG_RESET_COMPRESSION;
- int streamId = 13;
- Headers headers = new Headers();
- headers.put("a", "b");
- HeadersFrame frame1 = new HeadersFrame(SPDY.V2, flags, streamId, headers);
- Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
- ByteBuffer buffer = generator.control(frame1);
-
- Assert.assertNotNull(buffer);
-
- TestSPDYParserListener listener = new TestSPDYParserListener();
- Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
- parser.addListener(listener);
while (buffer.hasRemaining())
parser.parse(ByteBuffer.wrap(new byte[]{buffer.get()}));
- ControlFrame frame2 = listener.getControlFrame();
- Assert.assertNotNull(frame2);
- Assert.assertEquals(ControlFrameType.HEADERS, frame2.getType());
- HeadersFrame headersFrame = (HeadersFrame)frame2;
- Assert.assertEquals(SPDY.V2, headersFrame.getVersion());
- Assert.assertEquals(streamId, headersFrame.getStreamId());
- Assert.assertEquals(flags, headersFrame.getFlags());
- Assert.assertEquals(headers, headersFrame.getHeaders());
+ assertExpectationsAreMet(headers);
+ }
+
+ @Test
+ public void testHeadersAreTranslatedToLowerCase()
+ {
+ Headers headers = new Headers();
+ headers.put("Via","localhost");
+ parser.parse(createHeadersFrameBuffer(headers));
+ HeadersFrame parsedHeadersFrame = assertExpectationsAreMet(headers);
+ Headers.Header viaHeader = parsedHeadersFrame.getHeaders().get("via");
+ assertThat("Via Header name is lowercase", viaHeader.name(), is("via"));
+ }
+
+ private HeadersFrame assertExpectationsAreMet(Headers headers)
+ {
+ ControlFrame parsedControlFrame = listener.getControlFrame();
+ assertThat("listener received controlFrame", parsedControlFrame, notNullValue());
+ assertThat("ControlFrame type is HEADERS", ControlFrameType.HEADERS, is(parsedControlFrame.getType()));
+ HeadersFrame headersFrame = (HeadersFrame)parsedControlFrame;
+ assertThat("Version matches", SPDY.V2, is(headersFrame.getVersion()));
+ assertThat("StreamId matches", streamId, is(headersFrame.getStreamId()));
+ assertThat("flags match", flags, is(headersFrame.getFlags()));
+ assertThat("headers match", headers, is(headersFrame.getHeaders()));
+ return headersFrame;
}
}
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/NoOpGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/NoOpGenerateParseTest.java
index 50afa5f4b6e..9c248be4ed6 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/NoOpGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/NoOpGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/PingGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/PingGenerateParseTest.java
index 231406a6a9f..1bd87f86010 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/PingGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/PingGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/RstStreamGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/RstStreamGenerateParseTest.java
index 378a3faf917..df70d3695d4 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/RstStreamGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/RstStreamGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SettingsGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SettingsGenerateParseTest.java
index 3fc531b93ad..88b640d63cc 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SettingsGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SettingsGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynReplyGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynReplyGenerateParseTest.java
index ed51e826753..6da3189c542 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynReplyGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynReplyGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynStreamGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynStreamGenerateParseTest.java
index 2fac2bbe9f3..5cf4b223c17 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynStreamGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynStreamGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
@@ -37,10 +34,11 @@ public class SynStreamGenerateParseTest
int streamId = 13;
int associatedStreamId = 11;
byte priority = 3;
+ short slot = 5;
Headers headers = new Headers();
headers.put("a", "b");
headers.put("c", "d");
- SynStreamFrame frame1 = new SynStreamFrame(SPDY.V2, flags, streamId, associatedStreamId, priority, headers);
+ SynStreamFrame frame1 = new SynStreamFrame(SPDY.V2, flags, streamId, associatedStreamId, priority, slot, headers);
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
ByteBuffer buffer = generator.control(frame1);
@@ -60,6 +58,7 @@ public class SynStreamGenerateParseTest
Assert.assertEquals(associatedStreamId, synStream.getAssociatedStreamId());
Assert.assertEquals(flags, synStream.getFlags());
Assert.assertEquals(priority, synStream.getPriority());
+ Assert.assertEquals(slot, synStream.getSlot());
Assert.assertEquals(headers, synStream.getHeaders());
}
@@ -70,10 +69,11 @@ public class SynStreamGenerateParseTest
int streamId = 13;
int associatedStreamId = 11;
byte priority = 3;
+ short slot = 5;
Headers headers = new Headers();
headers.put("a", "b");
headers.put("c", "d");
- SynStreamFrame frame1 = new SynStreamFrame(SPDY.V2, flags, streamId, associatedStreamId, priority, headers);
+ SynStreamFrame frame1 = new SynStreamFrame(SPDY.V2, flags, streamId, associatedStreamId, priority, slot, headers);
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
ByteBuffer buffer = generator.control(frame1);
@@ -94,6 +94,7 @@ public class SynStreamGenerateParseTest
Assert.assertEquals(associatedStreamId, synStream.getAssociatedStreamId());
Assert.assertEquals(flags, synStream.getFlags());
Assert.assertEquals(priority, synStream.getPriority());
+ Assert.assertEquals(slot, synStream.getSlot());
Assert.assertEquals(headers, synStream.getHeaders());
}
}
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/TestSPDYParserListener.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/TestSPDYParserListener.java
index 4642ca5d3bf..14e0cf35c87 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/TestSPDYParserListener.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/TestSPDYParserListener.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/WindowUpdateGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/WindowUpdateGenerateParseTest.java
index 8f7dbee2117..41bdf676acf 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/WindowUpdateGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/WindowUpdateGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/LiveChromiumRequestParserTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/LiveChromiumRequestParserTest.java
index 56b65f0b6fe..46b7897f7ac 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/LiveChromiumRequestParserTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/LiveChromiumRequestParserTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/ParseVersusCacheBenchmarkTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/ParseVersusCacheBenchmarkTest.java
index abaac53a2c2..cc92e0c6293 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/ParseVersusCacheBenchmarkTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/ParseVersusCacheBenchmarkTest.java
@@ -1,18 +1,15 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.parser;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameTest.java
index 750f407d4b4..12c470c40ce 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameTest.java
@@ -1,3 +1,16 @@
+//========================================================================
+//Copyright 2011-2012 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.parser;
import java.nio.ByteBuffer;
@@ -23,7 +36,7 @@ public class UnknownControlFrameTest
@Test
public void testUnknownControlFrame() throws Exception
{
- SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, new Headers());
+ SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, new Headers());
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor());
ByteBuffer buffer = generator.control(frame);
// Change the frame type to unknown
diff --git a/jetty-spdy/spdy-core/src/test/resources/keystore.jks b/jetty-spdy/spdy-core/src/test/resources/keystore.jks
new file mode 100644
index 00000000000..428ba54776e
Binary files /dev/null and b/jetty-spdy/spdy-core/src/test/resources/keystore.jks differ
diff --git a/jetty-spdy/spdy-core/src/test/resources/truststore.jks b/jetty-spdy/spdy-core/src/test/resources/truststore.jks
new file mode 100644
index 00000000000..839cb8c3515
Binary files /dev/null and b/jetty-spdy/spdy-core/src/test/resources/truststore.jks differ
diff --git a/jetty-spdy/spdy-jetty-http-webapp/pom.xml b/jetty-spdy/spdy-jetty-http-webapp/pom.xml
index 7aa8e915258..150217e98cb 100644
--- a/jetty-spdy/spdy-jetty-http-webapp/pom.xml
+++ b/jetty-spdy/spdy-jetty-http-webapp/pom.xml
@@ -39,7 +39,7 @@
quit
-Dlog4j.configuration=file://${basedir}/src/main/resources/log4j.properties
- -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${project.version}/npn-boot-${project.version}.jar
+ -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn.version}/npn-boot-${npn.version}.jar
${basedir}/src/main/config/etc/jetty-spdy.xml/
@@ -60,4 +60,45 @@
-->
+
+
+
diff --git a/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy-proxy.xml b/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy-proxy.xml
new file mode 100644
index 00000000000..9c637ec41f8
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy-proxy.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+ src/main/resources/keystore.jks
+ storepwd
+ src/main/resources/truststore.jks
+ storepwd
+ TLSv1
+
+
+
+
+
+
+
+
+ 9090
+
+
+ spdy/2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ spdy/2
+
+
+
+
+
+
+
+
+
+
+
+
+ 8080
+
+
+
+
+
+
+
+
+ 8443
+
+
+
+
+
+
diff --git a/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml b/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml
index 95c9c2b9c27..0d847bcbd48 100644
--- a/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml
+++ b/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml
@@ -11,9 +11,45 @@
TLSv1
+
+
+
+
+
+
+
+
8080
@@ -24,6 +60,24 @@
+
+
8443
diff --git a/jetty-spdy/spdy-jetty-http/pom.xml b/jetty-spdy/spdy-jetty-http/pom.xml
index e89e2098436..dfaf1b1f937 100644
--- a/jetty-spdy/spdy-jetty-http/pom.xml
+++ b/jetty-spdy/spdy-jetty-http/pom.xml
@@ -60,12 +60,23 @@
1.0.0.v20120402test
+
+ org.eclipse.jetty
+ jetty-client
+ ${project.version}
+ test
+ org.slf4jslf4j-log4j12${slf4j-version}test
+
+ org.mockito
+ mockito-core
+ test
+
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYServerConnector.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYServerConnector.java
new file mode 100644
index 00000000000..543f78323ca
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYServerConnector.java
@@ -0,0 +1,61 @@
+//========================================================================
+//Copyright 2011-2012 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.http;
+
+import java.io.IOException;
+
+import org.eclipse.jetty.http.HttpSchemes;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
+import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+public class AbstractHTTPSPDYServerConnector extends SPDYServerConnector
+{
+ public AbstractHTTPSPDYServerConnector(ServerSessionFrameListener listener, SslContextFactory sslContextFactory)
+ {
+ super(listener, sslContextFactory);
+ }
+
+ @Override
+ public void customize(EndPoint endPoint, Request request) throws IOException
+ {
+ super.customize(endPoint, request);
+ if (getSslContextFactory() != null)
+ request.setScheme(HttpSchemes.HTTPS);
+ }
+
+ @Override
+ public boolean isConfidential(Request request)
+ {
+ if (getSslContextFactory() != null)
+ {
+ int confidentialPort = getConfidentialPort();
+ return confidentialPort == 0 || confidentialPort == request.getServerPort();
+ }
+ return super.isConfidential(request);
+ }
+
+ @Override
+ public boolean isIntegral(Request request)
+ {
+ if (getSslContextFactory() != null)
+ {
+ int integralPort = getIntegralPort();
+ return integralPort == 0 || integralPort == request.getServerPort();
+ }
+ return super.isIntegral(request);
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYHeader.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYHeader.java
new file mode 100644
index 00000000000..7149aa5ae0b
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYHeader.java
@@ -0,0 +1,73 @@
+//========================================================================
+//Copyright 2011-2012 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.http;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jetty.spdy.api.SPDY;
+
+public enum HTTPSPDYHeader
+{
+ METHOD("method", ":method"),
+ URI("url", ":path"),
+ VERSION("version", ":version"),
+ SCHEME("scheme", ":scheme"),
+ HOST("host", ":host"),
+ STATUS("status", ":status");
+
+ public static HTTPSPDYHeader from(short version, String name)
+ {
+ switch (version)
+ {
+ case SPDY.V2:
+ return Names.v2Names.get(name);
+ case SPDY.V3:
+ return Names.v3Names.get(name);
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ private final String v2Name;
+ private final String v3Name;
+
+ private HTTPSPDYHeader(String v2Name, String v3Name)
+ {
+ this.v2Name = v2Name;
+ Names.v2Names.put(v2Name, this);
+ this.v3Name = v3Name;
+ Names.v3Names.put(v3Name, this);
+ }
+
+ public String name(short version)
+ {
+ switch (version)
+ {
+ case SPDY.V2:
+ return v2Name;
+ case SPDY.V3:
+ return v3Name;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ private static class Names
+ {
+ private static final Map v2Names = new HashMap<>();
+ private static final Map v3Names = new HashMap<>();
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java
index 63544a0356b..8b76589cb32 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java
@@ -1,91 +1,64 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.http;
-import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
-import org.eclipse.jetty.http.HttpSchemes;
-import org.eclipse.jetty.io.EndPoint;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.spdy.AsyncConnectionFactory;
-import org.eclipse.jetty.spdy.SPDYServerConnector;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.util.ssl.SslContextFactory;
-public class HTTPSPDYServerConnector extends SPDYServerConnector
+public class HTTPSPDYServerConnector extends AbstractHTTPSPDYServerConnector
{
- private final AsyncConnectionFactory defaultConnectionFactory;
- private final PushStrategy pushStrategy = new PushStrategy.None();
-
public HTTPSPDYServerConnector()
{
- this(null);
+ this(null, Collections.emptyMap());
+ }
+
+ public HTTPSPDYServerConnector(Map pushStrategies)
+ {
+ this(null, pushStrategies);
}
public HTTPSPDYServerConnector(SslContextFactory sslContextFactory)
{
+ this(sslContextFactory, Collections.emptyMap());
+ }
+
+ public HTTPSPDYServerConnector(SslContextFactory sslContextFactory, Map pushStrategies)
+ {
+ // We pass a null ServerSessionFrameListener because for
+ // HTTP over SPDY we need one that references the endPoint
super(null, sslContextFactory);
- // Override the default connection factory for non-SSL connections
- defaultConnectionFactory = new ServerHTTPAsyncConnectionFactory(this);
- }
-
- @Override
- protected void doStart() throws Exception
- {
- super.doStart();
- // Override the "spdy/2" protocol by handling HTTP over SPDY
- putAsyncConnectionFactory("spdy/2", new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), this, pushStrategy));
- // Add the "http/1.1" protocol for browsers that do not support NPN
+ clearAsyncConnectionFactories();
+ // The "spdy/3" protocol handles HTTP over SPDY
+ putAsyncConnectionFactory("spdy/3", new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V3, getByteBufferPool(), getExecutor(), getScheduler(), this, getPushStrategy(SPDY.V3,pushStrategies)));
+ // The "spdy/2" protocol handles HTTP over SPDY
+ putAsyncConnectionFactory("spdy/2", new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), this, getPushStrategy(SPDY.V2,pushStrategies)));
+ // The "http/1.1" protocol handles browsers that support NPN but not SPDY
putAsyncConnectionFactory("http/1.1", new ServerHTTPAsyncConnectionFactory(this));
+ // The default connection factory handles plain HTTP on non-SSL or non-NPN connections
+ setDefaultAsyncConnectionFactory(getAsyncConnectionFactory("http/1.1"));
}
- @Override
- protected AsyncConnectionFactory getDefaultAsyncConnectionFactory()
+ private PushStrategy getPushStrategy(short version, Map pushStrategies)
{
- return defaultConnectionFactory;
+ PushStrategy pushStrategy = pushStrategies.get(version);
+ if(pushStrategy == null)
+ pushStrategy = new PushStrategy.None();
+ return pushStrategy;
}
- @Override
- public void customize(EndPoint endPoint, Request request) throws IOException
- {
- super.customize(endPoint, request);
- if (getSslContextFactory() != null)
- request.setScheme(HttpSchemes.HTTPS);
- }
-
- @Override
- public boolean isConfidential(Request request)
- {
- if (getSslContextFactory() != null)
- {
- int confidentialPort = getConfidentialPort();
- return confidentialPort == 0 || confidentialPort == request.getServerPort();
- }
- return super.isConfidential(request);
- }
-
- @Override
- public boolean isIntegral(Request request)
- {
- if (getSslContextFactory() != null)
- {
- int integralPort = getIntegralPort();
- return integralPort == 0 || integralPort == request.getServerPort();
- }
- return super.isIntegral(request);
- }
}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/PushStrategy.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/PushStrategy.java
index 780a5b22d1d..c15fe5baac9 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/PushStrategy.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/PushStrategy.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.http;
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategy.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategy.java
index cf3fe06f1b6..00798977266 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategy.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategy.java
@@ -1,28 +1,28 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.http;
import java.util.Arrays;
import java.util.Collections;
-import java.util.LinkedHashSet;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
import org.eclipse.jetty.spdy.api.Headers;
@@ -37,64 +37,99 @@ import org.eclipse.jetty.util.log.Logger;
* will have a Referer HTTP header that points to index.html, which we
* use to link the associated resource to the main resource.
*
However, also following a hyperlink generates a HTTP request with a Referer
- * HTTP header that points to index.html; therefore main resources and associated
- * resources must be distinguishable.
- *
This class distinguishes associated resources by their URL path suffix.
+ * HTTP header that points to index.html; therefore a proper value for {@link #getReferrerPushPeriod()}
+ * has to be set. If the referrerPushPeriod for a main resource has been passed, no more
+ * associated resources will be added for that main resource.
+ *
This class distinguishes associated main resources by their URL path suffix and content
+ * type.
* CSS stylesheets, images and JavaScript files have recognizable URL path suffixes that
- * are classified as associated resources.
- *
Note however, that CSS stylesheets may refer to images, and the CSS image request
- * will have the CSS stylesheet as referrer, so there is some degree of recursion that
- * needs to be handled.
- *
- * TODO: this class is kind-of leaking since the resources map is always adding entries
- * TODO: although these entries will be limited by the number of application pages.
- * TODO: however, there is no ConcurrentLinkedHashMap yet in JDK (there is in Guava though)
- * TODO: so we cannot use the built-in LRU features of LinkedHashMap
- *
- * TODO: Wikipedia maps URLs like http://en.wikipedia.org/wiki/File:PNG-Gradient_hex.png
- * TODO: to text/html, so perhaps we need to improve isPushResource() by looking at the
- * TODO: response Content-Type header, and not only at the URL extension
+ * are classified as associated resources. The suffix regexs can be configured by constructor argument
+ *
When CSS stylesheets refer to images, the CSS image request will have the CSS
+ * stylesheet as referrer. This implementation will push also the CSS image.
+ *
The push metadata built by this implementation is limited by the number of pages
+ * of the application itself, and by the
+ * {@link #getMaxAssociatedResources() max associated resources} parameter.
+ * This parameter limits the number of associated resources per each main resource, so
+ * that if a main resource has hundreds of associated resources, only up to the number
+ * specified by this parameter will be pushed.
*/
public class ReferrerPushStrategy implements PushStrategy
{
private static final Logger logger = Log.getLogger(ReferrerPushStrategy.class);
- private final ConcurrentMap> resources = new ConcurrentHashMap<>();
- private final Set pushRegexps = new LinkedHashSet<>();
- private final Set allowedPushOrigins = new LinkedHashSet<>();
+ private final ConcurrentMap mainResources = new ConcurrentHashMap<>();
+ private final Set pushRegexps = new HashSet<>();
+ private final Set pushContentTypes = new HashSet<>();
+ private final Set allowedPushOrigins = new HashSet<>();
+ private volatile int maxAssociatedResources = 32;
+ private volatile int referrerPushPeriod = 5000;
public ReferrerPushStrategy()
{
- this(Arrays.asList(".*\\.css", ".*\\.js", ".*\\.png", ".*\\.jpg", ".*\\.gif"));
+ this(Arrays.asList(".*\\.css", ".*\\.js", ".*\\.png", ".*\\.jpeg", ".*\\.jpg", ".*\\.gif", ".*\\.ico"));
}
public ReferrerPushStrategy(List pushRegexps)
{
- this(pushRegexps, Collections.emptyList());
+ this(pushRegexps, Arrays.asList(
+ "text/css",
+ "text/javascript", "application/javascript", "application/x-javascript",
+ "image/png", "image/x-png",
+ "image/jpeg",
+ "image/gif",
+ "image/x-icon", "image/vnd.microsoft.icon"));
}
- public ReferrerPushStrategy(List pushRegexps, List allowedPushOrigins)
+ public ReferrerPushStrategy(List pushRegexps, List pushContentTypes)
+ {
+ this(pushRegexps, pushContentTypes, Collections.emptyList());
+ }
+
+ public ReferrerPushStrategy(List pushRegexps, List pushContentTypes, List allowedPushOrigins)
{
for (String pushRegexp : pushRegexps)
this.pushRegexps.add(Pattern.compile(pushRegexp));
+ this.pushContentTypes.addAll(pushContentTypes);
for (String allowedPushOrigin : allowedPushOrigins)
this.allowedPushOrigins.add(Pattern.compile(allowedPushOrigin.replace(".", "\\.").replace("*", ".*")));
}
+ public int getMaxAssociatedResources()
+ {
+ return maxAssociatedResources;
+ }
+
+ public void setMaxAssociatedResources(int maxAssociatedResources)
+ {
+ this.maxAssociatedResources = maxAssociatedResources;
+ }
+
+ public int getReferrerPushPeriod()
+ {
+ return referrerPushPeriod;
+ }
+
+ public void setReferrerPushPeriod(int referrerPushPeriod)
+ {
+ this.referrerPushPeriod = referrerPushPeriod;
+ }
+
@Override
public Set apply(Stream stream, Headers requestHeaders, Headers responseHeaders)
{
- Set result = Collections.emptySet();
- String scheme = requestHeaders.get("scheme").value();
- String host = requestHeaders.get("host").value();
- String origin = new StringBuilder(scheme).append("://").append(host).toString();
- String url = requestHeaders.get("url").value();
- String absoluteURL = new StringBuilder(origin).append(url).toString();
- logger.debug("Applying push strategy for {}", absoluteURL);
- if (isValidMethod(requestHeaders.get("method").value()))
+ Set result = Collections.emptySet();
+ short version = stream.getSession().getVersion();
+ if (!isIfModifiedSinceHeaderPresent(requestHeaders) && isValidMethod(requestHeaders.get(HTTPSPDYHeader.METHOD.name(version)).value()))
{
+ String scheme = requestHeaders.get(HTTPSPDYHeader.SCHEME.name(version)).value();
+ String host = requestHeaders.get(HTTPSPDYHeader.HOST.name(version)).value();
+ String origin = scheme + "://" + host;
+ String url = requestHeaders.get(HTTPSPDYHeader.URI.name(version)).value();
+ String absoluteURL = origin + url;
+ logger.debug("Applying push strategy for {}", absoluteURL);
if (isMainResource(url, responseHeaders))
{
- result = pushResources(absoluteURL);
+ MainResource mainResource = getOrCreateMainResource(absoluteURL);
+ result = mainResource.getResources();
}
else if (isPushResource(url, responseHeaders))
{
@@ -102,18 +137,49 @@ public class ReferrerPushStrategy implements PushStrategy
if (referrerHeader != null)
{
String referrer = referrerHeader.value();
- Set pushResources = resources.get(referrer);
- if (pushResources == null || !pushResources.contains(url))
- buildMetadata(origin, url, referrer);
+ MainResource mainResource = mainResources.get(referrer);
+ if (mainResource == null)
+ mainResource = getOrCreateMainResource(referrer);
+
+ Set pushResources = mainResource.getResources();
+ if (!pushResources.contains(url))
+ mainResource.addResource(url, origin, referrer);
else
- result = pushResources(absoluteURL);
+ result = getPushResources(absoluteURL);
}
}
+ logger.debug("Pushing {} resources for {}: {}", result.size(), absoluteURL, result);
}
- logger.debug("Push resources for {}: {}", absoluteURL, result);
return result;
}
+ private Set getPushResources(String absoluteURL)
+ {
+ Set result = Collections.emptySet();
+ if (mainResources.get(absoluteURL) != null)
+ result = mainResources.get(absoluteURL).getResources();
+ return result;
+ }
+
+ private MainResource getOrCreateMainResource(String absoluteURL)
+ {
+ MainResource mainResource = mainResources.get(absoluteURL);
+ if (mainResource == null)
+ {
+ logger.debug("Creating new main resource for {}", absoluteURL);
+ MainResource value = new MainResource(absoluteURL);
+ mainResource = mainResources.putIfAbsent(absoluteURL, value);
+ if (mainResource == null)
+ mainResource = value;
+ }
+ return mainResource;
+ }
+
+ private boolean isIfModifiedSinceHeaderPresent(Headers headers)
+ {
+ return headers.get("if-modified-since") != null;
+ }
+
private boolean isValidMethod(String method)
{
return "GET".equalsIgnoreCase(method);
@@ -129,43 +195,85 @@ public class ReferrerPushStrategy implements PushStrategy
for (Pattern pushRegexp : pushRegexps)
{
if (pushRegexp.matcher(url).matches())
- return true;
- }
- return false;
- }
-
- private Set pushResources(String absoluteURL)
- {
- Set pushResources = resources.get(absoluteURL);
- if (pushResources == null)
- return Collections.emptySet();
- return Collections.unmodifiableSet(pushResources);
- }
-
- private void buildMetadata(String origin, String url, String referrer)
- {
- if (referrer.startsWith(origin) || isPushOriginAllowed(origin))
- {
- Set pushResources = resources.get(referrer);
- if (pushResources == null)
{
- pushResources = Collections.newSetFromMap(new ConcurrentHashMap());
- Set existing = resources.putIfAbsent(referrer, pushResources);
- if (existing != null)
- pushResources = existing;
- }
- pushResources.add(url);
- logger.debug("Built push metadata for {}: {}", referrer, pushResources);
- }
- }
+ Headers.Header header = responseHeaders.get("content-type");
+ if (header == null)
+ return true;
- private boolean isPushOriginAllowed(String origin)
- {
- for (Pattern allowedPushOrigin : allowedPushOrigins)
- {
- if (allowedPushOrigin.matcher(origin).matches())
- return true;
+ String contentType = header.value().toLowerCase();
+ for (String pushContentType : pushContentTypes)
+ if (contentType.startsWith(pushContentType))
+ return true;
+ }
}
return false;
}
+
+ private class MainResource
+ {
+ private final String name;
+ private final Set resources = Collections.newSetFromMap(new ConcurrentHashMap());
+ private final AtomicLong firstResourceAdded = new AtomicLong(-1);
+
+ private MainResource(String name)
+ {
+ this.name = name;
+ }
+
+ public boolean addResource(String url, String origin, String referrer)
+ {
+ // We start the push period here and not when initializing the main resource, because a browser with a
+ // prefilled cache won't request the subresources. If the browser with warmed up cache now hits the main
+ // resource after a server restart, the push period shouldn't start until the first subresource is
+ // being requested.
+ firstResourceAdded.compareAndSet(-1, System.nanoTime());
+
+ long delay = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - firstResourceAdded.get());
+ if (!referrer.startsWith(origin) && !isPushOriginAllowed(origin))
+ {
+ logger.debug("Skipped store of push metadata {} for {}: Origin: {} doesn't match or origin not allowed",
+ url, name, origin);
+ return false;
+ }
+
+ // This check is not strictly concurrent-safe, but limiting
+ // the number of associated resources is achieved anyway
+ // although in rare cases few more resources will be stored
+ if (resources.size() >= maxAssociatedResources)
+ {
+ logger.debug("Skipped store of push metadata {} for {}: max associated resources ({}) reached",
+ url, name, maxAssociatedResources);
+ return false;
+ }
+ if (delay > referrerPushPeriod)
+ {
+ logger.debug("Delay: {}ms longer than referrerPushPeriod: {}ms. Not adding resource: {} for: {}", delay, referrerPushPeriod, url, name);
+ return false;
+ }
+
+ logger.debug("Adding resource: {} for: {} with delay: {}ms.", url, name, delay);
+ resources.add(url);
+ return true;
+ }
+
+ public Set getResources()
+ {
+ return Collections.unmodifiableSet(resources);
+ }
+
+ public String toString()
+ {
+ return "MainResource: " + name + " associated resources:" + resources.size();
+ }
+
+ private boolean isPushOriginAllowed(String origin)
+ {
+ for (Pattern allowedPushOrigin : allowedPushOrigins)
+ {
+ if (allowedPushOrigin.matcher(origin).matches())
+ return true;
+ }
+ return false;
+ }
+ }
}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPAsyncConnectionFactory.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPAsyncConnectionFactory.java
index 3622b2fdf69..b0bae06de1c 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPAsyncConnectionFactory.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPAsyncConnectionFactory.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.http;
@@ -21,18 +19,23 @@ 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;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
public class ServerHTTPAsyncConnectionFactory implements AsyncConnectionFactory
{
- private final Connector connector;
+ private final SPDYServerConnector connector;
- public ServerHTTPAsyncConnectionFactory(Connector connector)
+ public ServerHTTPAsyncConnectionFactory(SPDYServerConnector connector)
{
this.connector = connector;
}
+ public SPDYServerConnector getConnector()
+ {
+ return connector;
+ }
+
@Override
public AsyncConnection newAsyncConnection(SocketChannel channel, AsyncEndPoint endPoint, Object attachment)
{
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java
index f82b3f08e1a..ecc241ea975 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.http;
@@ -24,8 +22,10 @@ import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.http.HttpException;
import org.eclipse.jetty.http.HttpFields;
@@ -47,11 +47,13 @@ import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.spdy.SPDYAsyncConnection;
import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
+import org.eclipse.jetty.spdy.api.BytesDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.Handler;
import org.eclipse.jetty.spdy.api.Headers;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
@@ -66,6 +68,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
private final Queue tasks = new LinkedList<>();
private final BlockingQueue dataInfos = new LinkedBlockingQueue<>();
+ private final short version;
private final SPDYAsyncConnection connection;
private final PushStrategy pushStrategy;
private final Stream stream;
@@ -75,9 +78,10 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
private volatile State state = State.INITIAL;
private boolean dispatched; // Guarded by synchronization on tasks
- public ServerHTTPSPDYAsyncConnection(Connector connector, AsyncEndPoint endPoint, Server server, SPDYAsyncConnection connection, PushStrategy pushStrategy, Stream stream)
+ public ServerHTTPSPDYAsyncConnection(Connector connector, AsyncEndPoint endPoint, Server server, short version, SPDYAsyncConnection connection, PushStrategy pushStrategy, Stream stream)
{
super(connector, endPoint, server);
+ this.version = version;
this.connection = connection;
this.pushStrategy = pushStrategy;
this.stream = stream;
@@ -159,9 +163,9 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
}
case REQUEST:
{
- Headers.Header method = headers.get("method");
- Headers.Header uri = headers.get("url");
- Headers.Header version = headers.get("version");
+ Headers.Header method = headers.get(HTTPSPDYHeader.METHOD.name(version));
+ Headers.Header uri = headers.get(HTTPSPDYHeader.URI.name(version));
+ Headers.Header version = headers.get(HTTPSPDYHeader.VERSION.name(this.version));
if (method == null || uri == null || version == null)
throw new HttpException(HttpStatus.BAD_REQUEST_400);
@@ -172,6 +176,10 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
logger.debug("HTTP > {} {} {}", m, u, v);
startRequest(new ByteArrayBuffer(m), new ByteArrayBuffer(u), new ByteArrayBuffer(v));
+ Headers.Header schemeHeader = headers.get(HTTPSPDYHeader.SCHEME.name(this.version));
+ if(schemeHeader != null)
+ _request.setScheme(schemeHeader.value());
+
updateState(State.HEADERS);
handle();
break;
@@ -181,15 +189,19 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
for (Headers.Header header : headers)
{
String name = header.name();
+
+ // Skip special SPDY headers, unless it's the "host" header
+ HTTPSPDYHeader specialHeader = HTTPSPDYHeader.from(version, name);
+ if (specialHeader != null)
+ {
+ if (specialHeader == HTTPSPDYHeader.HOST)
+ name = "host";
+ else
+ continue;
+ }
+
switch (name)
{
- case "method":
- case "version":
- case "url":
- {
- // Skip request line headers
- continue;
- }
case "connection":
case "keep-alive":
case "proxy-connection":
@@ -264,8 +276,8 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
else
{
Headers headers = new Headers();
- headers.put("status", String.valueOf(status));
- headers.put("version", "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.STATUS.name(version), String.valueOf(status));
+ headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
stream.reply(new ReplyInfo(headers, true));
}
}
@@ -393,46 +405,67 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
{
if (!stream.isUnidirectional())
stream.reply(replyInfo);
- if (replyInfo.getHeaders().get("status").value().startsWith("200") && !stream.isClosed() && !isIfModifiedSinceHeaderPresent())
+ if (replyInfo.getHeaders().get(HTTPSPDYHeader.STATUS.name(version)).value().startsWith("200") &&
+ !stream.isClosed())
{
// We have a 200 OK with some content to send
- Headers.Header scheme = headers.get("scheme");
- Headers.Header host = headers.get("host");
- Headers.Header url = headers.get("url");
- Set pushResources = pushStrategy.apply(stream, this.headers, replyInfo.getHeaders());
- String referrer = new StringBuilder(scheme.value()).append("://").append(host.value()).append(url.value()).toString();
- for (String pushURL : pushResources)
+ Headers.Header scheme = headers.get(HTTPSPDYHeader.SCHEME.name(version));
+ Headers.Header host = headers.get(HTTPSPDYHeader.HOST.name(version));
+ Headers.Header uri = headers.get(HTTPSPDYHeader.URI.name(version));
+ Set pushResources = pushStrategy.apply(stream, headers, replyInfo.getHeaders());
+
+ for (String pushResourcePath : pushResources)
{
- final Headers pushHeaders = new Headers();
- pushHeaders.put("method", "GET");
- pushHeaders.put("url", pushURL);
- pushHeaders.put("version", "HTTP/1.1");
- pushHeaders.put(scheme);
- pushHeaders.put(host);
- pushHeaders.put("referer", referrer);
- // Remember support for gzip encoding
- pushHeaders.put(headers.get("accept-encoding"));
+ final Headers requestHeaders = createRequestHeaders(scheme, host, uri, pushResourcePath);
+ final Headers pushHeaders = createPushHeaders(scheme, host, pushResourcePath);
+
stream.syn(new SynInfo(pushHeaders, false), getMaxIdleTime(), TimeUnit.MILLISECONDS, new Handler.Adapter()
{
@Override
public void completed(Stream pushStream)
{
- Synchronous pushConnection = new Synchronous(getConnector(), getEndPoint(), getServer(), connection, pushStrategy, pushStream);
- pushConnection.beginRequest(pushHeaders, true);
+ ServerHTTPSPDYAsyncConnection pushConnection =
+ new ServerHTTPSPDYAsyncConnection(getConnector(), getEndPoint(), getServer(), version, connection, pushStrategy, pushStream);
+ pushConnection.beginRequest(requestHeaders, true);
}
});
}
}
}
- private boolean isIfModifiedSinceHeaderPresent()
- {
- if (headers.get("if-modified-since") != null)
- return true;
- return false;
- }
-
+ private Headers createRequestHeaders(Headers.Header scheme, Headers.Header host, Headers.Header uri, String pushResourcePath)
+ {
+ final Headers requestHeaders = new Headers();
+ requestHeaders.put(HTTPSPDYHeader.METHOD.name(version), "GET");
+ requestHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
+ requestHeaders.put(scheme);
+ requestHeaders.put(host);
+ requestHeaders.put(HTTPSPDYHeader.URI.name(version), pushResourcePath);
+ String referrer = scheme.value() + "://" + host.value() + uri.value();
+ requestHeaders.put("referer", referrer);
+ // Remember support for gzip encoding
+ requestHeaders.put(headers.get("accept-encoding"));
+ requestHeaders.put("x-spdy-push", "true");
+ return requestHeaders;
+ }
+
+ private Headers createPushHeaders(Headers.Header scheme, Headers.Header host, String pushResourcePath)
+ {
+ final Headers pushHeaders = new Headers();
+ if (version == SPDY.V2)
+ pushHeaders.put(HTTPSPDYHeader.URI.name(version), scheme.value() + "://" + host.value() + pushResourcePath);
+ else
+ {
+ pushHeaders.put(HTTPSPDYHeader.URI.name(version), pushResourcePath);
+ pushHeaders.put(scheme);
+ pushHeaders.put(host);
+ }
+ pushHeaders.put(HTTPSPDYHeader.STATUS.name(version), "200");
+ pushHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
+ return pushHeaders;
+ }
+
private Buffer consumeContent(long maxIdleTime) throws IOException, InterruptedException
{
while (true)
@@ -614,11 +647,11 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
{
Headers headers = new Headers();
String version = "HTTP/1.1";
- headers.put("version", version);
+ headers.put(HTTPSPDYHeader.VERSION.name(ServerHTTPSPDYAsyncConnection.this.version), version);
StringBuilder status = new StringBuilder().append(_status);
if (_reason != null)
status.append(" ").append(_reason.toString("UTF-8"));
- headers.put("status", status.toString());
+ headers.put(HTTPSPDYHeader.STATUS.name(ServerHTTPSPDYAsyncConnection.this.version), status.toString());
logger.debug("HTTP < {} {}", version, status);
if (fields != null)
@@ -634,19 +667,14 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
}
// We have to query the HttpGenerator and its buffers to know
- // whether there is content buffered; if so, send the data frame
+ // whether there is content buffered and update the generator state
Buffer content = getContentBuffer();
reply(stream, new ReplyInfo(headers, content == null));
if (content != null)
{
- closed = allContentAdded || isAllContentWritten();
- ByteBuffer buffer = ByteBuffer.wrap(content.asArray());
- logger.debug("HTTP < {} bytes of content", buffer.remaining());
- // Send the data frame
- stream.data(new ByteBufferDataInfo(buffer, closed));
+ closed = false;
// Update HttpGenerator fields so that they remain consistent
- content.clear();
- _state = closed ? HttpGenerator.STATE_END : HttpGenerator.STATE_CONTENT;
+ _state = HttpGenerator.STATE_CONTENT;
}
else
{
@@ -660,7 +688,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
{
if (_buffer != null && _buffer.length() > 0)
return _buffer;
- if (_bypass && _content != null && _content.length() > 0)
+ if (_content != null && _content.length() > 0)
return _content;
return null;
}
@@ -685,22 +713,48 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
@Override
public void flush(long maxIdleTime) throws IOException
{
- while (_content != null && _content.length() > 0)
+ try
{
- _content.skip(_buffer.put(_content));
- ByteBuffer buffer = ByteBuffer.wrap(_buffer.asArray());
- logger.debug("HTTP < {} bytes of content", buffer.remaining());
- _buffer.clear();
- closed = _content.length() == 0 && _last;
- stream.data(new ByteBufferDataInfo(buffer, closed));
-
- boolean expired = !connection.getEndPoint().blockWritable(maxIdleTime);
- if (expired)
+ Buffer content = getContentBuffer();
+ while (content != null)
{
- stream.getSession().goAway();
- throw new EOFException("write timeout");
+ DataInfo dataInfo = toDataInfo(content, closed);
+ logger.debug("HTTP < {} bytes of content", dataInfo.length());
+ stream.data(dataInfo).get(maxIdleTime, TimeUnit.MILLISECONDS);
+ content.clear();
+ _bypass = false;
+ content = getContentBuffer();
}
}
+ catch (TimeoutException x)
+ {
+ stream.getSession().goAway();
+ throw new EOFException("write timeout");
+ }
+ catch (InterruptedException x)
+ {
+ throw new InterruptedIOException();
+ }
+ catch (ExecutionException x)
+ {
+ throw new IOException(x.getCause());
+ }
+ }
+
+ private DataInfo toDataInfo(Buffer buffer, boolean close)
+ {
+ if (buffer instanceof ByteArrayBuffer)
+ return new BytesDataInfo(buffer.array(), buffer.getIndex(), buffer.length(), close);
+
+ if (buffer instanceof NIOBuffer)
+ {
+ ByteBuffer byteBuffer = ((NIOBuffer)buffer).getByteBuffer();
+ byteBuffer.limit(buffer.putIndex());
+ byteBuffer.position(buffer.getIndex());
+ return new ByteBufferDataInfo(byteBuffer, close);
+ }
+
+ return new BytesDataInfo(buffer.asArray(), close);
}
@Override
@@ -727,35 +781,17 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
Buffer content = getContentBuffer();
if (content != null)
{
- ByteBuffer buffer = ByteBuffer.wrap(content.asArray());
- logger.debug("HTTP < {} bytes of content", buffer.remaining());
- // Update HttpGenerator fields so that they remain consistent
- content.clear();
+ closed = true;
_state = STATE_END;
- // Send the data frame
- stream.data(new ByteBufferDataInfo(buffer, true));
+ flush(getMaxIdleTime());
}
else if (!closed)
{
closed = true;
_state = STATE_END;
- // Send the data frame
+ // Send the last, empty, data frame
stream.data(new ByteBufferDataInfo(ZERO_BYTES, true));
}
}
}
-
- private static class Synchronous extends ServerHTTPSPDYAsyncConnection
- {
- private Synchronous(Connector connector, AsyncEndPoint endPoint, Server server, SPDYAsyncConnection connection, PushStrategy pushStrategy, Stream stream)
- {
- super(connector, endPoint, server, connection, pushStrategy, stream);
- }
-
- @Override
- protected void execute(Runnable task)
- {
- task.run();
- }
- }
}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java
index 16db295eebf..7a5f381b3c3 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.http;
@@ -52,7 +50,7 @@ public class ServerHTTPSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
}
@Override
- protected ServerSessionFrameListener newServerSessionFrameListener(AsyncEndPoint endPoint, Object attachment)
+ protected ServerSessionFrameListener provideServerSessionFrameListener(AsyncEndPoint endPoint, Object attachment)
{
return new HTTPServerFrameListener(endPoint);
}
@@ -78,8 +76,8 @@ public class ServerHTTPSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
logger.debug("Received {} on {}", synInfo, stream);
HTTPSPDYAsyncEndPoint asyncEndPoint = new HTTPSPDYAsyncEndPoint(endPoint, stream);
- ServerHTTPSPDYAsyncConnection connection = new ServerHTTPSPDYAsyncConnection(connector,
- asyncEndPoint, connector.getServer(), (SPDYAsyncConnection)endPoint.getConnection(),
+ ServerHTTPSPDYAsyncConnection connection = new ServerHTTPSPDYAsyncConnection(connector, asyncEndPoint,
+ connector.getServer(), getVersion(), (SPDYAsyncConnection)endPoint.getConnection(),
pushStrategy, stream);
asyncEndPoint.setConnection(connection);
stream.setAttribute(CONNECTION_ATTRIBUTE, connection);
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/HTTPSPDYProxyConnector.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/HTTPSPDYProxyConnector.java
new file mode 100644
index 00000000000..2827af05ceb
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/HTTPSPDYProxyConnector.java
@@ -0,0 +1,39 @@
+//========================================================================
+//Copyright 2011-2012 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.proxy;
+
+import org.eclipse.jetty.spdy.ServerSPDYAsyncConnectionFactory;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.http.AbstractHTTPSPDYServerConnector;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+public class HTTPSPDYProxyConnector extends AbstractHTTPSPDYServerConnector
+{
+ public HTTPSPDYProxyConnector(ProxyEngineSelector proxyEngineSelector)
+ {
+ this(proxyEngineSelector, null);
+ }
+
+ public HTTPSPDYProxyConnector(ProxyEngineSelector proxyEngineSelector, SslContextFactory sslContextFactory)
+ {
+ super(proxyEngineSelector, sslContextFactory);
+ clearAsyncConnectionFactories();
+
+ putAsyncConnectionFactory("spdy/3", new ServerSPDYAsyncConnectionFactory(SPDY.V3, getByteBufferPool(), getExecutor(), getScheduler(), proxyEngineSelector));
+ putAsyncConnectionFactory("spdy/2", new ServerSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), proxyEngineSelector));
+ putAsyncConnectionFactory("http/1.1", new ProxyHTTPAsyncConnectionFactory(this, SPDY.V2, proxyEngineSelector));
+ setDefaultAsyncConnectionFactory(getAsyncConnectionFactory("http/1.1"));
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyEngine.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyEngine.java
new file mode 100644
index 00000000000..0a172614a56
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyEngine.java
@@ -0,0 +1,94 @@
+//========================================================================
+//Copyright 2011-2012 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.proxy;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+/**
+ *
{@link ProxyEngine} is the class for SPDY proxy functionalities that receives a SPDY request and converts it to
+ * any protocol to its server side.
+ *
This class listens for SPDY events sent by clients; subclasses are responsible for translating
+ * these SPDY client events into appropriate events to forward to the server, in the appropriate
+ * protocol that is understood by the server.
{@link ProxyEngineSelector} is the main entry point for syn stream events of a jetty SPDY proxy. It receives the
+ * syn stream frames from the clients, checks if there's an appropriate {@link ProxyServerInfo} for the given target
+ * host and forwards the syn to a {@link ProxyEngine} for the protocol defined in {@link ProxyServerInfo}.
+ *
+ *
If no {@link ProxyServerInfo} can be found for the given target host or no {@link ProxyEngine} can be found for
+ * the given protocol, it resets the client stream.
+ *
+ *
This class also provides configuration for the proxy rules.
+ */
+public class ProxyEngineSelector extends ServerSessionFrameListener.Adapter
+{
+ protected final Logger logger = Log.getLogger(getClass());
+ private final Map proxyInfos = new ConcurrentHashMap<>();
+ private final Map proxyEngines = new ConcurrentHashMap<>();
+
+ @Override
+ public final StreamFrameListener onSyn(final Stream clientStream, SynInfo clientSynInfo)
+ {
+ logger.debug("C -> P {} on {}", clientSynInfo, clientStream);
+
+ final Session clientSession = clientStream.getSession();
+ short clientVersion = clientSession.getVersion();
+ Headers headers = new Headers(clientSynInfo.getHeaders(), false);
+
+ Headers.Header hostHeader = headers.get(HTTPSPDYHeader.HOST.name(clientVersion));
+ if (hostHeader == null)
+ {
+ rst(clientStream);
+ return null;
+ }
+
+ String host = hostHeader.value();
+ int colon = host.indexOf(':');
+ if (colon >= 0)
+ host = host.substring(0, colon);
+
+ ProxyServerInfo proxyServerInfo = getProxyServerInfo(host);
+ if (proxyServerInfo == null)
+ {
+ rst(clientStream);
+ return null;
+ }
+
+ String protocol = proxyServerInfo.getProtocol();
+ ProxyEngine proxyEngine = proxyEngines.get(protocol);
+ if (proxyEngine == null)
+ {
+ rst(clientStream);
+ return null;
+ }
+
+ return proxyEngine.proxy(clientStream, clientSynInfo, proxyServerInfo);
+ }
+
+ @Override
+ public void onPing(Session clientSession, PingInfo pingInfo)
+ {
+ // We do not know to which upstream server
+ // to send the PING so we just ignore it
+ }
+
+ @Override
+ public void onGoAway(Session session, GoAwayInfo goAwayInfo)
+ {
+ // TODO:
+ }
+
+ public Map getProxyEngines()
+ {
+ return new HashMap<>(proxyEngines);
+ }
+
+ public void setProxyEngines(Map proxyEngines)
+ {
+ this.proxyEngines.clear();
+ this.proxyEngines.putAll(proxyEngines);
+ }
+
+ public ProxyEngine getProxyEngine(String protocol)
+ {
+ return proxyEngines.get(protocol);
+ }
+
+ public void putProxyEngine(String protocol, ProxyEngine proxyEngine)
+ {
+ proxyEngines.put(protocol, proxyEngine);
+ }
+
+ public Map getProxyServerInfos()
+ {
+ return new HashMap<>(proxyInfos);
+ }
+
+ protected ProxyServerInfo getProxyServerInfo(String host)
+ {
+ return proxyInfos.get(host);
+ }
+
+ public void setProxyServerInfos(Map proxyServerInfos)
+ {
+ this.proxyInfos.clear();
+ this.proxyInfos.putAll(proxyServerInfos);
+ }
+
+ public void putProxyServerInfo(String host, ProxyServerInfo proxyServerInfo)
+ {
+ proxyInfos.put(host, proxyServerInfo);
+ }
+
+ private void rst(Stream stream)
+ {
+ RstInfo rstInfo = new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM);
+ stream.getSession().rst(rstInfo);
+ }
+
+ public static class ProxyServerInfo
+ {
+ private final String protocol;
+ private final String host;
+ private final InetSocketAddress address;
+
+ public ProxyServerInfo(String protocol, String host, int port)
+ {
+ this.protocol = protocol;
+ this.host = host;
+ this.address = new InetSocketAddress(host, port);
+ }
+
+ public String getProtocol()
+ {
+ return protocol;
+ }
+
+ public String getHost()
+ {
+ return host;
+ }
+
+ public InetSocketAddress getAddress()
+ {
+ return address;
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPAsyncConnectionFactory.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPAsyncConnectionFactory.java
new file mode 100644
index 00000000000..f73c7e819bb
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPAsyncConnectionFactory.java
@@ -0,0 +1,41 @@
+//========================================================================
+//Copyright 2011-2012 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.proxy;
+
+import java.nio.channels.SocketChannel;
+
+import org.eclipse.jetty.io.AsyncEndPoint;
+import org.eclipse.jetty.io.nio.AsyncConnection;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
+import org.eclipse.jetty.spdy.http.ServerHTTPAsyncConnectionFactory;
+
+public class ProxyHTTPAsyncConnectionFactory extends ServerHTTPAsyncConnectionFactory
+{
+ private final short version;
+ private final ProxyEngineSelector proxyEngineSelector;
+
+ public ProxyHTTPAsyncConnectionFactory(SPDYServerConnector connector, short version, ProxyEngineSelector proxyEngineSelector)
+ {
+ super(connector);
+ this.version = version;
+ this.proxyEngineSelector = proxyEngineSelector;
+ }
+
+ @Override
+ public AsyncConnection newAsyncConnection(SocketChannel channel, AsyncEndPoint endPoint, Object attachment)
+ {
+ return new ProxyHTTPSPDYAsyncConnection(getConnector(), endPoint, version, proxyEngineSelector);
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYAsyncConnection.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYAsyncConnection.java
new file mode 100644
index 00000000000..92c318479a6
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYAsyncConnection.java
@@ -0,0 +1,337 @@
+//========================================================================
+//Copyright 2011-2012 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.proxy;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jetty.http.HttpFields;
+import org.eclipse.jetty.http.HttpGenerator;
+import org.eclipse.jetty.io.AsyncEndPoint;
+import org.eclipse.jetty.io.Buffer;
+import org.eclipse.jetty.io.ByteArrayBuffer;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.io.nio.DirectNIOBuffer;
+import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
+import org.eclipse.jetty.io.nio.NIOBuffer;
+import org.eclipse.jetty.server.AsyncHttpConnection;
+import org.eclipse.jetty.spdy.ISession;
+import org.eclipse.jetty.spdy.IStream;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
+import org.eclipse.jetty.spdy.StandardSession;
+import org.eclipse.jetty.spdy.StandardStream;
+import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
+import org.eclipse.jetty.spdy.api.BytesDataInfo;
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.GoAwayInfo;
+import org.eclipse.jetty.spdy.api.Handler;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.HeadersInfo;
+import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.RstInfo;
+import org.eclipse.jetty.spdy.api.SessionStatus;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
+
+public class ProxyHTTPSPDYAsyncConnection extends AsyncHttpConnection
+{
+ private final Headers headers = new Headers();
+ private final short version;
+ private final ProxyEngineSelector proxyEngineSelector;
+ private final HttpGenerator generator;
+ private final ISession session;
+ private HTTPStream stream;
+ private Buffer content;
+
+ public ProxyHTTPSPDYAsyncConnection(SPDYServerConnector connector, EndPoint endPoint, short version, ProxyEngineSelector proxyEngineSelector)
+ {
+ super(connector, endPoint, connector.getServer());
+ this.version = version;
+ this.proxyEngineSelector = proxyEngineSelector;
+ this.generator = (HttpGenerator)_generator;
+ this.session = new HTTPSession(version, connector);
+ this.session.setAttribute("org.eclipse.jetty.spdy.remoteAddress", endPoint.getRemoteAddr());
+ }
+
+ @Override
+ public AsyncEndPoint getEndPoint()
+ {
+ return (AsyncEndPoint)super.getEndPoint();
+ }
+
+ @Override
+ protected void startRequest(Buffer method, Buffer uri, Buffer httpVersion) throws IOException
+ {
+ SPDYServerConnector connector = (SPDYServerConnector)getConnector();
+ String scheme = connector.getSslContextFactory() != null ? "https" : "http";
+ headers.put(HTTPSPDYHeader.SCHEME.name(version), scheme);
+ headers.put(HTTPSPDYHeader.METHOD.name(version), method.toString("UTF-8"));
+ headers.put(HTTPSPDYHeader.URI.name(version), uri.toString("UTF-8"));
+ headers.put(HTTPSPDYHeader.VERSION.name(version), httpVersion.toString("UTF-8"));
+ }
+
+ @Override
+ protected void parsedHeader(Buffer name, Buffer value) throws IOException
+ {
+ String headerName = name.toString("UTF-8").toLowerCase();
+ String headerValue = value.toString("UTF-8");
+ switch (headerName)
+ {
+ case "host":
+ headers.put(HTTPSPDYHeader.HOST.name(version), headerValue);
+ break;
+ default:
+ headers.put(headerName, headerValue);
+ break;
+ }
+ }
+
+ @Override
+ protected void headerComplete() throws IOException
+ {
+ }
+
+ @Override
+ protected void content(Buffer buffer) throws IOException
+ {
+ if (content == null)
+ {
+ stream = syn(false);
+ content = buffer;
+ }
+ else
+ {
+ stream.getStreamFrameListener().onData(stream, toDataInfo(buffer, false));
+ }
+ }
+
+ @Override
+ public void messageComplete(long contentLength) throws IOException
+ {
+ if (stream == null)
+ {
+ assert content == null;
+ if (headers.isEmpty())
+ proxyEngineSelector.onGoAway(session, new GoAwayInfo(0, SessionStatus.OK));
+ else
+ syn(true);
+ }
+ else
+ {
+ stream.getStreamFrameListener().onData(stream, toDataInfo(content, true));
+ }
+ headers.clear();
+ stream = null;
+ content = null;
+ }
+
+ private HTTPStream syn(boolean close)
+ {
+ HTTPStream stream = new HTTPStream(1, (byte)0, session, null);
+ StreamFrameListener streamFrameListener = proxyEngineSelector.onSyn(stream, new SynInfo(headers, close));
+ stream.setStreamFrameListener(streamFrameListener);
+ return stream;
+ }
+
+ private DataInfo toDataInfo(Buffer buffer, boolean close)
+ {
+ if (buffer instanceof ByteArrayBuffer)
+ return new BytesDataInfo(buffer.array(), buffer.getIndex(), buffer.length(), close);
+
+ if (buffer instanceof NIOBuffer)
+ {
+ ByteBuffer byteBuffer = ((NIOBuffer)buffer).getByteBuffer();
+ byteBuffer.limit(buffer.putIndex());
+ byteBuffer.position(buffer.getIndex());
+ return new ByteBufferDataInfo(byteBuffer, close);
+ }
+
+ return new BytesDataInfo(buffer.asArray(), close);
+ }
+
+ private class HTTPSession extends StandardSession
+ {
+ private HTTPSession(short version, SPDYServerConnector connector)
+ {
+ super(version, connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), null, null, 1, proxyEngineSelector, null, null);
+ }
+
+ @Override
+ public void rst(RstInfo rstInfo, long timeout, TimeUnit unit, Handler handler)
+ {
+ // Not much we can do in HTTP land: just close the connection
+ goAway(timeout, unit, handler);
+ }
+
+ @Override
+ public void goAway(long timeout, TimeUnit unit, Handler handler)
+ {
+ try
+ {
+ getEndPoint().close();
+ handler.completed(null);
+ }
+ catch (IOException x)
+ {
+ handler.failed(null, x);
+ }
+ }
+ }
+
+ /**
+ *
This stream will convert the SPDY invocations performed by the proxy into HTTP to be sent to the client.
+ */
+ private class HTTPStream extends StandardStream
+ {
+ private final Pattern statusRegexp = Pattern.compile("(\\d{3})\\s*(.*)");
+
+ private HTTPStream(int id, byte priority, ISession session, IStream associatedStream)
+ {
+ super(id, priority, session, associatedStream);
+ }
+
+ @Override
+ public void syn(SynInfo synInfo, long timeout, TimeUnit unit, Handler handler)
+ {
+ // HTTP does not support pushed streams
+ handler.completed(new HTTPPushStream(2, getPriority(), getSession(), this));
+ }
+
+ @Override
+ public void headers(HeadersInfo headersInfo, long timeout, TimeUnit unit, Handler handler)
+ {
+ // TODO
+ throw new UnsupportedOperationException("Not Yet Implemented");
+ }
+
+ @Override
+ public void reply(ReplyInfo replyInfo, long timeout, TimeUnit unit, Handler handler)
+ {
+ try
+ {
+ Headers headers = new Headers(replyInfo.getHeaders(), false);
+
+ headers.remove(HTTPSPDYHeader.SCHEME.name(version));
+
+ String status = headers.remove(HTTPSPDYHeader.STATUS.name(version)).value();
+ Matcher matcher = statusRegexp.matcher(status);
+ matcher.matches();
+ int code = Integer.parseInt(matcher.group(1));
+ String reason = matcher.group(2);
+ generator.setResponse(code, reason);
+
+ String httpVersion = headers.remove(HTTPSPDYHeader.VERSION.name(version)).value();
+ generator.setVersion(Integer.parseInt(httpVersion.replaceAll("\\D", "")));
+
+ Headers.Header host = headers.remove(HTTPSPDYHeader.HOST.name(version));
+ if (host != null)
+ headers.put("host", host.value());
+
+ HttpFields fields = new HttpFields();
+ for (Headers.Header header : headers)
+ {
+ String name = camelize(header.name());
+ fields.put(name, header.value());
+ }
+ generator.completeHeader(fields, replyInfo.isClose());
+
+ if (replyInfo.isClose())
+ complete();
+
+ handler.completed(null);
+ }
+ catch (IOException x)
+ {
+ handler.failed(null, x);
+ }
+ }
+
+ private String camelize(String name)
+ {
+ char[] chars = name.toCharArray();
+ chars[0] = Character.toUpperCase(chars[0]);
+
+ for (int i = 0; i < chars.length; ++i)
+ {
+ char c = chars[i];
+ int j = i + 1;
+ if (c == '-' && j < chars.length)
+ chars[j] = Character.toUpperCase(chars[j]);
+ }
+ return new String(chars);
+ }
+
+ @Override
+ public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Handler handler)
+ {
+ try
+ {
+ // Data buffer must be copied, as the ByteBuffer is pooled
+ ByteBuffer byteBuffer = dataInfo.asByteBuffer(false);
+
+ Buffer buffer = byteBuffer.isDirect() ?
+ new DirectNIOBuffer(byteBuffer, false) :
+ new IndirectNIOBuffer(byteBuffer, false);
+
+ generator.addContent(buffer, dataInfo.isClose());
+ generator.flush(unit.toMillis(timeout));
+
+ if (dataInfo.isClose())
+ complete();
+
+ handler.completed(null);
+ }
+ catch (IOException x)
+ {
+ handler.failed(null, x);
+ }
+ }
+
+ private void complete() throws IOException
+ {
+ generator.complete();
+ // We need to call asyncDispatch() as if the HTTP request
+ // has been suspended and now we complete the response
+ getEndPoint().asyncDispatch();
+ }
+ }
+
+ private class HTTPPushStream extends StandardStream
+ {
+ private HTTPPushStream(int id, byte priority, ISession session, IStream associatedStream)
+ {
+ super(id, priority, session, associatedStream);
+ }
+
+ @Override
+ public void headers(HeadersInfo headersInfo, long timeout, TimeUnit unit, Handler handler)
+ {
+ // Ignore pushed headers
+ handler.completed(null);
+ }
+
+ @Override
+ public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Handler handler)
+ {
+ // Ignore pushed data
+ handler.completed(null);
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/SPDYProxyEngine.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/SPDYProxyEngine.java
new file mode 100644
index 00000000000..c01af3ef0f8
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/SPDYProxyEngine.java
@@ -0,0 +1,514 @@
+//========================================================================
+//Copyright 2011-2012 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.proxy;
+
+import java.net.InetSocketAddress;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.spdy.SPDYClient;
+import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.GoAwayInfo;
+import org.eclipse.jetty.spdy.api.Handler;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.HeadersInfo;
+import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.RstInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.SessionFrameListener;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.StreamStatus;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
+
+/**
+ *
{@link SPDYProxyEngine} implements a SPDY to SPDY proxy, that is, converts SPDY events received by
+ * clients into SPDY events for the servers.
+ */
+public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
+{
+ private static final String STREAM_HANDLER_ATTRIBUTE = "org.eclipse.jetty.spdy.http.proxy.streamHandler";
+ private static final String CLIENT_STREAM_ATTRIBUTE = "org.eclipse.jetty.spdy.http.proxy.clientStream";
+
+ private final ConcurrentMap serverSessions = new ConcurrentHashMap<>();
+ private final SessionFrameListener sessionListener = new ProxySessionFrameListener();
+ private final SPDYClient.Factory factory;
+ private volatile long connectTimeout = 15000;
+ private volatile long timeout = 60000;
+
+ public SPDYProxyEngine(SPDYClient.Factory factory)
+ {
+ this.factory = factory;
+ }
+
+ public long getConnectTimeout()
+ {
+ return connectTimeout;
+ }
+
+ public void setConnectTimeout(long connectTimeout)
+ {
+ this.connectTimeout = connectTimeout;
+ }
+
+ public long getTimeout()
+ {
+ return timeout;
+ }
+
+ public void setTimeout(long timeout)
+ {
+ this.timeout = timeout;
+ }
+
+ public StreamFrameListener proxy(final Stream clientStream, SynInfo clientSynInfo, ProxyEngineSelector.ProxyServerInfo proxyServerInfo)
+ {
+ Headers headers = new Headers(clientSynInfo.getHeaders(), false);
+
+ short serverVersion = getVersion(proxyServerInfo.getProtocol());
+ InetSocketAddress address = proxyServerInfo.getAddress();
+ Session serverSession = produceSession(proxyServerInfo.getHost(), serverVersion, address);
+ if (serverSession == null)
+ {
+ rst(clientStream);
+ return null;
+ }
+
+ final Session clientSession = clientStream.getSession();
+
+ addRequestProxyHeaders(clientStream, headers);
+ customizeRequestHeaders(clientStream, headers);
+ convert(clientSession.getVersion(), serverVersion, headers);
+
+ SynInfo serverSynInfo = new SynInfo(headers, clientSynInfo.isClose());
+ StreamFrameListener listener = new ProxyStreamFrameListener(clientStream);
+ StreamHandler handler = new StreamHandler(clientStream, serverSynInfo);
+ clientStream.setAttribute(STREAM_HANDLER_ATTRIBUTE, handler);
+ serverSession.syn(serverSynInfo, listener, timeout, TimeUnit.MILLISECONDS, handler);
+ return this;
+ }
+
+ private static short getVersion(String protocol)
+ {
+ switch (protocol)
+ {
+ case "spdy/2":
+ return SPDY.V2;
+ case "spdy/3":
+ return SPDY.V3;
+ default:
+ throw new IllegalArgumentException("Procotol: " + protocol + " is not a known SPDY protocol");
+ }
+ }
+
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ // Servers do not receive replies
+ }
+
+ @Override
+ public void onHeaders(Stream stream, HeadersInfo headersInfo)
+ {
+ // TODO
+ throw new UnsupportedOperationException("Not Yet Implemented");
+ }
+
+ @Override
+ public void onData(Stream clientStream, final DataInfo clientDataInfo)
+ {
+ logger.debug("C -> P {} on {}", clientDataInfo, clientStream);
+
+ ByteBufferDataInfo serverDataInfo = new ByteBufferDataInfo(clientDataInfo.asByteBuffer(false), clientDataInfo.isClose())
+ {
+ @Override
+ public void consume(int delta)
+ {
+ super.consume(delta);
+ clientDataInfo.consume(delta);
+ }
+ };
+
+ StreamHandler streamHandler = (StreamHandler)clientStream.getAttribute(STREAM_HANDLER_ATTRIBUTE);
+ streamHandler.data(serverDataInfo);
+ }
+
+ private Session produceSession(String host, short version, InetSocketAddress address)
+ {
+ try
+ {
+ Session session = serverSessions.get(host);
+ if (session == null)
+ {
+ SPDYClient client = factory.newSPDYClient(version);
+ session = client.connect(address, sessionListener).get(getConnectTimeout(), TimeUnit.MILLISECONDS);
+ logger.debug("Proxy session connected to {}", address);
+ Session existing = serverSessions.putIfAbsent(host, session);
+ if (existing != null)
+ {
+ session.goAway(getTimeout(), TimeUnit.MILLISECONDS, new Handler.Adapter());
+ session = existing;
+ }
+ }
+ return session;
+ }
+ catch (Exception x)
+ {
+ logger.debug(x);
+ return null;
+ }
+ }
+
+ private void convert(short fromVersion, short toVersion, Headers headers)
+ {
+ if (fromVersion != toVersion)
+ {
+ for (HTTPSPDYHeader httpHeader : HTTPSPDYHeader.values())
+ {
+ Headers.Header header = headers.remove(httpHeader.name(fromVersion));
+ if (header != null)
+ {
+ String toName = httpHeader.name(toVersion);
+ for (String value : header.values())
+ headers.add(toName, value);
+ }
+ }
+ }
+ }
+
+ private void rst(Stream stream)
+ {
+ RstInfo rstInfo = new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM);
+ stream.getSession().rst(rstInfo, getTimeout(), TimeUnit.MILLISECONDS, new Handler.Adapter());
+ }
+
+ private class ProxyStreamFrameListener extends StreamFrameListener.Adapter
+ {
+ private final Stream clientStream;
+ private volatile ReplyInfo replyInfo;
+
+ public ProxyStreamFrameListener(Stream clientStream)
+ {
+ this.clientStream = clientStream;
+ }
+
+ @Override
+ public void onReply(final Stream stream, ReplyInfo replyInfo)
+ {
+ logger.debug("S -> P {} on {}", replyInfo, stream);
+
+ short serverVersion = stream.getSession().getVersion();
+ Headers headers = new Headers(replyInfo.getHeaders(), false);
+
+ addResponseProxyHeaders(stream, headers);
+ customizeResponseHeaders(stream, headers);
+ short clientVersion = this.clientStream.getSession().getVersion();
+ convert(serverVersion, clientVersion, headers);
+
+ this.replyInfo = new ReplyInfo(headers, replyInfo.isClose());
+ if (replyInfo.isClose())
+ reply(stream);
+ }
+
+ @Override
+ public void onHeaders(Stream stream, HeadersInfo headersInfo)
+ {
+ // TODO
+ throw new UnsupportedOperationException("Not Yet Implemented");
+ }
+
+ @Override
+ public void onData(final Stream stream, final DataInfo dataInfo)
+ {
+ logger.debug("S -> P {} on {}", dataInfo, stream);
+
+ if (replyInfo != null)
+ {
+ if (dataInfo.isClose())
+ replyInfo.getHeaders().put("content-length", String.valueOf(dataInfo.available()));
+ reply(stream);
+ }
+ data(stream, dataInfo);
+ }
+
+ private void reply(final Stream stream)
+ {
+ final ReplyInfo replyInfo = this.replyInfo;
+ this.replyInfo = null;
+ clientStream.reply(replyInfo, getTimeout(), TimeUnit.MILLISECONDS, new Handler()
+ {
+ @Override
+ public void completed(Void context)
+ {
+ logger.debug("P -> C {} from {} to {}", replyInfo, stream, clientStream);
+ }
+
+ @Override
+ public void failed(Void context, Throwable x)
+ {
+ logger.debug(x);
+ rst(clientStream);
+ }
+ });
+ }
+
+ private void data(final Stream stream, final DataInfo dataInfo)
+ {
+ clientStream.data(dataInfo, getTimeout(), TimeUnit.MILLISECONDS, new Handler()
+ {
+ @Override
+ public void completed(Void context)
+ {
+ dataInfo.consume(dataInfo.length());
+ logger.debug("P -> C {} from {} to {}", dataInfo, stream, clientStream);
+ }
+
+ @Override
+ public void failed(Void context, Throwable x)
+ {
+ logger.debug(x);
+ rst(clientStream);
+ }
+ });
+ }
+ }
+
+ /**
+ *
{@link StreamHandler} implements the forwarding of DATA frames from the client to the server.
+ *
Instances of this class buffer DATA frames sent by clients and send them to the server.
+ * The buffering happens between the send of the SYN_STREAM to the server (where DATA frames may arrive
+ * from the client before the SYN_STREAM has been fully sent), and between DATA frames, if the client
+ * is a fast producer and the server a slow consumer, or if the client is a SPDY v2 client (and hence
+ * without flow control) while the server is a SPDY v3 server (and hence with flow control).
+ */
+ private class StreamHandler implements Handler
+ {
+ private final Queue queue = new LinkedList<>();
+ private final Stream clientStream;
+ private final SynInfo serverSynInfo;
+ private Stream serverStream;
+
+ private StreamHandler(Stream clientStream, SynInfo serverSynInfo)
+ {
+ this.clientStream = clientStream;
+ this.serverSynInfo = serverSynInfo;
+ }
+
+ @Override
+ public void completed(Stream serverStream)
+ {
+ logger.debug("P -> S {} from {} to {}", serverSynInfo, clientStream, serverStream);
+
+ serverStream.setAttribute(CLIENT_STREAM_ATTRIBUTE, clientStream);
+
+ DataInfoHandler dataInfoHandler;
+ synchronized (queue)
+ {
+ this.serverStream = serverStream;
+ dataInfoHandler = queue.peek();
+ if (dataInfoHandler != null)
+ {
+ if (dataInfoHandler.flushing)
+ {
+ logger.debug("SYN completed, flushing {}, queue size {}", dataInfoHandler.dataInfo, queue.size());
+ dataInfoHandler = null;
+ }
+ else
+ {
+ dataInfoHandler.flushing = true;
+ logger.debug("SYN completed, queue size {}", queue.size());
+ }
+ }
+ else
+ {
+ logger.debug("SYN completed, queue empty");
+ }
+ }
+ if (dataInfoHandler != null)
+ flush(serverStream, dataInfoHandler);
+ }
+
+ @Override
+ public void failed(Stream serverStream, Throwable x)
+ {
+ logger.debug(x);
+ rst(clientStream);
+ }
+
+ public void data(DataInfo dataInfo)
+ {
+ Stream serverStream;
+ DataInfoHandler dataInfoHandler = null;
+ DataInfoHandler item = new DataInfoHandler(dataInfo);
+ synchronized (queue)
+ {
+ queue.offer(item);
+ serverStream = this.serverStream;
+ if (serverStream != null)
+ {
+ dataInfoHandler = queue.peek();
+ if (dataInfoHandler.flushing)
+ {
+ logger.debug("Queued {}, flushing {}, queue size {}", dataInfo, dataInfoHandler.dataInfo, queue.size());
+ serverStream = null;
+ }
+ else
+ {
+ dataInfoHandler.flushing = true;
+ logger.debug("Queued {}, queue size {}", dataInfo, queue.size());
+ }
+ }
+ else
+ {
+ logger.debug("Queued {}, SYN incomplete, queue size {}", dataInfo, queue.size());
+ }
+ }
+ if (serverStream != null)
+ flush(serverStream, dataInfoHandler);
+ }
+
+ private void flush(Stream serverStream, DataInfoHandler dataInfoHandler)
+ {
+ logger.debug("P -> S {} on {}", dataInfoHandler.dataInfo, serverStream);
+ serverStream.data(dataInfoHandler.dataInfo, getTimeout(), TimeUnit.MILLISECONDS, dataInfoHandler);
+ }
+
+ private class DataInfoHandler implements Handler
+ {
+ private final DataInfo dataInfo;
+ private boolean flushing;
+
+ private DataInfoHandler(DataInfo dataInfo)
+ {
+ this.dataInfo = dataInfo;
+ }
+
+ @Override
+ public void completed(Void context)
+ {
+ Stream serverStream;
+ DataInfoHandler dataInfoHandler;
+ synchronized (queue)
+ {
+ serverStream = StreamHandler.this.serverStream;
+ assert serverStream != null;
+ dataInfoHandler = queue.poll();
+ assert dataInfoHandler == this;
+ dataInfoHandler = queue.peek();
+ if (dataInfoHandler != null)
+ {
+ assert !dataInfoHandler.flushing;
+ dataInfoHandler.flushing = true;
+ logger.debug("Completed {}, queue size {}", dataInfo, queue.size());
+ }
+ else
+ {
+ logger.debug("Completed {}, queue empty", dataInfo);
+ }
+ }
+ if (dataInfoHandler != null)
+ flush(serverStream, dataInfoHandler);
+ }
+
+ @Override
+ public void failed(Void context, Throwable x)
+ {
+ logger.debug(x);
+ rst(clientStream);
+ }
+ }
+ }
+
+ private class ProxySessionFrameListener extends SessionFrameListener.Adapter implements StreamFrameListener
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream serverStream, SynInfo serverSynInfo)
+ {
+ logger.debug("S -> P pushed {} on {}", serverSynInfo, serverStream);
+
+ Headers headers = new Headers(serverSynInfo.getHeaders(), false);
+
+ addResponseProxyHeaders(serverStream, headers);
+ customizeResponseHeaders(serverStream, headers);
+ Stream clientStream = (Stream)serverStream.getAssociatedStream().getAttribute(CLIENT_STREAM_ATTRIBUTE);
+ convert(serverStream.getSession().getVersion(), clientStream.getSession().getVersion(), headers);
+
+ StreamHandler handler = new StreamHandler(clientStream, serverSynInfo);
+ serverStream.setAttribute(STREAM_HANDLER_ATTRIBUTE, handler);
+ clientStream.syn(new SynInfo(headers, serverSynInfo.isClose()), getTimeout(), TimeUnit.MILLISECONDS, handler);
+
+ return this;
+ }
+
+ @Override
+ public void onRst(Session serverSession, RstInfo serverRstInfo)
+ {
+ Stream serverStream = serverSession.getStream(serverRstInfo.getStreamId());
+ if (serverStream != null)
+ {
+ Stream clientStream = (Stream)serverStream.getAttribute(CLIENT_STREAM_ATTRIBUTE);
+ if (clientStream != null)
+ {
+ Session clientSession = clientStream.getSession();
+ RstInfo clientRstInfo = new RstInfo(clientStream.getId(), serverRstInfo.getStreamStatus());
+ clientSession.rst(clientRstInfo, getTimeout(), TimeUnit.MILLISECONDS, new Handler.Adapter());
+ }
+ }
+ }
+
+ @Override
+ public void onGoAway(Session serverSession, GoAwayInfo goAwayInfo)
+ {
+ serverSessions.values().remove(serverSession);
+ }
+
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ // Push streams never send a reply
+ }
+
+ @Override
+ public void onHeaders(Stream stream, HeadersInfo headersInfo)
+ {
+ throw new UnsupportedOperationException(); //TODO
+ }
+
+ @Override
+ public void onData(Stream serverStream, final DataInfo serverDataInfo)
+ {
+ logger.debug("S -> P pushed {} on {}", serverDataInfo, serverStream);
+
+ ByteBufferDataInfo clientDataInfo = new ByteBufferDataInfo(serverDataInfo.asByteBuffer(false), serverDataInfo.isClose())
+ {
+ @Override
+ public void consume(int delta)
+ {
+ super.consume(delta);
+ serverDataInfo.consume(delta);
+ }
+ };
+
+ StreamHandler handler = (StreamHandler)serverStream.getAttribute(STREAM_HANDLER_ATTRIBUTE);
+ handler.data(clientDataInfo);
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java
index 84dd3271a5b..a5c4c280439 100644
--- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.http;
@@ -54,9 +52,14 @@ public abstract class AbstractHTTPSPDYTest
protected SPDYServerConnector connector;
protected InetSocketAddress startHTTPServer(Handler handler) throws Exception
+ {
+ return startHTTPServer(SPDY.V2, handler);
+ }
+
+ protected InetSocketAddress startHTTPServer(short version, Handler handler) throws Exception
{
server = new Server();
- connector = newHTTPSPDYServerConnector();
+ connector = newHTTPSPDYServerConnector(version);
connector.setPort(0);
server.addConnector(connector);
server.setHandler(handler);
@@ -64,20 +67,21 @@ public abstract class AbstractHTTPSPDYTest
return new InetSocketAddress("localhost", connector.getLocalPort());
}
- protected SPDYServerConnector newHTTPSPDYServerConnector()
+ protected SPDYServerConnector newHTTPSPDYServerConnector(short version)
{
// For these tests, we need the connector to speak HTTP over SPDY even in non-SSL
- return new HTTPSPDYServerConnector()
- {
- @Override
- protected AsyncConnectionFactory getDefaultAsyncConnectionFactory()
- {
- return new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), this, new PushStrategy.None());
- }
- };
+ SPDYServerConnector connector = new HTTPSPDYServerConnector();
+ AsyncConnectionFactory defaultFactory = new ServerHTTPSPDYAsyncConnectionFactory(version, connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, new PushStrategy.None());
+ connector.setDefaultAsyncConnectionFactory(defaultFactory);
+ 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
{
if (clientFactory == null)
{
@@ -86,7 +90,7 @@ public abstract class AbstractHTTPSPDYTest
clientFactory = newSPDYClientFactory(threadPool);
clientFactory.start();
}
- return clientFactory.newSPDYClient(SPDY.V2).connect(socketAddress, listener).get(5, TimeUnit.SECONDS);
+ return clientFactory.newSPDYClient(version).connect(socketAddress, listener).get(5, TimeUnit.SECONDS);
}
protected SPDYClient.Factory newSPDYClientFactory(Executor threadPool)
@@ -107,4 +111,9 @@ public abstract class AbstractHTTPSPDYTest
server.join();
}
}
+
+ protected short version()
+ {
+ return SPDY.V2;
+ }
}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ConcurrentStreamsTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ConcurrentStreamsTest.java
index a26555004b9..56cb5ef7c75 100644
--- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ConcurrentStreamsTest.java
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ConcurrentStreamsTest.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.http;
@@ -73,10 +71,10 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest
// Perform slow request. This will wait on server side until the fast request wakes it up
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/slow");
- headers.put("version", "HTTP/1.1");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/slow");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch slowClientLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -91,10 +89,10 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest
// Perform the fast request. This will wake up the slow request
headers.clear();
- headers.put("method", "GET");
- headers.put("url", "/fast");
- headers.put("version", "HTTP/1.1");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/fast");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch fastClientLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java
index e9cca9d33b5..5de439b2066 100644
--- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.http;
@@ -27,7 +25,6 @@ import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.spdy.AsyncConnectionFactory;
import org.eclipse.jetty.spdy.SPDYServerConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
@@ -109,9 +106,8 @@ public class ProtocolNegotiationTest
public String selectProtocol(List strings)
{
Assert.assertNotNull(strings);
- Assert.assertEquals(1, strings.size());
- String protocol = strings.get(0);
- Assert.assertEquals("http/1.1", protocol);
+ String protocol = "http/1.1";
+ Assert.assertTrue(strings.contains(protocol));
return protocol;
}
});
@@ -166,11 +162,11 @@ public class ProtocolNegotiationTest
public String selectProtocol(List 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);
+ 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;
}
});
@@ -198,14 +194,9 @@ public class ProtocolNegotiationTest
@Test
public void testServerAdvertisingSPDYAndHTTPSpeaksDefaultProtocolWhenNPNMissing() throws Exception
{
- InetSocketAddress address = startServer(new SPDYServerConnector(null, newSslContextFactory())
- {
- @Override
- protected AsyncConnectionFactory getDefaultAsyncConnectionFactory()
- {
- return new ServerHTTPAsyncConnectionFactory(connector);
- }
- });
+ SPDYServerConnector connector = new SPDYServerConnector(null, newSslContextFactory());
+ connector.setDefaultAsyncConnectionFactory(new ServerHTTPAsyncConnectionFactory(connector));
+ InetSocketAddress address = startServer(connector);
connector.putAsyncConnectionFactory("http/1.1", new ServerHTTPAsyncConnectionFactory(connector));
SslContextFactory sslContextFactory = newSslContextFactory();
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/PushStrategyBenchmarkTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/PushStrategyBenchmarkTest.java
new file mode 100644
index 00000000000..9486157de24
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/PushStrategyBenchmarkTest.java
@@ -0,0 +1,395 @@
+//========================================================================
+//Copyright 2011-2012 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.http;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.Assert;
+import org.eclipse.jetty.client.Address;
+import org.eclipse.jetty.client.ContentExchange;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.HttpExchange;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.spdy.AsyncConnectionFactory;
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.SessionFrameListener;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.junit.Test;
+
+public class PushStrategyBenchmarkTest extends AbstractHTTPSPDYTest
+{
+ // Sample resources size from webtide.com home page
+ private final int[] htmlResources = new int[]
+ {8 * 1024};
+ private final int[] cssResources = new int[]
+ {12 * 1024, 2 * 1024};
+ private final int[] jsResources = new int[]
+ {75 * 1024, 24 * 1024, 36 * 1024};
+ private final int[] pngResources = new int[]
+ {1024, 45 * 1024, 6 * 1024, 2 * 1024, 2 * 1024, 2 * 1024, 3 * 1024, 512, 512, 19 * 1024, 512, 128, 32};
+ private final Set pushedResources = Collections.newSetFromMap(new ConcurrentHashMap());
+ private final AtomicReference latch = new AtomicReference<>();
+ private final long roundtrip = 100;
+ private final int runs = 10;
+
+ @Test
+ public void benchmarkPushStrategy() throws Exception
+ {
+ InetSocketAddress address = startHTTPServer(version(), new PushStrategyBenchmarkHandler());
+
+ // Plain HTTP
+ AsyncConnectionFactory dacf = new ServerHTTPAsyncConnectionFactory(connector);
+ connector.setDefaultAsyncConnectionFactory(dacf);
+ HttpClient httpClient = new HttpClient();
+ // Simulate browsers, that open 6 connection per origin
+ httpClient.setMaxConnectionsPerAddress(6);
+ httpClient.start();
+ benchmarkHTTP(httpClient);
+ httpClient.stop();
+
+ // First push strategy
+ PushStrategy pushStrategy = new PushStrategy.None();
+ dacf = new ServerHTTPSPDYAsyncConnectionFactory(version(), connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy);
+ connector.setDefaultAsyncConnectionFactory(dacf);
+ Session session = startClient(version(), address, new ClientSessionFrameListener());
+ benchmarkSPDY(pushStrategy, session);
+ session.goAway().get(5, TimeUnit.SECONDS);
+
+ // Second push strategy
+ pushStrategy = new ReferrerPushStrategy();
+ dacf = new ServerHTTPSPDYAsyncConnectionFactory(version(), connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy);
+ connector.setDefaultAsyncConnectionFactory(dacf);
+ session = startClient(version(), address, new ClientSessionFrameListener());
+ benchmarkSPDY(pushStrategy, session);
+ session.goAway().get(5, TimeUnit.SECONDS);
+ }
+
+ private void benchmarkHTTP(HttpClient httpClient) throws Exception
+ {
+ // Warm up
+ performHTTPRequests(httpClient);
+ performHTTPRequests(httpClient);
+
+ long total = 0;
+ for (int i = 0; i < runs; ++i)
+ {
+ long begin = System.nanoTime();
+ int requests = performHTTPRequests(httpClient);
+ long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - begin);
+ total += elapsed;
+ System.err.printf("HTTP: run %d, %d request(s), roundtrip delay %d ms, elapsed = %d%n",
+ i, requests, roundtrip, elapsed);
+ }
+ System.err.printf("HTTP: roundtrip delay %d ms, average = %d%n%n",
+ roundtrip, total / runs);
+ }
+
+ private int performHTTPRequests(HttpClient httpClient) throws Exception
+ {
+ int result = 0;
+
+ for (int j = 0; j < htmlResources.length; ++j)
+ {
+ latch.set(new CountDownLatch(cssResources.length + jsResources.length + pngResources.length));
+
+ String primaryPath = "/" + j + ".html";
+ String referrer = new StringBuilder("http://localhost:").append(connector.getLocalPort()).append(primaryPath).toString();
+ ContentExchange exchange = new ContentExchange(true);
+ exchange.setMethod("GET");
+ exchange.setRequestURI(primaryPath);
+ exchange.setVersion("HTTP/1.1");
+ exchange.setAddress(new Address("localhost", connector.getLocalPort()));
+ exchange.setRequestHeader("Host", "localhost:" + connector.getLocalPort());
+ ++result;
+ httpClient.send(exchange);
+ Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
+ Assert.assertEquals(200, exchange.getResponseStatus());
+
+ for (int i = 0; i < cssResources.length; ++i)
+ {
+ String path = "/" + i + ".css";
+ exchange = createExchangeWithReferrer(referrer, path);
+ ++result;
+ httpClient.send(exchange);
+ }
+ for (int i = 0; i < jsResources.length; ++i)
+ {
+ String path = "/" + i + ".js";
+ exchange = createExchangeWithReferrer(referrer, path);
+ ++result;
+ httpClient.send(exchange);
+ }
+ for (int i = 0; i < pngResources.length; ++i)
+ {
+ String path = "/" + i + ".png";
+ exchange = createExchangeWithReferrer(referrer, path);
+ ++result;
+ httpClient.send(exchange);
+ }
+
+ Assert.assertTrue(latch.get().await(5, TimeUnit.SECONDS));
+ }
+
+ return result;
+ }
+
+ private ContentExchange createExchangeWithReferrer(String referrer, String path)
+ {
+ ContentExchange exchange;
+ exchange = new TestExchange();
+ exchange.setMethod("GET");
+ exchange.setRequestURI(path);
+ exchange.setVersion("HTTP/1.1");
+ exchange.setAddress(new Address("localhost", connector.getLocalPort()));
+ exchange.setRequestHeader("Host", "localhost:" + connector.getLocalPort());
+ exchange.setRequestHeader("referer", referrer);
+ return exchange;
+ }
+
+
+ private void benchmarkSPDY(PushStrategy pushStrategy, Session session) throws Exception
+ {
+ // Warm up PushStrategy
+ performRequests(session);
+ performRequests(session);
+
+ long total = 0;
+ for (int i = 0; i < runs; ++i)
+ {
+ long begin = System.nanoTime();
+ int requests = performRequests(session);
+ long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - begin);
+ total += elapsed;
+ System.err.printf("SPDY(%s): run %d, %d request(s), roundtrip delay %d ms, elapsed = %d%n",
+ pushStrategy.getClass().getSimpleName(), i, requests, roundtrip, elapsed);
+ }
+ System.err.printf("SPDY(%s): roundtrip delay %d ms, average = %d%n%n",
+ pushStrategy.getClass().getSimpleName(), roundtrip, total / runs);
+ }
+
+ private int performRequests(Session session) throws Exception
+ {
+ int result = 0;
+
+ for (int j = 0; j < htmlResources.length; ++j)
+ {
+ latch.set(new CountDownLatch(cssResources.length + jsResources.length + pngResources.length));
+ pushedResources.clear();
+
+ String primaryPath = "/" + j + ".html";
+ String referrer = new StringBuilder("http://localhost:").append(connector.getLocalPort()).append(primaryPath).toString();
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), primaryPath);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
+ // Wait for the HTML to simulate browser's behavior
+ ++result;
+ final CountDownLatch htmlLatch = new CountDownLatch(1);
+ session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ htmlLatch.countDown();
+ }
+ });
+ Assert.assertTrue(htmlLatch.await(5, TimeUnit.SECONDS));
+
+ for (int i = 0; i < cssResources.length; ++i)
+ {
+ String path = "/" + i + ".css";
+ if (pushedResources.contains(path))
+ continue;
+ headers = createRequestHeaders(referrer, path);
+ ++result;
+ session.syn(new SynInfo(headers, true), new DataListener());
+ }
+ for (int i = 0; i < jsResources.length; ++i)
+ {
+ String path = "/" + i + ".js";
+ if (pushedResources.contains(path))
+ continue;
+ headers = createRequestHeaders(referrer, path);
+ ++result;
+ session.syn(new SynInfo(headers, true), new DataListener());
+ }
+ for (int i = 0; i < pngResources.length; ++i)
+ {
+ String path = "/" + i + ".png";
+ if (pushedResources.contains(path))
+ continue;
+ headers = createRequestHeaders(referrer, path);
+ ++result;
+ session.syn(new SynInfo(headers, true), new DataListener());
+ }
+
+ Assert.assertTrue(latch.get().await(5, TimeUnit.SECONDS));
+ }
+
+ return result;
+ }
+
+ private Headers createRequestHeaders(String referrer, String path)
+ {
+ Headers headers;
+ headers = new Headers();
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
+ headers.put("referer", referrer);
+ return headers;
+ }
+
+ private void sleep(long delay) throws ServletException
+ {
+ try
+ {
+ TimeUnit.MILLISECONDS.sleep(delay);
+ }
+ catch (InterruptedException x)
+ {
+ throw new ServletException(x);
+ }
+ }
+
+ private class PushStrategyBenchmarkHandler extends AbstractHandler
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+
+ // Sleep half of the roundtrip time, to simulate the delay of responses, even for pushed resources
+ sleep(roundtrip / 2);
+ // If it's not a pushed resource, sleep half of the roundtrip time, to simulate the delay of requests
+ if (request.getHeader("x-spdy-push") == null)
+ sleep(roundtrip / 2);
+
+ String suffix = target.substring(target.indexOf('.') + 1);
+ int index = Integer.parseInt(target.substring(1, target.length() - suffix.length() - 1));
+
+ int contentLength;
+ String contentType;
+ switch (suffix)
+ {
+ case "html":
+ contentLength = htmlResources[index];
+ contentType = "text/html";
+ break;
+ case "css":
+ contentLength = cssResources[index];
+ contentType = "text/css";
+ break;
+ case "js":
+ contentLength = jsResources[index];
+ contentType = "text/javascript";
+ break;
+ case "png":
+ contentLength = pngResources[index];
+ contentType = "image/png";
+ break;
+ default:
+ throw new ServletException();
+ }
+
+ response.setContentType(contentType);
+ response.setContentLength(contentLength);
+ response.getOutputStream().write(new byte[contentLength]);
+ }
+ }
+
+ private void addPushedResource(String pushedURI)
+ {
+ switch (version())
+ {
+ case SPDY.V2:
+ {
+ Matcher matcher = Pattern.compile("https?://[^:]+:\\d+(/.*)").matcher(pushedURI);
+ Assert.assertTrue(matcher.matches());
+ pushedResources.add(matcher.group(1));
+ break;
+ }
+ case SPDY.V3:
+ {
+ pushedResources.add(pushedURI);
+ break;
+ }
+ default:
+ {
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ private class ClientSessionFrameListener extends SessionFrameListener.Adapter
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ String path = synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version())).value();
+ addPushedResource(path);
+ return new DataListener();
+ }
+ }
+
+ private class DataListener extends StreamFrameListener.Adapter
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ latch.get().countDown();
+ }
+ }
+
+ private class TestExchange extends ContentExchange
+ {
+ private TestExchange()
+ {
+ super(true);
+ }
+
+ @Override
+ protected void onResponseComplete() throws IOException
+ {
+ latch.get().countDown();
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyTest.java
deleted file mode 100644
index f18ff00b412..00000000000
--- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyTest.java
+++ /dev/null
@@ -1,471 +0,0 @@
-package org.eclipse.jetty.spdy.http;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.InetSocketAddress;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.handler.AbstractHandler;
-import org.eclipse.jetty.spdy.AsyncConnectionFactory;
-import org.eclipse.jetty.spdy.SPDYServerConnector;
-import org.eclipse.jetty.spdy.api.DataInfo;
-import org.eclipse.jetty.spdy.api.Headers;
-import org.eclipse.jetty.spdy.api.ReplyInfo;
-import org.eclipse.jetty.spdy.api.SPDY;
-import org.eclipse.jetty.spdy.api.Session;
-import org.eclipse.jetty.spdy.api.SessionFrameListener;
-import org.eclipse.jetty.spdy.api.Stream;
-import org.eclipse.jetty.spdy.api.StreamFrameListener;
-import org.eclipse.jetty.spdy.api.SynInfo;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
-{
- @Override
- protected SPDYServerConnector newHTTPSPDYServerConnector()
- {
- return new HTTPSPDYServerConnector()
- {
- private final AsyncConnectionFactory defaultAsyncConnectionFactory =
- new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), this, new ReferrerPushStrategy());
-
- @Override
- protected AsyncConnectionFactory getDefaultAsyncConnectionFactory()
- {
- return defaultAsyncConnectionFactory;
- }
- };
- }
-
- @Test
- public void testAssociatedResourceIsPushed() throws Exception
- {
- InetSocketAddress address = startHTTPServer(new AbstractHandler()
- {
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
- String url = request.getRequestURI();
- PrintWriter output = response.getWriter();
- if (url.endsWith(".html"))
- output.print("HELLO");
- else if (url.endsWith(".css"))
- output.print("body { background: #FFF; }");
- baseRequest.setHandled(true);
- }
- });
- Session session1 = startClient(address, null);
-
- final CountDownLatch mainResourceLatch = new CountDownLatch(1);
- Headers mainRequestHeaders = new Headers();
- mainRequestHeaders.put("method", "GET");
- String mainResource = "/index.html";
- mainRequestHeaders.put("url", mainResource);
- mainRequestHeaders.put("version", "HTTP/1.1");
- mainRequestHeaders.put("scheme", "http");
- mainRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainResourceLatch.countDown();
- }
- });
- Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
-
- final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
- Headers associatedRequestHeaders = new Headers();
- associatedRequestHeaders.put("method", "GET");
- associatedRequestHeaders.put("url", "/style.css");
- associatedRequestHeaders.put("version", "HTTP/1.1");
- associatedRequestHeaders.put("scheme", "http");
- associatedRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- associatedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + mainResource);
- session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- associatedResourceLatch.countDown();
- }
- });
- Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
-
- // Create another client, and perform the same request for the main resource, we expect the css being pushed
-
- final CountDownLatch mainStreamLatch = new CountDownLatch(2);
- final CountDownLatch pushDataLatch = new CountDownLatch(1);
- Session session2 = startClient(address, new SessionFrameListener.Adapter()
- {
- @Override
- public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
- {
- Assert.assertTrue(stream.isUnidirectional());
- return new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- pushDataLatch.countDown();
- }
- };
- }
- });
- session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onReply(Stream stream, ReplyInfo replyInfo)
- {
- Assert.assertFalse(replyInfo.isClose());
- mainStreamLatch.countDown();
- }
-
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainStreamLatch.countDown();
- }
- });
-
- Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
- Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
- }
-
- @Test
- public void testNestedAssociatedResourceIsPushed() throws Exception
- {
- InetSocketAddress address = startHTTPServer(new AbstractHandler()
- {
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
- String url = request.getRequestURI();
- PrintWriter output = response.getWriter();
- if (url.endsWith(".html"))
- output.print("HELLO");
- else if (url.endsWith(".css"))
- output.print("body { background: #FFF; }");
- else if (url.endsWith(".gif"))
- output.print("\u0000");
- baseRequest.setHandled(true);
- }
- });
- Session session1 = startClient(address, null);
-
- final CountDownLatch mainResourceLatch = new CountDownLatch(1);
- Headers mainRequestHeaders = new Headers();
- mainRequestHeaders.put("method", "GET");
- String mainResource = "/index.html";
- mainRequestHeaders.put("url", mainResource);
- mainRequestHeaders.put("version", "HTTP/1.1");
- mainRequestHeaders.put("scheme", "http");
- mainRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainResourceLatch.countDown();
- }
- });
- Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
-
- final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
- Headers associatedRequestHeaders = new Headers();
- associatedRequestHeaders.put("method", "GET");
- String associatedResource = "/style.css";
- associatedRequestHeaders.put("url", associatedResource);
- associatedRequestHeaders.put("version", "HTTP/1.1");
- associatedRequestHeaders.put("scheme", "http");
- associatedRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- associatedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + mainResource);
- session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- associatedResourceLatch.countDown();
- }
- });
- Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
-
- final CountDownLatch nestedResourceLatch = new CountDownLatch(1);
- Headers nestedRequestHeaders = new Headers();
- nestedRequestHeaders.put("method", "GET");
- nestedRequestHeaders.put("url", "/image.gif");
- nestedRequestHeaders.put("version", "HTTP/1.1");
- nestedRequestHeaders.put("scheme", "http");
- nestedRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- nestedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + associatedResource);
- session1.syn(new SynInfo(nestedRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- nestedResourceLatch.countDown();
- }
- });
- Assert.assertTrue(nestedResourceLatch.await(5, TimeUnit.SECONDS));
-
- // Create another client, and perform the same request for the main resource, we expect the css and the image being pushed
-
- final CountDownLatch mainStreamLatch = new CountDownLatch(2);
- final CountDownLatch pushDataLatch = new CountDownLatch(2);
- Session session2 = startClient(address, new SessionFrameListener.Adapter()
- {
- @Override
- public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
- {
- Assert.assertTrue(stream.isUnidirectional());
- return new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- pushDataLatch.countDown();
- }
- };
- }
- });
- session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onReply(Stream stream, ReplyInfo replyInfo)
- {
- Assert.assertFalse(replyInfo.isClose());
- mainStreamLatch.countDown();
- }
-
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainStreamLatch.countDown();
- }
- });
-
- Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
- Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
- }
-
- @Test
- public void testMainResourceWithReferrerIsNotPushed() throws Exception
- {
- InetSocketAddress address = startHTTPServer(new AbstractHandler()
- {
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
- String url = request.getRequestURI();
- PrintWriter output = response.getWriter();
- if (url.endsWith(".html"))
- output.print("HELLO");
- baseRequest.setHandled(true);
- }
- });
- Session session1 = startClient(address, null);
-
- final CountDownLatch mainResourceLatch = new CountDownLatch(1);
- Headers mainRequestHeaders = new Headers();
- mainRequestHeaders.put("method", "GET");
- String mainResource = "/index.html";
- mainRequestHeaders.put("url", mainResource);
- mainRequestHeaders.put("version", "HTTP/1.1");
- mainRequestHeaders.put("scheme", "http");
- mainRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainResourceLatch.countDown();
- }
- });
- Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
-
- final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
- Headers associatedRequestHeaders = new Headers();
- associatedRequestHeaders.put("method", "GET");
- associatedRequestHeaders.put("url", "/home.html");
- associatedRequestHeaders.put("version", "HTTP/1.1");
- associatedRequestHeaders.put("scheme", "http");
- associatedRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- associatedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + mainResource);
- session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- associatedResourceLatch.countDown();
- }
- });
- Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
-
- // Create another client, and perform the same request for the main resource, we expect nothing being pushed
-
- final CountDownLatch mainStreamLatch = new CountDownLatch(2);
- final CountDownLatch pushLatch = new CountDownLatch(1);
- Session session2 = startClient(address, new SessionFrameListener.Adapter()
- {
- @Override
- public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
- {
- pushLatch.countDown();
- return null;
- }
- });
- session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onReply(Stream stream, ReplyInfo replyInfo)
- {
- Assert.assertFalse(replyInfo.isClose());
- mainStreamLatch.countDown();
- }
-
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainStreamLatch.countDown();
- }
- });
-
- Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
- Assert.assertFalse(pushLatch.await(1, TimeUnit.SECONDS));
- }
-
- @Test
- public void testRequestWithIfModifiedSinceHeaderPreventsPush() throws Exception
- {
- InetSocketAddress address = startHTTPServer(new AbstractHandler()
- {
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
- String url = request.getRequestURI();
- PrintWriter output = response.getWriter();
- if (url.endsWith(".html"))
- output.print("HELLO");
- else if (url.endsWith(".css"))
- output.print("body { background: #FFF; }");
- baseRequest.setHandled(true);
- }
- });
- Session session1 = startClient(address, null);
-
- final CountDownLatch mainResourceLatch = new CountDownLatch(1);
- Headers mainRequestHeaders = new Headers();
- mainRequestHeaders.put("method", "GET");
- String mainResource = "/index.html";
- mainRequestHeaders.put("url", mainResource);
- mainRequestHeaders.put("version", "HTTP/1.1");
- mainRequestHeaders.put("scheme", "http");
- mainRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- mainRequestHeaders.put("If-Modified-Since", "Tue, 27 Mar 2012 16:36:52 GMT");
- session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainResourceLatch.countDown();
- }
- });
- Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
-
- final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
- Headers associatedRequestHeaders = new Headers();
- associatedRequestHeaders.put("method", "GET");
- associatedRequestHeaders.put("url", "/style.css");
- associatedRequestHeaders.put("version", "HTTP/1.1");
- associatedRequestHeaders.put("scheme", "http");
- associatedRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- associatedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + mainResource);
- session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- associatedResourceLatch.countDown();
- }
- });
- Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
-
- // Create another client, and perform the same request for the main resource, we expect the css NOT being pushed as the main request contains an
- // if-modified-since header
-
- final CountDownLatch mainStreamLatch = new CountDownLatch(2);
- final CountDownLatch pushDataLatch = new CountDownLatch(1);
- Session session2 = startClient(address, new SessionFrameListener.Adapter()
- {
- @Override
- public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
- {
- Assert.assertTrue(stream.isUnidirectional());
- return new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- pushDataLatch.countDown();
- }
- };
- }
- });
- session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onReply(Stream stream, ReplyInfo replyInfo)
- {
- Assert.assertFalse(replyInfo.isClose());
- mainStreamLatch.countDown();
- }
-
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainStreamLatch.countDown();
- }
- });
-
- Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
- Assert.assertFalse("We don't expect data to be pushed as the main request contained an if-modified-since header",pushDataLatch.await(1, TimeUnit.SECONDS));
- }
-}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyUnitTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyUnitTest.java
new file mode 100644
index 00000000000..0edbcf8a333
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyUnitTest.java
@@ -0,0 +1,119 @@
+//========================================================================
+//Copyright 2011-2012 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.http;
+
+import java.util.Set;
+
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ReferrerPushStrategyUnitTest
+{
+ public static final short VERSION = SPDY.V3;
+ public static final String SCHEME = "http";
+ public static final String HOST = "localhost";
+ public static final String MAIN_URI = "/index.html";
+ public static final String METHOD = "GET";
+
+ // class under test
+ private ReferrerPushStrategy referrerPushStrategy;
+
+ @Mock
+ Stream stream;
+ @Mock
+ Session session;
+
+
+ @Before
+ public void setup()
+ {
+ referrerPushStrategy = new ReferrerPushStrategy();
+ }
+
+ @Test
+ public void testReferrerCallsAfterTimeoutAreNotAddedAsPushResources() throws InterruptedException
+ {
+ Headers requestHeaders = getBaseHeaders(VERSION);
+ int referrerCallTimeout = 1000;
+ referrerPushStrategy.setReferrerPushPeriod(referrerCallTimeout);
+ setMockExpectations();
+
+ String referrerUrl = fillPushStrategyCache(requestHeaders);
+ Set pushResources;
+
+ // sleep to pretend that the user manually clicked on a linked resource instead the browser requesting subresources immediately
+ Thread.sleep(referrerCallTimeout + 1);
+
+ requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), "image2.jpg");
+ requestHeaders.put("referer", referrerUrl);
+ pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ assertThat("pushResources is empty", pushResources.size(), is(0));
+
+ requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), MAIN_URI);
+ pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ // as the image2.jpg request has been a link and not a subresource, we expect that pushResources.size() is still 2
+ assertThat("pushResources contains two elements image.jpg and style.css", pushResources.size(), is(2));
+ }
+
+ private Headers getBaseHeaders(short version)
+ {
+ Headers requestHeaders = new Headers();
+ requestHeaders.put(HTTPSPDYHeader.SCHEME.name(version), SCHEME);
+ requestHeaders.put(HTTPSPDYHeader.HOST.name(version), HOST);
+ requestHeaders.put(HTTPSPDYHeader.URI.name(version), MAIN_URI);
+ requestHeaders.put(HTTPSPDYHeader.METHOD.name(version), METHOD);
+ return requestHeaders;
+ }
+
+ private void setMockExpectations()
+ {
+ when(stream.getSession()).thenReturn(session);
+ when(session.getVersion()).thenReturn(VERSION);
+ }
+
+ private String fillPushStrategyCache(Headers requestHeaders)
+ {
+ Set pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ assertThat("pushResources is empty", pushResources.size(), is(0));
+
+ String origin = SCHEME + "://" + HOST;
+ String referrerUrl = origin + MAIN_URI;
+
+ requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), "image.jpg");
+ requestHeaders.put("referer", referrerUrl);
+ pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ assertThat("pushResources is empty", pushResources.size(), is(0));
+
+ requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), "style.css");
+ pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ assertThat("pushResources is empty", pushResources.size(), is(0));
+
+ requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), MAIN_URI);
+ pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ assertThat("pushResources contains two elements image.jpg and style.css", pushResources.size(), is(2));
+ return referrerUrl;
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV2Test.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV2Test.java
new file mode 100644
index 00000000000..8bc79c3f586
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV2Test.java
@@ -0,0 +1,797 @@
+//========================================================================
+//Copyright 2011-2012 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.http;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.InetSocketAddress;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.spdy.AsyncConnectionFactory;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.SessionFrameListener;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ReferrerPushStrategyV2Test extends AbstractHTTPSPDYTest
+{
+
+ private final String mainResource = "/index.html";
+ private final String cssResource = "/style.css";
+
+ @Override
+ protected SPDYServerConnector newHTTPSPDYServerConnector(short version)
+ {
+ SPDYServerConnector connector = super.newHTTPSPDYServerConnector(version);
+ AsyncConnectionFactory defaultFactory = new ServerHTTPSPDYAsyncConnectionFactory(version, connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, new ReferrerPushStrategy());
+ connector.setDefaultAsyncConnectionFactory(defaultFactory);
+ return connector;
+ }
+
+ @Test
+ public void testPushHeadersAreValid() throws Exception
+ {
+ InetSocketAddress address = createServer();
+
+ ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy();
+ int referrerPushPeriod = 1000;
+ pushStrategy.setReferrerPushPeriod(referrerPushPeriod);
+ AsyncConnectionFactory defaultFactory = new ServerHTTPSPDYAsyncConnectionFactory(version(), connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy);
+ connector.setDefaultAsyncConnectionFactory(defaultFactory);
+
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+ Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders);
+
+ // Sleep for pushPeriod This should prevent application.js from being mapped as pushResource
+ Thread.sleep(referrerPushPeriod + 1);
+
+ sendJSRequest(session1);
+
+ run2ndClientRequests(address, mainRequestHeaders, true);
+ }
+
+ @Test
+ public void testReferrerPushPeriod() throws Exception
+ {
+ InetSocketAddress address = createServer();
+
+ ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy();
+ int referrerPushPeriod = 1000;
+ pushStrategy.setReferrerPushPeriod(referrerPushPeriod);
+ AsyncConnectionFactory defaultFactory = new ServerHTTPSPDYAsyncConnectionFactory(version(), connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy);
+ connector.setDefaultAsyncConnectionFactory(defaultFactory);
+
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+ Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders);
+
+ // Sleep for pushPeriod This should prevent application.js from being mapped as pushResource
+ Thread.sleep(referrerPushPeriod+1);
+
+ sendJSRequest(session1);
+
+ run2ndClientRequests(address, mainRequestHeaders, false);
+ }
+
+ @Test
+ public void testMaxAssociatedResources() throws Exception
+ {
+ InetSocketAddress address = createServer();
+
+ ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy();
+ pushStrategy.setMaxAssociatedResources(1);
+ AsyncConnectionFactory defaultFactory = new ServerHTTPSPDYAsyncConnectionFactory(version(), connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy);
+ connector.setDefaultAsyncConnectionFactory(defaultFactory);
+
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+ Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders);
+
+ sendJSRequest(session1);
+
+ run2ndClientRequests(address, mainRequestHeaders, false);
+ }
+
+ private InetSocketAddress createServer() throws Exception
+ {
+ return startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ output.print("HELLO");
+ else if (url.endsWith(".css"))
+ output.print("body { background: #FFF; }");
+ else if (url.endsWith(".js"))
+ output.print("function(){}();");
+ baseRequest.setHandled(true);
+ }
+ });
+ }
+
+ private Session sendMainRequestAndCSSRequest(InetSocketAddress address, Headers mainRequestHeaders) throws Exception
+ {
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch1 = new CountDownLatch(1);
+ Headers associatedRequestHeaders1 = createHeaders(cssResource);
+ session1.syn(new SynInfo(associatedRequestHeaders1, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch1.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch1.await(5, TimeUnit.SECONDS));
+ return session1;
+ }
+
+
+ private void sendJSRequest(Session session1) throws InterruptedException
+ {
+ final CountDownLatch associatedResourceLatch2 = new CountDownLatch(1);
+ String jsResource = "/application.js";
+ Headers associatedRequestHeaders2 = createHeaders(jsResource);
+ session1.syn(new SynInfo(associatedRequestHeaders2, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch2.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch2.await(5, TimeUnit.SECONDS));
+ }
+
+ private void run2ndClientRequests(InetSocketAddress address, Headers mainRequestHeaders, final boolean validateHeaders) throws Exception
+ {
+ // Create another client, and perform the same request for the main resource,
+ // we expect the css being pushed, but not the js
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushDataLatch = new CountDownLatch(1);
+ final CountDownLatch pushSynHeadersValid = new CountDownLatch(1);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ if(validateHeaders)
+ validateHeaders(synInfo.getHeaders(), pushSynHeadersValid);
+
+ Assert.assertTrue(stream.isUnidirectional());
+ Assert.assertTrue(synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version())).value().endsWith(".css"));
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue("Main request reply and/or data not received", mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue("Pushed data not received", pushDataLatch.await(5, TimeUnit.SECONDS));
+ if(validateHeaders)
+ Assert.assertTrue("Push syn headers not valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testAssociatedResourceIsPushed() throws Exception
+ {
+ InetSocketAddress address = startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ output.print("HELLO");
+ else if (url.endsWith(".css"))
+ output.print("body { background: #FFF; }");
+ baseRequest.setHandled(true);
+ }
+ });
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
+ Headers associatedRequestHeaders = createHeaders(cssResource);
+ session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ // Create another client, and perform the same request for the main resource, we expect the css being pushed
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushDataLatch = new CountDownLatch(1);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(stream.isUnidirectional());
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testAssociatedResourceWithWrongContentTypeIsNotPushed() throws Exception
+ {
+ final String fakeResource = "/fake.png";
+ InetSocketAddress address = startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ {
+ response.setContentType("text/html");
+ output.print("HELLO");
+ }
+ else if (url.equals(fakeResource))
+ {
+ response.setContentType("text/html");
+ output.print("IMAGE");
+ }
+ else if (url.endsWith(".css"))
+ {
+ response.setContentType("text/css");
+ output.print("body { background: #FFF; }");
+ }
+ baseRequest.setHandled(true);
+ }
+ });
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
+ String cssResource = "/stylesheet.css";
+ Headers associatedRequestHeaders = createHeaders(cssResource);
+ session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch fakeAssociatedResourceLatch = new CountDownLatch(1);
+ Headers fakeAssociatedRequestHeaders = createHeaders(fakeResource);
+ session1.syn(new SynInfo(fakeAssociatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ fakeAssociatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(fakeAssociatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ // Create another client, and perform the same request for the main resource,
+ // we expect the css being pushed but not the fake PNG
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushDataLatch = new CountDownLatch(1);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(stream.isUnidirectional());
+ Assert.assertTrue(synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version())).value().endsWith(".css"));
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testNestedAssociatedResourceIsPushed() throws Exception
+ {
+ InetSocketAddress address = startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ output.print("HELLO");
+ else if (url.endsWith(".css"))
+ output.print("body { background: #FFF; }");
+ else if (url.endsWith(".gif"))
+ output.print("\u0000");
+ baseRequest.setHandled(true);
+ }
+ });
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
+ Headers associatedRequestHeaders = createHeaders(cssResource);
+ session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch nestedResourceLatch = new CountDownLatch(1);
+ String imageUrl = "/image.gif";
+ Headers nestedRequestHeaders = createHeaders(imageUrl, cssResource);
+
+ session1.syn(new SynInfo(nestedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ nestedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(nestedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ // Create another client, and perform the same request for the main resource, we expect the css and the image being pushed
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushDataLatch = new CountDownLatch(2);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(stream.isUnidirectional());
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testMainResourceWithReferrerIsNotPushed() throws Exception
+ {
+ InetSocketAddress address = startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ output.print("HELLO");
+ baseRequest.setHandled(true);
+ }
+ });
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
+ String associatedResource = "/home.html";
+ Headers associatedRequestHeaders = createHeaders(associatedResource);
+
+ session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ // Create another client, and perform the same request for the main resource, we expect nothing being pushed
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushLatch = new CountDownLatch(1);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ pushLatch.countDown();
+ return null;
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertFalse(pushLatch.await(1, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testRequestWithIfModifiedSinceHeaderPreventsPush() throws Exception
+ {
+ InetSocketAddress address = startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ output.print("HELLO");
+ else if (url.endsWith(".css"))
+ output.print("body { background: #FFF; }");
+ baseRequest.setHandled(true);
+ }
+ });
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ Headers mainRequestHeaders = createHeaders(mainResource);
+ mainRequestHeaders.put("If-Modified-Since", "Tue, 27 Mar 2012 16:36:52 GMT");
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
+ Headers associatedRequestHeaders = createHeaders(cssResource);
+ session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ // Create another client, and perform the same request for the main resource, we expect the css NOT being pushed as the main request contains an
+ // if-modified-since header
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushDataLatch = new CountDownLatch(1);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(stream.isUnidirectional());
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertFalse("We don't expect data to be pushed as the main request contained an if-modified-since header",pushDataLatch.await(1, TimeUnit.SECONDS));
+ }
+
+ private void validateHeaders(Headers headers, CountDownLatch pushSynHeadersValid)
+ {
+ if (validateHeader(headers, HTTPSPDYHeader.STATUS.name(version()), "200")
+ && validateHeader(headers, HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1")
+ && validateUriHeader(headers))
+ pushSynHeadersValid.countDown();
+ }
+
+ private boolean validateHeader(Headers headers, String name, String expectedValue)
+ {
+ Headers.Header header = headers.get(name);
+ if (header != null && expectedValue.equals(header.value()))
+ return true;
+ System.out.println(name + " not valid! " + headers);
+ return false;
+ }
+
+ private boolean validateUriHeader(Headers headers)
+ {
+ Headers.Header uriHeader = headers.get(HTTPSPDYHeader.URI.name(version()));
+ if (uriHeader != null)
+ if (version() == SPDY.V2 && uriHeader.value().startsWith("http://"))
+ return true;
+ else if (version() == SPDY.V3 && uriHeader.value().startsWith("/")
+ && headers.get(HTTPSPDYHeader.HOST.name(version())) != null && headers.get(HTTPSPDYHeader.SCHEME.name(version())) != null)
+ return true;
+ System.out.println(HTTPSPDYHeader.URI.name(version()) + " not valid!");
+ return false;
+ }
+
+ private Headers createHeaders(String resource)
+ {
+ return createHeaders(resource, mainResource);
+ }
+
+ private Headers createHeaders(String resource, String referrer)
+ {
+ Headers associatedRequestHeaders = createHeadersWithoutReferrer(resource);
+ associatedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + referrer);
+ return associatedRequestHeaders;
+ }
+
+ private Headers createHeadersWithoutReferrer(String resource)
+ {
+ Headers associatedRequestHeaders = new Headers();
+ associatedRequestHeaders.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ associatedRequestHeaders.put(HTTPSPDYHeader.URI.name(version()), resource);
+ associatedRequestHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ associatedRequestHeaders.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ associatedRequestHeaders.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
+ return associatedRequestHeaders;
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV3Test.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV3Test.java
new file mode 100644
index 00000000000..2b637cb2cdb
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV3Test.java
@@ -0,0 +1,26 @@
+//========================================================================
+//Copyright 2011-2012 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.http;
+
+import org.eclipse.jetty.spdy.api.SPDY;
+
+public class ReferrerPushStrategyV3Test extends ReferrerPushStrategyV2Test
+{
+ @Override
+ protected short version()
+ {
+ return SPDY.V3;
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/SSLExternalServerTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/SSLExternalServerTest.java
new file mode 100644
index 00000000000..42bd5be8fd0
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/SSLExternalServerTest.java
@@ -0,0 +1,94 @@
+//========================================================================
+//Copyright 2011-2012 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.http;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jetty.spdy.SPDYClient;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class SSLExternalServerTest extends AbstractHTTPSPDYTest
+{
+ @Override
+ protected SPDYClient.Factory newSPDYClientFactory(Executor threadPool)
+ {
+ SslContextFactory sslContextFactory = new SslContextFactory();
+ // Force TLSv1
+ sslContextFactory.setIncludeProtocols("TLSv1");
+ return new SPDYClient.Factory(threadPool, sslContextFactory);
+ }
+
+ @Test
+ public void testExternalServer() throws Exception
+ {
+ String host = "encrypted.google.com";
+ int port = 443;
+ InetSocketAddress address = new InetSocketAddress(host, port);
+
+ try
+ {
+ // Test whether there is connectivity to avoid fail the test when offline
+ Socket socket = new Socket();
+ socket.connect(address, 5000);
+ socket.close();
+ }
+ catch (IOException x)
+ {
+ Assume.assumeNoException(x);
+ }
+
+ final short version = SPDY.V2;
+ Session session = startClient(version, address, null);
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.SCHEME.name(version), "https");
+ headers.put(HTTPSPDYHeader.HOST.name(version), host + ":" + port);
+ headers.put(HTTPSPDYHeader.METHOD.name(version), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version), "/");
+ headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
+ final CountDownLatch latch = new CountDownLatch(1);
+ session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Headers headers = replyInfo.getHeaders();
+ Headers.Header versionHeader = headers.get(HTTPSPDYHeader.STATUS.name(version));
+ if (versionHeader != null)
+ {
+ Matcher matcher = Pattern.compile("(\\d{3}).*").matcher(versionHeader.value());
+ if (matcher.matches() && Integer.parseInt(matcher.group(1)) < 400)
+ latch.countDown();
+ }
+ }
+ });
+ Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv2Test.java
similarity index 71%
rename from jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java
rename to jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv2Test.java
index 8b0c85e54a7..5bab1f512e3 100644
--- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv2Test.java
@@ -1,21 +1,20 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.http;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -48,14 +47,14 @@ import org.eclipse.jetty.spdy.api.SynInfo;
import org.junit.Assert;
import org.junit.Test;
-public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
+public class ServerHTTPSPDYv2Test extends AbstractHTTPSPDYTest
{
@Test
public void testSimpleGET() throws Exception
{
final String path = "/foo";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -71,11 +70,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", path);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -84,7 +83,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
});
@@ -99,7 +98,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String query = "p=1";
final String uri = path + "?" + query;
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -115,11 +114,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", uri);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), uri);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -128,7 +127,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
});
@@ -141,7 +140,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final String path = "/foo";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -156,11 +155,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "HEAD");
- headers.put("url", path);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "HEAD");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -169,7 +168,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
});
@@ -183,7 +182,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String path = "/foo";
final String data = "a=1&b=2";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -206,11 +205,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", path);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
@@ -220,7 +219,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
@@ -237,7 +236,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String data1 = "a=1&";
final String data2 = "b=2";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -252,11 +251,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", path);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
@@ -266,7 +265,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
@@ -286,7 +285,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String data1 = "a=1&";
final String data2 = "b=2";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -301,11 +300,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", path);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
@@ -315,7 +314,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.toString(), replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.toString(), replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
@@ -332,7 +331,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final String data = "0123456789ABCDEF";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -347,11 +346,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -361,7 +360,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -383,7 +382,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final char data = 'x';
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -398,11 +397,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -412,7 +411,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -437,7 +436,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String data1 = "0123456789ABCDEF";
final String data2 = "FEDCBA9876543210";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -454,11 +453,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(2);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -472,7 +471,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replyFrames.incrementAndGet());
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -499,7 +498,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final byte[] data = new byte[128 * 1024];
Arrays.fill(data, (byte)'x');
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -514,11 +513,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -530,7 +529,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -556,7 +555,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final byte[] data = new byte[128 * 1024];
Arrays.fill(data, (byte)'y');
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -572,11 +571,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -588,7 +587,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -613,7 +612,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final String data = "0123456789ABCDEF";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -630,11 +629,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -646,7 +645,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -674,7 +673,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String data1 = "0123456789ABCDEF";
final String data2 = "FEDCBA9876543210";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -693,11 +692,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -709,7 +708,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -736,7 +735,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final String suffix = "/redirect";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -751,11 +750,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -767,7 +766,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replies.incrementAndGet());
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("302"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("302"));
Assert.assertTrue(replyHeaders.get("location").value().endsWith(suffix));
replyLatch.countDown();
}
@@ -780,7 +779,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
public void testGETWithSendError() throws Exception
{
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -793,11 +792,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -810,15 +809,15 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replies.incrementAndGet());
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("404"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("404"));
replyLatch.countDown();
}
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
- Assert.assertTrue(dataInfo.isClose());
- dataLatch.countDown();
+ if (dataInfo.isClose())
+ dataLatch.countDown();
}
});
Assert.assertTrue(handlerLatch.await(5, TimeUnit.SECONDS));
@@ -829,7 +828,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
@Test
public void testGETWithException() throws Exception
{
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -840,11 +839,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -856,7 +855,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replies.incrementAndGet());
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("500"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("500"));
replyLatch.countDown();
}
});
@@ -869,7 +868,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String pangram1 = "the quick brown fox jumps over the lazy dog";
final String pangram2 = "qualche vago ione tipo zolfo, bromo, sodio";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -887,11 +886,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(2);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -905,7 +904,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replyFrames.incrementAndGet());
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
Assert.assertTrue(replyHeaders.get("extra").value().contains("X"));
replyLatch.countDown();
}
@@ -933,11 +932,30 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
@Test
- public void testGETWithMediumContentByPassed() throws Exception
+ public void testGETWithMediumContentAsInputStreamByPassed() throws Exception
+ {
+ byte[] data = new byte[2048];
+ testGETWithContentByPassed(new ByteArrayInputStream(data), data.length);
+ }
+
+ @Test
+ public void testGETWithBigContentAsInputStreamByPassed() throws Exception
+ {
+ byte[] data = new byte[128 * 1024];
+ testGETWithContentByPassed(new ByteArrayInputStream(data), data.length);
+ }
+
+ @Test
+ public void testGETWithMediumContentAsBufferByPassed() throws Exception
+ {
+ byte[] data = new byte[2048];
+ testGETWithContentByPassed(new ByteArrayBuffer(data), data.length);
+ }
+
+ private void testGETWithContentByPassed(final Object content, final int length) throws Exception
{
- final byte[] data = new byte[2048];
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -947,23 +965,23 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
// We use this trick that's present in Jetty code: if we add a request attribute
// called "org.eclipse.jetty.server.sendContent", then it will trigger the
// content bypass that we want to test
- request.setAttribute("org.eclipse.jetty.server.sendContent", new ByteArrayBuffer(data));
+ request.setAttribute("org.eclipse.jetty.server.sendContent", content);
handlerLatch.countDown();
}
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
private final AtomicInteger replyFrames = new AtomicInteger();
- private final AtomicInteger dataFrames = new AtomicInteger();
+ private final AtomicInteger contentLength = new AtomicInteger();
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@@ -971,17 +989,19 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replyFrames.incrementAndGet());
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
- Assert.assertEquals(1, dataFrames.incrementAndGet());
- Assert.assertTrue(dataInfo.isClose());
- Assert.assertArrayEquals(data, dataInfo.asBytes(true));
- dataLatch.countDown();
+ contentLength.addAndGet(dataInfo.asBytes(true).length);
+ if (dataInfo.isClose())
+ {
+ Assert.assertEquals(length, contentLength.get());
+ dataLatch.countDown();
+ }
}
});
Assert.assertTrue(handlerLatch.await(5, TimeUnit.SECONDS));
@@ -989,12 +1009,67 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
}
+ @Test
+ public void testGETWithMultipleMediumContentByPassed() throws Exception
+ {
+ final byte[] data = new byte[2048];
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
+ throws IOException, ServletException
+ {
+ // The sequence of write/flush/write/write below triggers a condition where
+ // HttpGenerator._bypass is set to true on the second write(), and the
+ // third write causes an infinite spin loop on the third write().
+ request.setHandled(true);
+ OutputStream output = httpResponse.getOutputStream();
+ output.write(data);
+ output.flush();
+ output.write(data);
+ output.write(data);
+ }
+ }), null);
+
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
+ final CountDownLatch replyLatch = new CountDownLatch(1);
+ final CountDownLatch dataLatch = new CountDownLatch(1);
+ final AtomicInteger contentLength = new AtomicInteger();
+ session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ Headers replyHeaders = replyInfo.getHeaders();
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
+ replyLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.available());
+ contentLength.addAndGet(dataInfo.length());
+ if (dataInfo.isClose())
+ dataLatch.countDown();
+ }
+ });
+ Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertEquals(3 * data.length, contentLength.get());
+ }
+
@Test
public void testPOSTThenSuspendRequestThenReadOneChunkThenComplete() throws Exception
{
final byte[] data = new byte[2000];
final CountDownLatch latch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, final Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -1030,11 +1105,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
{
@@ -1042,7 +1117,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
public void onReply(Stream stream, ReplyInfo replyInfo)
{
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
@@ -1057,7 +1132,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final byte[] data = new byte[2000];
final CountDownLatch latch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, final Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -1093,11 +1168,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
{
@@ -1105,7 +1180,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
public void onReply(Stream stream, ReplyInfo replyInfo)
{
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
@@ -1121,7 +1196,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final byte[] data = new byte[1000];
final CountDownLatch latch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, final Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -1166,11 +1241,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch responseLatch = new CountDownLatch(2);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
{
@@ -1178,7 +1253,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
public void onReply(Stream stream, ReplyInfo replyInfo)
{
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
responseLatch.countDown();
}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv3Test.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv3Test.java
new file mode 100644
index 00000000000..e6c4de2ac30
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv3Test.java
@@ -0,0 +1,26 @@
+//========================================================================
+//Copyright 2011-2012 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.http;
+
+import org.eclipse.jetty.spdy.api.SPDY;
+
+public class ServerHTTPSPDYv3Test extends ServerHTTPSPDYv2Test
+{
+ @Override
+ protected short version()
+ {
+ return SPDY.V3;
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYv2Test.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYv2Test.java
new file mode 100644
index 00000000000..6c2c89bc874
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYv2Test.java
@@ -0,0 +1,764 @@
+//========================================================================
+//Copyright 2011-2012 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.proxy;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.spdy.SPDYClient;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
+import org.eclipse.jetty.spdy.ServerSPDYAsyncConnectionFactory;
+import org.eclipse.jetty.spdy.api.BytesDataInfo;
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.GoAwayInfo;
+import org.eclipse.jetty.spdy.api.Handler;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.PingInfo;
+import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.RstInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.SessionFrameListener;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.StreamStatus;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
+import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestWatchman;
+import org.junit.runners.model.FrameworkMethod;
+
+public class ProxyHTTPSPDYv2Test
+{
+ @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());
+ }
+ };
+
+ private SPDYClient.Factory factory;
+ private Server server;
+ private Server proxy;
+ private SPDYServerConnector proxyConnector;
+
+ protected short version()
+ {
+ return SPDY.V2;
+ }
+
+ protected InetSocketAddress startServer(ServerSessionFrameListener listener) throws Exception
+ {
+ server = new Server();
+ SPDYServerConnector serverConnector = new SPDYServerConnector(listener);
+ serverConnector.setDefaultAsyncConnectionFactory(new ServerSPDYAsyncConnectionFactory(version(), serverConnector.getByteBufferPool(), serverConnector.getExecutor(), serverConnector.getScheduler(), listener));
+ serverConnector.setPort(0);
+ server.addConnector(serverConnector);
+ server.start();
+ return new InetSocketAddress("localhost", serverConnector.getLocalPort());
+ }
+
+ protected InetSocketAddress startProxy(InetSocketAddress address) throws Exception
+ {
+ proxy = new Server();
+ ProxyEngineSelector proxyEngineSelector = new ProxyEngineSelector();
+ SPDYProxyEngine spdyProxyEngine = new SPDYProxyEngine(factory);
+ proxyEngineSelector.putProxyEngine("spdy/" + version(), spdyProxyEngine);
+ proxyEngineSelector.putProxyServerInfo("localhost", new ProxyEngineSelector.ProxyServerInfo("spdy/" + version(), address.getHostName(), address.getPort()));
+ proxyConnector = new HTTPSPDYProxyConnector(proxyEngineSelector);
+ proxyConnector.setPort(0);
+ proxy.addConnector(proxyConnector);
+ proxy.start();
+ return new InetSocketAddress("localhost", proxyConnector.getLocalPort());
+ }
+
+ @Before
+ public void init() throws Exception
+ {
+ factory = new SPDYClient.Factory();
+ factory.start();
+ }
+
+ @After
+ public void destroy() throws Exception
+ {
+ if (server != null)
+ {
+ server.stop();
+ server.join();
+ }
+ if (proxy != null)
+ {
+ proxy.stop();
+ proxy.join();
+ }
+ factory.stop();
+ }
+
+ @Test
+ public void testClosingClientDoesNotCloseServer() throws Exception
+ {
+ final CountDownLatch closeLatch = new CountDownLatch(1);
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+ stream.reply(new ReplyInfo(responseHeaders, true));
+ return null;
+ }
+
+ @Override
+ public void onGoAway(Session session, GoAwayInfo goAwayInfo)
+ {
+ closeLatch.countDown();
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "\r\n";
+ output.write(request.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(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ Assert.assertFalse(reader.ready());
+
+ client.close();
+
+ // Must not close, other clients may still be connected
+ Assert.assertFalse(closeLatch.await(1, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testGETThenNoContentFromTwoClients() throws Exception
+ {
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(synInfo.isClose());
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+ ReplyInfo replyInfo = new ReplyInfo(responseHeaders, true);
+ stream.reply(replyInfo);
+ return null;
+ }
+ }));
+
+ Socket client1 = new Socket();
+ client1.connect(proxyAddress);
+ OutputStream output1 = client1.getOutputStream();
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "\r\n";
+ output1.write(request.getBytes("UTF-8"));
+ output1.flush();
+
+ InputStream input1 = client1.getInputStream();
+ BufferedReader reader1 = new BufferedReader(new InputStreamReader(input1, "UTF-8"));
+ String line = reader1.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader1.readLine();
+ Assert.assertFalse(reader1.ready());
+
+ // Perform another request with another client
+ Socket client2 = new Socket();
+ client2.connect(proxyAddress);
+ OutputStream output2 = client2.getOutputStream();
+
+ output2.write(request.getBytes("UTF-8"));
+ output2.flush();
+
+ InputStream input2 = client2.getInputStream();
+ BufferedReader reader2 = new BufferedReader(new InputStreamReader(input2, "UTF-8"));
+ line = reader2.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader2.readLine();
+ Assert.assertFalse(reader2.ready());
+
+ client1.close();
+ client2.close();
+ }
+
+ @Test
+ public void testGETThenSmallResponseContent() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(synInfo.isClose());
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+ ReplyInfo replyInfo = new ReplyInfo(responseHeaders, false);
+ stream.reply(replyInfo);
+ stream.data(new BytesDataInfo(data, true));
+
+ return null;
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "\r\n";
+ output.write(request.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(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ for (byte datum : data)
+ Assert.assertEquals(datum, reader.read());
+ Assert.assertFalse(reader.ready());
+
+ // Perform another request so that we are sure we reset the states of parsers and generators
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ line = reader.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ for (byte datum : data)
+ Assert.assertEquals(datum, reader.read());
+ Assert.assertFalse(reader.ready());
+
+ client.close();
+ }
+
+ @Test
+ public void testPOSTWithSmallRequestContentThenRedirect() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ {
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.STATUS.name(version()), "303 See Other");
+ stream.reply(new ReplyInfo(headers, true));
+ }
+ }
+ };
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "POST / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "Content-Length: " + data.length + "\r\n" +
+ "Content-Type: application/octet-stream\r\n" +
+ "\r\n";
+ output.write(request.getBytes("UTF-8"));
+ output.write(data);
+ output.flush();
+
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ String line = reader.readLine();
+ Assert.assertTrue(line.contains(" 303"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ Assert.assertFalse(reader.ready());
+
+ // Perform another request so that we are sure we reset the states of parsers and generators
+ output.write(request.getBytes("UTF-8"));
+ output.write(data);
+ output.flush();
+
+ line = reader.readLine();
+ Assert.assertTrue(line.contains(" 303"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ Assert.assertFalse(reader.ready());
+
+ client.close();
+ }
+
+ @Test
+ public void testPOSTWithSmallRequestContentThenSmallResponseContent() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ {
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+ ReplyInfo replyInfo = new ReplyInfo(responseHeaders, false);
+ stream.reply(replyInfo);
+ stream.data(new BytesDataInfo(data, true));
+ }
+ }
+ };
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "POST / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "Content-Length: " + data.length + "\r\n" +
+ "Content-Type: application/octet-stream\r\n" +
+ "\r\n";
+ output.write(request.getBytes("UTF-8"));
+ output.write(data);
+ output.flush();
+
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ String line = reader.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ for (byte datum : data)
+ Assert.assertEquals(datum, reader.read());
+ Assert.assertFalse(reader.ready());
+
+ // Perform another request so that we are sure we reset the states of parsers and generators
+ output.write(request.getBytes("UTF-8"));
+ output.write(data);
+ output.flush();
+
+ line = reader.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ for (byte datum : data)
+ Assert.assertEquals(datum, reader.read());
+ Assert.assertFalse(reader.ready());
+
+ client.close();
+ }
+
+ @Test
+ public void testSYNThenREPLY() throws Exception
+ {
+ final String header = "foo";
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+ Assert.assertNotNull(requestHeaders.get(header));
+
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(header, "baz");
+ stream.reply(new ReplyInfo(responseHeaders, true));
+ return null;
+ }
+ }));
+ proxyConnector.setDefaultAsyncConnectionFactory(proxyConnector.getAsyncConnectionFactory("spdy/" + version()));
+
+ Session client = factory.newSPDYClient(version()).connect(proxyAddress, null).get(5, TimeUnit.SECONDS);
+
+ final CountDownLatch replyLatch = new CountDownLatch(1);
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + proxyAddress.getPort());
+ headers.put(header, "bar");
+ client.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Headers headers = replyInfo.getHeaders();
+ Assert.assertNotNull(headers.get(header));
+ replyLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
+
+ client.goAway().get(5, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void testSYNThenREPLYAndDATA() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ final String header = "foo";
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+ Assert.assertNotNull(requestHeaders.get(header));
+
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(header, "baz");
+ stream.reply(new ReplyInfo(responseHeaders, false));
+ stream.data(new BytesDataInfo(data, true));
+ return null;
+ }
+ }));
+ proxyConnector.setDefaultAsyncConnectionFactory(proxyConnector.getAsyncConnectionFactory("spdy/" + version()));
+
+ Session client = factory.newSPDYClient(version()).connect(proxyAddress, null).get(5, TimeUnit.SECONDS);
+
+ final CountDownLatch replyLatch = new CountDownLatch(1);
+ final CountDownLatch dataLatch = new CountDownLatch(1);
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + proxyAddress.getPort());
+ headers.put(header, "bar");
+ client.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ private final ByteArrayOutputStream result = new ByteArrayOutputStream();
+
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Headers headers = replyInfo.getHeaders();
+ Assert.assertNotNull(headers.get(header));
+ replyLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ result.write(dataInfo.asBytes(true), 0, dataInfo.length());
+ if (dataInfo.isClose())
+ {
+ Assert.assertArrayEquals(data, result.toByteArray());
+ dataLatch.countDown();
+ }
+ }
+ });
+
+ Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
+
+ client.goAway().get(5, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void testGETThenSPDYPushIsIgnored() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+
+ Headers pushHeaders = new Headers();
+ pushHeaders.put(HTTPSPDYHeader.URI.name(version()), "/push");
+ stream.syn(new SynInfo(pushHeaders, false), 5, TimeUnit.SECONDS, new Handler.Adapter()
+ {
+ @Override
+ public void completed(Stream pushStream)
+ {
+ pushStream.data(new BytesDataInfo(data, true));
+ }
+ });
+
+ stream.reply(new ReplyInfo(responseHeaders, true));
+ return null;
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "\r\n";
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ client.setSoTimeout(1000);
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ String line = reader.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ Assert.assertFalse(reader.ready());
+
+ client.close();
+ }
+
+ @Test
+ public void testSYNThenSPDYPushIsReceived() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+ stream.reply(new ReplyInfo(responseHeaders, false));
+
+ Headers pushHeaders = new Headers();
+ pushHeaders.put(HTTPSPDYHeader.URI.name(version()), "/push");
+ stream.syn(new SynInfo(pushHeaders, false), 5, TimeUnit.SECONDS, new Handler.Adapter()
+ {
+ @Override
+ public void completed(Stream pushStream)
+ {
+ pushStream.data(new BytesDataInfo(data, true));
+ }
+ });
+
+ stream.data(new BytesDataInfo(data, true));
+
+ return null;
+ }
+ }));
+ proxyConnector.setDefaultAsyncConnectionFactory(proxyConnector.getAsyncConnectionFactory("spdy/" + version()));
+
+ final CountDownLatch pushSynLatch = new CountDownLatch(1);
+ final CountDownLatch pushDataLatch = new CountDownLatch(1);
+ Session client = factory.newSPDYClient(version()).connect(proxyAddress, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ pushSynLatch.countDown();
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ }).get(5, TimeUnit.SECONDS);
+
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + proxyAddress.getPort());
+ final CountDownLatch replyLatch = new CountDownLatch(1);
+ final CountDownLatch dataLatch = new CountDownLatch(1);
+ client.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ replyLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ dataLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(pushSynLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
+
+ client.goAway().get(5, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void testPING() throws Exception
+ {
+ // PING is per hop, and it does not carry the information to which server to ping to
+ // We just verify that it works
+
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()));
+ proxyConnector.setDefaultAsyncConnectionFactory(proxyConnector.getAsyncConnectionFactory("spdy/" + version()));
+
+ final CountDownLatch pingLatch = new CountDownLatch(1);
+ Session client = factory.newSPDYClient(version()).connect(proxyAddress, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public void onPing(Session session, PingInfo pingInfo)
+ {
+ pingLatch.countDown();
+ }
+ }).get(5, TimeUnit.SECONDS);
+
+ client.ping().get(5, TimeUnit.SECONDS);
+
+ Assert.assertTrue(pingLatch.await(5, TimeUnit.SECONDS));
+
+ client.goAway().get(5, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void testGETThenReset() throws Exception
+ {
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(synInfo.isClose());
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+
+ stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM));
+
+ return null;
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "\r\n";
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ Assert.assertNull(reader.readLine());
+
+ client.close();
+ }
+
+ @Test
+ public void testSYNThenReset() throws Exception
+ {
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(synInfo.isClose());
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+
+ stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM));
+
+ return null;
+ }
+ }));
+ proxyConnector.setDefaultAsyncConnectionFactory(proxyConnector.getAsyncConnectionFactory("spdy/" + version()));
+
+ final CountDownLatch resetLatch = new CountDownLatch(1);
+ Session client = factory.newSPDYClient(version()).connect(proxyAddress, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public void onRst(Session session, RstInfo rstInfo)
+ {
+ resetLatch.countDown();
+ }
+ }).get(5, TimeUnit.SECONDS);
+
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + proxyAddress.getPort());
+ client.syn(new SynInfo(headers, true), null);
+
+ Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
+
+ client.goAway().get(5, TimeUnit.SECONDS);
+ }
+}
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/AsyncConnectionFactory.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/AsyncConnectionFactory.java
index 37077870474..97f9db59c40 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/AsyncConnectionFactory.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/AsyncConnectionFactory.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncConnection.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncConnection.java
index 70a9ac146af..a2888ce88e5 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncConnection.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncConnection.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncEndPoint.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncEndPoint.java
index c1fd5e2e251..58dbc8a9aa2 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncEndPoint.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncEndPoint.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategyFactory.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategyFactory.java
new file mode 100644
index 00000000000..a668f2f2f07
--- /dev/null
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategyFactory.java
@@ -0,0 +1,37 @@
+//========================================================================
+//Copyright 2011-2012 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;
+
+import org.eclipse.jetty.spdy.api.SPDY;
+
+public class FlowControlStrategyFactory
+{
+ private FlowControlStrategyFactory()
+ {
+ }
+
+ public static FlowControlStrategy newFlowControlStrategy(short version)
+ {
+ switch (version)
+ {
+ case SPDY.V2:
+ return new FlowControlStrategy.None();
+ case SPDY.V3:
+ return new SPDYv3FlowControlStrategy();
+ default:
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java
index 40dfecde36b..bb6b45cd5ec 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java
@@ -1,18 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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;
@@ -122,7 +120,8 @@ public class SPDYAsyncConnection extends AbstractConnection implements AsyncConn
catch (Exception x)
{
close(false);
- handler.failed(x);
+ handler.failed(context, x);
+ return -1;
}
finally
{
@@ -222,6 +221,7 @@ public class SPDYAsyncConnection extends AbstractConnection implements AsyncConn
@Override
public void onIdleExpired(long idleForMs)
{
+ logger.debug("Idle timeout expired for {}", getEndPoint());
session.goAway();
}
@@ -234,4 +234,9 @@ public class SPDYAsyncConnection extends AbstractConnection implements AsyncConn
{
this.session = session;
}
+
+ public String toString()
+ {
+ return String.format("%s@%x{endp=%s@%x}",getClass().getSimpleName(),hashCode(),getEndPoint().getClass().getSimpleName(),getEndPoint().hashCode());
+ }
}
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java
index 438e2e3cf03..65ecc2f53a5 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java
@@ -1,23 +1,16 @@
-/*
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
package org.eclipse.jetty.spdy;
@@ -38,7 +31,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
@@ -64,7 +56,8 @@ public class SPDYClient
private final short version;
private final Factory factory;
private SocketAddress bindAddress;
- private long maxIdleTime;
+ private long maxIdleTime = -1;
+ private volatile int initialWindowSize = 65536;
protected SPDYClient(short version, Factory factory)
{
@@ -101,7 +94,7 @@ public class SPDYClient
channel.socket().setTcpNoDelay(true);
channel.configureBlocking(false);
- SessionPromise result = new SessionPromise(this, listener);
+ SessionPromise result = new SessionPromise(channel, this, listener);
channel.connect(address);
factory.selector.register(channel, result);
@@ -119,6 +112,16 @@ public class SPDYClient
this.maxIdleTime = maxIdleTime;
}
+ public int getInitialWindowSize()
+ {
+ return initialWindowSize;
+ }
+
+ public void setInitialWindowSize(int initialWindowSize)
+ {
+ this.initialWindowSize = initialWindowSize;
+ }
+
protected String selectProtocol(List serverProtocols)
{
if (serverProtocols == null)
@@ -173,6 +176,11 @@ public class SPDYClient
return engine;
}
+ protected FlowControlStrategy newFlowControlStrategy()
+ {
+ return FlowControlStrategyFactory.newFlowControlStrategy(version);
+ }
+
public static class Factory extends AggregateLifeCycle
{
private final Map factories = new ConcurrentHashMap<>();
@@ -314,7 +322,7 @@ public class SPDYClient
}
@Override
- public AsyncConnection newConnection(final SocketChannel channel, AsyncEndPoint endPoint, Object attachment)
+ public AsyncConnection newConnection(final SocketChannel channel, AsyncEndPoint endPoint, final Object attachment)
{
SessionPromise sessionPromise = (SessionPromise)attachment;
final SPDYClient client = sessionPromise.client;
@@ -323,31 +331,18 @@ public class SPDYClient
{
if (sslContextFactory != null)
{
- final AtomicReference sslEndPointRef = new AtomicReference<>();
- final AtomicReference