예제 #1
0
  @Override
  protected int doReadMessages(List<Object> buf) throws Exception {
    DatagramChannel ch = javaChannel();
    DatagramChannelConfig config = config();
    RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();

    ByteBuf data = allocHandle.allocate(config.getAllocator());
    allocHandle.attemptedBytesRead(data.writableBytes());
    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;
      }

      allocHandle.lastBytesRead(nioData.position() - pos);
      buf.add(
          new DatagramPacket(
              data.writerIndex(data.writerIndex() + allocHandle.lastBytesRead()),
              localAddress(),
              remoteAddress));
      free = false;
      return 1;
    } catch (Throwable cause) {
      PlatformDependent.throwException(cause);
      return -1;
    } finally {
      if (free) {
        data.release();
      }
    }
  }
예제 #2
0
 private SSLEngineResult unwrap(
     SSLEngine engine, ByteBuf in, int readerIndex, int len, ByteBuf out) throws SSLException {
   int nioBufferCount = in.nioBufferCount();
   int writerIndex = out.writerIndex();
   final SSLEngineResult result;
   if (engine instanceof OpenSslEngine && nioBufferCount > 1) {
     /**
      * If {@link OpenSslEngine} is in use, we can use a special {@link
      * OpenSslEngine#unwrap(ByteBuffer[], ByteBuffer[])} method that accepts multiple {@link
      * ByteBuffer}s without additional memory copies.
      */
     OpenSslEngine opensslEngine = (OpenSslEngine) engine;
     try {
       singleBuffer[0] = toByteBuffer(out, writerIndex, out.writableBytes());
       result = opensslEngine.unwrap(in.nioBuffers(readerIndex, len), singleBuffer);
       out.writerIndex(writerIndex + result.bytesProduced());
     } finally {
       singleBuffer[0] = null;
     }
   } else {
     result =
         engine.unwrap(
             toByteBuffer(in, readerIndex, len),
             toByteBuffer(out, writerIndex, out.writableBytes()));
   }
   out.writerIndex(writerIndex + result.bytesProduced());
   return result;
 }
예제 #3
0
 @Override
 public ByteBuf translateFrame(ByteBuf readBuffer)
     throws LimitExedeedException, InvalidDataException {
   while (readBuffer.isReadable()) {
     switch (status) {
       case STATUS_H:
         h = readBuffer.readByte();
         status = STATUS_L;
         break;
       case STATUS_L:
         l = readBuffer.readByte();
         final int blen =
             Protocol.order == ByteOrder.BIG_ENDIAN
                 ? (0x0000ff00 & (h << 8)) | (0x000000ff & l)
                 : (0x0000ff00 & (l << 8)) | (0x000000ff & h);
         if (context != null) {
           if (blen <= 0 || blen > maxFrameSize) {
             throw new LimitExedeedException("帧长度非法:" + h + "/" + l + ":" + blen);
           }
         }
         incompleteframe = PooledByteBufAllocator.DEFAULT.buffer(blen + 16 + 2);
         incompleteframe = incompleteframe.order(Protocol.order);
         incompleteframe.writeShort(blen);
         status = STATUS_C;
         break;
       case STATUS_C:
         int len = incompleteframe.writableBytes() - 16;
         len = len < readBuffer.readableBytes() ? len : readBuffer.readableBytes();
         // incompleteframe.writeBytes(readBuffer, len);
         if (readBuffer.hasMemoryAddress()) {
           PlatformDependent.copyMemory(
               readBuffer.memoryAddress() + readBuffer.readerIndex(),
               incompleteframe.memoryAddress() + incompleteframe.writerIndex(),
               len);
         } else if (readBuffer.hasArray()) {
           PlatformDependent.copyMemory(
               readBuffer.array(),
               readBuffer.arrayOffset() + readBuffer.readerIndex(),
               incompleteframe.memoryAddress() + incompleteframe.writerIndex(),
               len);
         }
         incompleteframe.writerIndex(incompleteframe.writerIndex() + len);
         readBuffer.readerIndex(readBuffer.readerIndex() + len);
         if ((incompleteframe.writableBytes() - 16) <= 0) {
           status = STATUS_H;
           return incompleteframe;
         }
         break;
     }
   }
   return null;
 }
예제 #4
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();
      }
    }
  }
