@Override
  protected boolean read(final SelectionKey key) {
    final NioDatagramChannel channel = (NioDatagramChannel) key.attachment();
    ReceiveBufferSizePredictor predictor = channel.getConfig().getReceiveBufferSizePredictor();
    final ChannelBufferFactory bufferFactory = channel.getConfig().getBufferFactory();
    final DatagramChannel nioChannel = (DatagramChannel) key.channel();

    // Allocating a non-direct buffer with a max udp packge size.
    // Would using a direct buffer be more efficient or would this negatively
    // effect performance, as direct buffer allocation has a higher upfront cost
    // where as a ByteBuffer is heap allocated.
    final ByteBuffer byteBuffer =
        ByteBuffer.allocate(predictor.nextReceiveBufferSize())
            .order(bufferFactory.getDefaultOrder());

    boolean failure = true;
    SocketAddress remoteAddress = null;
    try {
      // Receive from the channel in a non blocking mode. We have already been notified that
      // the channel is ready to receive.
      remoteAddress = nioChannel.receive(byteBuffer);
      failure = false;
    } catch (ClosedChannelException e) {
      // Can happen, and does not need a user attention.
    } catch (Throwable t) {
      fireExceptionCaught(channel, t);
    }

    if (remoteAddress != null) {
      // Flip the buffer so that we can wrap it.
      byteBuffer.flip();

      int readBytes = byteBuffer.remaining();
      if (readBytes > 0) {
        // Update the predictor.
        predictor.previousReceiveBufferSize(readBytes);

        // Notify the interested parties about the newly arrived message.
        fireMessageReceived(channel, bufferFactory.getBuffer(byteBuffer), remoteAddress);
      }
    }

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

    return true;
  }
Example #2
0
  private boolean read(SelectionKey k) {
    final SctpChannelImpl channel = (SctpChannelImpl) k.attachment();

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

    boolean messageReceived = false;
    boolean failure = true;
    MessageInfo messageInfo = null;

    ByteBuffer bb = recvBufferPool.acquire(predictedRecvBufSize);
    try {
      messageInfo = channel.channel.receive(bb, null, notificationHandler);
      if (messageInfo != null) {
        messageReceived = true;
        if (!messageInfo.isUnordered()) {
          failure = false;
        } else {
          if (logger.isErrorEnabled()) {
            logger.error("Received unordered SCTP Packet");
          }
          failure = true;
        }
      } else {
        messageReceived = false;
        failure = false;
      }
    } catch (ClosedChannelException e) {
      // Can happen, and does not need a user attention.
    } catch (Throwable t) {
      fireExceptionCaught(channel, t);
    }

    if (messageReceived) {
      bb.flip();

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

      recvBufferPool.release(bb);

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

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

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

    return true;
  }