@Override
  protected int doReadMessages(List<Object> buf) throws Exception {
    DatagramChannel ch = javaChannel();
    DatagramChannelConfig config = config();
    RecvByteBufAllocator.Handle allocHandle = this.allocHandle;
    if (allocHandle == null) {
      this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle();
    }
    ByteBuf data = allocHandle.allocate(config.getAllocator());
    boolean free = true;
    try {
      ByteBuffer nioData = data.internalNioBuffer(data.writerIndex(), data.writableBytes());
      int pos = nioData.position();
      InetSocketAddress remoteAddress = (InetSocketAddress) ch.receive(nioData);
      if (remoteAddress == null) {
        return 0;
      }

      int readBytes = nioData.position() - pos;
      data.writerIndex(data.writerIndex() + readBytes);
      allocHandle.record(readBytes);

      buf.add(new DatagramPacket(data, localAddress(), remoteAddress));
      free = false;
      return 1;
    } catch (Throwable cause) {
      PlatformDependent.throwException(cause);
      return -1;
    } finally {
      if (free) {
        data.release();
      }
    }
  }
示例#2
0
  @Override
  protected int doReadMessages(List<Object> buf) throws Exception {
    SctpChannel ch = javaChannel();

    RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
    ByteBuf buffer = allocHandle.allocate(config().getAllocator());
    boolean free = true;
    try {
      ByteBuffer data = buffer.internalNioBuffer(buffer.writerIndex(), buffer.writableBytes());
      int pos = data.position();

      MessageInfo messageInfo = ch.receive(data, null, notificationHandler);
      if (messageInfo == null) {
        return 0;
      }
      buf.add(
          new SctpMessage(
              messageInfo, buffer.writerIndex(buffer.writerIndex() + data.position() - pos)));
      free = false;
      return 1;
    } catch (Throwable cause) {
      PlatformDependent.throwException(cause);
      return -1;
    } finally {
      int bytesRead = buffer.readableBytes();
      allocHandle.record(bytesRead);
      if (free) {
        buffer.release();
      }
    }
  }
    @Override
    public void handleEvent(ConduitStreamSourceChannel channel) {
      final ChannelConfig config = config();
      final ChannelPipeline pipeline = pipeline();
      final ByteBufAllocator allocator = config.getAllocator();
      final int maxMessagesPerRead = config.getMaxMessagesPerRead();
      RecvByteBufAllocator.Handle allocHandle = this.allocHandle;
      if (allocHandle == null) {
        this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle();
      }
      if (!config.isAutoRead()) {
        removeReadOp(channel);
      }

      ByteBuf byteBuf = null;
      int messages = 0;
      boolean close = false;
      try {
        do {
          byteBuf = allocHandle.allocate(allocator);
          int localReadAmount = byteBuf.writeBytes(channel, byteBuf.writableBytes());
          if (localReadAmount <= 0) {
            // not was read release the buffer
            byteBuf.release();
            close = localReadAmount < 0;
            break;
          }
          pipeline.fireChannelRead(byteBuf);
          byteBuf = null;
          allocHandle.record(localReadAmount);
        } while (++messages < maxMessagesPerRead);

        pipeline.fireChannelReadComplete();

        if (close) {
          closeOnRead();
          close = false;
        }
      } catch (Throwable t) {
        handleReadException(pipeline, byteBuf, t, close);
      }
    }
    @Override
    void epollInReady() {
      final ChannelConfig config = config();
      final ChannelPipeline pipeline = pipeline();
      final ByteBufAllocator allocator = config.getAllocator();
      RecvByteBufAllocator.Handle allocHandle = this.allocHandle;
      if (allocHandle == null) {
        this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle();
      }

      ByteBuf byteBuf = null;
      boolean close = false;
      try {
        int byteBufCapacity = allocHandle.guess();
        int totalReadAmount = 0;
        for (; ; ) {
          // we use a direct buffer here as the native implementations only be able
          // to handle direct buffers.
          byteBuf = allocator.directBuffer(byteBufCapacity);
          int writable = byteBuf.writableBytes();
          int localReadAmount = doReadBytes(byteBuf);
          if (localReadAmount <= 0) {
            // not was read release the buffer
            byteBuf.release();
            close = localReadAmount < 0;
            break;
          }
          readPending = false;
          pipeline.fireChannelRead(byteBuf);
          byteBuf = null;

          if (totalReadAmount >= Integer.MAX_VALUE - localReadAmount) {
            allocHandle.record(totalReadAmount);

            // Avoid overflow.
            totalReadAmount = localReadAmount;
          } else {
            totalReadAmount += localReadAmount;
          }

          if (localReadAmount < writable) {
            // Read less than what the buffer can hold,
            // which might mean we drained the recv buffer completely.
            break;
          }
        }
        pipeline.fireChannelReadComplete();
        allocHandle.record(totalReadAmount);

        if (close) {
          closeOnRead(pipeline);
          close = false;
        }
      } catch (Throwable t) {
        boolean closed = handleReadException(pipeline, byteBuf, t, close);
        if (!closed) {
          // trigger a read again as there may be something left to read and because of epoll ET we
          // will not get notified again until we read everything from the socket
          eventLoop()
              .execute(
                  new Runnable() {
                    @Override
                    public void run() {
                      epollInReady();
                    }
                  });
        }
      } finally {
        // Check if there is a readPending which was not processed yet.
        // This could be for two reasons:
        // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...)
        // method
        // * The user called Channel.read() or ChannelHandlerContext.read() in
        // channelReadComplete(...) method
        //
        // See https://github.com/netty/netty/issues/2254
        if (!config.isAutoRead() && !readPending) {
          clearEpollIn0();
        }
      }
    }