예제 #5
0
  @Override
  protected int doReadMessages(MessageBuf<Object> buf) throws Exception {
    DatagramChannel ch = javaChannel();
    ByteBuf buffer = alloc().directBuffer(config().getReceivePacketSize());
    boolean free = true;
    try {
      ByteBuffer data = buffer.nioBuffer(buffer.writerIndex(), buffer.writableBytes());

      InetSocketAddress remoteAddress = (InetSocketAddress) ch.receive(data);
      if (remoteAddress == null) {
        return 0;
      }
      buf.add(
          new DatagramPacket(
              buffer.writerIndex(buffer.writerIndex() + data.remaining()), remoteAddress));
      free = false;
      return 1;
    } catch (Throwable cause) {
      if (cause instanceof Error) {
        throw (Error) cause;
      }
      if (cause instanceof RuntimeException) {
        throw (RuntimeException) cause;
      }
      if (cause instanceof Exception) {
        throw (Exception) cause;
      }
      throw new ChannelException(cause);
    } finally {
      if (free) {
        buffer.free();
      }
    }
  }
  private boolean handleCompressedFrame(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
      throws Exception {
    if (!in.isReadable(FRAME_COMPRESS_HEADER_LENGTH)) {
      return false;
    }

    int compressedPayloadLength = in.readInt();
    if (!in.isReadable(compressedPayloadLength)) {
      return false;
    }

    // decompress payload
    Inflater inflater = new Inflater();
    if (in.hasArray()) {
      inflater.setInput(in.array(), in.arrayOffset() + in.readerIndex(), compressedPayloadLength);
      in.skipBytes(compressedPayloadLength);
    } else {
      byte[] array = new byte[compressedPayloadLength];
      in.readBytes(array);
      inflater.setInput(array);
    }

    while (!inflater.finished()) {
      ByteBuf decompressed = ctx.alloc().heapBuffer(1024, 1024);
      byte[] outArray = decompressed.array();
      int count =
          inflater.inflate(outArray, decompressed.arrayOffset(), decompressed.writableBytes());
      decompressed.writerIndex(count);
      // put data in the pipeline
      out.add(decompressed);
    }

    return true;
  }
  private void testBuffer(ByteBuf buf, boolean isDirect) {
    assertEquals(11, buf.capacity());

    assertEquals(isDirect, buf.isDirect());

    assertEquals(0, buf.readableBytes());
    assertEquals(11, buf.writableBytes());
  }
예제 #8
0
 private void writeBuffer(byte[] data) {
   int newSize = 0;
   int oldSize = buffer.capacity();
   int length = data.length;
   if (buffer.writableBytes() <= length) {
     if (length > oldSize) {
       newSize = length * 2;
     } else {
       newSize = 2 * oldSize;
     }
     buffer.capacity(newSize);
   }
   buffer.writeBytes(data);
 }
예제 #9
0
 private static SSLEngineResult wrap(SSLEngine engine, ByteBuf in, ByteBuf out)
     throws SSLException {
   ByteBuffer in0 = in.nioBuffer();
   for (; ; ) {
     ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes());
     SSLEngineResult result = engine.wrap(in0, out0);
     in.skipBytes(result.bytesConsumed());
     out.writerIndex(out.writerIndex() + result.bytesProduced());
     if (result.getStatus() == Status.BUFFER_OVERFLOW) {
       out.ensureWritableBytes(engine.getSession().getPacketBufferSize());
     } else {
       return result;
     }
   }
 }
예제 #10
0
 /** Read bytes into the given {@link ByteBuf} and return the amount. */
 private int doReadBytes(ByteBuf byteBuf) throws Exception {
   int writerIndex = byteBuf.writerIndex();
   int localReadAmount;
   if (byteBuf.hasMemoryAddress()) {
     localReadAmount =
         Native.readAddress(fd, byteBuf.memoryAddress(), writerIndex, byteBuf.capacity());
   } else {
     ByteBuffer buf = byteBuf.internalNioBuffer(writerIndex, byteBuf.writableBytes());
     localReadAmount = Native.read(fd, buf, buf.position(), buf.limit());
   }
   if (localReadAmount > 0) {
     byteBuf.writerIndex(writerIndex + localReadAmount);
   }
   return localReadAmount;
 }
예제 #11
0
 private static SSLEngineResult unwrap(SSLEngine engine, ByteBuf in, ByteBuf out)
     throws SSLException {
   ByteBuffer in0 = in.nioBuffer();
   for (; ; ) {
     ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes());
     SSLEngineResult result = engine.unwrap(in0, out0);
     in.skipBytes(result.bytesConsumed());
     out.writerIndex(out.writerIndex() + result.bytesProduced());
     switch (result.getStatus()) {
       case BUFFER_OVERFLOW:
         out.ensureWritableBytes(engine.getSession().getApplicationBufferSize());
         break;
       default:
         return result;
     }
   }
 }
    @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);
      }
    }
예제 #13
0
 private static SSLEngineResult unwrap(SSLEngine engine, ByteBuffer in, ByteBuf out)
     throws SSLException {
   int overflows = 0;
   for (; ; ) {
     ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes());
     SSLEngineResult result = engine.unwrap(in, out0);
     out.writerIndex(out.writerIndex() + result.bytesProduced());
     switch (result.getStatus()) {
       case BUFFER_OVERFLOW:
         int max = engine.getSession().getApplicationBufferSize();
         switch (overflows++) {
           case 0:
             out.ensureWritable(Math.min(max, in.remaining()));
             break;
           default:
             out.ensureWritable(max);
         }
         break;
       default:
         return result;
     }
   }
 }
