use of io.netty.channel.ChannelFutureListener in project netty by netty.
the class Http2TestUtil method newVoidPromise.
static ChannelPromise newVoidPromise(final Channel channel) {
return new DefaultChannelPromise(channel, ImmediateEventExecutor.INSTANCE) {
@Override
public ChannelPromise addListener(GenericFutureListener<? extends Future<? super Void>> listener) {
throw new AssertionFailedError();
}
@Override
public ChannelPromise addListeners(GenericFutureListener<? extends Future<? super Void>>... listeners) {
throw new AssertionFailedError();
}
@Override
public boolean isVoid() {
return true;
}
@Override
public boolean tryFailure(Throwable cause) {
channel().pipeline().fireExceptionCaught(cause);
return true;
}
@Override
public ChannelPromise setFailure(Throwable cause) {
tryFailure(cause);
return this;
}
@Override
public ChannelPromise unvoid() {
ChannelPromise promise = new DefaultChannelPromise(channel, ImmediateEventExecutor.INSTANCE);
promise.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
channel().pipeline().fireExceptionCaught(future.cause());
}
}
});
return promise;
}
};
}
use of io.netty.channel.ChannelFutureListener in project netty by netty.
the class Http2ConnectionRoundtripTest method listenerExceptionShouldCloseConnection.
@Test
public void listenerExceptionShouldCloseConnection() throws Exception {
final Http2Headers headers = dummyHeaders();
doThrow(new RuntimeException("Fake Exception")).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(3), eq(headers), eq(0), eq((short) 16), eq(false), eq(0), eq(false));
bootstrapEnv(1, 0, 1, 1);
// Create a latch to track when the close occurs.
final CountDownLatch closeLatch = new CountDownLatch(1);
clientChannel.closeFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
closeLatch.countDown();
}
});
// Create a single stream by sending a HEADERS frame to the server.
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() throws Http2Exception {
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, newPromise());
http2Client.flush(ctx());
}
});
// Wait for the server to create the stream.
assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
assertTrue(requestLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
// Wait for the close to occur.
assertTrue(closeLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
assertFalse(clientChannel.isOpen());
}
use of io.netty.channel.ChannelFutureListener in project netty by netty.
the class Http2ConnectionRoundtripTest method encodeViolatesMaxHeaderListSizeCanStillUseConnection.
@Test
public void encodeViolatesMaxHeaderListSizeCanStillUseConnection() throws Exception {
bootstrapEnv(1, 2, 1, 0, 0);
final CountDownLatch serverSettingsAckLatch1 = new CountDownLatch(2);
final CountDownLatch serverSettingsAckLatch2 = new CountDownLatch(3);
final CountDownLatch clientSettingsLatch1 = new CountDownLatch(3);
final CountDownLatch serverRevHeadersLatch = new CountDownLatch(1);
final CountDownLatch clientHeadersLatch = new CountDownLatch(1);
final CountDownLatch clientDataWrite = new CountDownLatch(1);
final AtomicReference<Throwable> clientHeadersWriteException = new AtomicReference<Throwable>();
final AtomicReference<Throwable> clientHeadersWriteException2 = new AtomicReference<Throwable>();
final AtomicReference<Throwable> clientDataWriteException = new AtomicReference<Throwable>();
final Http2Headers headers = dummyHeaders();
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
serverSettingsAckLatch1.countDown();
serverSettingsAckLatch2.countDown();
return null;
}
}).when(serverListener).onSettingsAckRead(any(ChannelHandlerContext.class));
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
clientSettingsLatch1.countDown();
return null;
}
}).when(clientListener).onSettingsRead(any(ChannelHandlerContext.class), any(Http2Settings.class));
// Manually add a listener for when we receive the expected headers on the server.
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
serverRevHeadersLatch.countDown();
return null;
}
}).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(5), eq(headers), anyInt(), anyShort(), anyBoolean(), eq(0), eq(true));
// Set the maxHeaderListSize to 100 so we may be able to write some headers, but not all. We want to verify
// that we don't corrupt state if some can be written but not all.
runInChannel(serverConnectedChannel, new Http2Runnable() {
@Override
public void run() throws Http2Exception {
http2Server.encoder().writeSettings(serverCtx(), new Http2Settings().copyFrom(http2Server.decoder().localSettings()).maxHeaderListSize(100), serverNewPromise());
http2Server.flush(serverCtx());
}
});
assertTrue(serverSettingsAckLatch1.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() throws Http2Exception {
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, false, newPromise()).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
clientHeadersWriteException.set(future.cause());
}
});
// It is expected that this write should fail locally and the remote peer will never see this.
http2Client.encoder().writeData(ctx(), 3, Unpooled.buffer(), 0, true, newPromise()).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
clientDataWriteException.set(future.cause());
clientDataWrite.countDown();
}
});
http2Client.flush(ctx());
}
});
assertTrue(clientDataWrite.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
assertNotNull("Header encode should have exceeded maxHeaderListSize!", clientHeadersWriteException.get());
assertNotNull("Data on closed stream should fail!", clientDataWriteException.get());
// Set the maxHeaderListSize to the max value so we can send the headers.
runInChannel(serverConnectedChannel, new Http2Runnable() {
@Override
public void run() throws Http2Exception {
http2Server.encoder().writeSettings(serverCtx(), new Http2Settings().copyFrom(http2Server.decoder().localSettings()).maxHeaderListSize(Http2CodecUtil.MAX_HEADER_LIST_SIZE), serverNewPromise());
http2Server.flush(serverCtx());
}
});
assertTrue(clientSettingsLatch1.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
assertTrue(serverSettingsAckLatch2.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() throws Http2Exception {
http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, true, newPromise()).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
clientHeadersWriteException2.set(future.cause());
clientHeadersLatch.countDown();
}
});
http2Client.flush(ctx());
}
});
assertTrue(clientHeadersLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
assertNull("Client write of headers should succeed with increased header list size!", clientHeadersWriteException2.get());
assertTrue(serverRevHeadersLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
verify(serverListener, never()).onDataRead(any(ChannelHandlerContext.class), anyInt(), any(ByteBuf.class), anyInt(), anyBoolean());
// Verify that no errors have been received.
verify(serverListener, never()).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
verify(serverListener, never()).onRstStreamRead(any(ChannelHandlerContext.class), anyInt(), anyLong());
verify(clientListener, never()).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
verify(clientListener, never()).onRstStreamRead(any(ChannelHandlerContext.class), anyInt(), anyLong());
}
use of io.netty.channel.ChannelFutureListener in project netty by netty.
the class SslHandler method safeClose.
private void safeClose(final ChannelHandlerContext ctx, final ChannelFuture flushFuture, final ChannelPromise promise) {
if (!ctx.channel().isActive()) {
ctx.close(promise);
return;
}
final ScheduledFuture<?> timeoutFuture;
if (!flushFuture.isDone()) {
long closeNotifyTimeout = closeNotifyFlushTimeoutMillis;
if (closeNotifyTimeout > 0) {
// Force-close the connection if close_notify is not fully sent in time.
timeoutFuture = ctx.executor().schedule(new Runnable() {
@Override
public void run() {
// May be done in the meantime as cancel(...) is only best effort.
if (!flushFuture.isDone()) {
logger.warn("{} Last write attempt timed out; force-closing the connection.", ctx.channel());
addCloseListener(ctx.close(ctx.newPromise()), promise);
}
}
}, closeNotifyTimeout, TimeUnit.MILLISECONDS);
} else {
timeoutFuture = null;
}
} else {
timeoutFuture = null;
}
// Close the connection if close_notify is sent in time.
flushFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) throws Exception {
if (timeoutFuture != null) {
timeoutFuture.cancel(false);
}
final long closeNotifyReadTimeout = closeNotifyReadTimeoutMillis;
if (closeNotifyReadTimeout <= 0) {
// Trigger the close in all cases to make sure the promise is notified
// See https://github.com/netty/netty/issues/2358
addCloseListener(ctx.close(ctx.newPromise()), promise);
} else {
final ScheduledFuture<?> closeNotifyReadTimeoutFuture;
if (!sslClosePromise.isDone()) {
closeNotifyReadTimeoutFuture = ctx.executor().schedule(new Runnable() {
@Override
public void run() {
if (!sslClosePromise.isDone()) {
logger.debug("{} did not receive close_notify in {}ms; force-closing the connection.", ctx.channel(), closeNotifyReadTimeout);
// Do the close now...
addCloseListener(ctx.close(ctx.newPromise()), promise);
}
}
}, closeNotifyReadTimeout, TimeUnit.MILLISECONDS);
} else {
closeNotifyReadTimeoutFuture = null;
}
// Do the close once the we received the close_notify.
sslClosePromise.addListener(new FutureListener<Channel>() {
@Override
public void operationComplete(Future<Channel> future) throws Exception {
if (closeNotifyReadTimeoutFuture != null) {
closeNotifyReadTimeoutFuture.cancel(false);
}
addCloseListener(ctx.close(ctx.newPromise()), promise);
}
});
}
}
});
}
use of io.netty.channel.ChannelFutureListener in project netty by netty.
the class BootstrapTest method testLateRegisterSuccessBindFailed.
@Test
public void testLateRegisterSuccessBindFailed() throws Exception {
TestEventLoopGroup group = new TestEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(group);
bootstrap.channelFactory(new ChannelFactory<ServerChannel>() {
@Override
public ServerChannel newChannel() {
return new LocalServerChannel() {
@Override
public ChannelFuture bind(SocketAddress localAddress) {
// Close the Channel to emulate what NIO and others impl do on bind failure
// See https://github.com/netty/netty/issues/2586
close();
return newFailedFuture(new SocketException());
}
@Override
public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
// Close the Channel to emulate what NIO and others impl do on bind failure
// See https://github.com/netty/netty/issues/2586
close();
return promise.setFailure(new SocketException());
}
};
}
});
bootstrap.childHandler(new DummyHandler());
bootstrap.localAddress(new LocalAddress("1"));
ChannelFuture future = bootstrap.bind();
assertFalse(future.isDone());
group.promise.setSuccess();
final BlockingQueue<Boolean> queue = new LinkedBlockingQueue<Boolean>();
future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
queue.add(future.channel().eventLoop().inEventLoop(Thread.currentThread()));
queue.add(future.isSuccess());
}
});
assertTrue(queue.take());
assertFalse(queue.take());
} finally {
group.shutdownGracefully();
group.terminationFuture().sync();
}
}
Aggregations