示例#1
0
  @Override
  protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception {
    SctpMessage packet = (SctpMessage) msg;
    ByteBuf data = packet.content();
    int dataLen = data.readableBytes();
    if (dataLen == 0) {
      return true;
    }

    ByteBufAllocator alloc = alloc();
    boolean needsCopy = data.nioBufferCount() != 1;
    if (!needsCopy) {
      if (!data.isDirect() && alloc.isDirectBufferPooled()) {
        needsCopy = true;
      }
    }
    ByteBuffer nioData;
    if (!needsCopy) {
      nioData = data.nioBuffer();
    } else {
      data = alloc.directBuffer(dataLen).writeBytes(data);
      nioData = data.nioBuffer();
    }
    final MessageInfo mi =
        MessageInfo.createOutgoing(association(), null, packet.streamIdentifier());
    mi.payloadProtocolID(packet.protocolIdentifier());
    mi.streamNumber(packet.streamIdentifier());
    mi.unordered(packet.isUnordered());

    final int writtenBytes = javaChannel().send(nioData, mi);
    return writtenBytes > 0;
  }
  public ByteBuf allocateBuffer(ByteBufAllocator allocator) {
    if (configuration.isPreferDirectBuffer()) {
      return allocator.ioBuffer();
    }

    return allocator.heapBuffer();
  }
 /**
  * Adds a fragment to the block.
  *
  * @param fragment the fragment of the headers block to be added.
  * @param alloc allocator for new blocks if needed.
  * @param endOfHeaders flag indicating whether the current frame is the end of the headers. This
  *     is used for an optimization for when the first fragment is the full block. In that case,
  *     the buffer is used directly without copying.
  */
 final void addFragment(ByteBuf fragment, ByteBufAllocator alloc, boolean endOfHeaders)
     throws Http2Exception {
   if (headerBlock == null) {
     if (fragment.readableBytes() > headersDecoder.configuration().maxHeaderSize()) {
       headerSizeExceeded();
     }
     if (endOfHeaders) {
       // Optimization - don't bother copying, just use the buffer as-is. Need
       // to retain since we release when the header block is built.
       headerBlock = fragment.retain();
     } else {
       headerBlock = alloc.buffer(fragment.readableBytes());
       headerBlock.writeBytes(fragment);
     }
     return;
   }
   if (headersDecoder.configuration().maxHeaderSize() - fragment.readableBytes()
       < headerBlock.readableBytes()) {
     headerSizeExceeded();
   }
   if (headerBlock.isWritable(fragment.readableBytes())) {
     // The buffer can hold the requested bytes, just write it directly.
     headerBlock.writeBytes(fragment);
   } else {
     // Allocate a new buffer that is big enough to hold the entire header block so far.
     ByteBuf buf = alloc.buffer(headerBlock.readableBytes() + fragment.readableBytes());
     buf.writeBytes(headerBlock);
     buf.writeBytes(fragment);
     headerBlock.release();
     headerBlock = buf;
   }
 }
示例#4
0
 /**
  * Always prefer a direct buffer when it's pooled, so that we reduce the number of memory copies
  * in {@link OpenSslEngine}.
  */
 private ByteBuf allocate(ChannelHandlerContext ctx, int capacity) {
   ByteBufAllocator alloc = ctx.alloc();
   if (wantsDirectBuffer) {
     return alloc.directBuffer(capacity);
   } else {
     return alloc.buffer(capacity);
   }
 }
  /**
   * 쓰레드 덤프를 요청하는 전문을 보낸다<br>
   * <br>
   *
   * @param threadDumpData
   * @param agentId
   * @param channel
   * @author Kim Ji Hye
   * @since 2015. 11. 26.
   */
  public ThreadDumpData sendThreadDumpRequest(ThreadDumpData td) {

    // Assembler를 사용하여 socket에 write한다.
    byte[] sendData = Assembler.getSendData(td, true);
    Channel channel = AgentClientSocketHandler.getClient(td.getAgentId());
    if (channel != null) {
      ByteBufAllocator alloc = channel.alloc();
      ByteBuf buf = alloc.buffer(sendData.length);
      buf.writeBytes(sendData);
      channel.writeAndFlush(buf);
    }
    return td;
  }
示例#6
0
    /**
     * Reads the content of the entry into a new buffer. Use {@link #readContent(ByteBufAllocator,
     * InputStream)} when the length of the stream is unknown.
     */
    protected ByteBuf readContent(ByteBufAllocator alloc, InputStream in, int length)
        throws IOException {
      if (length == 0) {
        return Unpooled.EMPTY_BUFFER;
      }

      ByteBuf buf = null;
      boolean success = false;
      try {
        buf = alloc.directBuffer(length);

        int remaining = length;
        for (; ; ) {
          final int readBytes = buf.writeBytes(in, remaining);
          if (readBytes < 0) {
            break;
          }
          remaining -= readBytes;
          if (remaining <= 0) {
            break;
          }
        }

        success = true;
        return buf;
      } finally {
        if (!success && buf != null) {
          buf.release();
        }
      }
    }
