From df274ad6ea68360749baa9b9bfe0a663d2804e65 Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Mon, 30 Sep 2024 00:23:36 +0200 Subject: [PATCH] Split out SDP fragment parsing, add test. --- webserver/whip.go | 30 ++++++++++++++++-------------- webserver/whip_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 webserver/whip_test.go diff --git a/webserver/whip.go b/webserver/whip.go index 2838375..cf7d798 100644 --- a/webserver/whip.go +++ b/webserver/whip.go @@ -1,6 +1,7 @@ package webserver import ( + "bufio" "bytes" "crypto/aes" "crypto/cipher" @@ -345,23 +346,25 @@ func whipResourceHandler(w http.ResponseWriter, r *http.Request) { return } - body, err := io.ReadAll(http.MaxBytesReader(w, r.Body, sdpLimit)) + err = parseSDPFrag( + http.MaxBytesReader(w, r.Body, sdpLimit), + c.GotICECandidate, + ) if err != nil { - httpError(w, err) + log.Printf("WHIP trickle ICE: %v", err) + http.Error(w, "bad request", http.StatusBadRequest) return } + w.WriteHeader(http.StatusNoContent) +} - if len(body) < 2 { - http.Error(w, "SDP truncated", http.StatusBadRequest) - return - } - - // RFC 8840 - lines := bytes.Split(body, []byte{'\n'}) +// RFC 8840 +func parseSDPFrag(r io.Reader, f func(webrtc.ICECandidateInit) error) error { + scanner := bufio.NewScanner(r) mLineIndex := -1 var mid, ufrag []byte - for _, l := range lines { - l = bytes.TrimRight(l, " \r") + for scanner.Scan() { + l := scanner.Bytes() if bytes.HasPrefix(l, []byte("a=ice-ufrag:")) { ufrag = l[len("a=ice-ufrag:"):] } else if bytes.HasPrefix(l, []byte("m=")) { @@ -385,12 +388,11 @@ func whipResourceHandler(w http.ResponseWriter, r *http.Request) { s := string(ufrag) init.UsernameFragment = &s } - err := c.GotICECandidate(init) + err := f(init) if err != nil { log.Printf("WHIP candidate: %v", err) } } } - w.WriteHeader(http.StatusNoContent) - return + return nil } diff --git a/webserver/whip_test.go b/webserver/whip_test.go new file mode 100644 index 0000000..7fb03f7 --- /dev/null +++ b/webserver/whip_test.go @@ -0,0 +1,35 @@ +package webserver + +import ( + "strings" + "testing" + + "github.com/pion/webrtc/v3" +) + +func TestParseSDPFrag(t *testing.T) { + sdp := `a=ice-ufrag:FZ0m +a=ice-pwd:NRT+gj1EhsEwMm9MA7ljzBRy +m=audio 9 UDP/TLS/RTP/SAVPF 0 +a=mid:0 +a=candidate:2930517337 1 udp 2113937151 1eaafdf1-4127-499f-90d4-8c35ea49d5e6.local 44360 typ host generation 0 ufrag FZ0m network-cost 999 +2024/09/30 00:07:41 {candidate:2930517337 1 udp 2113937151 1eaafdf1-4127-499f-90d4-8c35ea49d5e6.local 44360 typ host generation 0 ufrag FZ0m network-cost 999 0xc00062a580 0xc000620288 0xc00062a590} +a=end-of-candidates` + r := strings.NewReader(sdp) + candidates := []webrtc.ICECandidateInit(nil) + err := parseSDPFrag(r, func(c webrtc.ICECandidateInit) error { + candidates = append(candidates, c) + return nil + }) + if err != nil { + t.Errorf("parseSDPFrag: %v", err) + } + if len(candidates) != 1 { + t.Errorf("Expected 1, got %v", candidates) + } + if *candidates[0].SDPMLineIndex != 0 || + *candidates[0].SDPMid != "0" || + *candidates[0].UsernameFragment != "FZ0m" { + t.Errorf("Got %v", candidates[0]) + } +}