Пример #1
0
  /**
   * Return how much bytes can be read out of the encrypted data. Be aware that this method will not
   * increase the readerIndex of the given {@link ByteBuf}.
   *
   * @param buffer The {@link ByteBuf} to read from. Be aware that it must have at least 5 bytes to
   *     read, otherwise it will throw an {@link IllegalArgumentException}.
   * @return length The length of the encrypted packet that is included in the buffer. This will
   *     return {@code -1} if the given {@link ByteBuf} is not encrypted at all.
   * @throws IllegalArgumentException Is thrown if the given {@link ByteBuf} has not at least 5
   *     bytes to read.
   */
  private static int getEncryptedPacketLength(ByteBuf buffer, int offset) {
    int packetLength = 0;

    // SSLv3 or TLS - Check ContentType
    boolean tls;
    switch (buffer.getUnsignedByte(offset)) {
      case 20: // change_cipher_spec
      case 21: // alert
      case 22: // handshake
      case 23: // application_data
        tls = true;
        break;
      default:
        // SSLv2 or bad data
        tls = false;
    }

    if (tls) {
      // SSLv3 or TLS - Check ProtocolVersion
      int majorVersion = buffer.getUnsignedByte(offset + 1);
      if (majorVersion == 3) {
        // SSLv3 or TLS
        packetLength = buffer.getUnsignedShort(offset + 3) + 5;
        if (packetLength <= 5) {
          // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data)
          tls = false;
        }
      } else {
        // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data)
        tls = false;
      }
    }

    if (!tls) {
      // SSLv2 or bad data - Check the version
      boolean sslv2 = true;
      int headerLength = (buffer.getUnsignedByte(offset) & 0x80) != 0 ? 2 : 3;
      int majorVersion = buffer.getUnsignedByte(offset + headerLength + 1);
      if (majorVersion == 2 || majorVersion == 3) {
        // SSLv2
        if (headerLength == 2) {
          packetLength = (buffer.getShort(offset) & 0x7FFF) + 2;
        } else {
          packetLength = (buffer.getShort(offset) & 0x3FFF) + 3;
        }
        if (packetLength <= headerLength) {
          sslv2 = false;
        }
      } else {
        sslv2 = false;
      }

      if (!sslv2) {
        return -1;
      }
    }
    return packetLength;
  }
 protected void decode(ChannelHandlerContext context, ByteBuf buffer) throws Exception {
   ChannelPipeline pipeline = context.pipeline();
   if (detectSsl && SslHandler.isEncrypted(buffer)) {
     SSLEngine engine = SSL_SERVER_CONTEXT.getValue().createSSLEngine();
     engine.setUseClientMode(false);
     pipeline.addLast(
         new SslHandler(engine),
         new ChunkedWriteHandler(),
         new PortUnificationServerHandler(delegatingHttpRequestHandler, false, detectGzip));
   } else {
     int magic1 = buffer.getUnsignedByte(buffer.readerIndex());
     int magic2 = buffer.getUnsignedByte(buffer.readerIndex() + 1);
     if (detectGzip && magic1 == 31 && magic2 == 139) {
       pipeline.addLast(
           new JZlibEncoder(ZlibWrapper.GZIP),
           new JdkZlibDecoder(ZlibWrapper.GZIP),
           new PortUnificationServerHandler(delegatingHttpRequestHandler, detectSsl, false));
     } else if (isHttp(magic1, magic2)) {
       NettyUtil.initHttpHandlers(pipeline);
       pipeline.addLast(delegatingHttpRequestHandler);
       if (BuiltInServer.LOG.isDebugEnabled()) {
         pipeline.addLast(
             new ChannelOutboundHandlerAdapter() {
               @Override
               public void write(
                   ChannelHandlerContext context, Object message, ChannelPromise promise)
                   throws Exception {
                 if (message instanceof HttpResponse) {
                   //                BuiltInServer.LOG.debug("OUT HTTP:\n" + message);
                   HttpResponse response = (HttpResponse) message;
                   BuiltInServer.LOG.debug(
                       "OUT HTTP: "
                           + response.getStatus().code()
                           + " "
                           + response.headers().get("Content-type"));
                 }
                 super.write(context, message, promise);
               }
             });
       }
     } else if (magic1 == 'C' && magic2 == 'H') {
       buffer.skipBytes(2);
       pipeline.addLast(new CustomHandlerDelegator());
     } else {
       BuiltInServer.LOG.warn("unknown request, first two bytes " + magic1 + " " + magic2);
       context.close();
     }
   }
   // must be after new channels handlers addition (netty bug?)
   ensureThatExceptionHandlerIsLast(pipeline);
   pipeline.remove(this);
   context.fireChannelRead(buffer);
 }