示例#7
0
    /**
     * Reads the content of the entry into a new buffer. Use {@link #readContent(ByteBufAllocator,
     * InputStream, int)} when the length of the stream is known.
     */
    protected ByteBuf readContent(ByteBufAllocator alloc, InputStream in) throws IOException {
      ByteBuf buf = null;
      boolean success = false;
      try {
        buf = alloc.directBuffer();
        for (; ; ) {
          if (buf.writeBytes(in, 8192) < 0) {
            break;
          }
        }

        success = true;

        if (buf.isReadable()) {
          return buf;
        } else {
          buf.release();
          return Unpooled.EMPTY_BUFFER;
        }
      } finally {
        if (!success && buf != null) {
          buf.release();
        }
      }
    }
  private void run0() throws InterruptedException {
    ByteBufAllocator allocator = m_descriptor.getByteBufAllocator();
    int initialCapacity = 4 * 1024; // 4K
    ByteBuf buf = allocator.buffer(initialCapacity);
    TransportHub hub = m_descriptor.getHub();

    while (m_active.get()) {
      Channel channel = m_channelManager.getActiveChannel();

      if (channel != null && channel.isWritable()) {
        do {
          if (hub.fill(buf)) {
            channel.writeAndFlush(buf);
            buf = allocator.buffer(initialCapacity);
          } else {
            break;
          }
        } while (channel.isWritable());
      }

      TimeUnit.MILLISECONDS.sleep(1); // 1ms
    }

    long end = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(3); // 3s timeout

    while (true) {
      Channel channel = m_channelManager.getActiveChannel();

      if (channel != null && channel.isWritable()) {
        do {
          if (hub.fill(buf)) {
            channel.writeAndFlush(buf);
            buf = allocator.buffer(initialCapacity);
          } else {
            break;
          }
        } while (channel.isWritable());
      }

      if (System.currentTimeMillis() >= end) {
        throw new InterruptedException("Timeout with messages left in the queue!");
      }

      TimeUnit.MILLISECONDS.sleep(1); // 1ms
    }
  }
 private static MqttPublishMessage createPublishMessage() {
   MqttFixedHeader mqttFixedHeader =
       new MqttFixedHeader(MqttMessageType.PUBLISH, false, MqttQoS.AT_LEAST_ONCE, true, 0);
   MqttPublishVariableHeader mqttPublishVariableHeader =
       MqttPublishVariableHeader.from("/abc", 1234);
   ByteBuf payload = ALLOCATOR.buffer();
   payload.writeBytes("whatever".getBytes(CharsetUtil.UTF_8));
   return new MqttPublishMessage(mqttFixedHeader, mqttPublishVariableHeader, payload);
 }
  @Override
  public ByteBuf serializeResponseAsBinary(
      final ResponseMessage responseMessage, final ByteBufAllocator allocator)
      throws SerializationException {
    ByteBuf encodedMessage = null;
    try {
      final Kryo kryo = kryoThreadLocal.get();
      try (final OutputStream baos = new ByteArrayOutputStream()) {
        final Output output = new Output(baos);

        // request id - if present
        kryo.writeObjectOrNull(
            output,
            responseMessage.getRequestId() != null ? responseMessage.getRequestId() : null,
            UUID.class);

        // status
        output.writeShort(responseMessage.getStatus().getCode().getValue());
        output.writeString(responseMessage.getStatus().getMessage());
        kryo.writeClassAndObject(output, responseMessage.getStatus().getAttributes());

        // result
        kryo.writeClassAndObject(
            output,
            serializeToString
                ? serializeResultToString(responseMessage)
                : responseMessage.getResult().getData());
        kryo.writeClassAndObject(output, responseMessage.getResult().getMeta());

        final long size = output.total();
        if (size > Integer.MAX_VALUE)
          throw new SerializationException(
              String.format("Message size of %s exceeds allocatable space", size));

        encodedMessage = allocator.buffer((int) output.total());
        encodedMessage.writeBytes(output.toBytes());
      }

      return encodedMessage;
    } catch (Exception ex) {
      if (encodedMessage != null) ReferenceCountUtil.release(encodedMessage);

      logger.warn(
          "Response [{}] could not be serialized by {}.",
          responseMessage.toString(),
          GryoMessageSerializerV1d0.class.getName());
      throw new SerializationException(ex);
    }
  }
