Example #1
0
  public static NPFPacket create(byte[] plaintext, BasePeerNode pn) {
    NPFPacket packet = new NPFPacket();
    if (pn == null)
      throw new IllegalArgumentException("Can't estimate an ack type of received packet");
    int offset = 0;

    if (plaintext.length < (offset + 5)) { // Sequence number + the number of acks
      packet.error = true;
      return packet;
    }

    packet.sequenceNumber =
        ((plaintext[offset] & 0xFF) << 24)
            | ((plaintext[offset + 1] & 0xFF) << 16)
            | ((plaintext[offset + 2] & 0xFF) << 8)
            | (plaintext[offset + 3] & 0xFF);
    offset += 4;

    // Process received acks

    int numAckRanges = plaintext[offset++] & 0xFF;
    if (numAckRanges > 0) {
      try {
        int ack, prevAck = 0;

        for (int i = 0; i < numAckRanges; i++) {
          if (i == 0) {
            ack =
                ((plaintext[offset] & 0xFF) << 24)
                    | ((plaintext[offset + 1] & 0xFF) << 16)
                    | ((plaintext[offset + 2] & 0xFF) << 8)
                    | (plaintext[offset + 3] & 0xFF);
            offset += 4;
          } else {
            int distanceFromPrevious = (plaintext[offset++] & 0xFF);
            if (distanceFromPrevious != 0) {
              ack = prevAck + distanceFromPrevious;
            } else {
              // Far offset
              ack =
                  ((plaintext[offset] & 0xFF) << 24)
                      | ((plaintext[offset + 1] & 0xFF) << 16)
                      | ((plaintext[offset + 2] & 0xFF) << 8)
                      | (plaintext[offset + 3] & 0xFF);
              offset += 4;
            }
          }

          int rangeSize = (plaintext[offset++] & 0xFF);
          for (int j = 1; j <= rangeSize; j++) {
            packet.acks.add(ack++);
          }

          prevAck = ack - 1;
        }
      } catch (ArrayIndexOutOfBoundsException e) {
        // The packet's length is not big enough
        packet.error = true;
        return packet;
      }
    }

    // Handle received message fragments
    int prevFragmentID = -1;
    while (offset < plaintext.length) {
      boolean shortMessage = (plaintext[offset] & 0x80) != 0;
      boolean isFragmented = (plaintext[offset] & 0x40) != 0;
      boolean firstFragment = (plaintext[offset] & 0x20) != 0;

      if (!isFragmented && !firstFragment) {
        // Padding or lossy messages.
        offset = tryParseLossyMessages(packet, plaintext, offset);
        break;
      }

      int messageID = -1;
      if ((plaintext[offset] & 0x10) != 0) {
        if (plaintext.length < (offset + 4)) {
          packet.error = true;
          return packet;
        }

        messageID =
            ((plaintext[offset] & 0x0F) << 24)
                | ((plaintext[offset + 1] & 0xFF) << 16)
                | ((plaintext[offset + 2] & 0xFF) << 8)
                | (plaintext[offset + 3] & 0xFF);
        offset += 4;
      } else {
        if (plaintext.length < (offset + 2)) {
          packet.error = true;
          return packet;
        }

        if (prevFragmentID == -1) {
          Logger.warning(NPFPacket.class, "First fragment doesn't have full message id");
          packet.error = true;
          return packet;
        }
        messageID =
            prevFragmentID + (((plaintext[offset] & 0x0F) << 8) | (plaintext[offset + 1] & 0xFF));
        offset += 2;
      }
      prevFragmentID = messageID;

      int requiredLength =
          offset + (shortMessage ? 1 : 2) + (isFragmented ? (shortMessage ? 1 : 3) : 0);
      if (plaintext.length < requiredLength) {
        packet.error = true;
        return packet;
      }

      int fragmentLength;
      if (shortMessage) {
        fragmentLength = plaintext[offset++] & 0xFF;
      } else {
        fragmentLength = ((plaintext[offset] & 0xFF) << 8) | (plaintext[offset + 1] & 0xFF);
        offset += 2;
      }

      int messageLength = -1;
      int fragmentOffset = 0;
      if (isFragmented) {
        int value;
        if (shortMessage) {
          value = plaintext[offset++] & 0xFF;
        } else {
          value = ((plaintext[offset] & 0xFF) << 8) | (plaintext[offset + 1] & 0xFF);
          offset += 2;
        }

        if (firstFragment) {
          messageLength = value;
          if (messageLength == fragmentLength) {
            Logger.warning(
                NPFPacket.class,
                "Received fragmented message, but fragment contains the entire message");
          }
        } else {
          fragmentOffset = value;
        }
      } else {
        messageLength = fragmentLength;
      }
      if ((offset + fragmentLength) > plaintext.length) {
        Logger.error(
            NPFPacket.class,
            "Fragment doesn't fit in the received packet: offset is "
                + offset
                + " fragment length is "
                + fragmentLength
                + " plaintext length is "
                + plaintext.length
                + " message length "
                + messageLength
                + " message ID "
                + messageID
                + (pn == null ? "" : (" from " + pn.shortToString())));
        packet.error = true;
        break;
      }
      byte[] fragmentData = Arrays.copyOfRange(plaintext, offset, offset + fragmentLength);
      offset += fragmentLength;

      packet.fragments.add(
          new MessageFragment(
              shortMessage,
              isFragmented,
              firstFragment,
              messageID,
              fragmentLength,
              messageLength,
              fragmentOffset,
              fragmentData,
              null));
    }

    packet.length = offset;

    return packet;
  }
