@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 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); }
@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); } }); } }