From f1062a4c36a47a693f84cb2d477788c814bc9003 Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Sun, 10 May 2026 20:34:47 -0400 Subject: [PATCH] =?UTF-8?q?webrtc:=20emit=20RFC=209261=20=C2=A75.2=20Link?= =?UTF-8?q?=20headers=20on=20WHIP=20201=20Publish=20response=20(issue=20#2?= =?UTF-8?q?1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/webrtc/whip_handler.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/webrtc/whip_handler.go b/app/webrtc/whip_handler.go index fb3bfb4..06e187d 100644 --- a/app/webrtc/whip_handler.go +++ b/app/webrtc/whip_handler.go @@ -174,6 +174,13 @@ func (h *WHIPHandler) Publish(c echo.Context) error { h.recordRequest("publish", id, http.StatusCreated, t0) + // RFC 9261 §5.2: emit one Link header per configured ICE server so + // that the publisher (OBS, browser, GStreamer, etc.) can discover + // STUN/TURN without a separate signalling round-trip — symmetric + // with the WHEP Subscribe Link header added in issue #19. + for _, uri := range h.sub.ICEServerURIs() { + c.Response().Header().Add("Link", "<"+uri+">; rel=\"ice-server\"") + } c.Response().Header().Set("Content-Type", "application/sdp") c.Response().Header().Set("Location", "/whip/"+id+"/"+rid) c.Response().Header().Set("ETag", `"`+rid+`"`) @@ -229,6 +236,13 @@ func (h *WHIPHandler) Unpublish(c echo.Context) error { // TrickleIngest handles PATCH /whip/:id/:resource — adds ICE candidates // from a trickle-ice-sdpfrag body. // +// The body format follows draft-ietf-wish-whip §5: one or more +// "a=candidate:…" lines in application/trickle-ice-sdpfrag. Each +// matching line is forwarded directly to the underlying PeerConnection. +// An empty body or a body with no candidate lines is a no-op (clients +// signal end-of-candidates via an a=end-of-candidates line, which +// AddICECandidate correctly ignores at the Pion level). +// // @Summary Trickle ICE candidates for a WHIP publish session // @Tags v16.16.0 // @ID webrtc-3-whip-trickle