diff options
author | Simone Bordet | 2016-02-05 17:14:56 +0000 |
---|---|---|
committer | Simone Bordet | 2016-02-05 17:14:56 +0000 |
commit | cb79379b79e01fcd33b74c61edd2dc0a9a9686dd (patch) | |
tree | 188aec81ba0d950f0ce85a621da88ccca689145d /jetty-http2 | |
parent | acde7a7d56f526339ef3976db40ea8e63a194877 (diff) | |
parent | 4a7fae30fbecfedf49200f2c2b6c644aea2df7b0 (diff) | |
download | org.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')
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 { |