Example #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;
  }
Example #2
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;
     }
   }
 }
Example #3
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();
      }
    }
  }
Example #4
0
  @Override
  public boolean renameTo(File dest) throws IOException {
    if (dest == null) {
      throw new NullPointerException("dest");
    }
    if (byteBuf == null) {
      // empty file
      dest.createNewFile();
      isRenamed = true;
      return true;
    }
    int length = byteBuf.readableBytes();
    FileOutputStream outputStream = new FileOutputStream(dest);
    FileChannel fileChannel = outputStream.getChannel();
    int written = 0;
    if (byteBuf.nioBufferCount() == 1) {
      ByteBuffer byteBuffer = byteBuf.nioBuffer();
      while (written < length) {
        written += fileChannel.write(byteBuffer);
      }
    } else {
      ByteBuffer[] byteBuffers = byteBuf.nioBuffers();
      while (written < length) {
        written += fileChannel.write(byteBuffers);
      }
    }

    fileChannel.force(false);
    fileChannel.close();
    outputStream.close();
    isRenamed = true;
    return written == length;
  }
  @Override
  protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    ByteBufferInput input = new ByteBufferInput(in.nioBuffer(), false);
    T newMsg = schema.newMessage();

    schema.mergeFrom(input, newMsg);
    out.add(newMsg);
  }
Example #6
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;
     }
   }
 }
Example #7
0
    /**
     * Transfers data from the original message to the channel, encrypting it in the process.
     *
     * <p>This method also breaks down the original message into smaller chunks when needed. This is
     * done to keep memory usage under control. This avoids having to copy the whole message data
     * into memory at once, and can avoid ballooning memory usage when transferring large messages
     * such as shuffle blocks.
     *
     * <p>The {@link #transfered()} counter also behaves a little funny, in that it won't go forward
     * until a whole chunk has been written. This is done because the code can't use the actual
     * number of bytes written to the channel as the transferred count (see {@link #count()}).
     * Instead, once an encrypted chunk is written to the output (including its header), the size of
     * the original block will be added to the {@link #transfered()} amount.
     */
    @Override
    public long transferTo(final WritableByteChannel target, final long position)
        throws IOException {

      Preconditions.checkArgument(position == transfered(), "Invalid position.");

      long reportedWritten = 0L;
      long actuallyWritten = 0L;
      do {
        if (currentChunk == null) {
          nextChunk();
        }

        if (currentHeader.readableBytes() > 0) {
          int bytesWritten = target.write(currentHeader.nioBuffer());
          currentHeader.skipBytes(bytesWritten);
          actuallyWritten += bytesWritten;
          if (currentHeader.readableBytes() > 0) {
            // Break out of loop if there are still header bytes left to write.
            break;
          }
        }

        actuallyWritten += target.write(currentChunk);
        if (!currentChunk.hasRemaining()) {
          // Only update the count of written bytes once a full chunk has been written.
          // See method javadoc.
          long chunkBytesRemaining = unencryptedChunkSize - currentReportedBytes;
          reportedWritten += chunkBytesRemaining;
          transferred += chunkBytesRemaining;
          currentHeader.release();
          currentHeader = null;
          currentChunk = null;
          currentChunkSize = 0;
          currentReportedBytes = 0;
        }
      } while (currentChunk == null && transfered() + reportedWritten < count());

      // Returning 0 triggers a backoff mechanism in netty which may harm performance. Instead,
      // we return 1 until we can (i.e. until the reported count would actually match the size
      // of the current chunk), at which point we resort to returning 0 so that the counts still
      // match, at the cost of some performance. That situation should be rare, though.
      if (reportedWritten != 0L) {
        return reportedWritten;
      }

      if (actuallyWritten > 0 && currentReportedBytes < currentChunkSize - 1) {
        transferred += 1L;
        currentReportedBytes += 1L;
        return 1L;
      }

      return 0L;
    }
