Class ProtectedPacket
java.lang.Object
io.github.mahmoudimus.quic.packet.ProtectedPacket
A packet whose unprotected header fields are parsed but whose packet number and payload are
still protected: quinn's
PartialDecode. The version, type and connection IDs are enough
to pick the keys; the sample offset is where header protection
samples. Removing protection works in place on the datagram buffer:
ProtectedPacket p = ProtectedPacket.parse(datagram, localIdLength);
PacketHeader.Numbered h = p.removeHeaderProtection(keys.remote().header(), largestReceived);
Packet packet = p.decrypt(keys.remote().packet()); // null if authentication failed
A Retry or Version Negotiation packet is fully decoded by parse(java.nio.ByteBuffer, int); see header().
Instances are single-use and not thread-safe; they share content with the datagram buffer.
-
Method Summary
Modifier and TypeMethodDescriptionbytes()A view of the whole packet, header protection included or removed as it stands.Opens the payload in place, once header protection is removed.The Destination Connection ID.intend()The index just past this packet in the datagram buffer.header()The decoded header: available at once for Retry and Version Negotiation packets, and for protected packets afterremoveHeaderProtection(io.github.mahmoudimus.quic.crypto.HeaderKey, long).intlength()The packet length, header and tag included.intThe index of the (protected) packet number.static ProtectedPacketparse(ByteBuffer datagram, int shortHeaderIdLength) Parses the packet at the buffer's position, requiring the Fixed Bit.static ProtectedPacketparse(ByteBuffer datagram, int shortHeaderIdLength, boolean allowClearFixedBit) Parses the packet at the buffer's position.removeHeaderProtection(HeaderKey key, long largestPacketNumber) Removes header protection in place and recovers the full packet number.intThe index of the header protection sample: four bytes past the start of the packet number.sourceId()The Source Connection ID of a long header.static List<ProtectedPacket> splitDatagram(ByteBuffer datagram, int shortHeaderIdLength, boolean allowClearFixedBit) Splits a datagram into its coalesced packets (RFC 9000 section 12.2).intstart()The index of the first byte of this packet in the datagram buffer.byte[]token()The token of an Initial or Retry packet.type()The packet type.unprotect(DirectionalKeys keys, long largestPacketNumber) Removes header and payload protection in one step, for levels without key phases.booleanverifyRetry(ConnectionId originalDestinationId) Checks the integrity tag of a Retry packet (RFC 9001 section 5.8).version()The QUIC version of a long header.
-
Method Details
-
parse
public static ProtectedPacket parse(ByteBuffer datagram, int shortHeaderIdLength) throws PacketDecodeException Parses the packet at the buffer's position, requiring the Fixed Bit.- Parameters:
datagram- the datagram; on success its position moves to the end of this packet, which for short headers, Retry and Version Negotiation is the buffer's limitshortHeaderIdLength- the length of this endpoint's connection IDs, which short headers do not encode- Returns:
- the packet
- Throws:
UnsupportedVersionException- for a long header of a version other than 1 and 2PacketDecodeException- if the header is malformed; the position is then unchanged
-
parse
public static ProtectedPacket parse(ByteBuffer datagram, int shortHeaderIdLength, boolean allowClearFixedBit) throws PacketDecodeException Parses the packet at the buffer's position.- Parameters:
datagram- the datagram; on success its position moves to the end of this packetshortHeaderIdLength- the length of this endpoint's connection IDsallowClearFixedBit- whether to accept a cleared Fixed Bit, as an endpoint that sent thegrease_quic_bittransport parameter must (RFC 9287)- Returns:
- the packet
- Throws:
UnsupportedVersionException- for a long header of a version other than 1 and 2PacketDecodeException- if the header is malformed; the position is then unchanged
-
splitDatagram
public static List<ProtectedPacket> splitDatagram(ByteBuffer datagram, int shortHeaderIdLength, boolean allowClearFixedBit) throws PacketDecodeException Splits a datagram into its coalesced packets (RFC 9000 section 12.2). Parsing stops, and the rest of the datagram is ignored, at the first packet after the first that fails to parse or carries a different Destination Connection ID.- Parameters:
datagram- the datagram between its position and limit; the buffer's position is not changed, but protection is later removed in its contentshortHeaderIdLength- the length of this endpoint's connection IDsallowClearFixedBit- whether to accept a cleared Fixed Bit (RFC 9287)- Returns:
- the packets, at least one
- Throws:
PacketDecodeException- if the first packet cannot be parsed
-
type
The packet type.- Returns:
- the type
-
version
The QUIC version of a long header.- Returns:
- the version, or null for short headers and Version Negotiation
-
destinationId
The Destination Connection ID.- Returns:
- the connection ID
-
sourceId
The Source Connection ID of a long header.- Returns:
- the connection ID, or null for short headers
-
token
public byte[] token()The token of an Initial or Retry packet.- Returns:
- a copy of the token, or null for other types
-
start
public int start()The index of the first byte of this packet in the datagram buffer.- Returns:
- the absolute start index
-
end
public int end()The index just past this packet in the datagram buffer.- Returns:
- the absolute end index
-
length
public int length()The packet length, header and tag included.- Returns:
end() - start()
-
packetNumberOffset
public int packetNumberOffset()The index of the (protected) packet number.- Returns:
- the absolute index, or -1 for Retry and Version Negotiation
-
sampleOffset
public int sampleOffset()The index of the header protection sample: four bytes past the start of the packet number.- Returns:
- the absolute index, or -1 for Retry and Version Negotiation
-
bytes
A view of the whole packet, header protection included or removed as it stands.- Returns:
- a new buffer over
[start(), end())
-
header
The decoded header: available at once for Retry and Version Negotiation packets, and for protected packets afterremoveHeaderProtection(io.github.mahmoudimus.quic.crypto.HeaderKey, long).- Returns:
- the header, or null before header protection is removed
-
verifyRetry
Checks the integrity tag of a Retry packet (RFC 9001 section 5.8).- Parameters:
originalDestinationId- the Destination Connection ID of the client's first Initial- Returns:
- true if the tag is valid
- Throws:
IllegalStateException- if this is not a Retry packet
-
removeHeaderProtection
Removes header protection in place and recovers the full packet number.- Parameters:
key- the header protection key of the packet's level (it is the same for both key phases)largestPacketNumber- the largest packet number successfully processed in this packet number space, or -1 if none- Returns:
- the header; for short headers it carries the key phase that picks the packet key
- Throws:
IllegalStateException- if the packet is not protected or protection was already removed
-
decrypt
Opens the payload in place, once header protection is removed. After authentication succeeds, the reserved header bits must be zero (RFC 9000 section 17).- Parameters:
key- the packet key for the packet's level and, for 1-RTT, its key phase- Returns:
- the packet, or null if it failed authentication (drop it; its payload bytes are then unspecified)
- Throws:
QuicException- withPROTOCOL_VIOLATIONif an authenticated packet has reserved bits setIllegalStateException- if header protection was not removed first
-
unprotect
Removes header and payload protection in one step, for levels without key phases.- Parameters:
keys- the receiver's keys for the packet's level (Keys.remote())largestPacketNumber- the largest packet number processed in this space, or -1- Returns:
- the packet, or null if it failed authentication
- Throws:
QuicException- withPROTOCOL_VIOLATIONif reserved bits are set
-