@Override public void dispose() { if (ch.eventLoop().inEventLoop()) { dereference(); } else { ch.eventLoop().execute(this::dereference); } ch.config().setAutoRead(false); }
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // TODO: Suspend incoming traffic until connected to the remote host. // Currently, we just keep the inbound traffic in the client channel's outbound buffer. final Channel inboundChannel = ctx.channel(); // Start the connection attempt. Bootstrap b = new Bootstrap(); b.group(inboundChannel.eventLoop()) .channel(NioSocketChannel.class) .remoteAddress(remoteHost, remotePort) .handler(new HexDumpProxyBackendHandler(inboundChannel)); ChannelFuture f = b.connect(); outboundChannel = f.channel(); f.addListener( new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { // Connection attempt succeeded: // TODO: Begin to accept incoming traffic. } else { // Close the connection if the connection attempt has failed. inboundChannel.close(); } } }); }
public void close() { if (closed) { return; } final SslHandler sslHandler = (SslHandler) channel.pipeline().get("ssl"); EventLoop eventLoop = channel.eventLoop(); boolean inEventLoop = eventLoop.inEventLoop(); // if we are in an event loop we need to close the channel after the writes have finished if (!inEventLoop) { closeSSLAndChannel(sslHandler, channel); } else { eventLoop.execute( new Runnable() { @Override public void run() { closeSSLAndChannel(sslHandler, channel); } }); } closed = true; listener.connectionDestroyed(getID()); }
private static void doBind0( final ChannelFuture regFuture, final Channel channel, final SocketAddress localAddress, final ChannelPromise promise) { // This method is invoked before channelRegistered() is triggered. Give user handlers a chance // to set up // the pipeline in its channelRegistered() implementation. channel .eventLoop() .execute( new Runnable() { @Override public void run() { if (regFuture.isSuccess()) { channel .bind(localAddress, promise) .addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } else { promise.setFailure(regFuture.cause()); } } }); }
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { final Channel inboundChannel = ctx.channel(); // Start the connection attempt. Bootstrap bootstrap = new Bootstrap(); bootstrap .group(inboundChannel.eventLoop()) .channel(ctx.channel().getClass()) .handler( new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // Create a default pipeline implementation. ChannelPipeline pipeline = ch.pipeline(); // add logging if (logger.isDebugEnabled()) { pipeline.addLast("logger", new LoggingHandler(" -->")); } // add HTTPS proxy -> server support if (secure) { SSLEngine engine = SSLFactory.sslContext().createSSLEngine(); engine.setUseClientMode(true); pipeline.addLast("proxy -> server ssl", new SslHandler(engine)); } // add handler pipeline.addLast( new ProxyRelayHandler( inboundChannel, bufferedCapacity, new RequestInterceptor(), " -->")); } }) .option(ChannelOption.AUTO_READ, false); ChannelFuture channelFuture = bootstrap.connect(remoteSocketAddress); outboundChannel = channelFuture.channel(); channelFuture.addListener( new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { channelBuffer.clear(); bufferedMode = bufferedCapacity > 0; flushedBuffer = false; // connection complete start to read first data inboundChannel.read(); } else { // Close the connection if the connection attempt has failed. inboundChannel.close(); } } }); }
private void connected(final Channel ch, final Handler<ClientConnection> connectHandler) { actualCtx.execute( ch.eventLoop(), new Runnable() { public void run() { createConn(ch, connectHandler); } }); }
private boolean exitAfterHandlingReactiveStreams( Channel channel, NettyResponseFuture<?> future, HttpResponse response, AsyncHandler<?> handler, HttpRequest httpRequest) throws IOException { if (handler instanceof StreamedAsyncHandler) { StreamedAsyncHandler<?> streamedAsyncHandler = (StreamedAsyncHandler<?>) handler; StreamedResponsePublisher publisher = new StreamedResponsePublisher(channel.eventLoop(), channelManager, future, channel); // FIXME do we really need to pass the event loop? // FIXME move this to ChannelManager channel.pipeline().addLast(channel.eventLoop(), "streamedAsyncHandler", publisher); Channels.setAttribute(channel, publisher); return streamedAsyncHandler.onStream(publisher) != State.CONTINUE; } return false; }
@Before public void setUp() { _channelPipeline.addFirst(new AnnotatedObjectDecoder()); Channel channel = _channelPipeline.channel(); _fileResponseChannelHandler = new FileResponseChannelHandler(_asyncBroker, channel.eventLoop()); _channelPipeline.addFirst(_fileResponseChannelHandler); _channelHandlerContext = _channelPipeline.firstContext(); }
private void a(final Packet var1, final GenericFutureListener[] var2) { final EnumProtocol var3 = EnumProtocol.a(var1); final EnumProtocol var4 = (EnumProtocol) k.attr(c).get(); if (var4 != var3) { g.debug("Disabled auto read"); k.config().setAutoRead(false); } if (k.eventLoop().inEventLoop()) { if (var3 != var4) { this.a(var3); } ChannelFuture var5 = k.writeAndFlush(var1); if (var2 != null) { var5.addListeners(var2); } var5.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); } else { k.eventLoop() .execute( new Runnable() { @Override public void run() { if (var3 != var4) { class_ek.this.a(var3); } ChannelFuture var1x = k.writeAndFlush(var1); if (var2 != null) { var1x.addListeners(var2); } var1x.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); } }); } }
private void uninjectChannel(final Channel channel) { if (!closed) { uninjectedChannels.add(channel); } channel .eventLoop() .execute( new Runnable() { @Override public void run() { channel.pipeline().remove(handlerName); } }); }
@Before public void before() throws Exception { when(context.channel()).thenReturn(channel); when(channel.pipeline()).thenReturn(pipeline); when(channel.eventLoop()).thenReturn(eventLoop); when(eventLoop.submit(any(Runnable.class))) .thenAnswer( new Answer<Future<?>>() { @Override public Future<?> answer(InvocationOnMock invocation) throws Throwable { Runnable r = (Runnable) invocation.getArguments()[0]; r.run(); return null; } }); }
@SuppressWarnings("unchecked") public NettyChannelHandler( ChannelHandler<ByteBuf, ByteBuf, NettyChannel> handler, ChannelBridge<C> bridgeFactory, io.netty.channel.Channel ch, NettyChannelHandler parent) { this.handler = handler; if (parent == null) { this.inboundEmitter = new InboundSink(ch); // guard requests/cancel/subscribe this.input = Flux.from(this).subscribeOn(Schedulers.fromExecutor(ch.eventLoop())); } else { this.inboundEmitter = parent.inboundEmitter; this.input = parent.input; } this.bridgeFactory = bridgeFactory; }
private void unregisterChannelHandler() { if (serverChannelHandler == null) return; for (Channel serverChannel : serverChannels) { final ChannelPipeline pipeline = serverChannel.pipeline(); serverChannel .eventLoop() .execute( new Runnable() { @Override public void run() { try { pipeline.remove(serverChannelHandler); } catch (NoSuchElementException e) { } } }); } }
@Override protected void channelRead( final C connection, final DefaultContext context, final ChannelHandlerContext chctx, final Object msg) throws Exception { if (connection != null) { // we are reading from the channel Channel ch = chctx.channel(); // We need to do this since it's possible the server is being used from a worker context if (context.isOnCorrectWorker(ch.eventLoop())) { try { vertx.setContext(context); doMessageReceived(connection, chctx, msg); } catch (Throwable t) { context.reportException(t); } } else { context.execute( new Runnable() { public void run() { try { doMessageReceived(connection, chctx, msg); } catch (Throwable t) { context.reportException(t); } } }); } } else { try { doMessageReceived(connection, chctx, msg); } catch (Throwable t) { chctx.pipeline().fireExceptionCaught(t); } } }
private void failed( final Channel ch, final Handler<Throwable> connectionExceptionHandler, final Throwable t) { // If no specific exception handler is provided, fall back to the HttpClient's exception // handler. final Handler<Throwable> exHandler = connectionExceptionHandler == null ? exceptionHandler : connectionExceptionHandler; actualCtx.execute( ch.eventLoop(), new Runnable() { public void run() { pool.connectionClosed(); try { ch.close(); } catch (Exception ignore) { } if (exHandler != null) { exHandler.handle(t); } else { actualCtx.reportException(t); } } }); }
@NotNull public final EventLoop getEventLoop() { return channel.eventLoop(); }
public void write( ActiveMQBuffer buffer, final boolean flush, final boolean batched, final ChannelFutureListener futureListener) { try { writeLock.acquire(); try { if (batchBuffer == null && batchingEnabled && batched && !flush) { // Lazily create batch buffer batchBuffer = ActiveMQBuffers.dynamicBuffer(BATCHING_BUFFER_SIZE); } if (batchBuffer != null) { batchBuffer.writeBytes(buffer, 0, buffer.writerIndex()); if (batchBuffer.writerIndex() >= BATCHING_BUFFER_SIZE || !batched || flush) { // If the batch buffer is full or it's flush param or not batched then flush the buffer buffer = batchBuffer; } else { return; } if (!batched || flush) { batchBuffer = null; } else { // Create a new buffer batchBuffer = ActiveMQBuffers.dynamicBuffer(BATCHING_BUFFER_SIZE); } } // depending on if we need to flush or not we can use a voidPromise or // use a normal promise final ByteBuf buf = buffer.byteBuf(); final ChannelPromise promise; if (flush || futureListener != null) { promise = channel.newPromise(); } else { promise = channel.voidPromise(); } EventLoop eventLoop = channel.eventLoop(); boolean inEventLoop = eventLoop.inEventLoop(); if (!inEventLoop) { if (futureListener != null) { channel.writeAndFlush(buf, promise).addListener(futureListener); } else { channel.writeAndFlush(buf, promise); } } else { // create a task which will be picked up by the eventloop and trigger the write. // This is mainly needed as this method is triggered by different threads for the same // channel. // if we not do this we may produce out of order writes. final Runnable task = new Runnable() { @Override public void run() { if (futureListener != null) { channel.writeAndFlush(buf, promise).addListener(futureListener); } else { channel.writeAndFlush(buf, promise); } } }; // execute the task on the eventloop eventLoop.execute(task); } // only try to wait if not in the eventloop otherwise we will produce a deadlock if (flush && !inEventLoop) { while (true) { try { boolean ok = promise.await(10000); if (!ok) { ActiveMQClientLogger.LOGGER.timeoutFlushingPacket(); } break; } catch (InterruptedException e) { throw new ActiveMQInterruptedException(e); } } } } finally { writeLock.release(); } } catch (InterruptedException e) { throw new ActiveMQInterruptedException(e); } }
@Test(timeout = 30000) @Ignore public void testConcurrentMessageBufferAccess() throws Throwable { EventLoopGroup l = new LocalEventLoopGroup(4, new DefaultThreadFactory("l")); EventExecutorGroup e1 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e1")); EventExecutorGroup e2 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e2")); EventExecutorGroup e3 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e3")); EventExecutorGroup e4 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e4")); EventExecutorGroup e5 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e5")); try { final MessageForwarder1 h1 = new MessageForwarder1(); final MessageForwarder2 h2 = new MessageForwarder2(); final MessageForwarder3 h3 = new MessageForwarder3(); final MessageForwarder1 h4 = new MessageForwarder1(); final MessageForwarder2 h5 = new MessageForwarder2(); final MessageDiscarder h6 = new MessageDiscarder(); final Channel ch = new LocalChannel(); // inbound: int -> byte[4] -> int -> int -> byte[4] -> int -> /dev/null // outbound: int -> int -> byte[4] -> int -> int -> byte[4] -> /dev/null ch.pipeline() .addLast(h1) .addLast(e1, h2) .addLast(e2, h3) .addLast(e3, h4) .addLast(e4, h5) .addLast(e5, h6); l.register(ch).sync().channel().connect(localAddr).sync(); final int ROUNDS = 1024; final int ELEMS_PER_ROUNDS = 8192; final int TOTAL_CNT = ROUNDS * ELEMS_PER_ROUNDS; for (int i = 0; i < TOTAL_CNT; ) { final int start = i; final int end = i + ELEMS_PER_ROUNDS; i = end; ch.eventLoop() .execute( new Runnable() { @Override public void run() { for (int j = start; j < end; j++) { ch.pipeline().fireChannelRead(Integer.valueOf(j)); } } }); } while (h1.inCnt < TOTAL_CNT || h2.inCnt < TOTAL_CNT || h3.inCnt < TOTAL_CNT || h4.inCnt < TOTAL_CNT || h5.inCnt < TOTAL_CNT || h6.inCnt < TOTAL_CNT) { if (h1.exception.get() != null) { throw h1.exception.get(); } if (h2.exception.get() != null) { throw h2.exception.get(); } if (h3.exception.get() != null) { throw h3.exception.get(); } if (h4.exception.get() != null) { throw h4.exception.get(); } if (h5.exception.get() != null) { throw h5.exception.get(); } if (h6.exception.get() != null) { throw h6.exception.get(); } Thread.sleep(10); } for (int i = 0; i < TOTAL_CNT; ) { final int start = i; final int end = i + ELEMS_PER_ROUNDS; i = end; ch.pipeline() .context(h6) .executor() .execute( new Runnable() { @Override public void run() { for (int j = start; j < end; j++) { ch.write(Integer.valueOf(j)); } ch.flush(); } }); } while (h1.outCnt < TOTAL_CNT || h2.outCnt < TOTAL_CNT || h3.outCnt < TOTAL_CNT || h4.outCnt < TOTAL_CNT || h5.outCnt < TOTAL_CNT || h6.outCnt < TOTAL_CNT) { if (h1.exception.get() != null) { throw h1.exception.get(); } if (h2.exception.get() != null) { throw h2.exception.get(); } if (h3.exception.get() != null) { throw h3.exception.get(); } if (h4.exception.get() != null) { throw h4.exception.get(); } if (h5.exception.get() != null) { throw h5.exception.get(); } if (h6.exception.get() != null) { throw h6.exception.get(); } Thread.sleep(10); } ch.close().sync(); } finally { l.shutdownGracefully(); e1.shutdownGracefully(); e2.shutdownGracefully(); e3.shutdownGracefully(); e4.shutdownGracefully(); e5.shutdownGracefully(); l.terminationFuture().sync(); e1.terminationFuture().sync(); e2.terminationFuture().sync(); e3.terminationFuture().sync(); e4.terminationFuture().sync(); e5.terminationFuture().sync(); } }