Example #8
0
    private void nextChunk() throws IOException {
      byteChannel.reset();
      if (isByteBuf) {
        int copied = byteChannel.write(buf.nioBuffer());
        buf.skipBytes(copied);
      } else {
        region.transferTo(byteChannel, region.transfered());
      }

      byte[] encrypted = backend.wrap(byteChannel.getData(), 0, byteChannel.length());
      this.currentChunk = ByteBuffer.wrap(encrypted);
      this.currentChunkSize = encrypted.length;
      this.currentHeader = Unpooled.copyLong(8 + currentChunkSize);
      this.unencryptedChunkSize = byteChannel.length();
    }
Example #9
0
  @Override
  protected int doWriteMessages(MessageBuf<Object> buf, boolean lastSpin) throws Exception {
    DatagramPacket packet = (DatagramPacket) buf.peek();
    ByteBuf data = packet.data();
    int dataLen = data.readableBytes();
    ByteBuffer nioData;
    if (data.nioBufferCount() == 1) {
      nioData = data.nioBuffer();
    } else {
      nioData = ByteBuffer.allocate(dataLen);
      data.getBytes(data.readerIndex(), nioData);
      nioData.flip();
    }

    final int writtenBytes = javaChannel().send(nioData, packet.remoteAddress());

    final SelectionKey key = selectionKey();
    final int interestOps = key.interestOps();
    if (writtenBytes <= 0 && dataLen > 0) {
      // Did not write a packet.
      // 1) If 'lastSpin' is false, the caller will call this method again real soon.
      //    - Do not update OP_WRITE.
      // 2) If 'lastSpin' is true, the caller will not retry.
      //    - Set OP_WRITE so that the event loop calls flushForcibly() later.
      if (lastSpin) {
        if ((interestOps & SelectionKey.OP_WRITE) == 0) {
          key.interestOps(interestOps | SelectionKey.OP_WRITE);
        }
      }
      return 0;
    }

    // Wrote a packet.
    buf.remove();

    // packet was written free up buffer
    packet.free();

    if (buf.isEmpty()) {
      // Wrote the outbound buffer completely - clear OP_WRITE.
      if ((interestOps & SelectionKey.OP_WRITE) != 0) {
        key.interestOps(interestOps & ~SelectionKey.OP_WRITE);
      }
    }
    return 1;
  }
Example #10
0
  @Override
  public Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
    ByteBuf frame = null;
    try {
      frame = (ByteBuf) super.decode(ctx, in);
      if (null == frame) {
        return null;
      }

      ByteBuffer byteBuffer = frame.nioBuffer();

      return Command.decode(byteBuffer);
    } catch (Exception e) {
      logger.error("decode exception, " + " error ip = ", e);
      RemotingUtil.closeChannel(ctx.channel());
    } finally {
      if (null != frame) {
        frame.release();
      }
    }

    return null;
  }
Example #11
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;
     }
   }
 }
Example #12
0
 @Override
 public ByteBuffer nioBuffer() {
   return buf.nioBuffer();
 }