예제 #14
0
  @Override
  protected void encode(ChannelHandlerContext ctx, Object msg, List<Object> out) throws Exception {
    ByteBuf buf = null;
    if (msg instanceof HttpMessage) {
      if (state != ST_INIT) {
        throw new IllegalStateException(
            "unexpected message type: " + StringUtil.simpleClassName(msg));
      }

      @SuppressWarnings({"unchecked", "CastConflictsWithInstanceof"})
      H m = (H) msg;

      buf = ctx.alloc().buffer();
      // Encode the message.
      encodeInitialLine(buf, m);
      HttpHeaders.encode(m.headers(), buf);
      buf.writeBytes(CRLF);
      state = HttpHeaders.isTransferEncodingChunked(m) ? ST_CONTENT_CHUNK : ST_CONTENT_NON_CHUNK;
    }
    if (msg instanceof HttpContent || msg instanceof ByteBuf || msg instanceof FileRegion) {
      if (state == ST_INIT) {
        throw new IllegalStateException(
            "unexpected message type: " + StringUtil.simpleClassName(msg));
      }

      int contentLength = contentLength(msg);
      if (state == ST_CONTENT_NON_CHUNK) {
        if (contentLength > 0) {
          if (buf != null && buf.writableBytes() >= contentLength && msg instanceof HttpContent) {
            // merge into other buffer for performance reasons
            buf.writeBytes(((HttpContent) msg).content());
            out.add(buf);
          } else {
            if (buf != null) {
              out.add(buf);
            }
            out.add(encodeAndRetain(msg));
          }
        } else {
          if (buf != null) {
            out.add(buf);
          } else {
            // Need to produce some output otherwise an
            // IllegalStateException will be thrown
            out.add(EMPTY_BUFFER);
          }
        }

        if (msg instanceof LastHttpContent) {
          state = ST_INIT;
        }
      } else if (state == ST_CONTENT_CHUNK) {
        if (buf != null) {
          out.add(buf);
        }
        encodeChunkedContent(ctx, msg, contentLength, out);
      } else {
        throw new Error();
      }
    } else {
      if (buf != null) {
        out.add(buf);
      }
    }
  }
예제 #15
0
    @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();
        }
      }
    }
예제 #16
0
  private SSLEngineResult wrap(ByteBufAllocator alloc, SSLEngine engine, ByteBuf in, ByteBuf out)
      throws SSLException {
    ByteBuf newDirectIn = null;
    try {
      int readerIndex = in.readerIndex();
      int readableBytes = in.readableBytes();

      // We will call SslEngine.wrap(ByteBuffer[], ByteBuffer) to allow efficient handling of
      // CompositeByteBuf without force an extra memory copy when CompositeByteBuffer.nioBuffer() is
      // called.
      final ByteBuffer[] in0;
      if (in.isDirect() || !wantsDirectBuffer) {
        // As CompositeByteBuf.nioBufferCount() can be expensive (as it needs to check all composed
        // ByteBuf
        // to calculate the count) we will just assume a CompositeByteBuf contains more then 1
        // ByteBuf.
        // The worst that can happen is that we allocate an extra ByteBuffer[] in
        // CompositeByteBuf.nioBuffers()
        // which is better then walking the composed ByteBuf in most cases.
        if (!(in instanceof CompositeByteBuf) && in.nioBufferCount() == 1) {
          in0 = singleBuffer;
          // We know its only backed by 1 ByteBuffer so use internalNioBuffer to keep object
          // allocation
          // to a minimum.
          in0[0] = in.internalNioBuffer(readerIndex, readableBytes);
        } else {
          in0 = in.nioBuffers();
        }
      } else {
        // We could even go further here and check if its a CompositeByteBuf and if so try to
        // decompose it and
        // only replace the ByteBuffer that are not direct. At the moment we just will replace the
        // whole
        // CompositeByteBuf to keep the complexity to a minimum
        newDirectIn = alloc.directBuffer(readableBytes);
        newDirectIn.writeBytes(in, readerIndex, readableBytes);
        in0 = singleBuffer;
        in0[0] = newDirectIn.internalNioBuffer(0, readableBytes);
      }

      for (; ; ) {
        ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes());
        SSLEngineResult result = engine.wrap(in0, out0);
        in.skipBytes(result.bytesConsumed());
        out.writerIndex(out.writerIndex() + result.bytesProduced());

        switch (result.getStatus()) {
          case BUFFER_OVERFLOW:
            out.ensureWritable(maxPacketBufferSize);
            break;
          default:
            return result;
        }
      }
    } finally {
      // Null out to allow GC of ByteBuffer
      singleBuffer[0] = null;

      if (newDirectIn != null) {
        newDirectIn.release();
      }
    }
  }
 @Override
 protected int doReadBytes(ByteBuf byteBuf) throws Exception {
   // 从channel中读出数据到buffer
   return byteBuf.writeBytes(javaChannel(), byteBuf.writableBytes());
 }
예제 #18
0
 @Override
 public int writableBytes() {
   return buf.writableBytes();
 }