示例#11
0
 /**
  * Serializes the header.
  *
  * <p>A header that has metadata of small will add the length of the packet in a byte, the header
  * that has a metadata of big will add the length of the packet in a short
  */
 @Override
 public ByteBuf serialize(ByteBufAllocator allocator) {
   ByteBuf buffer = allocator.buffer(1 + meta().ordinal()).writeByte(opcode());
   switch (meta()) {
     case EMPTY:
       break;
     case SMALL:
       buffer.writeByte(length());
       break;
     case BIG:
       buffer.writeShort(length());
       break;
   }
   return buffer;
 }
  @Override
  public ByteBuf serializeRequestAsBinary(
      final RequestMessage requestMessage, final ByteBufAllocator allocator)
      throws SerializationException {
    ByteBuf encodedMessage = null;
    try {
      final Kryo kryo = kryoThreadLocal.get();
      try (final OutputStream baos = new ByteArrayOutputStream()) {
        final Output output = new Output(baos);
        final String mimeType = serializeToString ? MIME_TYPE_STRINGD : MIME_TYPE;
        output.writeByte(mimeType.length());
        output.write(mimeType.getBytes(UTF8));

        kryo.writeObject(output, requestMessage.getRequestId());
        output.writeString(requestMessage.getProcessor());
        output.writeString(requestMessage.getOp());
        kryo.writeObject(output, requestMessage.getArgs());

        final long size = output.total();
        if (size > Integer.MAX_VALUE)
          throw new SerializationException(
              String.format("Message size of %s exceeds allocatable space", size));

        encodedMessage = allocator.buffer((int) size);
        encodedMessage.writeBytes(output.toBytes());
      }

      return encodedMessage;
    } catch (Exception ex) {
      if (encodedMessage != null) ReferenceCountUtil.release(encodedMessage);

      logger.warn(
          "Request [{}] could not be serialized by {}.",
          requestMessage.toString(),
          GryoMessageSerializerV1d0.class.getName());
      throw new SerializationException(ex);
    }
  }
    @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();
        }
      }
    }
