use of io.netty.util.concurrent.GenericFutureListener in project netty by netty.
the class Http2ConnectionHandlerTest method canSendGoAwayFrame.
@SuppressWarnings("unchecked")
@Test
public void canSendGoAwayFrame() throws Exception {
ByteBuf data = dummyData();
long errorCode = Http2Error.INTERNAL_ERROR.code();
when(future.isDone()).thenReturn(true);
when(future.isSuccess()).thenReturn(true);
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
((GenericFutureListener) invocation.getArgument(0)).operationComplete(future);
return null;
}
}).when(future).addListener(any(GenericFutureListener.class));
handler = newHandler();
handler.goAway(ctx, STREAM_ID, errorCode, data, promise);
verify(connection).goAwaySent(eq(STREAM_ID), eq(errorCode), eq(data));
verify(frameWriter).writeGoAway(eq(ctx), eq(STREAM_ID), eq(errorCode), eq(data), eq(promise));
verify(ctx).close();
assertEquals(0, data.refCnt());
}
use of io.netty.util.concurrent.GenericFutureListener in project herddb by diennea.
the class NettyChannel method sendOneWayMessage.
@Override
public void sendOneWayMessage(ByteBuf message, SendResultCallback callback) {
io.netty.channel.Channel _socket = this.socket;
if (_socket == null || !_socket.isOpen()) {
callback.messageSent(new Exception(this + " connection is closed"));
return;
}
if (LOGGER.isLoggable(Level.FINEST)) {
StringBuilder dumper = new StringBuilder();
ByteBufUtil.appendPrettyHexDump(dumper, message);
LOGGER.log(Level.FINEST, "Sending to {}: {}", new Object[] { _socket, dumper });
}
_socket.writeAndFlush(message).addListener(new GenericFutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (future.isSuccess()) {
callback.messageSent(null);
} else {
LOGGER.log(Level.SEVERE, this + ": error " + future.cause(), future.cause());
callback.messageSent(future.cause());
close();
}
}
});
unflushedWrites.incrementAndGet();
}
use of io.netty.util.concurrent.GenericFutureListener in project micronaut-core by micronaut-projects.
the class RoutingInBoundHandler method writeFinalNettyResponse.
private void writeFinalNettyResponse(MutableHttpResponse<?> message, HttpRequest<?> request, ChannelHandlerContext context) {
HttpStatus httpStatus = message.status();
final io.micronaut.http.HttpVersion httpVersion = request.getHttpVersion();
final boolean isHttp2 = httpVersion == io.micronaut.http.HttpVersion.HTTP_2_0;
boolean decodeError = request instanceof NettyHttpRequest && ((NettyHttpRequest<?>) request).getNativeRequest().decoderResult().isFailure();
final Object body = message.body();
if (body instanceof NettyCustomizableResponseTypeHandlerInvoker) {
// default Connection header if not set explicitly
if (!isHttp2) {
if (!message.getHeaders().contains(HttpHeaders.CONNECTION)) {
if (!decodeError && (httpStatus.getCode() < 500 || serverConfiguration.isKeepAliveOnServerError())) {
message.getHeaders().set(HttpHeaders.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
} else {
message.getHeaders().set(HttpHeaders.CONNECTION, HttpHeaderValues.CLOSE);
}
}
}
NettyCustomizableResponseTypeHandlerInvoker handler = (NettyCustomizableResponseTypeHandlerInvoker) body;
message.body(null);
handler.invoke(request, message, context);
} else {
io.netty.handler.codec.http.HttpResponse nettyResponse = NettyHttpResponseBuilder.toHttpResponse(message);
io.netty.handler.codec.http.HttpHeaders nettyHeaders = nettyResponse.headers();
// default Connection header if not set explicitly
if (!isHttp2) {
if (!nettyHeaders.contains(HttpHeaderNames.CONNECTION)) {
boolean expectKeepAlive = nettyResponse.protocolVersion().isKeepAliveDefault() || request.getHeaders().isKeepAlive();
if (!decodeError && (expectKeepAlive || httpStatus.getCode() < 500 || serverConfiguration.isKeepAliveOnServerError())) {
nettyHeaders.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
} else {
nettyHeaders.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
}
}
}
// default to Transfer-Encoding: chunked if Content-Length not set or not already set
if (!nettyHeaders.contains(HttpHeaderNames.CONTENT_LENGTH) && !nettyHeaders.contains(HttpHeaderNames.TRANSFER_ENCODING)) {
nettyHeaders.set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
}
// close handled by HttpServerKeepAliveHandler
final NettyHttpRequest<?> nettyHttpRequest = (NettyHttpRequest<?>) request;
if (isHttp2) {
addHttp2StreamHeader(request, nettyResponse);
}
io.netty.handler.codec.http.HttpRequest nativeRequest = nettyHttpRequest.getNativeRequest();
GenericFutureListener<Future<? super Void>> requestCompletor = future -> {
try {
if (!future.isSuccess()) {
final Throwable throwable = future.cause();
if (!(throwable instanceof ClosedChannelException)) {
if (throwable instanceof Http2Exception.StreamException) {
Http2Exception.StreamException se = (Http2Exception.StreamException) throwable;
if (se.error() == Http2Error.STREAM_CLOSED) {
// ignore
return;
}
}
if (LOG.isErrorEnabled()) {
LOG.error("Error writing final response: " + throwable.getMessage(), throwable);
}
}
}
} finally {
cleanupRequest(context, nettyHttpRequest);
context.read();
}
};
if (nativeRequest instanceof StreamedHttpRequest && !((StreamedHttpRequest) nativeRequest).isConsumed()) {
StreamedHttpRequest streamedHttpRequest = (StreamedHttpRequest) nativeRequest;
// We have to clear the buffer of FlowControlHandler before writing the response
// If this is a streamed request and there is still content to consume then subscribe
// and write the buffer is empty.
// noinspection ReactiveStreamsSubscriberImplementation
streamedHttpRequest.subscribe(new Subscriber<HttpContent>() {
private Subscription streamSub;
@Override
public void onSubscribe(Subscription s) {
streamSub = s;
s.request(1);
}
@Override
public void onNext(HttpContent httpContent) {
httpContent.release();
streamSub.request(1);
}
@Override
public void onError(Throwable t) {
syncWriteAndFlushNettyResponse(context, request, nettyResponse, requestCompletor);
}
@Override
public void onComplete() {
syncWriteAndFlushNettyResponse(context, request, nettyResponse, requestCompletor);
}
});
} else {
syncWriteAndFlushNettyResponse(context, request, nettyResponse, requestCompletor);
}
}
}
use of io.netty.util.concurrent.GenericFutureListener in project netconf by opendaylight.
the class TcpClientChannelInitializer method initialize.
@Override
public void initialize(final Channel ch, final Promise<NetconfClientSession> promise) {
final Future<NetconfClientSession> negotiationFuture = promise;
// We have to add this channel outbound handler to channel pipeline, in order
// to get notifications from netconf negotiatior. Set connection promise to
// success only after successful negotiation.
ch.pipeline().addFirst(new ChannelOutboundHandlerAdapter() {
ChannelPromise connectPromise;
GenericFutureListener<Future<NetconfClientSession>> negotiationFutureListener;
@Override
public void connect(final ChannelHandlerContext ctx, final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise channelPromise) {
connectPromise = channelPromise;
ChannelPromise tcpConnectFuture = new DefaultChannelPromise(ch);
negotiationFutureListener = future -> {
if (future.isSuccess()) {
channelPromise.setSuccess();
}
};
tcpConnectFuture.addListener(future -> {
if (future.isSuccess()) {
// complete connection promise with netconf negotiation future
negotiationFuture.addListener(negotiationFutureListener);
} else {
channelPromise.setFailure(future.cause());
}
});
ctx.connect(remoteAddress, localAddress, tcpConnectFuture);
}
@Override
public void disconnect(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception {
if (connectPromise == null) {
return;
}
// reconnect logic
if (connectPromise.isSuccess()) {
ctx.fireChannelInactive();
}
// we must set connection promise to failure
if (!connectPromise.isDone()) {
connectPromise.setFailure(new IllegalStateException("Negotiation failed"));
}
// Remove listener from negotiation future, we don't want notifications
// from negotiation anymore
negotiationFuture.removeListener(negotiationFutureListener);
super.disconnect(ctx, promise);
promise.setSuccess();
}
});
super.initialize(ch, promise);
}
use of io.netty.util.concurrent.GenericFutureListener in project netconf by opendaylight.
the class NetconfDeviceCommunicatorTest method testSendRequestWithWithSendFailure.
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
public void testSendRequestWithWithSendFailure() throws Exception {
setupSession();
NetconfMessage message = new NetconfMessage(UntrustedXML.newDocumentBuilder().newDocument());
QName rpc = QName.create("", "mockRpc");
ArgumentCaptor<GenericFutureListener> futureListener = ArgumentCaptor.forClass(GenericFutureListener.class);
ChannelFuture mockChannelFuture = mock(ChannelFuture.class);
doReturn(mockChannelFuture).when(mockChannelFuture).addListener(futureListener.capture());
doReturn(mockChannelFuture).when(mockSession).sendMessage(same(message));
ListenableFuture<RpcResult<NetconfMessage>> resultFuture = communicator.sendRequest(message, rpc);
assertNotNull("ListenableFuture is null", resultFuture);
verify(mockChannelFuture).addListener(futureListener.capture());
Future<Void> operationFuture = mock(Future.class);
doReturn(false).when(operationFuture).isSuccess();
doReturn(new Exception("mock error")).when(operationFuture).cause();
futureListener.getValue().operationComplete(operationFuture);
// Should have an immediate result
RpcResult<NetconfMessage> rpcResult = resultFuture.get(3, TimeUnit.MILLISECONDS);
RpcError rpcError = verifyErrorRpcResult(rpcResult, ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED);
assertEquals("RpcError message contains \"mock error\"", true, rpcError.getMessage().contains("mock error"));
}
Aggregations