Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimone Bordet2016-02-05 17:14:56 +0000
committerSimone Bordet2016-02-05 17:14:56 +0000
commitcb79379b79e01fcd33b74c61edd2dc0a9a9686dd (patch)
tree188aec81ba0d950f0ce85a621da88ccca689145d /jetty-http2
parentacde7a7d56f526339ef3976db40ea8e63a194877 (diff)
parent4a7fae30fbecfedf49200f2c2b6c644aea2df7b0 (diff)
downloadorg.eclipse.jetty.project-cb79379b79e01fcd33b74c61edd2dc0a9a9686dd.tar.gz
org.eclipse.jetty.project-cb79379b79e01fcd33b74c61edd2dc0a9a9686dd.tar.xz
org.eclipse.jetty.project-cb79379b79e01fcd33b74c61edd2dc0a9a9686dd.zip
Merged branch 'jetty-9.3.x' into 'master'.
Diffstat (limited to 'jetty-http2')
-rw-r--r--jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/ErrorCode.java45
-rw-r--r--jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpChannelOverHTTP2.java27
-rw-r--r--jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java3
-rw-r--r--jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java12
-rw-r--r--jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/AbstractTest.java34
-rw-r--r--jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java92
-rw-r--r--jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/MaxConcurrentStreamsTest.java14
7 files changed, 207 insertions, 20 deletions
diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/ErrorCode.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/ErrorCode.java
index e5a69b15c4..7022c37d7c 100644
--- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/ErrorCode.java
+++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/ErrorCode.java
@@ -21,21 +21,66 @@ package org.eclipse.jetty.http2;
import java.util.HashMap;
import java.util.Map;
+/**
+ * Standard HTTP/2 error codes.
+ */
public enum ErrorCode
{
+ /**
+ * Indicates no errors.
+ */
NO_ERROR(0),
+ /**
+ * Indicates a generic HTTP/2 protocol violation.
+ */
PROTOCOL_ERROR(1),
+ /**
+ * Indicates an internal error.
+ */
INTERNAL_ERROR(2),
+ /**
+ * Indicates a HTTP/2 flow control violation.
+ */
FLOW_CONTROL_ERROR(3),
+ /**
+ * Indicates that a SETTINGS frame did not receive a reply in a timely manner.
+ */
SETTINGS_TIMEOUT_ERROR(4),
+ /**
+ * Indicates that a stream frame has been received after the stream was closed.
+ */
STREAM_CLOSED_ERROR(5),
+ /**
+ * Indicates that a frame has an invalid length.
+ */
FRAME_SIZE_ERROR(6),
+ /**
+ * Indicates that a stream was rejected before application processing.
+ */
REFUSED_STREAM_ERROR(7),
+ /**
+ * Indicates that a stream is no longer needed.
+ */
CANCEL_STREAM_ERROR(8),
+ /**
+ * Indicates inability to maintain the HPACK compression context.
+ */
COMPRESSION_ERROR(9),
+ /**
+ * Indicates that the connection established by a HTTP CONNECT was abnormally closed.
+ */
HTTP_CONNECT_ERROR(10),
+ /**
+ * Indicates that the other peer might be generating excessive load.
+ */
ENHANCE_YOUR_CALM_ERROR(11),
+ /**
+ * Indicates that the transport properties do not meet minimum security requirements.
+ */
INADEQUATE_SECURITY_ERROR(12),
+ /**
+ * Indicates that HTTP/1.1 must be used rather than HTTP/2.
+ */
HTTP_1_1_REQUIRED_ERROR(13);
public final int code;
diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpChannelOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpChannelOverHTTP2.java
index 92e1158e9d..df999131b7 100644
--- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpChannelOverHTTP2.java
+++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpChannelOverHTTP2.java
@@ -24,8 +24,11 @@ import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.client.HttpReceiver;
import org.eclipse.jetty.client.HttpSender;
import org.eclipse.jetty.client.api.Result;
+import org.eclipse.jetty.http2.ErrorCode;
import org.eclipse.jetty.http2.api.Session;
import org.eclipse.jetty.http2.api.Stream;
+import org.eclipse.jetty.http2.frames.ResetFrame;
+import org.eclipse.jetty.util.Callback;
public class HttpChannelOverHTTP2 extends HttpChannel
{
@@ -33,6 +36,7 @@ public class HttpChannelOverHTTP2 extends HttpChannel
private final Session session;
private final HttpSenderOverHTTP2 sender;
private final HttpReceiverOverHTTP2 receiver;
+ private Stream stream;
public HttpChannelOverHTTP2(HttpDestination destination, HttpConnectionOverHTTP2 connection, Session session)
{
@@ -65,6 +69,16 @@ public class HttpChannelOverHTTP2 extends HttpChannel
return receiver;
}
+ public Stream getStream()
+ {
+ return stream;
+ }
+
+ public void setStream(Stream stream)
+ {
+ this.stream = stream;
+ }
+
@Override
public void send()
{
@@ -80,6 +94,19 @@ public class HttpChannelOverHTTP2 extends HttpChannel
}
@Override
+ public boolean abort(HttpExchange exchange, Throwable requestFailure, Throwable responseFailure)
+ {
+ boolean aborted = super.abort(exchange, requestFailure, responseFailure);
+ if (aborted)
+ {
+ Stream stream = getStream();
+ if (stream != null)
+ stream.reset(new ResetFrame(stream.getId(), ErrorCode.CANCEL_STREAM_ERROR.code), Callback.NOOP);
+ }
+ return aborted;
+ }
+
+ @Override
public void exchangeTerminated(HttpExchange exchange, Result result)
{
super.exchangeTerminated(exchange, result);
diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java
index 827a8740cc..51453e822a 100644
--- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java
+++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java
@@ -89,7 +89,10 @@ public class HttpReceiverOverHTTP2 extends HttpReceiver implements Stream.Listen
{
HttpExchange exchange = getHttpExchange();
if (exchange == null)
+ {
+ callback.failed(new IOException("terminated"));
return;
+ }
if (responseContent(exchange, frame.getData(), callback))
{
diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java
index db01d33c17..b13e68e097 100644
--- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java
+++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java
@@ -33,8 +33,6 @@ import org.eclipse.jetty.util.Promise;
public class HttpSenderOverHTTP2 extends HttpSender
{
- private Stream stream;
-
public HttpSenderOverHTTP2(HttpChannelOverHTTP2 channel)
{
super(channel);
@@ -59,7 +57,7 @@ public class HttpSenderOverHTTP2 extends HttpSender
@Override
public void succeeded(Stream stream)
{
- HttpSenderOverHTTP2.this.stream = stream;
+ getHttpChannel().setStream(stream);
stream.setIdleTimeout(request.getIdleTimeout());
if (content.hasContent() && !expects100Continue(request))
@@ -95,15 +93,9 @@ public class HttpSenderOverHTTP2 extends HttpSender
}
else
{
+ Stream stream = getHttpChannel().getStream();
DataFrame frame = new DataFrame(stream.getId(), content.getByteBuffer(), content.isLast());
stream.data(frame, callback);
}
}
-
- @Override
- protected void reset()
- {
- super.reset();
- stream = null;
- }
}
diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/AbstractTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/AbstractTest.java
index d4214dd29f..812253992b 100644
--- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/AbstractTest.java
+++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/AbstractTest.java
@@ -19,8 +19,11 @@
package org.eclipse.jetty.http2.client.http;
import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.http2.api.server.ServerSessionListener;
import org.eclipse.jetty.http2.client.HTTP2Client;
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
+import org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory;
+import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Server;
@@ -38,25 +41,38 @@ public class AbstractTest
protected ServerConnector connector;
protected HttpClient client;
- protected void start(int maxConcurrentStreams, Handler handler) throws Exception
+ protected void start(ServerSessionListener listener) throws Exception
+ {
+ prepareServer(new RawHTTP2ServerConnectionFactory(new HttpConfiguration(), listener));
+ server.start();
+ prepareClient();
+ client.start();
+ }
+
+ protected void start(Handler handler) throws Exception
+ {
+ prepareServer(new HTTP2ServerConnectionFactory(new HttpConfiguration()));
+ server.setHandler(handler);
+ server.start();
+ prepareClient();
+ client.start();
+ }
+
+ protected void prepareServer(ConnectionFactory connectionFactory)
{
QueuedThreadPool serverExecutor = new QueuedThreadPool();
serverExecutor.setName("server");
server = new Server(serverExecutor);
-
- HTTP2ServerConnectionFactory http2 = new HTTP2ServerConnectionFactory(new HttpConfiguration());
- http2.setMaxConcurrentStreams(maxConcurrentStreams);
- connector = new ServerConnector(server, 1, 1, http2);
+ connector = new ServerConnector(server, 1, 1, connectionFactory);
server.addConnector(connector);
+ }
- server.setHandler(handler);
- server.start();
-
+ protected void prepareClient() throws Exception
+ {
client = new HttpClient(new HttpClientTransportOverHTTP2(new HTTP2Client()), null);
QueuedThreadPool clientExecutor = new QueuedThreadPool();
clientExecutor.setName("client");
client.setExecutor(clientExecutor);
- client.start();
}
@After
diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java
index c2334eafac..1dcd6066d0 100644
--- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java
+++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java
@@ -18,19 +18,32 @@
package org.eclipse.jetty.http2.client.http;
+import java.nio.ByteBuffer;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.http.HttpVersion;
+import org.eclipse.jetty.http.MetaData;
+import org.eclipse.jetty.http2.api.Stream;
+import org.eclipse.jetty.http2.api.server.ServerSessionListener;
import org.eclipse.jetty.http2.client.HTTP2Client;
+import org.eclipse.jetty.http2.frames.DataFrame;
+import org.eclipse.jetty.http2.frames.HeadersFrame;
+import org.eclipse.jetty.http2.frames.ResetFrame;
+import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
-public class HttpClientTransportOverHTTP2Test
+public class HttpClientTransportOverHTTP2Test extends AbstractTest
{
@Test
public void testPropertiesAreForwarded() throws Exception
@@ -56,6 +69,83 @@ public class HttpClientTransportOverHTTP2Test
Assert.assertTrue(http2Client.isStopped());
}
+ @Test
+ public void testRequestAbortSendsResetFrame() throws Exception
+ {
+ CountDownLatch resetLatch = new CountDownLatch(1);
+ start(new ServerSessionListener.Adapter()
+ {
+ @Override
+ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
+ {
+ return new Stream.Listener.Adapter()
+ {
+ @Override
+ public void onReset(Stream stream, ResetFrame frame)
+ {
+ resetLatch.countDown();
+ }
+ };
+ }
+ });
+
+ try
+ {
+ client.newRequest("localhost", connector.getLocalPort())
+ .onRequestCommit(request -> request.abort(new Exception("explicitly_aborted_by_test")))
+ .send();
+ Assert.fail();
+ }
+ catch (ExecutionException x)
+ {
+ Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
+ }
+ }
+
+ @Test
+ public void testResponseAbortSendsResetFrame() throws Exception
+ {
+ CountDownLatch resetLatch = new CountDownLatch(1);
+ start(new ServerSessionListener.Adapter()
+ {
+ @Override
+ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
+ {
+ MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields());
+ stream.headers(new HeadersFrame(stream.getId(), metaData, null, false), new Callback()
+ {
+ @Override
+ public void succeeded()
+ {
+ ByteBuffer data = ByteBuffer.allocate(1024);
+ stream.data(new DataFrame(stream.getId(), data, false), NOOP);
+ }
+ });
+
+ return new Stream.Listener.Adapter()
+ {
+ @Override
+ public void onReset(Stream stream, ResetFrame frame)
+ {
+ resetLatch.countDown();
+ }
+ };
+ }
+ });
+
+ try
+ {
+ client.newRequest("localhost", connector.getLocalPort())
+ .onResponseContent((response, buffer) -> response.abort(new Exception("explicitly_aborted_by_test")))
+ .send();
+ Assert.fail();
+ }
+ catch (ExecutionException x)
+ {
+ Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
+ }
+ }
+
@Ignore
@Test
public void testExternalServer() throws Exception
diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/MaxConcurrentStreamsTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/MaxConcurrentStreamsTest.java
index 78b421969c..c456d0261a 100644
--- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/MaxConcurrentStreamsTest.java
+++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/MaxConcurrentStreamsTest.java
@@ -28,6 +28,9 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.junit.Assert;
@@ -35,6 +38,17 @@ import org.junit.Test;
public class MaxConcurrentStreamsTest extends AbstractTest
{
+ private void start(int maxConcurrentStreams, Handler handler) throws Exception
+ {
+ HTTP2ServerConnectionFactory http2 = new HTTP2ServerConnectionFactory(new HttpConfiguration());
+ http2.setMaxConcurrentStreams(maxConcurrentStreams);
+ prepareServer(http2);
+ server.setHandler(handler);
+ server.start();
+ prepareClient();
+ client.start();
+ }
+
@Test
public void testOneConcurrentStream() throws Exception
{

Back to the top