Пример #3
0
  protected String formatBuffer(String message, ByteBuf buf) {
    int length = buf.readableBytes();
    int rows = length / 16 + (length % 15 == 0 ? 0 : 1) + 4;
    StringBuilder dump = new StringBuilder(rows * 80 + message.length() + 16);

    dump.append(message).append('(').append(length).append('B').append(')');
    dump.append(
        NEWLINE
            + "         +-------------------------------------------------+"
            + NEWLINE
            + "         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |"
            + NEWLINE
            + "+--------+-------------------------------------------------+----------------+");

    final int startIndex = buf.readerIndex();
    final int endIndex = buf.writerIndex();

    int i;
    for (i = startIndex; i < endIndex; i++) {
      int relIdx = i - startIndex;
      int relIdxMod16 = relIdx & 15;
      if (relIdxMod16 == 0) {
        dump.append(NEWLINE);
        dump.append(Long.toHexString(relIdx & 0xFFFFFFFFL | 0x100000000L));
        dump.setCharAt(dump.length() - 9, '|');
        dump.append('|');
      }
      dump.append(BYTE2HEX[buf.getUnsignedByte(i)]);
      if (relIdxMod16 == 15) {
        dump.append(" |");
        for (int j = i - 15; j <= i; j++) {
          dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]);
        }
        dump.append('|');
      }
    }

    if ((i - startIndex & 15) != 0) {
      int remainder = length & 15;
      dump.append(HEXPADDING[remainder]);
      dump.append(" |");
      for (int j = i - remainder; j < i; j++) {
        dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]);
      }
      dump.append(BYTEPADDING[remainder]);
      dump.append('|');
    }

    dump.append(
        NEWLINE + "+--------+-------------------------------------------------+----------------+");

    return dump.toString();
  }
  @Override
  public boolean applyProtocol(ByteBuf buffer, ChannelPipeline pipeline) {
    boolean isThisProtocol = false;
    int size = buffer.readableBytes();
    byte[] newb = new byte[size];
    buffer.copy().readBytes(newb);
    LOGGER.trace("{}", newb);

    final int opcode = buffer.getUnsignedByte(buffer.readerIndex() + 2);
    final int protocolVersion = buffer.getUnsignedByte(buffer.readerIndex() + 3);
    if (isNadProtocol(opcode, protocolVersion)) {
      pipeline.addLast("framer", createLengthBasedFrameDecoder());
      pipeline.addLast("eventDecoder", eventDecoder);
      pipeline.addLast(LOGIN_HANDLER_NAME, loginHandler);
      pipeline.addLast("lengthFieldPrepender", lengthFieldPrepender);
      pipeline.addLast("eventEncoder", eventEncoder);
      isThisProtocol = true;
    }
    return isThisProtocol;
  }
Пример #5
0
 /**
  * Returns a decoded TXT (text) resource record, stored as an {@link java.util.ArrayList} of
  * {@code String}s.
  *
  * @param response the DNS response that contains the resource record being decoded
  * @param resource the resource record being decoded
  */
 @Override
 public List<String> decode(DnsResponse response, DnsResource resource) {
   List<String> list = new ArrayList<String>();
   ByteBuf data = resource.content().readerIndex(response.originalIndex());
   int index = data.readerIndex();
   while (index < data.writerIndex()) {
     int len = data.getUnsignedByte(index++);
     list.add(data.toString(index, len, CharsetUtil.UTF_8));
     index += len;
   }
   return list;
 }
  public long decodeLength(ByteBuf in, int offset) throws Exception {
    if (discardingTooLongFrame) {
      long bytesToDiscard = this.bytesToDiscard;
      int localBytesToDiscard = (int) Math.min(bytesToDiscard, in.readableBytes());
      in.skipBytes(localBytesToDiscard);
      bytesToDiscard -= localBytesToDiscard;
      this.bytesToDiscard = bytesToDiscard;

      failIfNecessary(false);
    }

    int readerIndex = in.readerIndex() + offset;
    short b = in.getUnsignedByte(readerIndex);
    int ubyte = b & 0xff;

    LOGGER.trace("message: " + toHex(ubyte));

    switch (ubyte) {
      case NIL:
        return 1L;
      case FALSE:
        return 1L;
      case TRUE:
        return 1L;
      case BIN8:
        {
          short length = in.getUnsignedByte(readerIndex + 1);
          return 2L + length;
        }
      case BIN16:
        {
          int length = in.getUnsignedShort(readerIndex + 1);
          return 3L + length;
        }
      case BIN32:
        {
          long length = in.getUnsignedInt(readerIndex + 1);
          return 5L + length;
        }
      case EXT8:
        {
          short length = in.getUnsignedByte(readerIndex + 1);
          return 3L + length;
        }
      case EXT16:
        {
          int length = in.getUnsignedShort(readerIndex + 1);
          return 4L + length;
        }
      case EXT32:
        {
          long length = in.getUnsignedInt(readerIndex + 1);
          return 6L + length;
        }

      case FLOAT32:
        return 5L;
      case FLOAT64:
        return 9L;
      case UINT8:
        return 2L;
      case UINT16:
        return 3L;
      case UINT32:
        return 5L;
      case UINT64:
        return 9L;
      case INT8:
        return 2L;
      case INT16:
        return 3L;
      case INT32:
        return 5L;
      case INT64:
        return 9L;
      case FIXEXT1:
        return 3L;
      case FIXEXT2:
        return 4L;
      case FIXEXT4:
        return 6L;
      case FIXEXT8:
        return 10L;
      case FIXEXT16:
        return 18L;
      case STR8:
        {
          short length = in.getUnsignedByte(readerIndex + 1);
          return 2L + length;
        }
      case STR16:
        {
          int length = in.getUnsignedShort(readerIndex + 1);
          return 3L + length;
        }
      case STR32:
        {
          long length = in.getUnsignedInt(readerIndex + 1);
          return 5L + length;
        }
      case ARRAY16:
        {
          int elemCount = in.getUnsignedShort(readerIndex + 1);
          return getArraySize(in, 3, offset, elemCount);
        }
      case ARRAY32:
        {
          long elemCount = in.getUnsignedInt(readerIndex + 1);
          return getArraySize(in, 5, offset, elemCount);
        }
      case MAP16:
        {
          int elemCount = in.getUnsignedShort(readerIndex + 1);
          return getArraySize(in, 3, offset, elemCount * 2);
        }
      case MAP32:
        {
          long elemCount = in.getUnsignedInt(readerIndex + 1);
          return getArraySize(in, 5, offset, elemCount * 2);
        }
      default:
        if ((ubyte >> 7) == 0) { // positive fixint
          return 1L;
        } else if ((ubyte >> 4) == 0b1000) { // fixmap
          int elemCount = ubyte & 0b00001111;
          return getArraySize(in, 1, offset, elemCount * 2);
        } else if ((ubyte >> 4) == 0b1001) { // fixarray
          int elemCount = ubyte & 0b00001111;
          return getArraySize(in, 1, offset, elemCount);
        } else if ((ubyte >> 5) == 0b101) { // fixstr
          int length = ubyte & 0b00011111;
          return 1L + length;
        } else if ((ubyte >> 5) == 0b111) { // negative fixint
          return 1L;
        } else {
          throw new CorruptedFrameException("Unknown header byte of message: " + toHex(ubyte));
        }
    }
  }
Пример #7
0
 @Override
 public short getUnsignedByte(int index) {
   return buf.getUnsignedByte(index);
 }
Пример #8
0
  /**
   * Return how much bytes can be read out of the encrypted data. Be aware that this method will not
   * increase the readerIndex of the given {@link ByteBuf}.
   *
   * @param buffer The {@link ByteBuf} to read from. Be aware that it must have at least 5 bytes to
   *     read, otherwise it will throw an {@link IllegalArgumentException}.
   * @return length The length of the encrypted packet that is included in the buffer. This will
   *     return {@code -1} if the given {@link ByteBuf} is not encrypted at all.
   * @throws IllegalArgumentException Is thrown if the given {@link ByteBuf} has not at least 5
   *     bytes to read.
   */
  private static int getEncryptedPacketLength(ByteBuf buffer) {
    if (buffer.readableBytes() < 5) {
      throw new IllegalArgumentException("buffer must have at least 5 readable bytes");
    }

    int packetLength = 0;

    // SSLv3 or TLS - Check ContentType
    boolean tls;
    switch (buffer.getUnsignedByte(buffer.readerIndex())) {
      case 20: // change_cipher_spec
      case 21: // alert
      case 22: // handshake
      case 23: // application_data
        tls = true;
        break;
      default:
        // SSLv2 or bad data
        tls = false;
    }

    if (tls) {
      // SSLv3 or TLS - Check ProtocolVersion
      int majorVersion = buffer.getUnsignedByte(buffer.readerIndex() + 1);
      if (majorVersion == 3) {
        // SSLv3 or TLS
        packetLength = (getShort(buffer, buffer.readerIndex() + 3) & 0xFFFF) + 5;
        if (packetLength <= 5) {
          // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data)
          tls = false;
        }
      } else {
        // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data)
        tls = false;
      }
    }

    if (!tls) {
      // SSLv2 or bad data - Check the version
      boolean sslv2 = true;
      int headerLength = (buffer.getUnsignedByte(buffer.readerIndex()) & 0x80) != 0 ? 2 : 3;
      int majorVersion = buffer.getUnsignedByte(buffer.readerIndex() + headerLength + 1);
      if (majorVersion == 2 || majorVersion == 3) {
        // SSLv2
        if (headerLength == 2) {
          packetLength = (getShort(buffer, buffer.readerIndex()) & 0x7FFF) + 2;
        } else {
          packetLength = (getShort(buffer, buffer.readerIndex()) & 0x3FFF) + 3;
        }
        if (packetLength <= headerLength) {
          sslv2 = false;
        }
      } else {
        sslv2 = false;
      }

      if (!sslv2) {
        return -1;
      }
    }
    return packetLength;
  }