示例#14
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 void doWrite(ChannelOutboundBuffer in) throws Exception {
    int writeSpinCount = -1;

    GatheringByteChannel sink = connection().getSinkChannel();
    for (; ; ) {
      // Do gathering write for a non-single buffer case.
      final int msgCount = in.size();
      if (msgCount > 0) {
        // Ensure the pending writes are made of ByteBufs only.
        ByteBuffer[] nioBuffers = in.nioBuffers();
        if (nioBuffers != null) {

          int nioBufferCnt = in.nioBufferCount();
          long expectedWrittenBytes = in.nioBufferSize();

          long writtenBytes = 0;
          boolean done = false;
          boolean setOpWrite = false;
          for (int i = config().getWriteSpinCount() - 1; i >= 0; i--) {
            final long localWrittenBytes = sink.write(nioBuffers, 0, nioBufferCnt);
            if (localWrittenBytes == 0) {
              setOpWrite = true;
              break;
            }
            expectedWrittenBytes -= localWrittenBytes;
            writtenBytes += localWrittenBytes;
            if (expectedWrittenBytes == 0) {
              done = true;
              break;
            }
          }

          if (done) {
            // Release all buffers
            for (int i = msgCount; i > 0; i--) {
              in.remove();
            }

            // Finish the write loop if no new messages were flushed by in.remove().
            if (in.isEmpty()) {
              connection().getSinkChannel().suspendWrites();
              break;
            }
          } else {
            // Did not write all buffers completely.
            // Release the fully written buffers and update the indexes of the partially written
            // buffer.

            for (int i = msgCount; i > 0; i--) {
              final ByteBuf buf = (ByteBuf) in.current();
              final int readerIndex = buf.readerIndex();
              final int readableBytes = buf.writerIndex() - readerIndex;

              if (readableBytes < writtenBytes) {
                in.progress(readableBytes);
                in.remove();
                writtenBytes -= readableBytes;
              } else if (readableBytes > writtenBytes) {
                buf.readerIndex(readerIndex + (int) writtenBytes);
                in.progress(writtenBytes);
                break;
              } else { // readableBytes == writtenBytes
                in.progress(readableBytes);
                in.remove();
                break;
              }
            }

            incompleteWrite(setOpWrite);
            break;
          }
          continue;
        }
      }

      Object msg = in.current();
      if (msg == null) {
        // Wrote all messages.
        connection().getSinkChannel().suspendWrites();
        break;
      }

      if (msg instanceof ByteBuf) {
        ByteBuf buf = (ByteBuf) msg;
        int readableBytes = buf.readableBytes();
        if (readableBytes == 0) {
          in.remove();
          continue;
        }

        if (!buf.isDirect()) {
          ByteBufAllocator alloc = alloc();
          if (alloc.isDirectBufferPooled()) {
            // Non-direct buffers are copied into JDK's own internal direct buffer on every I/O.
            // We can do a better job by using our pooled allocator. If the current allocator does
            // not
            // pool a direct buffer, we rely on JDK's direct buffer pool.
            buf = alloc.directBuffer(readableBytes).writeBytes(buf);
            in.current(buf);
          }
        }

        boolean setOpWrite = false;
        boolean done = false;
        long flushedAmount = 0;
        if (writeSpinCount == -1) {
          writeSpinCount = config().getWriteSpinCount();
        }
        for (int i = writeSpinCount - 1; i >= 0; i--) {
          int localFlushedAmount = buf.readBytes(sink, buf.readableBytes());
          if (localFlushedAmount == 0) {
            setOpWrite = true;
            break;
          }

          flushedAmount += localFlushedAmount;
          if (!buf.isReadable()) {
            done = true;
            break;
          }
        }

        in.progress(flushedAmount);

        if (done) {
          in.remove();
        } else {
          incompleteWrite(setOpWrite);
          break;
        }
      } else if (msg instanceof FileRegion) {
        FileRegion region = (FileRegion) msg;
        boolean setOpWrite = false;
        boolean done = false;
        long flushedAmount = 0;
        if (writeSpinCount == -1) {
          writeSpinCount = config().getWriteSpinCount();
        }
        for (int i = writeSpinCount - 1; i >= 0; i--) {
          long localFlushedAmount = region.transferTo(sink, region.transfered());
          if (localFlushedAmount == 0) {
            setOpWrite = true;
            break;
          }

          flushedAmount += localFlushedAmount;
          if (region.transfered() >= region.count()) {
            done = true;
            break;
          }
        }

        in.progress(flushedAmount);

        if (done) {
          in.remove();
        } else {
          incompleteWrite(setOpWrite);
          break;
        }
      } else {
        throw new UnsupportedOperationException(
            "unsupported message type: " + StringUtil.simpleClassName(msg));
      }
    }
  }
  @Override
  protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception {
    final Object m;
    final SocketAddress remoteAddress;
    ByteBuf data;
    if (msg instanceof AddressedEnvelope) {
      @SuppressWarnings("unchecked")
      AddressedEnvelope<Object, SocketAddress> envelope =
          (AddressedEnvelope<Object, SocketAddress>) msg;
      remoteAddress = envelope.recipient();
      m = envelope.content();
    } else {
      m = msg;
      remoteAddress = null;
    }

    if (m instanceof ByteBufHolder) {
      data = ((ByteBufHolder) m).content();
    } else if (m instanceof ByteBuf) {
      data = (ByteBuf) m;
    } else {
      throw new UnsupportedOperationException(
          "unsupported message type: " + StringUtil.simpleClassName(msg));
    }

    int dataLen = data.readableBytes();
    if (dataLen == 0) {
      return true;
    }

    ByteBufAllocator alloc = alloc();
    boolean needsCopy = data.nioBufferCount() != 1;
    if (!needsCopy) {
      if (!data.isDirect() && alloc.isDirectBufferPooled()) {
        needsCopy = true;
      }
    }
    ByteBuffer nioData;
    if (!needsCopy) {
      nioData = data.nioBuffer();
    } else {
      data = alloc.directBuffer(dataLen).writeBytes(data);
      nioData = data.nioBuffer();
    }

    final int writtenBytes;
    if (remoteAddress != null) {
      writtenBytes = javaChannel().send(nioData, remoteAddress);
    } else {
      writtenBytes = javaChannel().write(nioData);
    }

    boolean done = writtenBytes > 0;
    if (needsCopy) {
      // This means we have allocated a new buffer and need to store it back so we not need to
      // allocate it again
      // later
      if (remoteAddress == null) {
        // remoteAddress is null which means we can handle it as ByteBuf directly
        in.current(data);
      } else {
        if (!done) {
          // store it back with all the needed informations
          in.current(new DefaultAddressedEnvelope<ByteBuf, SocketAddress>(data, remoteAddress));
        } else {
          // Just store back the new create buffer so it is cleaned up once in.remove() is called.
          in.current(data);
        }
      }
    }
    return done;
  }
 @Override
 public ByteBuf allocate(ByteBufAllocator alloc) {
   return alloc.ioBuffer(nextReceiveBufferSize);
 }
示例#18
0
 public GameFrameBuilder(ByteBufAllocator alloc, int opcode, Type type) {
   this.alloc = alloc;
   this.buffer = alloc.buffer();
   this.opcode = opcode;
   this.type = type;
 }