Example #13
0
  @Override
  public Tuple2<UserIdentityToken, SignatureData> getIdentityToken(
      EndpointDescription endpoint, ByteString serverNonce) throws Exception {

    UserTokenPolicy tokenPolicy =
        Arrays.stream(endpoint.getUserIdentityTokens())
            .filter(t -> t.getTokenType() == UserTokenType.UserName)
            .findFirst()
            .orElseThrow(() -> new Exception("no username token policy found"));

    String policyId = tokenPolicy.getPolicyId();

    SecurityPolicy securityPolicy = SecurityPolicy.None;

    String securityPolicyUri = tokenPolicy.getSecurityPolicyUri();
    try {
      if (securityPolicyUri != null && !securityPolicyUri.isEmpty()) {
        securityPolicy = SecurityPolicy.fromUri(securityPolicyUri);
      } else {
        securityPolicyUri = endpoint.getSecurityPolicyUri();
        securityPolicy = SecurityPolicy.fromUri(securityPolicyUri);
      }
    } catch (Throwable t) {
      logger.warn(
          "Error parsing SecurityPolicy for uri={}, falling back to no security.",
          securityPolicyUri);
    }

    byte[] passwordBytes = password.getBytes("UTF-8");
    byte[] nonceBytes = Optional.ofNullable(serverNonce.bytes()).orElse(new byte[0]);

    ByteBuf buffer = Unpooled.buffer().order(ByteOrder.LITTLE_ENDIAN);

    if (securityPolicy == SecurityPolicy.None) {
      buffer.writeBytes(passwordBytes);
    } else {
      buffer.writeInt(passwordBytes.length + nonceBytes.length);
      buffer.writeBytes(passwordBytes);
      buffer.writeBytes(nonceBytes);

      ByteString bs = endpoint.getServerCertificate();
      X509Certificate certificate = CertificateUtil.decodeCertificate(bs.bytes());

      int plainTextBlockSize = getPlainTextBlockSize(certificate, securityPolicy);
      int cipherTextBlockSize = getCipherTextBlockSize(certificate, securityPolicy);
      int blockCount = (buffer.readableBytes() + plainTextBlockSize - 1) / plainTextBlockSize;
      Cipher cipher = getAndInitializeCipher(certificate, securityPolicy);

      ByteBuffer plainTextNioBuffer = buffer.nioBuffer();
      ByteBuffer cipherTextNioBuffer =
          Unpooled.buffer(cipherTextBlockSize * blockCount)
              .order(ByteOrder.LITTLE_ENDIAN)
              .nioBuffer(0, cipherTextBlockSize * blockCount);

      for (int blockNumber = 0; blockNumber < blockCount; blockNumber++) {
        int position = blockNumber * plainTextBlockSize;
        int limit = Math.min(buffer.readableBytes(), (blockNumber + 1) * plainTextBlockSize);
        plainTextNioBuffer.position(position).limit(limit);

        cipher.doFinal(plainTextNioBuffer, cipherTextNioBuffer);
      }

      cipherTextNioBuffer.flip();
      buffer = Unpooled.wrappedBuffer(cipherTextNioBuffer);
    }

    byte[] bs = new byte[buffer.readableBytes()];
    buffer.readBytes(bs);

    // UA Part 4, Section 7.35.3 UserNameIdentityToken:
    // encryptionAlgorithm parameter is null if the password is not encrypted.
    String securityAlgorithmUri = securityPolicy.getAsymmetricEncryptionAlgorithm().getUri();
    String encryptionAlgorithm = securityAlgorithmUri.isEmpty() ? null : securityAlgorithmUri;

    UserNameIdentityToken token =
        new UserNameIdentityToken(policyId, username, ByteString.of(bs), encryptionAlgorithm);

    return new Tuple2<>(token, new SignatureData());
  }
    @Override
    public void channelRead0(ChannelHandlerContext ctx, ByteBuf input) throws Exception {

      int readable = input.readableBytes();
      if (readable <= 0) {
        return;
      }

      com.alibaba.dubbo.remoting.buffer.ChannelBuffer message;
      if (buffer.readable()) {
        if (buffer instanceof DynamicChannelBuffer) {
          buffer.writeBytes(input.nioBuffer());
          message = buffer;
        } else {
          int size = buffer.readableBytes() + input.readableBytes();
          message =
              com.alibaba.dubbo.remoting.buffer.ChannelBuffers.dynamicBuffer(
                  size > bufferSize ? size : bufferSize);
          message.writeBytes(buffer, buffer.readableBytes());
          message.writeBytes(input.nioBuffer());
        }
      } else {
        message = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.wrappedBuffer(input.nioBuffer());
      }

      NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
      Object msg;
      int saveReaderIndex;

      try {
        // decode object.
        do {
          saveReaderIndex = message.readerIndex();
          try {
            msg = codec.decode(channel, message);
          } catch (IOException e) {
            buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
            throw e;
          }
          if (msg == Codec2.DecodeResult.NEED_MORE_INPUT) {
            message.readerIndex(saveReaderIndex);
            break;
          } else {
            if (saveReaderIndex == message.readerIndex()) {
              buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
              throw new IOException("Decode without read data.");
            }
            if (msg != null) {
              ctx.fireChannelRead(msg);
            }
          }
        } while (message.readable());
      } finally {
        if (message.readable()) {
          message.discardReadBytes();
          buffer = message;
        } else {
          buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
        }
        NettyChannel.removeChannelIfDisconnected(ctx.channel());
      }
    }
  @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 ByteBuffer nioBuffer(int var1, int var2) {
   return a.nioBuffer(var1, var2);
 }
