Search in sources :

Example 66 with ChannelFutureListener

use of io.netty.channel.ChannelFutureListener in project netty by netty.

the class SslHandlerTest method compositeBufSizeEstimationGuaranteesSynchronousWrite.

private void compositeBufSizeEstimationGuaranteesSynchronousWrite(SslProvider serverProvider, SslProvider clientProvider) throws CertificateException, SSLException, ExecutionException, InterruptedException {
    SelfSignedCertificate ssc = new SelfSignedCertificate();
    final SslContext sslServerCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).sslProvider(serverProvider).build();
    final SslContext sslClientCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).sslProvider(clientProvider).build();
    EventLoopGroup group = new NioEventLoopGroup();
    Channel sc = null;
    Channel cc = null;
    try {
        final Promise<Void> donePromise = group.next().newPromise();
        final int expectedBytes = 469 + 1024 + 1024;
        sc = new ServerBootstrap().group(group).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<Channel>() {

            @Override
            protected void initChannel(Channel ch) throws Exception {
                ch.pipeline().addLast(sslServerCtx.newHandler(ch.alloc()));
                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {

                    @Override
                    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
                        if (evt instanceof SslHandshakeCompletionEvent) {
                            SslHandshakeCompletionEvent sslEvt = (SslHandshakeCompletionEvent) evt;
                            if (sslEvt.isSuccess()) {
                                final ByteBuf input = ctx.alloc().buffer();
                                input.writeBytes(new byte[expectedBytes]);
                                CompositeByteBuf content = ctx.alloc().compositeBuffer();
                                content.addComponent(true, input.readRetainedSlice(469));
                                content.addComponent(true, input.readRetainedSlice(1024));
                                content.addComponent(true, input.readRetainedSlice(1024));
                                ctx.writeAndFlush(content).addListener(new ChannelFutureListener() {

                                    @Override
                                    public void operationComplete(ChannelFuture future) {
                                        input.release();
                                    }
                                });
                            } else {
                                donePromise.tryFailure(sslEvt.cause());
                            }
                        }
                        ctx.fireUserEventTriggered(evt);
                    }

                    @Override
                    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                        donePromise.tryFailure(cause);
                    }

                    @Override
                    public void channelInactive(ChannelHandlerContext ctx) {
                        donePromise.tryFailure(new IllegalStateException("server closed"));
                    }
                });
            }
        }).bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
        cc = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<Channel>() {

            @Override
            protected void initChannel(Channel ch) throws Exception {
                ch.pipeline().addLast(sslClientCtx.newHandler(ch.alloc()));
                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {

                    private int bytesSeen;

                    @Override
                    public void channelRead(ChannelHandlerContext ctx, Object msg) {
                        if (msg instanceof ByteBuf) {
                            bytesSeen += ((ByteBuf) msg).readableBytes();
                            if (bytesSeen == expectedBytes) {
                                donePromise.trySuccess(null);
                            }
                        }
                        ReferenceCountUtil.release(msg);
                    }

                    @Override
                    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                        donePromise.tryFailure(cause);
                    }

                    @Override
                    public void channelInactive(ChannelHandlerContext ctx) {
                        donePromise.tryFailure(new IllegalStateException("client closed"));
                    }
                });
            }
        }).connect(sc.localAddress()).syncUninterruptibly().channel();
        donePromise.get();
    } finally {
        if (cc != null) {
            cc.close().syncUninterruptibly();
        }
        if (sc != null) {
            sc.close().syncUninterruptibly();
        }
        group.shutdownGracefully();
        ReferenceCountUtil.release(sslServerCtx);
        ReferenceCountUtil.release(sslClientCtx);
        ssc.delete();
    }
}
Also used : SelfSignedCertificate(io.netty.handler.ssl.util.SelfSignedCertificate) InetSocketAddress(java.net.InetSocketAddress) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) CompositeByteBuf(io.netty.buffer.CompositeByteBuf) ByteBuf(io.netty.buffer.ByteBuf) CompositeByteBuf(io.netty.buffer.CompositeByteBuf) Bootstrap(io.netty.bootstrap.Bootstrap) ServerBootstrap(io.netty.bootstrap.ServerBootstrap) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) ChannelFuture(io.netty.channel.ChannelFuture) NioServerSocketChannel(io.netty.channel.socket.nio.NioServerSocketChannel) NioServerSocketChannel(io.netty.channel.socket.nio.NioServerSocketChannel) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) Channel(io.netty.channel.Channel) ChannelFutureListener(io.netty.channel.ChannelFutureListener) ServerBootstrap(io.netty.bootstrap.ServerBootstrap) IllegalReferenceCountException(io.netty.util.IllegalReferenceCountException) CodecException(io.netty.handler.codec.CodecException) SSLProtocolException(javax.net.ssl.SSLProtocolException) DecoderException(io.netty.handler.codec.DecoderException) SSLException(javax.net.ssl.SSLException) ClosedChannelException(java.nio.channels.ClosedChannelException) CertificateException(java.security.cert.CertificateException) ExecutionException(java.util.concurrent.ExecutionException) UnsupportedMessageTypeException(io.netty.handler.codec.UnsupportedMessageTypeException) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) EventLoopGroup(io.netty.channel.EventLoopGroup) ChannelInboundHandlerAdapter(io.netty.channel.ChannelInboundHandlerAdapter)

