static void close(OioDatagramChannel channel, ChannelFuture future) { boolean connected = channel.isConnected(); boolean bound = channel.isBound(); try { channel.socket.close(); if (channel.setClosed()) { future.setSuccess(); if (connected) { // Notify the worker so it stops reading. Thread currentThread = Thread.currentThread(); Thread workerThread = channel.workerThread; if (workerThread != null && currentThread != workerThread) { workerThread.interrupt(); } fireChannelDisconnected(channel); } if (bound) { fireChannelUnbound(channel); } fireChannelClosed(channel); } else { future.setSuccess(); } } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } }
static void close(NioSocketChannel channel, ChannelFuture future) { NioWorker worker = channel.worker; boolean connected = channel.isConnected(); boolean bound = channel.isBound(); try { channel.socket.close(); worker.cancelledKeys++; if (channel.setClosed()) { future.setSuccess(); if (connected) { fireChannelDisconnected(channel); } if (bound) { fireChannelUnbound(channel); } cleanUpWriteBuffer(channel); fireChannelClosed(channel); } else { future.setSuccess(); } } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } }
private void bind(OioDatagramChannel channel, ChannelFuture future, SocketAddress localAddress) { boolean bound = false; boolean workerStarted = false; try { channel.socket.bind(localAddress); bound = true; // Fire events future.setSuccess(); fireChannelBound(channel, channel.getLocalAddress()); // Start the business. workerExecutor.execute( new IoWorkerRunnable( new ThreadRenamingRunnable( new OioDatagramWorker(channel), "Old I/O datagram worker (channelId: " + channel.getId() + ", " + channel.getLocalAddress() + ')'))); workerStarted = true; } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } finally { if (bound && !workerStarted) { OioDatagramWorker.close(channel, future); } } }
@Test public void shouldPropagateDownstreamFlushOnPipelineFutureSuccess() throws Exception { context.checking( new Expectations() { { oneOf(upstream) .handleUpstream( with(any(ChannelHandlerContext.class)), with(any(PreparationEvent.class))); oneOf(upstream) .handleUpstream( with(any(ChannelHandlerContext.class)), with(channelState(OPEN, TRUE))); oneOf(downstream) .handleDownstream( with(any(ChannelHandlerContext.class)), with(any(FlushEvent.class))); } }); channelFactory.newChannel(pipeline); ChannelFuture executionFuture = execution.getHandlerFuture(); executionFuture.setSuccess(); ChannelFuture handlerFuture = handler.getHandlerFuture(); handlerFuture.sync(); context.assertIsSatisfied(); }
/** * Will bind the DatagramSocket to the passed-in address. Every call bind will spawn a new thread * using the that basically in turn */ private void bind( final NioDatagramChannel channel, final ChannelFuture future, final InetSocketAddress address) { boolean bound = false; boolean started = false; try { // First bind the DatagramSocket the specified port. channel.getDatagramChannel().socket().bind(address); bound = true; future.setSuccess(); fireChannelBound(channel, address); channel.worker.register(channel, null); started = true; } catch (final Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } finally { if (!started && bound) { close(channel, future); } } }
static void write( OioDatagramChannel channel, ChannelFuture future, Object message, SocketAddress remoteAddress) { try { ChannelBuffer buf = (ChannelBuffer) message; int length = buf.readableBytes(); ByteBuffer nioBuf = buf.toByteBuffer(); DatagramPacket packet; if (nioBuf.hasArray()) { // Avoid copy if the buffer is backed by an array. packet = new DatagramPacket(nioBuf.array(), nioBuf.arrayOffset(), length); } else { // Otherwise it will be expensive. byte[] arrayBuf = new byte[length]; buf.getBytes(0, arrayBuf); packet = new DatagramPacket(arrayBuf, length); } if (remoteAddress != null) { packet.setSocketAddress(remoteAddress); } channel.socket.send(packet); fireWriteComplete(channel, length); future.setSuccess(); } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } }
private void connect( OioDatagramChannel channel, ChannelFuture future, SocketAddress remoteAddress) { boolean bound = channel.isBound(); boolean connected = false; boolean workerStarted = false; future.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); // Clear the cached address so that the next getRemoteAddress() call // updates the cache. channel.remoteAddress = null; try { channel.socket.connect(remoteAddress); connected = true; // Fire events. future.setSuccess(); if (!bound) { fireChannelBound(channel, channel.getLocalAddress()); } fireChannelConnected(channel, channel.getRemoteAddress()); String threadName = "Old I/O datagram worker (channelId: " + channel.getId() + ", " + channel.getLocalAddress() + " => " + channel.getRemoteAddress() + ')'; if (!bound) { // Start the business. workerExecutor.execute( new IoWorkerRunnable( new ThreadRenamingRunnable(new OioDatagramWorker(channel), threadName))); } else { // Worker started by bind() - just rename. Thread workerThread = channel.workerThread; if (workerThread != null) { try { workerThread.setName(threadName); } catch (SecurityException e) { // Ignore. } } } workerStarted = true; } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } finally { if (connected && !workerStarted) { OioDatagramWorker.close(channel, future); } } }
private void close(NioDatagramChannel channel, ChannelFuture future) { try { channel.getDatagramChannel().socket().close(); if (channel.setClosed()) { future.setSuccess(); if (channel.isBound()) { fireChannelUnbound(channel); } fireChannelClosed(channel); } else { future.setSuccess(); } } catch (final Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } }
private void setHandshakeSuccess(Channel channel) { synchronized (handshakeLock) { handshaking = false; handshaken = true; if (handshakeFuture == null) { handshakeFuture = future(channel); } } handshakeFuture.setSuccess(); }
public void run() { SocketAddress localAddress = channel.getLocalAddress(); SocketAddress remoteAddress = channel.getRemoteAddress(); if (localAddress == null || remoteAddress == null) { if (future != null) { future.setFailure(new ClosedChannelException()); } close(channel, succeededFuture(channel)); return; } try { if (server) { channel.channel.configureBlocking(false); } synchronized (channel.interestOpsLock) { channel.channel.register(selector, channel.getRawInterestOps(), channel); } if (future != null) { channel.setConnected(); future.setSuccess(); } if (server || !((NioClientSocketChannel) channel).boundManually) { fireChannelBound(channel, localAddress); } fireChannelConnected(channel, remoteAddress); } catch (IOException e) { if (future != null) { future.setFailure(e); } close(channel, succeededFuture(channel)); if (!(e instanceof ClosedChannelException)) { throw new ChannelException("Failed to register a socket to the selector.", e); } } }
private void connect( NioDatagramChannel channel, ChannelFuture future, SocketAddress remoteAddress) { boolean bound = channel.isBound(); boolean connected = false; boolean workerStarted = false; future.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); // Clear the cached address so that the next getRemoteAddress() call // updates the cache. channel.remoteAddress = null; try { channel.getDatagramChannel().connect(remoteAddress); connected = true; // Fire events. future.setSuccess(); if (!bound) { fireChannelBound(channel, channel.getLocalAddress()); } fireChannelConnected(channel, channel.getRemoteAddress()); if (!bound) { channel.worker.register(channel, future); } workerStarted = true; } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } finally { if (connected && !workerStarted) { channel.worker.close(channel, future); } } }
static void setInterestOps(OioDatagramChannel channel, ChannelFuture future, int interestOps) { // Override OP_WRITE flag - a user cannot change this flag. interestOps &= ~Channel.OP_WRITE; interestOps |= channel.getInterestOps() & Channel.OP_WRITE; boolean changed = false; try { if (channel.getInterestOps() != interestOps) { if ((interestOps & Channel.OP_READ) != 0) { channel.setInterestOpsNow(Channel.OP_READ); } else { channel.setInterestOpsNow(Channel.OP_NONE); } changed = true; } future.setSuccess(); if (changed) { synchronized (channel.interestOpsLock) { channel.setInterestOpsNow(interestOps); // Notify the worker so it stops or continues reading. Thread currentThread = Thread.currentThread(); Thread workerThread = channel.workerThread; if (workerThread != null && currentThread != workerThread) { workerThread.interrupt(); } } fireChannelInterestChanged(channel); } } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } }
static void disconnect(OioDatagramChannel channel, ChannelFuture future) { boolean connected = channel.isConnected(); try { channel.socket.disconnect(); future.setSuccess(); if (connected) { // Update the worker's thread name to reflect the state change. Thread workerThread = channel.workerThread; if (workerThread != null) { try { workerThread.setName("Old I/O datagram worker (" + channel + ')'); } catch (SecurityException e) { // Ignore. } } // Notify. fireChannelDisconnected(channel); } } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } }
@Test public void shouldPropagateDownstreamMessageOnPipelineFutureSuccess() throws Exception { final ChannelBuffer[] expectedArr = new ChannelBuffer[3]; expectedArr[0] = wrappedBuffer(new byte[] {0x01, 0x02, 0x03}); expectedArr[1] = copiedBuffer("Hello, world", UTF_8); expectedArr[2] = wrappedBuffer(new byte[] {0x01, 0x02, 0x03}); final ChannelBuffer expected = masker.applyMask(wrappedBuffer(expectedArr)); context.checking( new Expectations() { { oneOf(upstream) .handleUpstream( with(any(ChannelHandlerContext.class)), with(any(PreparationEvent.class))); oneOf(upstream) .handleUpstream( with(any(ChannelHandlerContext.class)), with(channelState(OPEN, TRUE))); oneOf(downstream) .handleDownstream(with(any(ChannelHandlerContext.class)), with(message(expected))); oneOf(upstream) .handleUpstream( with(any(ChannelHandlerContext.class)), with(any(WriteCompletionEvent.class))); } }); expression.setValue(environment, new byte[] {0x01, 0x02, 0x03}); channelFactory.newChannel(pipeline); ChannelFuture executionFuture = execution.getHandlerFuture(); executionFuture.setSuccess(); ChannelFuture handlerFuture = handler.getHandlerFuture(); handlerFuture.sync(); context.assertIsSatisfied(); }
public ChannelFuture abort() { abortedFuture.setSuccess(); return finishedFuture; }
static void setInterestOps(NioSocketChannel channel, ChannelFuture future, int interestOps) { boolean changed = false; try { // interestOps can change at any time and at any thread. // Acquire a lock to avoid possible race condition. synchronized (channel.interestOpsLock) { NioWorker worker = channel.worker; Selector selector = worker.selector; SelectionKey key = channel.socket.keyFor(selector); if (key == null || selector == null) { // Not registered to the worker yet. // Set the rawInterestOps immediately; RegisterTask will pick it up. channel.setRawInterestOpsNow(interestOps); return; } // Override OP_WRITE flag - a user cannot change this flag. interestOps &= ~Channel.OP_WRITE; interestOps |= channel.getRawInterestOps() & Channel.OP_WRITE; switch (CONSTRAINT_LEVEL) { case 0: if (channel.getRawInterestOps() != interestOps) { key.interestOps(interestOps); if (Thread.currentThread() != worker.thread && worker.wakenUp.compareAndSet(false, true)) { selector.wakeup(); } changed = true; } break; case 1: case 2: if (channel.getRawInterestOps() != interestOps) { if (Thread.currentThread() == worker.thread) { key.interestOps(interestOps); changed = true; } else { worker.selectorGuard.readLock().lock(); try { if (worker.wakenUp.compareAndSet(false, true)) { selector.wakeup(); } key.interestOps(interestOps); changed = true; } finally { worker.selectorGuard.readLock().unlock(); } } } break; default: throw new Error(); } } future.setSuccess(); if (changed) { channel.setRawInterestOpsNow(interestOps); fireChannelInterestChanged(channel); } } catch (CancelledKeyException e) { // setInterestOps() was called on a closed channel. ClosedChannelException cce = new ClosedChannelException(); future.setFailure(cce); fireExceptionCaught(channel, cce); } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } }