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; }
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; }