Example 67 with ChannelFutureListener

use of io.netty.channel.ChannelFutureListener in project netty by netty.

the class ChunkedWriteHandlerTest method testListenerNotifiedWhenIsEnd.

// Test case which shows that there is not a bug like stated here:
// http://stackoverflow.com/a/10426305
@Test
public void testListenerNotifiedWhenIsEnd() {
    ByteBuf buffer = Unpooled.copiedBuffer("Test", CharsetUtil.ISO_8859_1);
    ChunkedInput<ByteBuf> input = new ChunkedInput<ByteBuf>() {

        private boolean done;

        private final ByteBuf buffer = Unpooled.copiedBuffer("Test", CharsetUtil.ISO_8859_1);

        @Override
        public boolean isEndOfInput() throws Exception {
            return done;
        }

        @Override
        public void close() throws Exception {
            buffer.release();
        }

        @Deprecated
        @Override
        public ByteBuf readChunk(ChannelHandlerContext ctx) throws Exception {
            return readChunk(ctx.alloc());
        }

        @Override
        public ByteBuf readChunk(ByteBufAllocator allocator) throws Exception {
            if (done) {
                return null;
            }
            done = true;
            return buffer.retainedDuplicate();
        }

        @Override
        public long length() {
            return -1;
        }

        @Override
        public long progress() {
            return 1;
        }
    };
    final AtomicBoolean listenerNotified = new AtomicBoolean(false);
    final ChannelFutureListener listener = new ChannelFutureListener() {

        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            listenerNotified.set(true);
        }
    };
    EmbeddedChannel ch = new EmbeddedChannel(new ChunkedWriteHandler());
    ch.writeAndFlush(input).addListener(listener).syncUninterruptibly();
    ch.checkException();
    ch.finish();
    // the listener should have been notified
    assertTrue(listenerNotified.get());
    ByteBuf buffer2 = ch.readOutbound();
    assertEquals(buffer, buffer2);
    assertNull(ch.readOutbound());
    buffer.release();
    buffer2.release();
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) ByteBufAllocator(io.netty.buffer.ByteBufAllocator) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ByteBuf(io.netty.buffer.ByteBuf) ChannelFutureListener(io.netty.channel.ChannelFutureListener) Test(org.junit.Test)

Example 68 with ChannelFutureListener

use of io.netty.channel.ChannelFutureListener in project netty by netty.

the class HttpObjectAggregator method handleOversizedMessage.

