From 1ad059a80bfb04fdde0755ac0a2a72bcff9bbb3c Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Fri, 24 Mar 2023 10:54:14 +0100 Subject: [PATCH] server: use absolute RTSP URL as control attribute (#210) this is necessary in order to make GStreamer's rtspsrc to send query parameters correctly in SETUP requests. --- client_play_test.go | 48 ++++++++++++------------ client_record_test.go | 2 +- client_test.go | 6 +-- pkg/media/media.go | 2 +- pkg/media/medias_test.go | 79 ++++++++++++++++++++++++++++++++++++---- server_conn.go | 18 +++++++-- server_play_test.go | 49 ++++++++++++++----------- server_record_test.go | 22 +++++------ server_test.go | 24 ++++++------ 9 files changed, 164 insertions(+), 86 deletions(-) diff --git a/client_play_test.go b/client_play_test.go index 34656096..9e828c48 100644 --- a/client_play_test.go +++ b/client_play_test.go @@ -23,15 +23,15 @@ import ( "github.com/aler9/gortsplib/v2/pkg/format" "github.com/aler9/gortsplib/v2/pkg/headers" "github.com/aler9/gortsplib/v2/pkg/media" - "github.com/aler9/gortsplib/v2/pkg/sdp" "github.com/aler9/gortsplib/v2/pkg/url" ) -func mustMarshalSDP(sdp *sdp.SessionDescription) []byte { - byts, err := sdp.Marshal() +func mustMarshalMedias(medias media.Medias) []byte { + byts, err := medias.Marshal(false).Marshal() if err != nil { panic(err) } + return byts } @@ -148,7 +148,7 @@ func TestClientPlayFormats(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -293,7 +293,7 @@ func TestClientPlay(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{scheme + "://" + listenIP + ":8554/test/stream?param=value/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -567,7 +567,7 @@ func TestClientPlayPartial(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://" + listenIP + ":8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -711,12 +711,12 @@ func TestClientPlayContentBase(t *testing.T) { Header: base.Header{ "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) case "inside control attribute": - body := string(mustMarshalSDP(medias.Marshal(false))) + body := string(mustMarshalMedias(medias)) body = strings.Replace(body, "t=0 0", "t=0 0\r\na=control:rtsp://localhost:8554/teststream", 1) err = conn.WriteResponse(&base.Response{ @@ -840,7 +840,7 @@ func TestClientPlayAnyPort(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -994,7 +994,7 @@ func TestClientPlayAutomaticProtocol(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -1109,7 +1109,7 @@ func TestClientPlayAutomaticProtocol(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -1178,7 +1178,7 @@ func TestClientPlayAutomaticProtocol(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -1302,7 +1302,7 @@ func TestClientPlayAutomaticProtocol(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -1384,7 +1384,7 @@ func TestClientPlayAutomaticProtocol(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -1522,7 +1522,7 @@ func TestClientPlayDifferentInterleavedIDs(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -1717,7 +1717,7 @@ func TestClientPlayRedirect(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -1878,7 +1878,7 @@ func TestClientPlayPause(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -2046,7 +2046,7 @@ func TestClientPlayRTCPReport(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -2224,7 +2224,7 @@ func TestClientPlayErrorTimeout(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -2370,7 +2370,7 @@ func TestClientPlayIgnoreTCPInvalidMedia(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -2493,7 +2493,7 @@ func TestClientPlaySeek(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -2657,7 +2657,7 @@ func TestClientPlayKeepaliveFromSession(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -2780,7 +2780,7 @@ func TestClientPlayDifferentSource(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/test/stream?param=value/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) @@ -2933,7 +2933,7 @@ func TestClientPlayDecodeErrors(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/stream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) diff --git a/client_record_test.go b/client_record_test.go index c9d798b1..3c63920c 100644 --- a/client_record_test.go +++ b/client_record_test.go @@ -170,7 +170,7 @@ func TestClientRecordSerial(t *testing.T) { require.NoError(t, err) require.Equal(t, base.Setup, req.Method) require.Equal(t, mustParseURL( - scheme+"://localhost:8554/teststream/"+controlAttribute(desc.MediaDescriptions[0])), req.URL) + scheme+"://localhost:8554/teststream/"+relativeControlAttribute(desc.MediaDescriptions[0])), req.URL) var inTH headers.Transport err = inTH.Unmarshal(req.Header["Transport"]) diff --git a/client_test.go b/client_test.go index 68ae72a3..2b9ab625 100644 --- a/client_test.go +++ b/client_test.go @@ -114,7 +114,7 @@ func TestClientSession(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp"}, "Session": base.HeaderValue{"123456"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) }() @@ -190,7 +190,7 @@ func TestClientAuth(t *testing.T) { Header: base.Header{ "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) }() @@ -250,7 +250,7 @@ func TestClientDescribeCharset(t *testing.T) { "Content-Type": base.HeaderValue{"application/sdp; charset=utf-8"}, "Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) }() diff --git a/pkg/media/media.go b/pkg/media/media.go index a115d410..6e5f0190 100644 --- a/pkg/media/media.go +++ b/pkg/media/media.go @@ -155,7 +155,7 @@ func (m Media) Marshal() *psdp.MediaDescription { return md } -// URL returns the media URL. +// URL returns the absolute URL of the media. func (m Media) URL(contentBase *url.URL) (*url.URL, error) { if contentBase == nil { return nil, fmt.Errorf("Content-Base header not provided") diff --git a/pkg/media/medias_test.go b/pkg/media/medias_test.go index 2baf33a8..670118ce 100644 --- a/pkg/media/medias_test.go +++ b/pkg/media/medias_test.go @@ -16,7 +16,7 @@ var casesMedias = []struct { medias Medias }{ { - "one track for each media", + "one format for each media, absolute", "v=0\r\n" + "o=- 0 0 IN IP4 10.0.0.131\r\n" + "s=Media Presentation\r\n" + @@ -84,7 +84,74 @@ var casesMedias = []struct { }, }, { - "multiple tracks for each media", + "one format for each media, relative", + "v=0\r\n" + + "o=- 0 0 IN IP4 10.0.0.131\r\n" + + "s=Media Presentation\r\n" + + "i=samsung\r\n" + + "c=IN IP4 0.0.0.0\r\n" + + "b=AS:2632\r\n" + + "t=0 0\r\n" + + "a=range:npt=now-\r\n" + + "m=video 42504 RTP/AVP 97\r\n" + + "b=AS:2560\r\n" + + "a=rtpmap:97 H264/90000\r\n" + + "a=control:trackID=1\r\n" + + "a=cliprect:0,0,1080,1920\r\n" + + "a=framesize:97 1920-1080\r\n" + + "a=framerate:30.0\r\n" + + "a=fmtp:97 packetization-mode=1;profile-level-id=640028;sprop-parameter-sets=Z2QAKKy0A8ARPyo=,aO4Bniw=\r\n" + + "m=audio 42506 RTP/AVP 0\r\n" + + "b=AS:64\r\n" + + "a=rtpmap:0 PCMU/8000\r\n" + + "a=control:trackID=2\r\n" + + "a=recvonly\r\n" + + "m=application 42508 RTP/AVP 107\r\n" + + "b=AS:8\r\n", + "v=0\r\n" + + "o=- 0 0 IN IP4 127.0.0.1\r\n" + + "s=Stream\r\n" + + "c=IN IP4 0.0.0.0\r\n" + + "t=0 0\r\n" + + "m=video 0 RTP/AVP 97\r\n" + + "a=control:trackID=1\r\n" + + "a=rtpmap:97 H264/90000\r\n" + + "a=fmtp:97 packetization-mode=1; profile-level-id=640028; sprop-parameter-sets=Z2QAKKy0A8ARPyo=,aO4Bniw=\r\n" + + "m=audio 0 RTP/AVP 0\r\n" + + "a=control:trackID=2\r\n" + + "a=recvonly\r\n" + + "a=rtpmap:0 PCMU/8000\r\n" + + "m=application 0 RTP/AVP 107\r\n" + + "a=control\r\n", + Medias{ + { + Type: "video", + Control: "trackID=1", + Formats: []format.Format{&format.H264{ + PayloadTyp: 97, + PacketizationMode: 1, + SPS: []byte{0x67, 0x64, 0x00, 0x28, 0xac, 0xb4, 0x03, 0xc0, 0x11, 0x3f, 0x2a}, + PPS: []byte{0x68, 0xee, 0x01, 0x9e, 0x2c}, + }}, + }, + { + Type: "audio", + Direction: DirectionRecvonly, + Control: "trackID=2", + Formats: []format.Format{&format.G711{ + MULaw: true, + }}, + }, + { + Type: "application", + Formats: []format.Format{&format.Generic{ + PayloadTyp: 107, + }}, + }, + }, + }, + { + "multiple formats for each media", "v=0\r\n" + "o=- 4158123474391860926 2 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + @@ -353,7 +420,7 @@ var casesMedias = []struct { }, }, { - "multiple tracks for each media 2", + "multiple formats for each media 2", "v=0\r\n" + "o=- 4158123474391860926 2 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + @@ -417,17 +484,14 @@ var casesMedias = []struct { "c=IN IP4 0.0.0.0\r\n" + "t=0 0\r\n" + "m=video 0 RTP/AVP 26\r\n" + - "a=control:rtsp://192.168.0.1/video\r\n" + "a=recvonly\r\n" + "a=rtpmap:26 JPEG/90000\r\n" + "m=audio 0 RTP/AVP 0\r\n" + - "a=control:rtsp://192.168.0.1/audio\r\n" + "a=recvonly\r\n" + "a=rtpmap:0 PCMU/8000\r\n" + "m=audio 0 RTP/AVP 0\r\n" + - "a=control:rtsp://192.168.0.1/audioback\r\n" + "a=sendonly\r\n" + "a=rtpmap:0 PCMU/8000\r\n", @@ -507,8 +571,7 @@ func TestMediasReadErrors(t *testing.T) { func TestMediasMarshal(t *testing.T) { for _, ca := range casesMedias { t.Run(ca.name, func(t *testing.T) { - sdp := ca.medias.Marshal(false) - byts, err := sdp.Marshal() + byts, err := ca.medias.Marshal(false).Marshal() require.NoError(t, err) require.Equal(t, ca.out, string(byts)) }) diff --git a/server_conn.go b/server_conn.go index 21ecca34..ac73ab83 100644 --- a/server_conn.go +++ b/server_conn.go @@ -25,15 +25,27 @@ func getSessionID(header base.Header) string { return "" } -func filterMedias(medias media.Medias, streamMedias map[*media.Media]*serverStreamMedia) media.Medias { +func mediasForSDP( + medias media.Medias, + streamMedias map[*media.Media]*serverStreamMedia, + contentBase *url.URL, +) media.Medias { copy := make(media.Medias, len(medias)) for i, medi := range medias { - copy[i] = &media.Media{ + mc := &media.Media{ Type: medi.Type, // Direction: skipped for the moment Formats: medi.Formats, Control: "mediaUUID=" + streamMedias[medi].uuid.String(), } + + // always use the absolute URL of the track as control attribute, in order + // to support GStreamer's rtspsrc. When a relative control is used, GStreamer + // puts it between path and query, instead of appending it to the URL. + u, _ := mc.URL(contentBase) + mc.Control = u.String() + + copy[i] = mc } return copy } @@ -392,7 +404,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) { } if stream != nil { - byts, _ := filterMedias(stream.medias, stream.streamMedias).Marshal(multicast).Marshal() + byts, _ := mediasForSDP(stream.medias, stream.streamMedias, req.URL).Marshal(multicast).Marshal() res.Body = byts } } diff --git a/server_play_test.go b/server_play_test.go index 26edbfe5..3dd91bde 100644 --- a/server_play_test.go +++ b/server_play_test.go @@ -52,7 +52,13 @@ func multicastCapableIP(t *testing.T) string { return "" } -func controlAttribute(md *psdp.MediaDescription) string { +func relativeControlAttribute(md *psdp.MediaDescription) string { + v, _ := md.Attribute("control") + i := strings.Index(v, "mediaUUID=") + return v[i:] +} + +func absoluteControlAttribute(md *psdp.MediaDescription) string { v, _ := md.Attribute("control") return v } @@ -60,7 +66,7 @@ func controlAttribute(md *psdp.MediaDescription) string { func doDescribe(conn *conn.Conn) (*sdp.SessionDescription, error) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Describe, - URL: mustParseURL("rtsp://localhost:8554/pa"), + URL: mustParseURL("rtsp://localhost:8554/teststream"), Header: base.Header{ "CSeq": base.HeaderValue{"1"}, }, @@ -198,11 +204,10 @@ func TestServerPlayPath(t *testing.T) { InterleavedIDs: &[2]int{0, 1}, } - v, _ := desc.MediaDescriptions[1].Attribute("control") - res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL(strings.ReplaceAll(ca.setupURL, "[control]", "/"+v)), + URL: mustParseURL(strings.ReplaceAll(ca.setupURL, "[control]", "/"+ + relativeControlAttribute(desc.MediaDescriptions[1]))), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": th.Marshal(), @@ -301,7 +306,7 @@ func TestServerPlaySetupErrors(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": th.Marshal(), @@ -320,7 +325,7 @@ func TestServerPlaySetupErrors(t *testing.T) { res, err = writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/test12stream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL("rtsp://localhost:8554/test12stream/" + relativeControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"3"}, "Transport": th.Marshal(), @@ -341,7 +346,7 @@ func TestServerPlaySetupErrors(t *testing.T) { res, err = writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"4"}, "Transport": th.Marshal(), @@ -425,7 +430,7 @@ func TestServerPlaySetupErrorSameUDPPortsAndIP(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": inTH.Marshal(), @@ -592,7 +597,7 @@ func TestServerPlay(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://" + listenIP + ":8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": inTH.Marshal(), @@ -886,7 +891,7 @@ func TestServerPlayDecodeErrors(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": inTH.Marshal(), @@ -1023,7 +1028,7 @@ func TestServerPlayRTCPReport(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": inTH.Marshal(), @@ -1226,7 +1231,7 @@ func TestServerPlayTCPResponseBeforeFrames(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": headers.Transport{ @@ -1306,7 +1311,7 @@ func TestServerPlayPlayPlay(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": headers.Transport{ @@ -1424,7 +1429,7 @@ func TestServerPlayPlayPausePlay(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": headers.Transport{ @@ -1549,7 +1554,7 @@ func TestServerPlayPlayPausePause(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": headers.Transport{ @@ -1697,7 +1702,7 @@ func TestServerPlayTimeout(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": inTH.Marshal(), @@ -1805,7 +1810,7 @@ func TestServerPlayWithoutTeardown(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": inTH.Marshal(), @@ -1899,7 +1904,7 @@ func TestServerPlayUDPChangeConn(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": inTH.Marshal(), @@ -2003,7 +2008,7 @@ func TestServerPlayPartialMedias(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[1])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[1])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": inTH.Marshal(), @@ -2058,7 +2063,7 @@ func TestServerPlayAdditionalInfos(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": inTH.Marshal(), @@ -2092,7 +2097,7 @@ func TestServerPlayAdditionalInfos(t *testing.T) { res, err = writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[1])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[1])), Header: base.Header{ "CSeq": base.HeaderValue{"3"}, "Transport": inTH.Marshal(), diff --git a/server_record_test.go b/server_record_test.go index 179ce2d9..e3172205 100644 --- a/server_record_test.go +++ b/server_record_test.go @@ -246,9 +246,7 @@ func TestServerRecordPath(t *testing.T) { TimeDescriptions: []psdp.TimeDescription{ {Timing: psdp.Timing{0, 0}}, //nolint:govet }, - MediaDescriptions: []*psdp.MediaDescription{ - media.Marshal(), - }, + MediaDescriptions: []*psdp.MediaDescription{media.Marshal()}, } byts, _ := sout.Marshal() @@ -348,7 +346,7 @@ func TestServerRecordErrorSetupMediaTwice(t *testing.T) { "CSeq": base.HeaderValue{"1"}, "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) require.Equal(t, base.StatusOK, res.StatusCode) @@ -468,7 +466,7 @@ func TestServerRecordErrorRecordPartialMedias(t *testing.T) { "CSeq": base.HeaderValue{"1"}, "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) require.Equal(t, base.StatusOK, res.StatusCode) @@ -641,7 +639,7 @@ func TestServerRecord(t *testing.T) { "CSeq": base.HeaderValue{"1"}, "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) require.Equal(t, base.StatusOK, res.StatusCode) @@ -845,7 +843,7 @@ func TestServerRecordErrorInvalidProtocol(t *testing.T) { "CSeq": base.HeaderValue{"1"}, "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) require.Equal(t, base.StatusOK, res.StatusCode) @@ -946,7 +944,7 @@ func TestServerRecordRTCPReport(t *testing.T) { "CSeq": base.HeaderValue{"1"}, "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) require.Equal(t, base.StatusOK, res.StatusCode) @@ -1121,7 +1119,7 @@ func TestServerRecordTimeout(t *testing.T) { "CSeq": base.HeaderValue{"1"}, "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) require.Equal(t, base.StatusOK, res.StatusCode) @@ -1244,7 +1242,7 @@ func TestServerRecordWithoutTeardown(t *testing.T) { "CSeq": base.HeaderValue{"1"}, "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) require.Equal(t, base.StatusOK, res.StatusCode) @@ -1357,7 +1355,7 @@ func TestServerRecordUDPChangeConn(t *testing.T) { "CSeq": base.HeaderValue{"1"}, "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) require.Equal(t, base.StatusOK, res.StatusCode) @@ -1512,7 +1510,7 @@ func TestServerRecordDecodeErrors(t *testing.T) { "CSeq": base.HeaderValue{"1"}, "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), }) require.NoError(t, err) require.Equal(t, base.StatusOK, res.StatusCode) diff --git a/server_test.go b/server_test.go index 7ba93246..bb0d2db0 100644 --- a/server_test.go +++ b/server_test.go @@ -359,7 +359,7 @@ func TestServerErrorMethodNotImplemented(t *testing.T) { if ca == "inside session" { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"1"}, "Transport": headers.Transport{ @@ -391,7 +391,7 @@ func TestServerErrorMethodNotImplemented(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.SetParameter, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: headers, }) require.NoError(t, err) @@ -459,7 +459,7 @@ func TestServerErrorTCPTwoConnOneSession(t *testing.T) { res, err := writeReqReadRes(conn1, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc1.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc1.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"1"}, "Transport": headers.Transport{ @@ -504,7 +504,7 @@ func TestServerErrorTCPTwoConnOneSession(t *testing.T) { res, err = writeReqReadRes(conn2, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc2.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc2.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"1"}, "Transport": headers.Transport{ @@ -570,7 +570,7 @@ func TestServerErrorTCPOneConnTwoSessions(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"1"}, "Transport": headers.Transport{ @@ -607,7 +607,7 @@ func TestServerErrorTCPOneConnTwoSessions(t *testing.T) { res, err = writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"3"}, "Transport": headers.Transport{ @@ -689,7 +689,7 @@ func TestServerSetupMultipleTransports(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"1"}, "Transport": inTHS.Marshal(), @@ -776,7 +776,7 @@ func TestServerGetSetParameter(t *testing.T) { if ca == "inside session" { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"2"}, "Transport": headers.Transport{ @@ -927,7 +927,7 @@ func TestServerSessionClose(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"1"}, "Transport": headers.Transport{ @@ -1008,7 +1008,7 @@ func TestServerSessionAutoClose(t *testing.T) { _, err = writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"1"}, "Transport": headers.Transport{ @@ -1068,7 +1068,7 @@ func TestServerSessionTeardown(t *testing.T) { res, err := writeReqReadRes(conn, base.Request{ Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])), + URL: mustParseURL(absoluteControlAttribute(desc.MediaDescriptions[0])), Header: base.Header{ "CSeq": base.HeaderValue{"1"}, "Transport": headers.Transport{ @@ -1156,7 +1156,7 @@ func TestServerAuth(t *testing.T) { "CSeq": base.HeaderValue{"1"}, "Content-Type": base.HeaderValue{"application/sdp"}, }, - Body: mustMarshalSDP(medias.Marshal(false)), + Body: mustMarshalMedias(medias), } res, err := writeReqReadRes(conn, req)