Example #2
0
  public static NPFPacket create(byte[] plaintext, BasePeerNode pn) {
    NPFPacket packet = new NPFPacket();
    int offset = 0;

    if (plaintext.length < (offset + 5)) { // Sequence number + the number of acks
      packet.error = true;
      return packet;
    }

    packet.sequenceNumber =
        ((plaintext[offset] & 0xFF) << 24)
            | ((plaintext[offset + 1] & 0xFF) << 16)
            | ((plaintext[offset + 2] & 0xFF) << 8)
            | (plaintext[offset + 3] & 0xFF);
    offset += 4;

    // Process received acks
    int numAcks = plaintext[offset++] & 0xFF;
    if (plaintext.length < (offset + numAcks + (numAcks > 0 ? 3 : 0))) {
      packet.error = true;
      return packet;
    }

    int prevAck = 0;
    for (int i = 0; i < numAcks; i++) {
      int ack = 0;
      if (i == 0) {
        ack =
            ((plaintext[offset] & 0xFF) << 24)
                | ((plaintext[offset + 1] & 0xFF) << 16)
                | ((plaintext[offset + 2] & 0xFF) << 8)
                | (plaintext[offset + 3] & 0xFF);
        offset += 4;
      } else {
        ack = prevAck + (plaintext[offset++] & 0xFF);
      }
      packet.acks.add(ack);
      prevAck = ack;
    }

    // Handle received message fragments
    int prevFragmentID = -1;
    while (offset < plaintext.length) {
      boolean shortMessage = (plaintext[offset] & 0x80) != 0;
      boolean isFragmented = (plaintext[offset] & 0x40) != 0;
      boolean firstFragment = (plaintext[offset] & 0x20) != 0;

      if (!isFragmented && !firstFragment) {
        // Padding or lossy messages.
        offset = tryParseLossyMessages(packet, plaintext, offset);
        break;
      }

      int messageID = -1;
      if ((plaintext[offset] & 0x10) != 0) {
        if (plaintext.length < (offset + 4)) {
          packet.error = true;
          return packet;
        }

        messageID =
            ((plaintext[offset] & 0x0F) << 24)
                | ((plaintext[offset + 1] & 0xFF) << 16)
                | ((plaintext[offset + 2] & 0xFF) << 8)
                | (plaintext[offset + 3] & 0xFF);
        offset += 4;
      } else {
        if (plaintext.length < (offset + 2)) {
          packet.error = true;
          return packet;
        }

        if (prevFragmentID == -1) {
          Logger.warning(NPFPacket.class, "First fragment doesn't have full message id");
          packet.error = true;
          return packet;
        }
        messageID =
            prevFragmentID + (((plaintext[offset] & 0x0F) << 8) | (plaintext[offset + 1] & 0xFF));
        offset += 2;
      }
      prevFragmentID = messageID;

      int requiredLength =
          offset + (shortMessage ? 1 : 2) + (isFragmented ? (shortMessage ? 1 : 3) : 0);
      if (plaintext.length < requiredLength) {
        packet.error = true;
        return packet;
      }

      int fragmentLength;
      if (shortMessage) {
        fragmentLength = plaintext[offset++] & 0xFF;
      } else {
        fragmentLength = ((plaintext[offset] & 0xFF) << 8) | (plaintext[offset + 1] & 0xFF);
        offset += 2;
      }

      int messageLength = -1;
      int fragmentOffset = 0;
      if (isFragmented) {
        int value;
        if (shortMessage) {
          value = plaintext[offset++] & 0xFF;
        } else {
          value = ((plaintext[offset] & 0xFF) << 8) | (plaintext[offset + 1] & 0xFF);
          offset += 2;
        }

        if (firstFragment) {
          messageLength = value;
          if (messageLength == fragmentLength) {
            Logger.warning(
                NPFPacket.class,
                "Received fragmented message, but fragment contains the entire message");
          }
        } else {
          fragmentOffset = value;
        }
      } else {
        messageLength = fragmentLength;
      }
      byte[] fragmentData = new byte[fragmentLength];
      if ((offset + fragmentLength) > plaintext.length) {
        Logger.error(
            NPFPacket.class,
            "Fragment doesn't fit in the received packet: offset is "
                + offset
                + " fragment length is "
                + fragmentLength
                + " plaintext length is "
                + plaintext.length
                + " message length "
                + messageLength
                + " message ID "
                + messageID
                + (pn == null ? "" : (" from " + pn.shortToString())));
        packet.error = true;
        break;
      }
      System.arraycopy(plaintext, offset, fragmentData, 0, fragmentLength);
      offset += fragmentLength;

      packet.fragments.add(
          new MessageFragment(
              shortMessage,
              isFragmented,
              firstFragment,
              messageID,
              fragmentLength,
              messageLength,
              fragmentOffset,
              fragmentData,
              null));
    }

    packet.length = offset;

    return packet;
  }