@Override
protected void handleOversizedMessage(final ChannelHandlerContext ctx, HttpMessage oversized) throws Exception {
    if (oversized instanceof HttpRequest) {
        // If keep-alive is off and 'Expect: 100-continue' is missing, no need to leave the connection open.
        if (oversized instanceof FullHttpMessage || !HttpUtil.is100ContinueExpected(oversized) && !HttpUtil.isKeepAlive(oversized)) {
            ChannelFuture future = ctx.writeAndFlush(TOO_LARGE_CLOSE.retainedDuplicate());
            future.addListener(new ChannelFutureListener() {

                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (!future.isSuccess()) {
                        logger.debug("Failed to send a 413 Request Entity Too Large.", future.cause());
                    }
                    ctx.close();
                }
            });
        } else {
            ctx.writeAndFlush(TOO_LARGE.retainedDuplicate()).addListener(new ChannelFutureListener() {

                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (!future.isSuccess()) {
                        logger.debug("Failed to send a 413 Request Entity Too Large.", future.cause());
                        ctx.close();
                    }
                }
            });
        }
        // If an oversized request was handled properly and the connection is still alive
        // (i.e. rejected 100-continue). the decoder should prepare to handle a new message.
        HttpObjectDecoder decoder = ctx.pipeline().get(HttpObjectDecoder.class);
        if (decoder != null) {
            decoder.reset();
        }
    } else if (oversized instanceof HttpResponse) {
        ctx.close();
        throw new TooLongFrameException("Response entity too large: " + oversized);
    } else {
        throw new IllegalStateException();
    }
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) TooLongFrameException(io.netty.handler.codec.TooLongFrameException) ChannelFutureListener(io.netty.channel.ChannelFutureListener) TooLongFrameException(io.netty.handler.codec.TooLongFrameException)

Example 69 with ChannelFutureListener

use of io.netty.channel.ChannelFutureListener in project netty by netty.

the class HttpServerUpgradeHandler method upgrade.

/**
     * Attempts to upgrade to the protocol(s) identified by the {@link HttpHeaderNames#UPGRADE} header (if provided
     * in the request).
     *
     * @param ctx the context for this handler.
     * @param request the HTTP request.
     * @return {@code true} if the upgrade occurred, otherwise {@code false}.
     */
private boolean upgrade(final ChannelHandlerContext ctx, final FullHttpRequest request) {
    // Select the best protocol based on those requested in the UPGRADE header.
    final List<CharSequence> requestedProtocols = splitHeader(request.headers().get(HttpHeaderNames.UPGRADE));
    final int numRequestedProtocols = requestedProtocols.size();
    UpgradeCodec upgradeCodec = null;
    CharSequence upgradeProtocol = null;
    for (int i = 0; i < numRequestedProtocols; i++) {
        final CharSequence p = requestedProtocols.get(i);
        final UpgradeCodec c = upgradeCodecFactory.newUpgradeCodec(p);
        if (c != null) {
            upgradeProtocol = p;
            upgradeCodec = c;
            break;
        }
    }
    if (upgradeCodec == null) {
        // None of the requested protocols are supported, don't upgrade.
        return false;
    }
    // Make sure the CONNECTION header is present.
    CharSequence connectionHeader = request.headers().get(HttpHeaderNames.CONNECTION);
    if (connectionHeader == null) {
        return false;
    }
    // Make sure the CONNECTION header contains UPGRADE as well as all protocol-specific headers.
    Collection<CharSequence> requiredHeaders = upgradeCodec.requiredUpgradeHeaders();
    List<CharSequence> values = splitHeader(connectionHeader);
    if (!containsContentEqualsIgnoreCase(values, HttpHeaderNames.UPGRADE) || !containsAllContentEqualsIgnoreCase(values, requiredHeaders)) {
        return false;
    }
    // Ensure that all required protocol-specific headers are found in the request.
    for (CharSequence requiredHeader : requiredHeaders) {
        if (!request.headers().contains(requiredHeader)) {
            return false;
        }
    }
    // Prepare and send the upgrade response. Wait for this write to complete before upgrading,
    // since we need the old codec in-place to properly encode the response.
    final FullHttpResponse upgradeResponse = createUpgradeResponse(upgradeProtocol);
    if (!upgradeCodec.prepareUpgradeResponse(ctx, request, upgradeResponse.headers())) {
        return false;
    }
    // Create the user event to be fired once the upgrade completes.
    final UpgradeEvent event = new UpgradeEvent(upgradeProtocol, request);
    final UpgradeCodec finalUpgradeCodec = upgradeCodec;
    ctx.writeAndFlush(upgradeResponse).addListener(new ChannelFutureListener() {

        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            try {
                if (future.isSuccess()) {
                    // Perform the upgrade to the new protocol.
                    sourceCodec.upgradeFrom(ctx);
                    finalUpgradeCodec.upgradeTo(ctx, request);
                    // Notify that the upgrade has occurred. Retain the event to offset
                    // the release() in the finally block.
                    ctx.fireUserEventTriggered(event.retain());
                    // Remove this handler from the pipeline.
                    ctx.pipeline().remove(HttpServerUpgradeHandler.this);
                } else {
                    future.channel().close();
                }
            } finally {
                // Release the event if the upgrade event wasn't fired.
                event.release();
            }
        }
    });
    return true;
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) ChannelFutureListener(io.netty.channel.ChannelFutureListener)

