WebRTC-HTTP Ingestion Protocol (WHIP)
updates
- rfc-8840 — A Session Initiation Protocol (SIP) Usage for Incremental Provisioning of Candidates for the Interactive Connectivity Establishment (Trickle ICE)
- rfc-8842 — Session Description Protocol (SDP) Offer/Answer Considerations for Datagram Transport Layer Security (DTLS) and Transport Layer Security (TLS)
Extracted elements (31)
The 'rel' attribute value 'ice-server' for STUN/TURN Link headers is intentionally not prefixed with 'urn:ietf:params:whip:' so it can be reused by other specifications that need to configure STUN/TURN servers, making the mechanism more broadly applicable.
The WHIP client is permitted to use SDP 'setup:active' (DTLS client role only) despite RFC 8842 requiring 'actpass' from the offerer. The rationale is that a WHIP client always communicates with a media server expected to support the DTLS server role, so a client-only DTLS implementation is a valid simplification.
The WHIP endpoint SHALL gather all ICE candidates before responding to the client and return them in the SDP answer; the server cannot trickle ICE candidates after the answer. This asymmetry simplifies the protocol by eliminating server-to-client PATCH signaling.
WHIP explicitly does not support SDP renegotiation: no modifications to 'm=' sections are permitted after the initial offer/answer exchange. Only ICE-related information can be updated via HTTP PATCH. This simplification lowers implementation complexity for both hardware encoders and media servers.
Some WebRTC implementations do not support updating STUN/TURN configuration after the local offer is created. To accommodate these clients, the WHIP endpoint MAY include STUN/TURN configuration in OPTIONS responses before the POST, though this is NOT RECOMMENDED for WHIP clients to rely upon.
WHIP updates RFC 8840 (Trickle ICE for SIP) by specifying that a WHIP session receiving updated 'ice-pwd' and 'ice-ufrag' attributes MUST treat the request as an ICE restart rather than discarding it as RFC 8840 requires, enabling ICE restarts via HTTP PATCH.
All WHIP entities MUST support HTTP authentication per RFC 9110. Bearer token authentication as defined in RFC 6750 MUST be supported by all WHIP endpoints, sessions, and clients. WHIP clients MUST send the Authorization header in all HTTP requests (except CORS preflight OPTIONS).
Both the WHIP client and WHIP endpoint SHALL support RFC 9143 and use the 'max-bundle' policy. They MUST support multiplexed media per RFC 9143 Section 9 and SHALL use RTP/RTCP multiplexing. Both MUST include the 'rtcp-mux-only' attribute in each bundled 'm=' section per RFC 8858.
ICE operations (Trickle ICE and ICE restarts) are performed via HTTP PATCH requests to the WHIP session URL. The PATCH body MUST have content type 'application/trickle-ice-sdpfrag'; any other content type or malformed SDP fragment MUST be rejected with an appropriate 4xx.
If the WHIP session supports ICE restarts, it MUST generate a unique strong entity-tag identifying the ICE session and return it in an ETag header in the '201 Created' response. Missing ETags in PATCH requests MUST elicit '428 Precondition Required'; mismatched ETags MUST elicit '412 Precondition Failed'.
Once a WHIP session is established, consent freshness per RFC 7675 SHALL be used to detect non-graceful disconnection. To explicitly terminate a session, the WHIP client MUST send an HTTP DELETE to the WHIP session URL from the Location header of the initial POST.
Protocol extensions supported by WHIP sessions MUST be advertised via Link header fields in the '201 Created' response. Each extension MUST register a unique URN starting with 'urn:ietf:params:whip:ext'. WHIP clients MUST ignore unknown 'rel' values; sessions MUST NOT require any extension.
The WHIP client MUST implement and use full ICE. The media server SHOULD support full ICE unless it has a publicly reachable IP for all authorized clients, in which case it MAY support only ICE lite.
The WHIP client MUST wait and buffer all gathered ICE candidates until the '201 Created' response is received before sending them, because the WHIP session URL is not known until then. The client SHOULD send a single aggregated HTTP PATCH with all buffered candidates.
The WHIP client SHOULD use the 'sendonly' attribute in the SDP offer (MAY use 'sendrecv'); the 'inactive' and 'recvonly' attributes MUST NOT be used. The WHIP endpoint MUST use the 'recvonly' attribute in the SDP answer, enforcing unidirectional media ingestion.
The WHIP endpoint MUST return a '201 Created' response with content type 'application/sdp', the SDP answer as the body, and a Location header field pointing to the newly created WHIP session URL. The SDP answer MUST be generated per JSEP initial answer rules.
The WHIP endpoint SHOULD NOT reject individual 'm=' sections on error; instead it SHOULD reject the entire HTTP POST with '422 Unprocessable Content' or '400 Bad Request' to prevent partially successful ingest sessions that could mislead end users.
To set up an ingest session, the WHIP client MUST send an HTTP POST request to the configured WHIP endpoint URL with a content type of 'application/sdp' containing an SDP offer generated per JSEP rules. If the content type differs or the SDP is malformed, the endpoint MUST reject with an appropriate 4xx error.
When a WHIP session receives a PATCH adding ICE candidates without an ICE restart, it MUST return '204 No Content' with no body and MUST NOT include an ETag header. Unsupported candidate transports MUST be silently discarded without failing the request.
When performing an ICE restart, the WHIP client MUST include updated 'ice-pwd' and 'ice-ufrag' in the PATCH body and MUST include an If-Match header with value '*'. The WHIP session MUST return '200 OK' with a new entity-tag and new ICE credentials/candidates in the response body.
WHIP clients SHALL support HTTP redirections per RFC 9110. Status codes '301 Moved Permanently' and '302 Found' MUST NOT be used for load balancing POST requests; '307 Temporary Redirect' is the preferred method to avoid POST-to-GET conversion.
WHIP supports only a single MediaStream: all 'm=' sections MUST contain a 'msid' attribute with the same value, and the MediaStream MUST NOT have two or more MediaStreamTracks of the same media kind. If these constraints are violated, the endpoint MUST reject with '422 Unprocessable Content' or '400 Bad Request'.
Protocol extensions are signaled by the WHIP endpoint via Link header fields in the '201 Created' response, where the 'rel' attribute contains the extension URN (prefixed 'urn:ietf:params:whip:ext') and the Link URL is the HTTP resource for that extension.
STUN/TURN server configuration is returned in the '201 Created' response via Link header fields with rel='ice-server'. The Link target URI is the server URI (RFC 7064/7065); credentials are encoded as 'username' and 'credential' Link target attributes for TURN servers.
The WHIP session URL is returned in the Location header field of the '201 Created' response to the initial HTTP POST. This URL is used for all subsequent PATCH requests (ICE operations) and DELETE requests (session termination).
IANA created the 'WebRTC-HTTP Ingestion Protocol (WHIP) URNs' registry (urn:ietf:params:whip namespace) and the 'WebRTC-HTTP Ingestion Protocol (WHIP) Extension URNs' registry (urn:ietf:params:whip:ext namespace), both with 'Specification Required' registration policy.
IANA registered a new link relation type 'ice-server' in the 'Link Relation Types' registry per RFC 8288. It conveys STUN and TURN server URIs usable by an ICE agent to establish a peer connection.
HTTP POST flooding can cause resource exhaustion: an authenticated attacker can submit many POST requests, forcing the endpoint to allocate ICE/DTLS resources that are held until timeout. WHIP endpoints SHOULD implement rate limiting and avalanche control for incoming POST requests.
HTTPS SHALL be used for all WHIP signaling to preserve the WebRTC security model. Security considerations from RFC 8826 (WebRTC security), RFC 8446 (TLS 1.3), RFC 9147 (DTLS 1.3), and RFC 9110 (HTTP) all apply.
Insecure Direct Object References (IDORs): if WHIP session URLs are guessable, an attacker can send HTTP DELETE requests to terminate all running sessions. Endpoints SHOULD generate session URLs with sufficient randomness using a CSPRNG per RFC 4086, and SHOULD rate-limit DELETE requests.
WHIP session lifecycle: (1) WHIP client sends HTTP POST with SDP offer → endpoint returns 201 Created with SDP answer and session URL; (2) ICE/DTLS establishment between client and media server; (3) RTP/RTCP media flow (unidirectional, client→server); (4) HTTP DELETE to session URL terminates the session. SDP renegotiation is not supported after step 1.