@Test
  public void testLocalAddressReuse() throws Exception {

    for (int i = 0; i < 2; i++) {
      LocalAddress addr = new LocalAddress(LOCAL_ADDR_ID);
      Bootstrap cb = new Bootstrap();
      ServerBootstrap sb = new ServerBootstrap();

      cb.eventLoop(new LocalEventLoop())
          .channel(new LocalChannel())
          .remoteAddress(addr)
          .handler(new TestHandler());

      sb.eventLoop(new LocalEventLoop(), new LocalEventLoop())
          .channel(new LocalServerChannel())
          .localAddress(addr)
          .childHandler(
              new ChannelInitializer<LocalChannel>() {
                @Override
                public void initChannel(LocalChannel ch) throws Exception {
                  ch.pipeline().addLast(new TestHandler());
                }
              });

      // Start server
      Channel sc = sb.bind().sync().channel();

      // Connect to the server
      Channel cc = cb.connect().sync().channel();

      // Send a message event up the pipeline.
      cc.pipeline().inboundMessageBuffer().add("Hello, World");
      cc.pipeline().fireInboundBufferUpdated();

      // Close the channel
      cc.close().sync();

      sb.shutdown();
      cb.shutdown();

      sc.closeFuture().sync();

      Assert.assertTrue(
          String.format(
              "Expected null, got channel '%s' for local address '%s'",
              LocalChannelRegistry.get(addr), addr),
          LocalChannelRegistry.get(addr) == null);
    }
  }
 @Override
 protected void doClose() throws Exception {
   if (state <= 1) {
     // Update all internal state before the closeFuture is notified.
     LocalChannelRegistry.unregister(localAddress);
     localAddress = null;
     state = 2;
   }
 }
Example #3
0
    @Override
    public void connect(
        final SocketAddress remoteAddress,
        SocketAddress localAddress,
        final ChannelPromise promise) {
      if (!promise.setUncancellable() || !ensureOpen(promise)) {
        return;
      }

      if (state == State.CONNECTED) {
        Exception cause = new AlreadyConnectedException();
        safeSetFailure(promise, cause);
        pipeline().fireExceptionCaught(cause);
        return;
      }

      if (connectPromise != null) {
        throw new ConnectionPendingException();
      }

      connectPromise = promise;

      if (state != State.BOUND) {
        // Not bound yet and no localAddress specified - get one.
        if (localAddress == null) {
          localAddress = new LocalAddress(LocalChannel.this);
        }
      }

      if (localAddress != null) {
        try {
          doBind(localAddress);
        } catch (Throwable t) {
          safeSetFailure(promise, t);
          close(voidPromise());
          return;
        }
      }

      Channel boundChannel = LocalChannelRegistry.get(remoteAddress);
      if (!(boundChannel instanceof LocalServerChannel)) {
        Exception cause = new ChannelException("connection refused");
        safeSetFailure(promise, cause);
        close(voidPromise());
        return;
      }

      LocalServerChannel serverChannel = (LocalServerChannel) boundChannel;
      peer = serverChannel.serve(LocalChannel.this);
    }
Example #4
0
  @Override
  protected void doClose() throws Exception {
    if (state > 2) {
      // Closed already
      return;
    }

    if (parent() == null) {
      LocalChannelRegistry.unregister(localAddress);
    }
    localAddress = null;
    state = 3;
    if (peer.isActive()) {
      peer.unsafe().close(peer.unsafe().voidFuture());
      peer = null;
    }
  }
Example #5
0
  @Override
  protected void doClose() throws Exception {
    if (state != State.CLOSED) {
      // Update all internal state before the closeFuture is notified.
      if (localAddress != null) {
        if (parent() == null) {
          LocalChannelRegistry.unregister(localAddress);
        }
        localAddress = null;
      }
      state = State.CLOSED;
    }

    final LocalChannel peer = this.peer;
    if (peer != null && peer.isActive()) {
      // Need to execute the close in the correct EventLoop
      // See https://github.com/netty/netty/issues/1777
      EventLoop eventLoop = peer.eventLoop();

      // Also check if the registration was not done yet. In this case we submit the close to the
      // EventLoop
      // to make sure it is run after the registration completes.
      //
      // See https://github.com/netty/netty/issues/2144
      if (eventLoop.inEventLoop() && !registerInProgress) {
        peer.unsafe().close(unsafe().voidPromise());
      } else {
        peer.eventLoop()
            .execute(
                new Runnable() {
                  @Override
                  public void run() {
                    peer.unsafe().close(unsafe().voidPromise());
                  }
                });
      }
      this.peer = null;
    }
  }
Example #6
0
 @Override
 protected void doBind(SocketAddress localAddress) throws Exception {
   this.localAddress = LocalChannelRegistry.register(this, this.localAddress, localAddress);
   state = State.BOUND;
 }
Example #7
0
    @Override
    public void connect(
        final SocketAddress remoteAddress, SocketAddress localAddress, final ChannelFuture future) {
      if (eventLoop().inEventLoop()) {
        if (!ensureOpen(future)) {
          return;
        }

        if (state == 2) {
          Exception cause = new AlreadyConnectedException();
          future.setFailure(cause);
          pipeline().fireExceptionCaught(cause);
          return;
        }

        if (connectFuture != null) {
          throw new ConnectionPendingException();
        }

        connectFuture = future;

        if (state != 1) {
          // Not bound yet and no localAddress specified - get one.
          if (localAddress == null) {
            localAddress = new LocalAddress(LocalChannel.this);
          }
        }

        if (localAddress != null) {
          try {
            doBind(localAddress);
          } catch (Throwable t) {
            future.setFailure(t);
            pipeline().fireExceptionCaught(t);
            close(voidFuture());
            return;
          }
        }

        Channel boundChannel = LocalChannelRegistry.get(remoteAddress);
        if (!(boundChannel instanceof LocalServerChannel)) {
          Exception cause = new ChannelException("connection refused");
          future.setFailure(cause);
          pipeline().fireExceptionCaught(cause);
          close(voidFuture());
          return;
        }

        LocalServerChannel serverChannel = (LocalServerChannel) boundChannel;
        peer = serverChannel.serve(LocalChannel.this);
      } else {
        final SocketAddress localAddress0 = localAddress;
        eventLoop()
            .execute(
                new Runnable() {
                  @Override
                  public void run() {
                    connect(remoteAddress, localAddress0, future);
                  }
                });
      }
    }