Пример #9
0
  public boolean decodePayload(final ByteBuf buf)
      throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
    LOG.debug(
        "About to pass message {} to {}. Buffer to read: {}.",
        message,
        message.senderSocket(),
        buf.readableBytes());
    if (!message.hasContent()) {
      return true;
    }

    // payload comes here
    int size;
    PublicKey receivedPublicKey;
    while (contentTypes.size() > 0) {
      Content content = contentTypes.peek();
      LOG.debug("Parse content: {} in message {}", content, message);
      switch (content) {
        case INTEGER:
          if (buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          message.intValue(buf.readInt());
          lastContent = contentTypes.poll();
          break;
        case LONG:
          if (buf.readableBytes() < Utils.LONG_BYTE_SIZE) {
            return false;
          }
          message.longValue(buf.readLong());
          lastContent = contentTypes.poll();
          break;
        case KEY:
          if (buf.readableBytes() < Number160.BYTE_ARRAY_SIZE) {
            return false;
          }
          byte[] me = new byte[Number160.BYTE_ARRAY_SIZE];
          buf.readBytes(me);
          message.key(new Number160(me));
          lastContent = contentTypes.poll();
          break;
        case BLOOM_FILTER:
          if (buf.readableBytes() < Utils.SHORT_BYTE_SIZE) {
            return false;
          }
          size = buf.getUnsignedShort(buf.readerIndex());
          if (buf.readableBytes() < size) {
            return false;
          }
          message.bloomFilter(new SimpleBloomFilter<Number160>(buf));
          lastContent = contentTypes.poll();
          break;
        case SET_NEIGHBORS:
          if (neighborSize == -1 && buf.readableBytes() < Utils.BYTE_BYTE_SIZE) {
            return false;
          }
          if (neighborSize == -1) {
            neighborSize = buf.readUnsignedByte();
          }
          if (neighborSet == null) {
            neighborSet = new NeighborSet(-1, new ArrayList<PeerAddress>(neighborSize));
          }
          for (int i = neighborSet.size(); i < neighborSize; i++) {
            if (buf.readableBytes() < Utils.SHORT_BYTE_SIZE) {
              return false;
            }
            int header = buf.getUnsignedShort(buf.readerIndex());
            size = PeerAddress.size(header);
            if (buf.readableBytes() < size) {
              return false;
            }
            PeerAddress pa = new PeerAddress(buf);
            neighborSet.add(pa);
          }
          message.neighborsSet(neighborSet);
          lastContent = contentTypes.poll();
          neighborSize = -1;
          neighborSet = null;
          break;
        case SET_PEER_SOCKET:
          if (peerSocketAddressSize == -1 && buf.readableBytes() < Utils.BYTE_BYTE_SIZE) {
            return false;
          }
          if (peerSocketAddressSize == -1) {
            peerSocketAddressSize = buf.readUnsignedByte();
          }
          if (peerSocketAddresses == null) {
            peerSocketAddresses = new ArrayList<PeerSocketAddress>(peerSocketAddressSize);
          }
          for (int i = peerSocketAddresses.size(); i < peerSocketAddressSize; i++) {
            if (buf.readableBytes() < Utils.BYTE_BYTE_SIZE) {
              return false;
            }
            int header = buf.getUnsignedByte(buf.readerIndex());
            boolean isIPv4 = header == 0;
            size = PeerSocketAddress.size(isIPv4);
            if (buf.readableBytes() < size + Utils.BYTE_BYTE_SIZE) {
              return false;
            }
            // skip the ipv4/ipv6 header
            buf.skipBytes(1);
            peerSocketAddresses.add(PeerSocketAddress.create(buf, isIPv4));
          }
          message.peerSocketAddresses(peerSocketAddresses);
          lastContent = contentTypes.poll();
          peerSocketAddressSize = -1;
          peerSocketAddresses = null;
          break;
        case SET_KEY640:
          if (keyCollectionSize == -1 && buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          if (keyCollectionSize == -1) {
            keyCollectionSize = buf.readInt();
          }
          if (keyCollection == null) {
            keyCollection = new KeyCollection(new ArrayList<Number640>(keyCollectionSize));
          }
          for (int i = keyCollection.size(); i < keyCollectionSize; i++) {
            if (buf.readableBytes()
                < Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE) {
              return false;
            }
            byte[] me2 = new byte[Number160.BYTE_ARRAY_SIZE];
            buf.readBytes(me2);
            Number160 locationKey = new Number160(me2);
            buf.readBytes(me2);
            Number160 domainKey = new Number160(me2);
            buf.readBytes(me2);
            Number160 contentKey = new Number160(me2);
            buf.readBytes(me2);
            Number160 versionKey = new Number160(me2);
            keyCollection.add(new Number640(locationKey, domainKey, contentKey, versionKey));
          }
          message.keyCollection(keyCollection);
          lastContent = contentTypes.poll();
          keyCollectionSize = -1;
          keyCollection = null;
          break;
        case MAP_KEY640_DATA:
          if (mapSize == -1 && buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          if (mapSize == -1) {
            mapSize = buf.readInt();
          }
          if (dataMap == null) {
            dataMap = new DataMap(new TreeMap<Number640, Data>());
          }
          if (data != null) {
            if (!data.decodeBuffer(buf)) {
              return false;
            }
            if (!data.decodeDone(buf, message.publicKey(0), signatureFactory)) {
              return false;
            }
            data = null;
            key = null;
          }
          for (int i = dataMap.size(); i < mapSize; i++) {
            if (key == null) {
              if (buf.readableBytes()
                  < Number160.BYTE_ARRAY_SIZE
                      + Number160.BYTE_ARRAY_SIZE
                      + Number160.BYTE_ARRAY_SIZE
                      + Number160.BYTE_ARRAY_SIZE) {
                return false;
              }
              byte[] me3 = new byte[Number160.BYTE_ARRAY_SIZE];
              buf.readBytes(me3);
              Number160 locationKey = new Number160(me3);
              buf.readBytes(me3);
              Number160 domainKey = new Number160(me3);
              buf.readBytes(me3);
              Number160 contentKey = new Number160(me3);
              buf.readBytes(me3);
              Number160 versionKey = new Number160(me3);
              key = new Number640(locationKey, domainKey, contentKey, versionKey);
            }
            LOG.debug("Key decoded in message {}, remaining {}", message, buf.readableBytes());
            data = Data.decodeHeader(buf, signatureFactory);
            if (data == null) {
              return false;
            }
            LOG.debug("Header decoded in message {}, remaining {}", message, buf.readableBytes());
            dataMap.dataMap().put(key, data);

            if (!data.decodeBuffer(buf)) {
              return false;
            }
            LOG.debug("Buffer decoded in message {}", message);
            if (!data.decodeDone(buf, message.publicKey(0), signatureFactory)) {
              return false;
            }
            LOG.debug("Done decoded in message {}", message);
            // if we have signed the message, set the public key anyway, but only if we indicated so
            inheritPublicKey(message, data);
            data = null;
            key = null;
          }

          message.setDataMap(dataMap);
          lastContent = contentTypes.poll();
          mapSize = -1;
          dataMap = null;
          break;
        case MAP_KEY640_KEYS:
          if (keyMap640KeysSize == -1 && buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          if (keyMap640KeysSize == -1) {
            keyMap640KeysSize = buf.readInt();
          }
          if (keyMap640Keys == null) {
            keyMap640Keys = new KeyMap640Keys(new TreeMap<Number640, Collection<Number160>>());
          }

          final int meta =
              Number160.BYTE_ARRAY_SIZE
                  + Number160.BYTE_ARRAY_SIZE
                  + Number160.BYTE_ARRAY_SIZE
                  + Number160.BYTE_ARRAY_SIZE;

          for (int i = keyMap640Keys.size(); i < keyMap640KeysSize; i++) {
            if (buf.readableBytes() < meta + Utils.BYTE_BYTE_SIZE) {
              return false;
            }
            size = buf.getUnsignedByte(buf.readerIndex() + meta);

            if (buf.readableBytes()
                < meta + Utils.BYTE_BYTE_SIZE + (size * Number160.BYTE_ARRAY_SIZE)) {
              return false;
            }
            byte[] me3 = new byte[Number160.BYTE_ARRAY_SIZE];
            buf.readBytes(me3);
            Number160 locationKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 domainKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 contentKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 versionKey = new Number160(me3);

            int numBasedOn = buf.readByte();
            Set<Number160> value = new HashSet<Number160>(numBasedOn);
            for (int j = 0; j < numBasedOn; j++) {
              buf.readBytes(me3);
              Number160 basedOnKey = new Number160(me3);
              value.add(basedOnKey);
            }

            keyMap640Keys.put(new Number640(locationKey, domainKey, contentKey, versionKey), value);
          }

          message.keyMap640Keys(keyMap640Keys);
          lastContent = contentTypes.poll();
          keyMap640KeysSize = -1;
          keyMap640Keys = null;
          break;
        case MAP_KEY640_BYTE:
          if (keyMapByteSize == -1 && buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          if (keyMapByteSize == -1) {
            keyMapByteSize = buf.readInt();
          }
          if (keyMapByte == null) {
            keyMapByte = new KeyMapByte(new HashMap<Number640, Byte>(2 * keyMapByteSize));
          }

          for (int i = keyMapByte.size(); i < keyMapByteSize; i++) {
            if (buf.readableBytes()
                < Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE
                    + Number160.BYTE_ARRAY_SIZE
                    + 1) {
              return false;
            }
            byte[] me3 = new byte[Number160.BYTE_ARRAY_SIZE];
            buf.readBytes(me3);
            Number160 locationKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 domainKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 contentKey = new Number160(me3);
            buf.readBytes(me3);
            Number160 versionKey = new Number160(me3);
            byte value = buf.readByte();
            keyMapByte.put(new Number640(locationKey, domainKey, contentKey, versionKey), value);
          }

          message.keyMapByte(keyMapByte);
          lastContent = contentTypes.poll();
          keyMapByteSize = -1;
          keyMapByte = null;
          break;
        case BYTE_BUFFER:
          if (bufferSize == -1 && buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) {
            return false;
          }
          if (bufferSize == -1) {
            bufferSize = buf.readInt();
          }
          if (buffer == null) {
            buffer = new DataBuffer();
          }

          final int remaining = bufferSize - bufferTransferred;
          bufferTransferred += buffer.transferFrom(buf, remaining);

          if (bufferTransferred < bufferSize) {
            LOG.debug(
                "Still looking for data. Indicating that its not finished yet. Already Transferred = {}, Size = {}.",
                bufferTransferred,
                bufferSize);
            return false;
          }

          message.buffer(new Buffer(buffer.toByteBuf(), bufferSize));
          lastContent = contentTypes.poll();
          bufferSize = -1;
          bufferTransferred = 0;
          buffer = null;
          break;
        case SET_TRACKER_DATA:
          if (trackerDataSize == -1 && buf.readableBytes() < Utils.BYTE_BYTE_SIZE) {
            return false;
          }
          if (trackerDataSize == -1) {
            trackerDataSize = buf.readUnsignedByte();
          }
          if (trackerData == null) {
            trackerData = new TrackerData(new HashMap<PeerAddress, Data>(2 * trackerDataSize));
          }
          if (currentTrackerData != null) {
            if (!currentTrackerData.decodeBuffer(buf)) {
              return false;
            }
            if (!currentTrackerData.decodeDone(buf, message.publicKey(0), signatureFactory)) {
              return false;
            }
            currentTrackerData = null;
          }
          for (int i = trackerData.size(); i < trackerDataSize; i++) {

            if (buf.readableBytes() < Utils.SHORT_BYTE_SIZE) {
              return false;
            }

            int header = buf.getUnsignedShort(buf.readerIndex());

            size = PeerAddress.size(header);

            if (buf.readableBytes() < size) {
              return false;
            }
            PeerAddress pa = new PeerAddress(buf);

            currentTrackerData = Data.decodeHeader(buf, signatureFactory);
            if (currentTrackerData == null) {
              return false;
            }
            trackerData.peerAddresses().put(pa, currentTrackerData);
            if (message.isSign()) {
              currentTrackerData.publicKey(message.publicKey(0));
            }

            if (!currentTrackerData.decodeBuffer(buf)) {
              return false;
            }
            if (!currentTrackerData.decodeDone(buf, message.publicKey(0), signatureFactory)) {
              return false;
            }
            currentTrackerData = null;
          }

          message.trackerData(trackerData);
          lastContent = contentTypes.poll();
          trackerDataSize = -1;
          trackerData = null;
          break;
        case PUBLIC_KEY: // fall-through
        case PUBLIC_KEY_SIGNATURE:
          receivedPublicKey = signatureFactory.decodePublicKey(buf);
          if (content == Content.PUBLIC_KEY_SIGNATURE) {
            if (receivedPublicKey == PeerBuilder.EMPTY_PUBLIC_KEY) {
              throw new InvalidKeyException("The public key cannot be empty.");
            }
          }
          if (receivedPublicKey == null) {
            return false;
          }

          message.publicKey(receivedPublicKey);
          lastContent = contentTypes.poll();
          break;
        default:
          break;
      }
    }
    LOG.debug("Parsed content in message {}", message);
    if (message.isSign()) {
      size = signatureFactory.signatureSize();
      if (buf.readableBytes() < size) {
        return false;
      }

      SignatureCodec signatureEncode = signatureFactory.signatureCodec(buf);
      message.receivedSignature(signatureEncode);
    }
    return true;
  }
 @Override
 public short getUnsignedByte(int var1) {
   return a.getUnsignedByte(var1);
 }