Peer-to-Peer Streaming Peer Protocol (PPSPP)
Extracted elements (31)
Bin numbers were designed to reduce per-peer state and wire overhead for expressing chunk intervals. By mapping binary tree intervals to a flat integer, PPSPP can use arrays instead of binary trees, reducing implementation complexity. A single bin number can compactly express any power-of-two-aligned interval.
BitTorrent distributes all chunk hashes upfront via .torrent metadata files. This is unsuitable for streaming because when chunks are small (as in PPSPP over UDP), it requires downloading a large number of hashes before content playback can begin, increasing time-till-playback. PPSPP's Merkle hash tree sends only the uncle hashes needed per chunk inline with the data.
PPSPP uses LEDBAT (RFC 6817) for congestion control so that seeding after download completes runs as background traffic, allowing the user to continue other network tasks without disruption. LEDBAT's low-extra-delay property makes it well suited for this background upload role.
PPSPP can be used in combination with STUN (RFC 5389) for NAT traversal. The channel multiplexing scheme is designed to be compatible with NATs and firewalls, allowing multiple swarms to share a single UDP port.
A HANDSHAKE message MUST always be the first message in a datagram.
ACK messages MUST be sent to acknowledge received chunks when PPSPP runs over an unreliable transport protocol. When LEDBAT is used, an ACK message MUST contain the one-way delay computed from the sender's system time received in the DATA message.
All peers in a swarm MUST use the same chunk addressing method.
For live streaming over the Internet, the Unified Merkle Tree method MUST be used for content authentication. The RSASHA1, RSASHA256, ECDSAP256SHA256, and ECDSAP384SHA384 algorithms are mandatory to implement.
For static content, the Merkle Hash Tree scheme MUST be used when PPSPP operates over the Internet, to satisfy the IETF requirement for strong security (RFC 3365). It MAY be used in benign environments. The scheme is therefore mandatory to implement.
If any check by the receiving Peer Q fails, or if the peers are not in the same swarm, Peer Q MUST NOT send a HANDSHAKE or any other message back, as the message from Peer P may have been spoofed.
Multiple messages MUST be multiplexed into a single datagram for transmission. Messages in a single datagram MUST be processed in the strict order in which they appear. If an invalid message is found in a datagram, the remaining messages MUST be discarded.
PEX_RESv4 (single IPv4 address and port) and PEX_RESv6 (single IPv6 address and port) messages MUST only be used in a benign environment such as a private network, as they provide no guarantee that the addressed host actually participates in a PPSPP swarm.
The Atomic Datagram Principle requires each datagram to be independently processable. The INTEGRITY messages (uncle hashes) needed to verify a chunk SHOULD be in the same datagram as the DATA message; if datagram size prevents this, the INTEGRITY messages MUST be sent first in one or more preceding datagrams.
The DATA message MUST contain the chunk ID of the chunk and the chunk itself. Because PPSPP currently uses LEDBAT (RFC 6817) for congestion control, the current system time MUST be included in every DATA message.
The first datagram from initiating Peer P MUST NOT include any heavy payload (DATA messages, SIGNED_INTEGRITY messages, or a large number of smaller messages). This prevents an amplification attack where a spoofed source address causes the responder to flood a victim.
When Peer B receives a CHOKE message from Peer A, it MUST NOT send new REQUEST messages and cannot expect answers to outstanding ones. When choked but receiving a HAVE from Peer A, Peer B is not automatically unchoked and MUST NOT send any new REQUEST messages.
Whenever a receiving peer has successfully checked the integrity of a chunk or interval of chunks, it MUST send a HAVE message to all peers it wants to allow to download those chunks. The HAVE message MUST contain the chunk specification of the biggest complete interval of all verified chunks covering the newly received interval.
Channels provide multiplexing allowing multiple swarms to share the same transport address. In the UDP encapsulation every datagram is prefixed with the 4-byte channel ID allocated by the receiving peer. Channel IDs must be randomly chosen. Channel ID 0 is reserved for handshake initiation.
In the Unified Merkle Tree scheme, the live injector generates NCHUNKS_PER_SIG chunks (a fixed power of 2, ≥2) per cycle, computes a munro hash (root of the new subtree), signs it with the swarm private key, and sends a SIGNED_INTEGRITY message containing the signed munro hash before the uncle hashes and DATA for each requested chunk. Peers verify the munro signature using the swarm public key (the swarm ID).
Peak hashes enable automatic content size detection when fixed-size chunks are used. A peak hash is the hash of a filled Merkle tree node whose sibling is incomplete; the set of peak hashes corresponds to the '1' bits in the binary representation of the chunk count. A newcomer peer verifies received peak hashes against the trusted root hash to determine approximate file size, then fetches the last chunk to get the exact size.
The INTEGRITY message carries cryptographic hashes enabling the receiver to verify chunk integrity. Under the Merkle Hash Tree scheme it MUST contain a hash of a subtree and the chunk specification identifying that subtree. A datagram carrying a chunk MUST consist of a list of INTEGRITY messages sorted descending by tree height, followed by a DATA message.
The SIGNED_INTEGRITY message carries a digitally signed chunk specification, timestamp, and digital signature for live stream content authentication. Its exact payload depends on the live content integrity protection scheme in use (Sign All or Unified Merkle Tree).
RFC 7574 creates six IANA registries: PPSPP Message Type, PPSPP Option, PPSPP Version Number, PPSPP Content Integrity Protection Method, PPSPP Merkle Hash Tree Function, and PPSPP Chunk Addressing Method. All use the Specification Required policy.
Channel IDs must be randomly chosen and the handshake requires the initiator's channel ID to be echoed in the responder's reply datagram prefix. This three-way check ensures both peers are reachable at their claimed addresses and prevents replay and spoofing attacks.
Implementations must limit resource exhaustion from bad or broken peers by enforcing per-message constraints: discarding unexpected HAVEs before handshake completion, ignoring DATA for unrequested chunks, rate-limiting PEX responses, and discarding unsolicited messages. Peers classified as bad (non-responsive or sending invalid messages) should be excluded from further communication.
The prohibition on heavy payload in the initial handshake datagram directly prevents amplification attacks: a spoofed initial HANDSHAKE cannot cause the responder to send large DATA payloads to the forged source address.
To prevent eclipse attacks via PEX, peers MUST ensure that part of their connections are to peers whose addresses came from a trusted and secured tracker. A peer must not obtain all its peer addresses through PEX alone.
The handshake follows a three-way procedure: (1) initiating Peer P sends a HANDSHAKE with random chanP and swarm metadata, prefixed with destination channel ID 0; (2) responding Peer Q replies with HANDSHAKE containing chanQ, prefixed with chanP; (3) the channel is fully established when Peer Q receives a datagram from Peer P carrying chanQ. Either peer may close with an all-zeros channel ID HANDSHAKE.
The Bin Numbers scheme encodes a binary interval of chunks as a single 32-bit or 64-bit integer. Leaf bins use even numbers (chunk index × 2); parent bin = (leftBin + rightBin) / 2. The special value 0xFFFFFFFF (32-bit) or 0xFFFFFFFFFFFFFFFF (64-bit) denotes an empty interval; 0x7FFF...FFF denotes 'everything'. Support is optional.
The Chunk Ranges scheme encodes a chunk specification as a (start chunk, end chunk) pair of 32-bit or 64-bit unsigned integers (end inclusive). Support is mandatory for all PPSPP peers. The optional Byte Ranges scheme uses two 64-bit byte offsets instead.
The live streaming swarm ID is a public key encoded as in a DNSSEC DNSKEY resource record (without Base64): a 1-byte Algorithm Number field (from the DNSSEC Algorithm Numbers registry) followed by a variable-length DNSSEC Public Key field.