Example 70 with ChannelFutureListener

use of io.netty.channel.ChannelFutureListener in project netty by netty.

the class DefaultHttp2ConnectionEncoder method writeHeaders.

@Override
public ChannelFuture writeHeaders(final ChannelHandlerContext ctx, final int streamId, final Http2Headers headers, final int streamDependency, final short weight, final boolean exclusive, final int padding, final boolean endOfStream, ChannelPromise promise) {
    try {
        Http2Stream stream = connection.stream(streamId);
        if (stream == null) {
            stream = connection.local().createStream(streamId, endOfStream);
        } else {
            switch(stream.state()) {
                case RESERVED_LOCAL:
                    stream.open(endOfStream);
                    break;
                case OPEN:
                case HALF_CLOSED_REMOTE:
                    // Allowed sending headers in these states.
                    break;
                default:
                    throw new IllegalStateException(String.format("Stream %d in unexpected state: %s", stream.id(), stream.state()));
            }
        }
        // Trailing headers must go through flow control if there are other frames queued in flow control
        // for this stream.
        Http2RemoteFlowController flowController = flowController();
        if (!endOfStream || !flowController.hasFlowControlled(stream)) {
            if (endOfStream) {
                final Http2Stream finalStream = stream;
                final ChannelFutureListener closeStreamLocalListener = new ChannelFutureListener() {

                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        lifecycleManager.closeStreamLocal(finalStream, future);
                    }
                };
                promise = promise.unvoid().addListener(closeStreamLocalListener);
            }
            ChannelFuture future = frameWriter.writeHeaders(ctx, streamId, headers, streamDependency, weight, exclusive, padding, endOfStream, promise);
            // Writing headers may fail during the encode state if they violate HPACK limits.
            Throwable failureCause = future.cause();
            if (failureCause == null) {
                // Synchronously set the headersSent flag to ensure that we do not subsequently write
                // other headers containing pseudo-header fields.
                stream.headersSent();
            } else {
                lifecycleManager.onError(ctx, failureCause);
            }
            return future;
        } else {
            // Pass headers to the flow-controller so it can maintain their sequence relative to DATA frames.
            flowController.addFlowControlled(stream, new FlowControlledHeaders(stream, headers, streamDependency, weight, exclusive, padding, true, promise));
            return promise;
        }
    } catch (Throwable t) {
        lifecycleManager.onError(ctx, t);
        promise.tryFailure(t);
        return promise;
    }
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) ChannelFutureListener(io.netty.channel.ChannelFutureListener)

Aggregations

ChannelFutureListener (io.netty.channel.ChannelFutureListener)90 ChannelFuture (io.netty.channel.ChannelFuture)85 Channel (io.netty.channel.Channel)27 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)24 Bootstrap (io.netty.bootstrap.Bootstrap)19 Test (org.junit.Test)19 ByteBuf (io.netty.buffer.ByteBuf)18 ClosedChannelException (java.nio.channels.ClosedChannelException)17 CountDownLatch (java.util.concurrent.CountDownLatch)16 ChannelInboundHandlerAdapter (io.netty.channel.ChannelInboundHandlerAdapter)15 ServerBootstrap (io.netty.bootstrap.ServerBootstrap)14 IOException (java.io.IOException)12 ChannelPromise (io.netty.channel.ChannelPromise)11 ConnectException (java.net.ConnectException)11 NioSocketChannel (io.netty.channel.socket.nio.NioSocketChannel)10 InetSocketAddress (java.net.InetSocketAddress)7 AtomicReference (java.util.concurrent.atomic.AtomicReference)7 AbstractChannel (io.netty.channel.AbstractChannel)6 EventLoopGroup (io.netty.channel.EventLoopGroup)6 ChannelPipeline (io.netty.channel.ChannelPipeline)4