Beispiel #1
0
 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);
   }
 }
  /**
   * 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);
      }
    }
  }
  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);
      }
    }
  }
Beispiel #4
0
  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);
    }
  }
Beispiel #5
0
    @Override
    public void run(Timeout timeout) throws Exception {
      if (timeout.isCancelled()) {
        return;
      }

      if (!ctx.getChannel().isOpen()) {
        return;
      }

      State state = (State) ctx.getAttachment();
      long currentTime = System.currentTimeMillis();
      long nextDelay = timeoutMillis - (currentTime - state.lastReadTime);
      if (nextDelay <= 0) {
        // Read timed out - set a new timeout and notify the callback.
        state.timeout = timer.newTimeout(this, timeoutMillis, TimeUnit.MILLISECONDS);
        try {
          // FIXME This should be called from an I/O thread.
          //       To be fixed in Netty 4.
          readTimedOut(ctx);
        } catch (Throwable t) {
          fireExceptionCaught(ctx, t);
        }
      } else {
        // Read occurred before the timeout - set a new timeout with shorter delay.
        state.timeout = timer.newTimeout(this, nextDelay, TimeUnit.MILLISECONDS);
      }
    }
Beispiel #6
0
  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);
      }
    }
  }
  @Override
  public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    HttpChildChannel httpChildChannel = this.httpChildChannel;
    if (httpChildChannel != null) {

      this.httpChildChannel = null;

      switch (httpChildChannel.readState()) {
        case UPGRADED:
          if (httpChildChannel.setReadClosed()) {
            fireChannelDisconnected(httpChildChannel);
            fireChannelUnbound(httpChildChannel);
            fireChannelClosed(httpChildChannel);
          }
          break;
        case CONTENT_COMPLETE:
          break;
        default:
          ChannelException exception = new ChannelException("Channel closed unexpectedly");
          exception.fillInStackTrace();
          fireExceptionCaught(httpChildChannel, exception);
          break;
      }

      switch (httpChildChannel.writeState()) {
        case UPGRADED:
        case CONTENT_CLOSE:
          if (httpChildChannel.setWriteClosed()) {
            fireChannelDisconnected(httpChildChannel);
            fireChannelUnbound(httpChildChannel);
            fireChannelClosed(httpChildChannel);
          }
          break;
        case CONTENT_COMPLETE:
          break;
        default:
          ChannelException exception = new ChannelException("Channel closed unexpectedly");
          exception.fillInStackTrace();
          fireExceptionCaught(httpChildChannel, exception);
          break;
      }
    }
  }
  @Override
  protected boolean read(SelectionKey k) {
    final SocketChannel ch = (SocketChannel) k.channel();
    final NioSocketChannel channel = (NioSocketChannel) k.attachment();

    final ReceiveBufferSizePredictor predictor =
        channel.getConfig().getReceiveBufferSizePredictor();
    final int predictedRecvBufSize = predictor.nextReceiveBufferSize();

    int ret = 0;
    int readBytes = 0;
    boolean failure = true;

    ByteBuffer bb = recvBufferPool.acquire(predictedRecvBufSize);
    try {
      while ((ret = ch.read(bb)) > 0) {
        readBytes += ret;
        if (!bb.hasRemaining()) {
          break;
        }
      }
      failure = false;
    } catch (ClosedChannelException e) {
      // Can happen, and does not need a user attention.
    } catch (Throwable t) {
      fireExceptionCaught(channel, t);
    }

    if (readBytes > 0) {
      bb.flip();

      final ChannelBufferFactory bufferFactory = channel.getConfig().getBufferFactory();
      final ChannelBuffer buffer = bufferFactory.getBuffer(readBytes);
      buffer.setBytes(0, bb);
      buffer.writerIndex(readBytes);

      recvBufferPool.release(bb);

      // Update the predictor.
      predictor.previousReceiveBufferSize(readBytes);

      // Fire the event.
      fireMessageReceived(channel, buffer);
    } else {
      recvBufferPool.release(bb);
    }

    if (ret < 0 || failure) {
      k.cancel(); // Some JDK implementations run into an infinite loop without this.
      close(channel, succeededFuture(channel));
      return false;
    }

    return true;
  }
Beispiel #10
0
 @Override
 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
   if (e.getMessage() instanceof List) {
     @SuppressWarnings("unchecked")
     List<OFMessage> msglist = (List<OFMessage>) e.getMessage();
     for (OFMessage ofm : msglist) {
       try {
         // Do the actual packet processing
         state.processOFMessage(ofm);
       } catch (Exception ex) {
         // We are the last handler in the stream, so run the
         // exception through the channel again by passing in
         // ctx.getChannel().
         Channels.fireExceptionCaught(ctx.getChannel(), ex);
       }
     }
   } else {
     Channels.fireExceptionCaught(
         ctx.getChannel(), new AssertionError("Message received from channel is not a list"));
   }
 }
Beispiel #11
0
  public void run() {
    channel.workerThread = Thread.currentThread();
    final MulticastSocket socket = channel.socket;

    while (channel.isOpen()) {
      synchronized (channel.interestOpsLock) {
        while (!channel.isReadable()) {
          try {
            // notify() is not called at all.
            // close() and setInterestOps() calls Thread.interrupt()
            channel.interestOpsLock.wait();
          } catch (InterruptedException e) {
            if (!channel.isOpen()) {
              break;
            }
          }
        }
      }

      ReceiveBufferSizePredictor predictor = channel.getConfig().getReceiveBufferSizePredictor();

      byte[] buf = new byte[predictor.nextReceiveBufferSize()];
      DatagramPacket packet = new DatagramPacket(buf, buf.length);
      try {
        socket.receive(packet);
      } catch (InterruptedIOException e) {
        // Can happen on interruption.
        // Keep receiving unless the channel is closed.
        continue;
      } catch (Throwable t) {
        if (!channel.socket.isClosed()) {
          fireExceptionCaught(channel, t);
        }
        break;
      }

      fireMessageReceived(
          channel,
          channel.getConfig().getBufferFactory().getBuffer(buf, 0, packet.getLength()),
          packet.getSocketAddress());
    }

    // Setting the workerThread to null will prevent any channel
    // operations from interrupting this thread from now on.
    channel.workerThread = null;

    // Clean up.
    close(channel, succeededFuture(channel));
  }
Beispiel #12
0
  private static void cleanUpWriteBuffer(NioSocketChannel channel) {
    Exception cause = null;
    boolean fireExceptionCaught = false;

    // Clean up the stale messages in the write buffer.
    synchronized (channel.writeLock) {
      MessageEvent evt = channel.currentWriteEvent;
      if (evt != null) {
        channel.currentWriteEvent = null;
        channel.currentWriteIndex = 0;

        // Create the exception only once to avoid the excessive overhead
        // caused by fillStackTrace.
        if (channel.isOpen()) {
          cause = new NotYetConnectedException();
        } else {
          cause = new ClosedChannelException();
        }
        evt.getFuture().setFailure(cause);
        fireExceptionCaught = true;
      }

      Queue<MessageEvent> writeBuffer = channel.writeBuffer;
      if (!writeBuffer.isEmpty()) {
        // Create the exception only once to avoid the excessive overhead
        // caused by fillStackTrace.
        if (cause == null) {
          if (channel.isOpen()) {
            cause = new NotYetConnectedException();
          } else {
            cause = new ClosedChannelException();
          }
        }

        for (; ; ) {
          evt = writeBuffer.poll();
          if (evt == null) {
            break;
          }
          evt.getFuture().setFailure(cause);
          fireExceptionCaught = true;
        }
      }
    }

    if (fireExceptionCaught) {
      fireExceptionCaught(channel, cause);
    }
  }
  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
    if (httpChildChannel != null) {
      HttpChildChannel httpChildChannel = this.httpChildChannel;
      this.httpChildChannel = null;

      if (httpChildChannel.setReadClosed() || httpChildChannel.setWriteClosed()) {
        fireExceptionCaught(httpChildChannel, e.getCause());
        fireChannelClosed(httpChildChannel);
      }
    }

    Channel channel = ctx.getChannel();
    channel.close();
  }
Beispiel #14
0
  private void handleRenegotiation(HandshakeStatus handshakeStatus) {
    if (handshakeStatus == HandshakeStatus.NOT_HANDSHAKING
        || handshakeStatus == HandshakeStatus.FINISHED) {
      // Not handshaking
      return;
    }

    if (!handshaken) {
      // Not renegotiation
      return;
    }

    final boolean renegotiate;
    synchronized (handshakeLock) {
      if (handshaking) {
        // Renegotiation in progress or failed already.
        // i.e. Renegotiation check has been done already below.
        return;
      }

      if (engine.isInboundDone() || engine.isOutboundDone()) {
        // Not handshaking but closing.
        return;
      }

      if (isEnableRenegotiation()) {
        // Continue renegotiation.
        renegotiate = true;
      } else {
        // Do not renegotiate.
        renegotiate = false;
        // Prevent reentrance of this method.
        handshaking = true;
      }
    }

    if (renegotiate) {
      // Renegotiate.
      handshake();
    } else {
      // Raise an exception.
      fireExceptionCaught(
          ctx, new SSLException("renegotiation attempted by peer; " + "closing the connection"));

      // Close the connection to stop renegotiation.
      Channels.close(ctx, succeededFuture(ctx.getChannel()));
    }
  }
 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);
   }
 }
Beispiel #16
0
  private static boolean read(SelectionKey k) {
    ScatteringByteChannel ch = (ScatteringByteChannel) k.channel();
    NioSocketChannel channel = (NioSocketChannel) k.attachment();

    ReceiveBufferSizePredictor predictor = channel.getConfig().getReceiveBufferSizePredictor();
    ChannelBufferFactory bufferFactory = channel.getConfig().getBufferFactory();

    ChannelBuffer buffer = bufferFactory.getBuffer(predictor.nextReceiveBufferSize());

    int ret = 0;
    int readBytes = 0;
    boolean failure = true;
    try {
      while ((ret = buffer.writeBytes(ch, buffer.writableBytes())) > 0) {
        readBytes += ret;
        if (!buffer.writable()) {
          break;
        }
      }
      failure = false;
    } catch (AsynchronousCloseException e) {
      // Can happen, and does not need a user attention.
    } catch (Throwable t) {
      fireExceptionCaught(channel, t);
    }

    if (readBytes > 0) {
      // Update the predictor.
      predictor.previousReceiveBufferSize(readBytes);

      // Fire the event.
      fireMessageReceived(channel, buffer);
    }

    if (ret < 0 || failure) {
      close(k);
      return false;
    }

    return true;
  }
  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);
      }
    }
  }
Beispiel #18
0
  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);
    }
  }
Beispiel #19
0
  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);
    }
  }
Beispiel #20
0
  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);
    }
  }
Beispiel #21
0
  private static void writeNow(NioSocketChannel channel, int writeSpinCount) {

    boolean open = true;
    boolean addOpWrite = false;
    boolean removeOpWrite = false;

    MessageEvent evt;
    ChannelBuffer buf;
    int bufIdx;
    int writtenBytes = 0;

    Queue<MessageEvent> writeBuffer = channel.writeBuffer;
    synchronized (channel.writeLock) {
      channel.inWriteNowLoop = true;
      evt = channel.currentWriteEvent;
      for (; ; ) {
        if (evt == null) {
          evt = writeBuffer.poll();
          if (evt == null) {
            channel.currentWriteEvent = null;
            removeOpWrite = true;
            break;
          }

          evt = consolidateComposite(evt);
          buf = (ChannelBuffer) evt.getMessage();
          bufIdx = buf.readerIndex();
        } else {
          buf = (ChannelBuffer) evt.getMessage();
          bufIdx = channel.currentWriteIndex;
        }

        try {
          for (int i = writeSpinCount; i > 0; i--) {
            int localWrittenBytes =
                buf.getBytes(bufIdx, channel.socket, buf.writerIndex() - bufIdx);

            if (localWrittenBytes != 0) {
              bufIdx += localWrittenBytes;
              writtenBytes += localWrittenBytes;
              break;
            }
          }

          if (bufIdx == buf.writerIndex()) {
            // Successful write - proceed to the next message.
            channel.currentWriteEvent = null;
            evt.getFuture().setSuccess();
            evt = null;
          } else {
            // Not written fully - perhaps the kernel buffer is full.
            channel.currentWriteEvent = evt;
            channel.currentWriteIndex = bufIdx;
            addOpWrite = true;
            break;
          }
        } catch (AsynchronousCloseException e) {
          // Doesn't need a user attention - ignore.
          channel.currentWriteEvent = evt;
          channel.currentWriteIndex = bufIdx;
        } catch (Throwable t) {
          channel.currentWriteEvent = null;
          evt.getFuture().setFailure(t);
          evt = null;
          fireExceptionCaught(channel, t);
          if (t instanceof IOException) {
            open = false;
            close(channel, succeededFuture(channel));
          }
        }
      }
      channel.inWriteNowLoop = false;
    }

    fireWriteComplete(channel, writtenBytes);

    if (open) {
      if (addOpWrite) {
        setOpWrite(channel);
      } else if (removeOpWrite) {
        clearOpWrite(channel);
      }
    }
  }
Beispiel #22
0
 protected void readTimedOut(ChannelHandlerContext ctx) throws Exception {
   Channels.fireExceptionCaught(ctx, EXCEPTION);
 }