@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());
  }
示例#4
0
  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();
            }
          }
        });
  }
示例#6
0
 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);
              }
            });
  }
示例#11
0
 @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) {
                  }
                }
              });
    }
  }
示例#14
0
 @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);
     }
   }
 }
示例#15
0
  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();
    }
  }