use of org.eclipse.jetty.http2.HTTP2Session in project jetty.project by eclipse.
the class HttpClientTransportOverHTTP2Test method testClientStopsServerDoesNotCloseClientCloses.
@Test
public void testClientStopsServerDoesNotCloseClientCloses() throws Exception {
try (ServerSocket server = new ServerSocket(0)) {
List<Session> sessions = new ArrayList<>();
HTTP2Client h2Client = new HTTP2Client();
HttpClient client = new HttpClient(new HttpClientTransportOverHTTP2(h2Client) {
@Override
protected HttpConnectionOverHTTP2 newHttpConnection(HttpDestination destination, Session session) {
sessions.add(session);
return super.newHttpConnection(destination, session);
}
}, null);
QueuedThreadPool clientExecutor = new QueuedThreadPool();
clientExecutor.setName("client");
client.setExecutor(clientExecutor);
client.start();
CountDownLatch resultLatch = new CountDownLatch(1);
client.newRequest("localhost", server.getLocalPort()).send(result -> {
if (result.getResponse().getStatus() == HttpStatus.OK_200)
resultLatch.countDown();
});
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
Generator generator = new Generator(byteBufferPool);
try (Socket socket = server.accept()) {
socket.setSoTimeout(1000);
OutputStream output = socket.getOutputStream();
InputStream input = socket.getInputStream();
ServerParser parser = new ServerParser(byteBufferPool, new ServerParser.Listener.Adapter() {
@Override
public void onHeaders(HeadersFrame request) {
// Server's preface.
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
// Reply to client's SETTINGS.
generator.control(lease, new SettingsFrame(new HashMap<>(), true));
// Response.
MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields());
HeadersFrame response = new HeadersFrame(request.getStreamId(), metaData, null, true);
generator.control(lease, response);
try {
// Write the frames.
for (ByteBuffer buffer : lease.getByteBuffers()) output.write(BufferUtil.toArray(buffer));
} catch (Throwable x) {
x.printStackTrace();
}
}
}, 4096, 8192);
byte[] bytes = new byte[1024];
while (true) {
try {
int read = input.read(bytes);
if (read < 0)
Assert.fail();
parser.parse(ByteBuffer.wrap(bytes, 0, read));
} catch (SocketTimeoutException x) {
break;
}
}
Assert.assertTrue(resultLatch.await(5, TimeUnit.SECONDS));
// The client will send a GO_AWAY, but the server will not close.
client.stop();
// Give some time to process the stop/close operations.
Thread.sleep(1000);
Assert.assertTrue(h2Client.getBeans(Session.class).isEmpty());
for (Session session : sessions) {
Assert.assertTrue(session.isClosed());
Assert.assertTrue(((HTTP2Session) session).isDisconnected());
}
}
}
}
use of org.eclipse.jetty.http2.HTTP2Session in project jetty.project by eclipse.
the class CloseTest method testClientAbruptlyClosesConnection.
@Test
public void testClientAbruptlyClosesConnection() throws Exception {
final CountDownLatch closeLatch = new CountDownLatch(1);
final AtomicReference<Session> sessionRef = new AtomicReference<>();
startServer(new ServerSessionListener.Adapter() {
@Override
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) {
try {
sessionRef.set(stream.getSession());
MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields());
// Reply with HEADERS.
stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP);
closeLatch.await(5, TimeUnit.SECONDS);
return null;
} catch (InterruptedException x) {
return null;
}
}
});
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
generator.control(lease, new PrefaceFrame());
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
MetaData.Request metaData = newRequest("GET", new HttpFields());
generator.control(lease, new HeadersFrame(1, metaData, null, true));
try (Socket client = new Socket("localhost", connector.getLocalPort())) {
OutputStream output = client.getOutputStream();
for (ByteBuffer buffer : lease.getByteBuffers()) {
output.write(BufferUtil.toArray(buffer));
}
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter() {
@Override
public void onHeaders(HeadersFrame frame) {
try {
// Close the connection just after
// receiving the response headers.
client.close();
closeLatch.countDown();
} catch (IOException x) {
throw new RuntimeIOException(x);
}
}
}, 4096, 8192);
parseResponse(client, parser);
// We need to give some time to the server to receive and process the TCP FIN.
Thread.sleep(1000);
Session session = sessionRef.get();
Assert.assertTrue(session.isClosed());
Assert.assertTrue(((HTTP2Session) session).isDisconnected());
}
}
use of org.eclipse.jetty.http2.HTTP2Session in project jetty.project by eclipse.
the class CloseTest method testClientSendsGoAwayButDoesNotCloseConnectionServerCloses.
@Test
public void testClientSendsGoAwayButDoesNotCloseConnectionServerCloses() throws Exception {
final AtomicReference<Session> sessionRef = new AtomicReference<>();
startServer(new ServerSessionListener.Adapter() {
@Override
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) {
sessionRef.set(stream.getSession());
MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields());
stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP);
return null;
}
});
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
generator.control(lease, new PrefaceFrame());
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
MetaData.Request metaData = newRequest("GET", new HttpFields());
generator.control(lease, new HeadersFrame(1, metaData, null, true));
generator.control(lease, new GoAwayFrame(1, ErrorCode.NO_ERROR.code, "OK".getBytes("UTF-8")));
try (Socket client = new Socket("localhost", connector.getLocalPort())) {
OutputStream output = client.getOutputStream();
for (ByteBuffer buffer : lease.getByteBuffers()) {
output.write(BufferUtil.toArray(buffer));
}
// Don't close the connection; the server should close.
final CountDownLatch responseLatch = new CountDownLatch(1);
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter() {
@Override
public void onHeaders(HeadersFrame frame) {
// Even if we sent the GO_AWAY immediately after the
// HEADERS, the server is able to send us the response.
responseLatch.countDown();
}
}, 4096, 8192);
parseResponse(client, parser);
Assert.assertTrue(responseLatch.await(5, TimeUnit.SECONDS));
// Wait for the server to close.
Thread.sleep(1000);
// Client received the TCP FIN from server.
Assert.assertEquals(-1, client.getInputStream().read());
// Server is closed.
Session session = sessionRef.get();
Assert.assertTrue(session.isClosed());
Assert.assertTrue(((HTTP2Session) session).isDisconnected());
}
}
use of org.eclipse.jetty.http2.HTTP2Session in project jetty.project by eclipse.
the class StreamCloseTest method testFailedSessionClosesIdleStream.
@Test
public void testFailedSessionClosesIdleStream() throws Exception {
AtomicReference<Session> sessionRef = new AtomicReference<>();
final CountDownLatch latch = new CountDownLatch(1);
final List<Stream> streams = new ArrayList<>();
start(new ServerSessionListener.Adapter() {
@Override
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) {
streams.add(stream);
MetaData.Request request = (MetaData.Request) frame.getMetaData();
if ("GET".equals(request.getMethod())) {
((HTTP2Session) stream.getSession()).getEndPoint().close();
// Try to write something to force an error.
stream.data(new DataFrame(stream.getId(), ByteBuffer.allocate(1024), true), Callback.NOOP);
}
return null;
}
@Override
public void onFailure(Session session, Throwable failure) {
sessionRef.set(session);
latch.countDown();
}
});
Session session = newClient(new Session.Listener.Adapter());
// First stream will be idle on server.
HeadersFrame request1 = new HeadersFrame(newRequest("HEAD", new HttpFields()), null, true);
session.newStream(request1, new Promise.Adapter<>(), new Stream.Listener.Adapter());
// Second stream will fail on server.
HeadersFrame request2 = new HeadersFrame(newRequest("GET", new HttpFields()), null, true);
session.newStream(request2, new Promise.Adapter<>(), new Stream.Listener.Adapter());
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
Session serverSession = sessionRef.get();
// Wait for the server to finish the close activities.
Thread.sleep(1000);
Assert.assertEquals(0, serverSession.getStreams().size());
for (Stream stream : streams) Assert.assertTrue(stream.isClosed());
}
use of org.eclipse.jetty.http2.HTTP2Session in project jetty.project by eclipse.
the class SessionFailureTest method testWriteFailure.
@Test
public void testWriteFailure() throws Exception {
final CountDownLatch writeLatch = new CountDownLatch(1);
final CountDownLatch serverFailureLatch = new CountDownLatch(1);
start(new ServerSessionListener.Adapter() {
@Override
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) {
// Forcibly close the connection.
((HTTP2Session) stream.getSession()).getEndPoint().close();
// Now try to write something: it should fail.
stream.headers(frame, new Callback() {
@Override
public void failed(Throwable x) {
writeLatch.countDown();
}
});
return null;
}
@Override
public void onFailure(Session session, Throwable failure) {
serverFailureLatch.countDown();
}
});
final CountDownLatch clientFailureLatch = new CountDownLatch(1);
Session session = newClient(new Session.Listener.Adapter() {
@Override
public void onFailure(Session session, Throwable failure) {
clientFailureLatch.countDown();
}
});
HeadersFrame frame = new HeadersFrame(newRequest("GET", new HttpFields()), null, true);
Promise<Stream> promise = new Promise.Adapter<>();
session.newStream(frame, promise, null);
Assert.assertTrue(writeLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(serverFailureLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(clientFailureLatch.await(5, TimeUnit.SECONDS));
long start = System.nanoTime();
long now = System.nanoTime();
while (((HTTP2Session) session).getEndPoint().isOpen()) {
if (TimeUnit.NANOSECONDS.toSeconds(now - start) > 5)
Assert.fail();
Thread.sleep(10);
now = System.nanoTime();
}
}
Aggregations