Example #17
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();
      }
    }
  }
Example #18
0
 private static ByteBuffer toByteBuffer(ByteBuf out, int index, int len) {
   return out.nioBufferCount() == 1
       ? out.internalNioBuffer(index, len)
       : out.nioBuffer(index, len);
 }
Example #19
0
 @Override
 public ByteBuffer nioBuffer(int index, int length) {
   return buf.nioBuffer(index, length);
 }
Example #20
0
 /**
  * @param buf
  * @param length
  */
 protected BaseDataBuffer(ByteBuf buf, int length) {
   allocationMode = Nd4j.alloc;
   this.wrappedBuffer = buf.nioBuffer();
   this.length = length;
 }
Example #21
0
  @Override
  protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
      throws SSLException {

    // Keeps the list of the length of every SSL record in the input buffer.
    int[] recordLengths = null;
    int nRecords = 0;

    final int startOffset = in.readerIndex();
    final int endOffset = in.writerIndex();
    int offset = startOffset;

    // If we calculated the length of the current SSL record before, use that information.
    if (packetLength > 0) {
      if (endOffset - startOffset < packetLength) {
        return;
      } else {
        recordLengths = new int[4];
        recordLengths[0] = packetLength;
        nRecords = 1;

        offset += packetLength;
        packetLength = 0;
      }
    }

    boolean nonSslRecord = false;

    for (; ; ) {
      final int readableBytes = endOffset - offset;
      if (readableBytes < 5) {
        break;
      }

      final int packetLength = getEncryptedPacketLength(in, offset);
      if (packetLength == -1) {
        nonSslRecord = true;
        break;
      }

      assert packetLength > 0;

      if (packetLength > readableBytes) {
        // wait until the whole packet can be read
        this.packetLength = packetLength;
        break;
      }

      // We have a whole packet.
      // Remember the length of the current packet.
      if (recordLengths == null) {
        recordLengths = new int[4];
      }
      if (nRecords == recordLengths.length) {
        recordLengths = Arrays.copyOf(recordLengths, recordLengths.length << 1);
      }
      recordLengths[nRecords++] = packetLength;

      // Increment the offset to handle the next packet.
      offset += packetLength;
    }

    final int totalLength = offset - startOffset;
    if (totalLength > 0) {
      // The buffer contains one or more full SSL records.
      // Slice out the whole packet so unwrap will only be called with complete packets.
      // Also directly reset the packetLength. This is needed as unwrap(..) may trigger
      // decode(...) again via:
      // 1) unwrap(..) is called
      // 2) wrap(...) is called from within unwrap(...)
      // 3) wrap(...) calls unwrapLater(...)
      // 4) unwrapLater(...) calls decode(...)
      //
      // See https://github.com/netty/netty/issues/1534
      in.skipBytes(totalLength);
      ByteBuffer buffer = in.nioBuffer(startOffset, totalLength);
      unwrapMultiple(ctx, buffer, totalLength, recordLengths, nRecords, out);
    }

    if (nonSslRecord) {
      // Not an SSL/TLS packet
      NotSslRecordException e =
          new NotSslRecordException("not an SSL/TLS record: " + ByteBufUtil.hexDump(in));
      in.skipBytes(in.readableBytes());
      ctx.fireExceptionCaught(e);
      setHandshakeFailure(e);
    }
  }