diff --git a/client.go b/client.go index 41dbdc7a..fea11857 100644 --- a/client.go +++ b/client.go @@ -29,7 +29,6 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/liberrors" "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/bluenviron/gortsplib/v4/pkg/sdp" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) // convert an URL into an address, in particular: @@ -37,7 +36,7 @@ import ( // * handle IPv6 with or without square brackets. // Adapted from net/http: // https://cs.opensource.google/go/go/+/refs/tags/go1.20.5:src/net/http/transport.go;l=2747 -func canonicalAddr(u *url.URL) string { +func canonicalAddr(u *base.URL) string { addr := u.Hostname() port := u.Port() @@ -56,10 +55,10 @@ func isAnyPort(p int) bool { return p == 0 || p == 1 } -func findBaseURL(sd *sdp.SessionDescription, res *base.Response, u *url.URL) (*url.URL, error) { +func findBaseURL(sd *sdp.SessionDescription, res *base.Response, u *base.URL) (*base.URL, error) { // use global control attribute if control, ok := sd.Attribute("control"); ok && control != "*" { - ret, err := url.Parse(control) + ret, err := base.ParseURL(control) if err != nil { return nil, fmt.Errorf("invalid control attribute: '%v'", control) } @@ -76,7 +75,7 @@ func findBaseURL(sd *sdp.SessionDescription, res *base.Response, u *url.URL) (*u return nil, fmt.Errorf("invalid Content-Base: '%v'", cb) } - ret, err := url.Parse(cb[0]) + ret, err := base.ParseURL(cb[0]) if err != nil { return nil, fmt.Errorf("invalid Content-Base: '%v'", cb) } @@ -138,23 +137,23 @@ func (s clientState) String() string { } type optionsReq struct { - url *url.URL + url *base.URL res chan clientRes } type describeReq struct { - url *url.URL + url *base.URL res chan clientRes } type announceReq struct { - url *url.URL + url *base.URL desc *description.Session res chan clientRes } type setupReq struct { - baseURL *url.URL + baseURL *base.URL media *description.Media rtpPort int rtcpPort int @@ -288,7 +287,7 @@ type Client struct { receiverReportPeriod time.Duration checkTimeoutPeriod time.Duration - connURL *url.URL + connURL *base.URL ctx context.Context ctxCancel func() state clientState @@ -299,8 +298,8 @@ type Client struct { cseq int optionsSent bool useGetParameter bool - lastDescribeURL *url.URL - baseURL *url.URL + lastDescribeURL *base.URL + baseURL *base.URL effectiveTransport *Transport medias map[*description.Media]*clientMedia tcpCallbackByChannel map[int]readFunc @@ -422,7 +421,7 @@ func (c *Client) Start(scheme string, host string) error { ctx, ctxCancel := context.WithCancel(context.Background()) - c.connURL = &url.URL{ + c.connURL = &base.URL{ Scheme: scheme, Host: host, } @@ -450,7 +449,7 @@ func (c *Client) Start(scheme string, host string) error { // StartRecording connects to the address and starts publishing given media. func (c *Client) StartRecording(address string, desc *description.Session) error { - u, err := url.Parse(address) + u, err := base.ParseURL(address) if err != nil { return err } @@ -755,7 +754,7 @@ func (c *Client) trySwitchingProtocol() error { return nil } -func (c *Client) trySwitchingProtocol2(medi *description.Media, baseURL *url.URL) (*base.Response, error) { +func (c *Client) trySwitchingProtocol2(medi *description.Media, baseURL *base.URL) (*base.Response, error) { c.OnTransportSwitch(liberrors.ErrClientSwitchToTCP2{}) prevConnURL := c.connURL @@ -1027,7 +1026,7 @@ func (c *Client) doKeepAlive() error { return err } -func (c *Client) doOptions(u *url.URL) (*base.Response, error) { +func (c *Client) doOptions(u *base.URL) (*base.Response, error) { err := c.checkState(map[clientState]struct{}{ clientStateInitial: {}, clientStatePrePlay: {}, @@ -1066,7 +1065,7 @@ func (c *Client) doOptions(u *url.URL) (*base.Response, error) { } // Options sends an OPTIONS request. -func (c *Client) Options(u *url.URL) (*base.Response, error) { +func (c *Client) Options(u *base.URL) (*base.Response, error) { cres := make(chan clientRes) select { case c.chOptions <- optionsReq{url: u, res: cres}: @@ -1078,7 +1077,7 @@ func (c *Client) Options(u *url.URL) (*base.Response, error) { } } -func (c *Client) doDescribe(u *url.URL) (*description.Session, *base.Response, error) { +func (c *Client) doDescribe(u *base.URL) (*description.Session, *base.Response, error) { err := c.checkState(map[clientState]struct{}{ clientStateInitial: {}, clientStatePrePlay: {}, @@ -1111,7 +1110,7 @@ func (c *Client) doDescribe(u *url.URL) (*description.Session, *base.Response, e len(res.Header["Location"]) == 1 { c.reset() - ru, err := url.Parse(res.Header["Location"][0]) + ru, err := base.ParseURL(res.Header["Location"][0]) if err != nil { return nil, nil, err } @@ -1120,7 +1119,7 @@ func (c *Client) doDescribe(u *url.URL) (*description.Session, *base.Response, e ru.User = u.User } - c.connURL = &url.URL{ + c.connURL = &base.URL{ Scheme: ru.Scheme, Host: ru.Host, } @@ -1167,7 +1166,7 @@ func (c *Client) doDescribe(u *url.URL) (*description.Session, *base.Response, e } // Describe sends a DESCRIBE request. -func (c *Client) Describe(u *url.URL) (*description.Session, *base.Response, error) { +func (c *Client) Describe(u *base.URL) (*description.Session, *base.Response, error) { cres := make(chan clientRes) select { case c.chDescribe <- describeReq{url: u, res: cres}: @@ -1179,7 +1178,7 @@ func (c *Client) Describe(u *url.URL) (*description.Session, *base.Response, err } } -func (c *Client) doAnnounce(u *url.URL, desc *description.Session) (*base.Response, error) { +func (c *Client) doAnnounce(u *base.URL, desc *description.Session) (*base.Response, error) { err := c.checkState(map[clientState]struct{}{ clientStateInitial: {}, }) @@ -1224,7 +1223,7 @@ func (c *Client) doAnnounce(u *url.URL, desc *description.Session) (*base.Respon } // Announce sends an ANNOUNCE request. -func (c *Client) Announce(u *url.URL, desc *description.Session) (*base.Response, error) { +func (c *Client) Announce(u *base.URL, desc *description.Session) (*base.Response, error) { cres := make(chan clientRes) select { case c.chAnnounce <- announceReq{url: u, desc: desc, res: cres}: @@ -1237,7 +1236,7 @@ func (c *Client) Announce(u *url.URL, desc *description.Session) (*base.Response } func (c *Client) doSetup( - baseURL *url.URL, + baseURL *base.URL, medi *description.Media, rtpPort int, rtcpPort int, @@ -1538,7 +1537,7 @@ func (c *Client) findFreeChannelPair() int { // rtpPort and rtcpPort are used only if transport is UDP. // if rtpPort and rtcpPort are zero, they are chosen automatically. func (c *Client) Setup( - baseURL *url.URL, + baseURL *base.URL, media *description.Media, rtpPort int, rtcpPort int, @@ -1561,7 +1560,7 @@ func (c *Client) Setup( } // SetupAll setups all the given medias. -func (c *Client) SetupAll(baseURL *url.URL, medias []*description.Media) error { +func (c *Client) SetupAll(baseURL *base.URL, medias []*description.Media) error { for _, m := range medias { _, err := c.Setup(baseURL, m, 0, 0) if err != nil { diff --git a/client_play_test.go b/client_play_test.go index 8a86bcc2..127feefc 100644 --- a/client_play_test.go +++ b/client_play_test.go @@ -21,7 +21,6 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/description" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/headers" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio" ) @@ -61,7 +60,7 @@ func mustMarshalPacketRTCP(pkt rtcp.Packet) []byte { } func readAll(c *Client, ur string, cb func(*description.Media, format.Format, *rtp.Packet)) error { - u, err := url.Parse(ur) + u, err := base.ParseURL(ur) if err != nil { return err } @@ -503,7 +502,7 @@ func TestClientPlay(t *testing.T) { }(), } - u, err := url.Parse(scheme + "://" + listenIP + ":8554/test/stream?param=value") + u, err := base.ParseURL(scheme + "://" + listenIP + ":8554/test/stream?param=value") require.NoError(t, err) err = c.Start(u.Scheme, u.Host) @@ -658,7 +657,7 @@ func TestClientPlayPartial(t *testing.T) { }(), } - u, err := url.Parse("rtsp://" + listenIP + ":8554/teststream") + u, err := base.ParseURL("rtsp://" + listenIP + ":8554/teststream") require.NoError(t, err) err = c.Start(u.Scheme, u.Host) @@ -2610,7 +2609,7 @@ func TestClientPlaySeek(t *testing.T) { }(), } - u, err := url.Parse("rtsp://localhost:8554/teststream") + u, err := base.ParseURL("rtsp://localhost:8554/teststream") require.NoError(t, err) err = c.Start(u.Scheme, u.Host) diff --git a/client_record_test.go b/client_record_test.go index 21716a49..039dbe57 100644 --- a/client_record_test.go +++ b/client_record_test.go @@ -20,7 +20,6 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/headers" "github.com/bluenviron/gortsplib/v4/pkg/sdp" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) var testH264Media = &description.Media{ @@ -74,7 +73,7 @@ func ntpTimeGoToRTCP(v time.Time) uint64 { } func record(c *Client, ur string, medias []*description.Media, cb func(*description.Media, rtcp.Packet)) error { - u, err := url.Parse(ur) + u, err := base.ParseURL(ur) if err != nil { return err } diff --git a/client_test.go b/client_test.go index e9469170..54af718f 100644 --- a/client_test.go +++ b/client_test.go @@ -12,11 +12,10 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/conn" "github.com/bluenviron/gortsplib/v4/pkg/description" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) -func mustParseURL(s string) *url.URL { - u, err := url.Parse(s) +func mustParseURL(s string) *base.URL { + u, err := base.ParseURL(s) if err != nil { panic(err) } @@ -82,7 +81,7 @@ func TestClientTLSSetServerName(t *testing.T) { require.EqualError(t, err, "remote error: tls: bad certificate") }() - u, err := url.Parse("rtsps://localhost:8554/stream") + u, err := base.ParseURL("rtsps://localhost:8554/stream") require.NoError(t, err) c := Client{ @@ -100,7 +99,7 @@ func TestClientTLSSetServerName(t *testing.T) { } func TestClientClose(t *testing.T) { - u, err := url.Parse("rtsp://localhost:8554/teststream") + u, err := base.ParseURL("rtsp://localhost:8554/teststream") require.NoError(t, err) c := Client{} @@ -158,7 +157,7 @@ func TestClientCloseDuringRequest(t *testing.T) { <-releaseConn }() - u, err := url.Parse("rtsp://localhost:8554/teststream") + u, err := base.ParseURL("rtsp://localhost:8554/teststream") require.NoError(t, err) c := Client{} @@ -227,7 +226,7 @@ func TestClientSession(t *testing.T) { require.NoError(t, err) }() - u, err := url.Parse("rtsp://localhost:8554/stream") + u, err := base.ParseURL("rtsp://localhost:8554/stream") require.NoError(t, err) c := Client{} @@ -303,7 +302,7 @@ func TestClientAuth(t *testing.T) { require.NoError(t, err) }() - u, err := url.Parse("rtsp://myuser:mypass@localhost:8554/stream") + u, err := base.ParseURL("rtsp://myuser:mypass@localhost:8554/stream") require.NoError(t, err) c := Client{} @@ -378,7 +377,7 @@ func TestClientCSeq(t *testing.T) { } }() - u, err := url.Parse("rtsp://localhost:8554/teststream") + u, err := base.ParseURL("rtsp://localhost:8554/teststream") require.NoError(t, err) c := Client{} @@ -440,7 +439,7 @@ func TestClientDescribeCharset(t *testing.T) { require.NoError(t, err) }() - u, err := url.Parse("rtsp://localhost:8554/teststream") + u, err := base.ParseURL("rtsp://localhost:8554/teststream") require.NoError(t, err) c := Client{} @@ -525,7 +524,7 @@ func TestClientReplyToServerRequest(t *testing.T) { } }() - u, err := url.Parse("rtsp://localhost:8554/stream") + u, err := base.ParseURL("rtsp://localhost:8554/stream") require.NoError(t, err) c := Client{} diff --git a/examples/client-query/main.go b/examples/client-query/main.go index d199dc60..a3f6e50a 100644 --- a/examples/client-query/main.go +++ b/examples/client-query/main.go @@ -4,7 +4,7 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" - "github.com/bluenviron/gortsplib/v4/pkg/url" + "github.com/bluenviron/gortsplib/v4/pkg/base" ) // This example shows how to @@ -14,7 +14,7 @@ import ( func main() { c := gortsplib.Client{} - u, err := url.Parse("rtsp://localhost:8554/mypath") + u, err := base.ParseURL("rtsp://localhost:8554/mypath") if err != nil { panic(err) } diff --git a/examples/client-read-format-av1/main.go b/examples/client-read-format-av1/main.go index bf4dc62f..b434a854 100644 --- a/examples/client-read-format-av1/main.go +++ b/examples/client-read-format-av1/main.go @@ -4,9 +4,9 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpvp9" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -19,7 +19,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-g711/main.go b/examples/client-read-format-g711/main.go index f643617f..f5548811 100644 --- a/examples/client-read-format-g711/main.go +++ b/examples/client-read-format-g711/main.go @@ -4,8 +4,8 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -18,7 +18,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-g722/main.go b/examples/client-read-format-g722/main.go index ae14e6b9..a6a34238 100644 --- a/examples/client-read-format-g722/main.go +++ b/examples/client-read-format-g722/main.go @@ -4,8 +4,8 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -18,7 +18,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-h264-convert-to-jpeg/main.go b/examples/client-read-format-h264-convert-to-jpeg/main.go index a1fc3306..0df413d9 100644 --- a/examples/client-read-format-h264-convert-to-jpeg/main.go +++ b/examples/client-read-format-h264-convert-to-jpeg/main.go @@ -9,9 +9,9 @@ import ( "time" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtph264" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/bluenviron/mediacommon/pkg/codecs/h264" "github.com/pion/rtp" ) @@ -46,7 +46,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-h264-save-to-disk/main.go b/examples/client-read-format-h264-save-to-disk/main.go index 46c562c5..d0a2682c 100644 --- a/examples/client-read-format-h264-save-to-disk/main.go +++ b/examples/client-read-format-h264-save-to-disk/main.go @@ -4,9 +4,9 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtph264" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -19,7 +19,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-h264/main.go b/examples/client-read-format-h264/main.go index 3ffb1301..fcdb7eaf 100644 --- a/examples/client-read-format-h264/main.go +++ b/examples/client-read-format-h264/main.go @@ -4,9 +4,9 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtph264" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -22,7 +22,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-h265-convert-to-jpeg/main.go b/examples/client-read-format-h265-convert-to-jpeg/main.go index 60946ea2..6fdc057e 100644 --- a/examples/client-read-format-h265-convert-to-jpeg/main.go +++ b/examples/client-read-format-h265-convert-to-jpeg/main.go @@ -9,9 +9,9 @@ import ( "time" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtph265" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/bluenviron/mediacommon/pkg/codecs/h265" "github.com/pion/rtp" ) @@ -46,7 +46,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-h265-save-to-disk/main.go b/examples/client-read-format-h265-save-to-disk/main.go index d85bbde7..49e12503 100644 --- a/examples/client-read-format-h265-save-to-disk/main.go +++ b/examples/client-read-format-h265-save-to-disk/main.go @@ -4,9 +4,9 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtph265" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -19,7 +19,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-h265/main.go b/examples/client-read-format-h265/main.go index 8773a323..2326f6e2 100644 --- a/examples/client-read-format-h265/main.go +++ b/examples/client-read-format-h265/main.go @@ -4,9 +4,9 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtph265" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -22,7 +22,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-lpcm/main.go b/examples/client-read-format-lpcm/main.go index 4db53936..0f7a221e 100644 --- a/examples/client-read-format-lpcm/main.go +++ b/examples/client-read-format-lpcm/main.go @@ -4,8 +4,8 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -18,7 +18,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-mjpeg/main.go b/examples/client-read-format-mjpeg/main.go index 7a0b3e0b..866acabf 100644 --- a/examples/client-read-format-mjpeg/main.go +++ b/examples/client-read-format-mjpeg/main.go @@ -6,9 +6,9 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpmjpeg" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -22,7 +22,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-mpeg4audio-save-to-disk/main.go b/examples/client-read-format-mpeg4audio-save-to-disk/main.go index 15fd17a8..67772927 100644 --- a/examples/client-read-format-mpeg4audio-save-to-disk/main.go +++ b/examples/client-read-format-mpeg4audio-save-to-disk/main.go @@ -4,8 +4,8 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -18,7 +18,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-mpeg4audio/main.go b/examples/client-read-format-mpeg4audio/main.go index 1b539a03..57428e2d 100644 --- a/examples/client-read-format-mpeg4audio/main.go +++ b/examples/client-read-format-mpeg4audio/main.go @@ -4,8 +4,8 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -18,7 +18,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-opus/main.go b/examples/client-read-format-opus/main.go index 7a027bf3..b64d7c7c 100644 --- a/examples/client-read-format-opus/main.go +++ b/examples/client-read-format-opus/main.go @@ -4,8 +4,8 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -18,7 +18,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-vp8/main.go b/examples/client-read-format-vp8/main.go index 45a260a3..5ec4f689 100644 --- a/examples/client-read-format-vp8/main.go +++ b/examples/client-read-format-vp8/main.go @@ -4,9 +4,9 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpvp8" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -19,7 +19,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-format-vp9/main.go b/examples/client-read-format-vp9/main.go index 529fcf68..beb6bfa7 100644 --- a/examples/client-read-format-vp9/main.go +++ b/examples/client-read-format-vp9/main.go @@ -4,9 +4,9 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpvp9" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -19,7 +19,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-options/main.go b/examples/client-read-options/main.go index c1c1a251..be350391 100644 --- a/examples/client-read-options/main.go +++ b/examples/client-read-options/main.go @@ -5,9 +5,9 @@ import ( "time" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/description" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtcp" "github.com/pion/rtp" ) @@ -28,7 +28,7 @@ func main() { } // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-pause/main.go b/examples/client-read-pause/main.go index faa9aa17..6d97ff96 100644 --- a/examples/client-read-pause/main.go +++ b/examples/client-read-pause/main.go @@ -5,9 +5,9 @@ import ( "time" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/description" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtcp" "github.com/pion/rtp" ) @@ -22,7 +22,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-republish/main.go b/examples/client-read-republish/main.go index 148ba62b..ab9f2483 100644 --- a/examples/client-read-republish/main.go +++ b/examples/client-read-republish/main.go @@ -4,9 +4,9 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/description" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -19,7 +19,7 @@ func main() { reader := gortsplib.Client{} // parse source URL - sourceURL, err := url.Parse("rtsp://localhost:8554/mystream") + sourceURL, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read-timestamp/main.go b/examples/client-read-timestamp/main.go index 8d164f67..4c177bad 100644 --- a/examples/client-read-timestamp/main.go +++ b/examples/client-read-timestamp/main.go @@ -4,9 +4,9 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/description" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -19,7 +19,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/client-read/main.go b/examples/client-read/main.go index 057baeab..6303ff27 100644 --- a/examples/client-read/main.go +++ b/examples/client-read/main.go @@ -4,9 +4,9 @@ import ( "log" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/description" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtcp" "github.com/pion/rtp" ) @@ -19,7 +19,7 @@ func main() { c := gortsplib.Client{} // parse URL - u, err := url.Parse("rtsp://localhost:8554/mystream") + u, err := base.ParseURL("rtsp://localhost:8554/mystream") if err != nil { panic(err) } diff --git a/examples/proxy/client.go b/examples/proxy/client.go index e6b1023c..3b932760 100644 --- a/examples/proxy/client.go +++ b/examples/proxy/client.go @@ -5,9 +5,9 @@ import ( "time" "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/description" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" "github.com/pion/rtp" ) @@ -44,7 +44,7 @@ func (c *client) read() error { rc := gortsplib.Client{} // parse URL - u, err := url.Parse(existingStream) + u, err := base.ParseURL(existingStream) if err != nil { return err } diff --git a/pkg/auth/auth_test.go b/pkg/auth/auth_test.go index 55df2e83..2b0beffd 100644 --- a/pkg/auth/auth_test.go +++ b/pkg/auth/auth_test.go @@ -7,11 +7,10 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/headers" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) -func mustParseURL(s string) *url.URL { - u, err := url.Parse(s) +func mustParseURL(s string) *base.URL { + u, err := base.ParseURL(s) if err != nil { panic(err) } diff --git a/pkg/auth/validate.go b/pkg/auth/validate.go index 913be3fa..e43d52b9 100644 --- a/pkg/auth/validate.go +++ b/pkg/auth/validate.go @@ -8,7 +8,6 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/headers" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) func md5Hex(in string) string { @@ -68,7 +67,7 @@ func Validate( req *base.Request, user string, pass string, - baseURL *url.URL, + baseURL *base.URL, methods []headers.AuthMethod, realm string, nonce string, diff --git a/pkg/base/path.go b/pkg/base/path.go new file mode 100644 index 00000000..d6fa6d9f --- /dev/null +++ b/pkg/base/path.go @@ -0,0 +1,15 @@ +package base + +import ( + "strings" +) + +// PathSplitQuery splits a path from a query. +func PathSplitQuery(pathAndQuery string) (string, string) { + i := strings.Index(pathAndQuery, "?") + if i >= 0 { + return pathAndQuery[:i], pathAndQuery[i+1:] + } + + return pathAndQuery, "" +} diff --git a/pkg/url/path_test.go b/pkg/base/path_test.go similarity index 96% rename from pkg/url/path_test.go rename to pkg/base/path_test.go index 7485197d..c110d412 100644 --- a/pkg/url/path_test.go +++ b/pkg/base/path_test.go @@ -1,4 +1,4 @@ -package url +package base import ( "testing" diff --git a/pkg/base/request.go b/pkg/base/request.go index d859f19b..1c1fd979 100644 --- a/pkg/base/request.go +++ b/pkg/base/request.go @@ -5,8 +5,6 @@ import ( "bufio" "fmt" "strconv" - - "github.com/bluenviron/gortsplib/v4/pkg/url" ) const ( @@ -39,7 +37,7 @@ type Request struct { Method Method // request url - URL *url.URL + URL *URL // map of header values Header Header @@ -67,7 +65,7 @@ func (req *Request) Unmarshal(br *bufio.Reader) error { rawURL := string(byts[:len(byts)-1]) if rawURL != "*" { - ur, err := url.Parse(rawURL) + ur, err := ParseURL(rawURL) if err != nil { return fmt.Errorf("invalid URL (%v)", rawURL) } diff --git a/pkg/base/request_test.go b/pkg/base/request_test.go index d39cdf11..88ad6c80 100644 --- a/pkg/base/request_test.go +++ b/pkg/base/request_test.go @@ -6,18 +6,8 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/bluenviron/gortsplib/v4/pkg/url" ) -func mustParseURL(s string) *url.URL { - u, err := url.Parse(s) - if err != nil { - panic(err) - } - return u -} - var casesRequest = []struct { name string byts []byte diff --git a/pkg/base/url.go b/pkg/base/url.go new file mode 100644 index 00000000..1205f1f1 --- /dev/null +++ b/pkg/base/url.go @@ -0,0 +1,105 @@ +package base + +import ( + "fmt" + "net/url" + "regexp" + "strings" +) + +// URL is a RTSP URL. +// This is basically an HTTP URL with some additional functions to handle +// control attributes. +type URL url.URL + +var escapeRegexp = regexp.MustCompile(`^(.+?)://(.*?)@(.*?)/(.*?)$`) + +// ParseURL parses a RTSP URL. +func ParseURL(s string) (*URL, error) { + // https://github.com/golang/go/issues/30611 + m := escapeRegexp.FindStringSubmatch(s) + if m != nil { + m[3] = strings.ReplaceAll(m[3], "%25", "%") + m[3] = strings.ReplaceAll(m[3], "%", "%25") + s = m[1] + "://" + m[2] + "@" + m[3] + "/" + m[4] + } + + u, err := url.Parse(s) + if err != nil { + return nil, err + } + + if u.Scheme != "rtsp" && u.Scheme != "rtsps" { + return nil, fmt.Errorf("unsupported scheme '%s'", u.Scheme) + } + + if u.Opaque != "" { + return nil, fmt.Errorf("URLs with opaque data are not supported") + } + + if u.Fragment != "" { + return nil, fmt.Errorf("URLs with fragments are not supported") + } + + return (*URL)(u), nil +} + +// String implements fmt.Stringer. +func (u *URL) String() string { + return (*url.URL)(u).String() +} + +// Clone clones a URL. +func (u *URL) Clone() *URL { + return (*URL)(&url.URL{ + Scheme: u.Scheme, + User: u.User, + Host: u.Host, + Path: u.Path, + RawPath: u.RawPath, + ForceQuery: u.ForceQuery, + RawQuery: u.RawQuery, + }) +} + +// CloneWithoutCredentials clones a URL without its credentials. +func (u *URL) CloneWithoutCredentials() *URL { + return (*URL)(&url.URL{ + Scheme: u.Scheme, + Host: u.Host, + Path: u.Path, + RawPath: u.RawPath, + ForceQuery: u.ForceQuery, + RawQuery: u.RawQuery, + }) +} + +// RTSPPathAndQuery returns the path and query of a RTSP URL. +func (u *URL) RTSPPathAndQuery() (string, bool) { + var pathAndQuery string + if u.RawPath != "" { + pathAndQuery = u.RawPath + } else { + pathAndQuery = u.Path + } + if u.RawQuery != "" { + pathAndQuery += "?" + u.RawQuery + } + + return pathAndQuery, true +} + +// Hostname returns u.Host, stripping any valid port number if present. +// +// If the result is enclosed in square brackets, as literal IPv6 addresses are, +// the square brackets are removed from the result. +func (u *URL) Hostname() string { + return (*url.URL)(u).Hostname() +} + +// Port returns the port part of u.Host, without the leading colon. +// +// If u.Host doesn't contain a valid numeric port, Port returns an empty string. +func (u *URL) Port() string { + return (*url.URL)(u).Port() +} diff --git a/pkg/url/url_test.go b/pkg/base/url_test.go similarity index 74% rename from pkg/url/url_test.go rename to pkg/base/url_test.go index 7bc12985..84878649 100644 --- a/pkg/url/url_test.go +++ b/pkg/base/url_test.go @@ -1,4 +1,4 @@ -package url +package base import ( "net/url" @@ -7,15 +7,15 @@ import ( "github.com/stretchr/testify/require" ) -func mustParse(s string) *URL { - u, err := Parse(s) +func mustParseURL(s string) *URL { + u, err := ParseURL(s) if err != nil { panic(err) } return u } -func TestURLParse(t *testing.T) { +func TestParseURL(t *testing.T) { for _, ca := range []struct { name string enc string @@ -33,7 +33,7 @@ func TestURLParse(t *testing.T) { }, } { t.Run(ca.name, func(t *testing.T) { - u, err := Parse(ca.enc) + u, err := ParseURL(ca.enc) require.NoError(t, err) require.Equal(t, ca.u, u) }) @@ -68,14 +68,14 @@ func TestURLParseErrors(t *testing.T) { }, } { t.Run(ca.name, func(t *testing.T) { - _, err := Parse(ca.enc) + _, err := ParseURL(ca.enc) require.EqualError(t, err, ca.err) }) } } func TestURLClone(t *testing.T) { - u := mustParse("rtsp://localhost:8554/test/stream") + u := mustParseURL("rtsp://localhost:8554/test/stream") u2 := u.Clone() u.Host = "otherhost" @@ -93,7 +93,7 @@ func TestURLClone(t *testing.T) { } func TestURLCloneWithoutCredentials(t *testing.T) { - u := mustParse("rtsp://user:pass@localhost:8554/test/stream") + u := mustParseURL("rtsp://user:pass@localhost:8554/test/stream") u2 := u.CloneWithoutCredentials() u.Host = "otherhost" @@ -119,42 +119,42 @@ func TestURLRTSPPathAndQuery(t *testing.T) { }{ { "standard", - mustParse("rtsp://localhost:8554/teststream/trackID=1"), + mustParseURL("rtsp://localhost:8554/teststream/trackID=1"), "/teststream/trackID=1", }, { "subpath", - mustParse("rtsp://localhost:8554/test/stream/trackID=1"), + mustParseURL("rtsp://localhost:8554/test/stream/trackID=1"), "/test/stream/trackID=1", }, { "path and query", - mustParse("rtsp://192.168.1.99:554/test?user=tmp&password=BagRep1&channel=1&stream=0.sdp/trackID=1"), + mustParseURL("rtsp://192.168.1.99:554/test?user=tmp&password=BagRep1&channel=1&stream=0.sdp/trackID=1"), "/test?user=tmp&password=BagRep1&channel=1&stream=0.sdp/trackID=1", }, { "path and query with special chars", - mustParse("rtsp://192.168.1.99:554/te!st?user=tmp&password=BagRep1!&channel=1&stream=0.sdp/trackID=1"), + mustParseURL("rtsp://192.168.1.99:554/te!st?user=tmp&password=BagRep1!&channel=1&stream=0.sdp/trackID=1"), "/te!st?user=tmp&password=BagRep1!&channel=1&stream=0.sdp/trackID=1", }, { "path and query attached", - mustParse("rtsp://192.168.1.99:554/user=tmp&password=BagRep1!&channel=1&stream=0.sdp/trackID=1"), + mustParseURL("rtsp://192.168.1.99:554/user=tmp&password=BagRep1!&channel=1&stream=0.sdp/trackID=1"), "/user=tmp&password=BagRep1!&channel=1&stream=0.sdp/trackID=1", }, { "no path", - mustParse("rtsp://192.168.1.99:554"), + mustParseURL("rtsp://192.168.1.99:554"), "", }, { "single slash", - mustParse("rtsp://192.168.1.99:554/"), + mustParseURL("rtsp://192.168.1.99:554/"), "/", }, { "no slash and query", - mustParse("rtsp://192.168.1.99:554?testing"), + mustParseURL("rtsp://192.168.1.99:554?testing"), "?testing", }, } { diff --git a/pkg/conn/conn_test.go b/pkg/conn/conn_test.go index c9b499cb..77b6670d 100644 --- a/pkg/conn/conn_test.go +++ b/pkg/conn/conn_test.go @@ -7,11 +7,10 @@ import ( "github.com/stretchr/testify/require" "github.com/bluenviron/gortsplib/v4/pkg/base" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) -func mustParseURL(s string) *url.URL { - u, err := url.Parse(s) +func mustParseURL(s string) *base.URL { + u, err := base.ParseURL(s) if err != nil { panic(err) } @@ -32,7 +31,7 @@ func TestRead(t *testing.T) { "\r\n"), &base.Request{ Method: base.Describe, - URL: &url.URL{ + URL: &base.URL{ Scheme: "rtsp", Host: "example.com", Path: "/media.mp4", diff --git a/pkg/description/media.go b/pkg/description/media.go index 88d06efd..11a42c50 100644 --- a/pkg/description/media.go +++ b/pkg/description/media.go @@ -12,8 +12,8 @@ import ( psdp "github.com/pion/sdp/v3" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) var smartRegexp = regexp.MustCompile("^([0-9]+) (.*?)/90000") @@ -252,7 +252,7 @@ func (m Media) Marshal() *psdp.MediaDescription { } // URL returns the absolute URL of the media. -func (m Media) URL(contentBase *url.URL) (*url.URL, error) { +func (m Media) URL(contentBase *base.URL) (*base.URL, error) { if contentBase == nil { return nil, fmt.Errorf("Content-Base header not provided") } @@ -265,7 +265,7 @@ func (m Media) URL(contentBase *url.URL) (*url.URL, error) { // control attribute contains an absolute path if strings.HasPrefix(m.Control, "rtsp://") || strings.HasPrefix(m.Control, "rtsps://") { - ur, err := url.Parse(m.Control) + ur, err := base.ParseURL(m.Control) if err != nil { return nil, err } @@ -285,7 +285,7 @@ func (m Media) URL(contentBase *url.URL) (*url.URL, error) { strURL += "/" } - ur, _ := url.Parse(strURL + m.Control) + ur, _ := base.ParseURL(strURL + m.Control) return ur, nil } diff --git a/pkg/description/media_test.go b/pkg/description/media_test.go index 73be8344..3af21991 100644 --- a/pkg/description/media_test.go +++ b/pkg/description/media_test.go @@ -5,13 +5,13 @@ import ( "github.com/stretchr/testify/require" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/sdp" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) -func mustParseURL(s string) *url.URL { - u, err := url.Parse(s) +func mustParseURL(s string) *base.URL { + u, err := base.ParseURL(s) if err != nil { panic(err) } @@ -22,8 +22,8 @@ func TestMediaURL(t *testing.T) { for _, ca := range []struct { name string sdp []byte - baseURL *url.URL - ur *url.URL + baseURL *base.URL + ur *base.URL }{ { "missing control", diff --git a/pkg/description/session.go b/pkg/description/session.go index 778865a3..aa4f6911 100644 --- a/pkg/description/session.go +++ b/pkg/description/session.go @@ -6,8 +6,8 @@ import ( psdp "github.com/pion/sdp/v3" + "github.com/bluenviron/gortsplib/v4/pkg/base" "github.com/bluenviron/gortsplib/v4/pkg/sdp" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) func atLeastOneHasMID(medias []*Media) bool { @@ -43,7 +43,7 @@ type SessionFECGroup []string // Session is the description of a RTSP stream. type Session struct { // Base URL of the stream (read only). - BaseURL *url.URL + BaseURL *base.URL // Title of the stream (optional). Title string diff --git a/pkg/url/path.go b/pkg/url/path.go index 85e880a8..5376c42e 100644 --- a/pkg/url/path.go +++ b/pkg/url/path.go @@ -1,15 +1,12 @@ package url import ( - "strings" + "github.com/bluenviron/gortsplib/v4/pkg/base" ) // PathSplitQuery splits a path from a query. +// +// Deprecated: replaced by base.PathSplitQuery func PathSplitQuery(pathAndQuery string) (string, string) { - i := strings.Index(pathAndQuery, "?") - if i >= 0 { - return pathAndQuery[:i], pathAndQuery[i+1:] - } - - return pathAndQuery, "" + return base.PathSplitQuery(pathAndQuery) } diff --git a/pkg/url/url.go b/pkg/url/url.go index ff4601e3..af25e117 100644 --- a/pkg/url/url.go +++ b/pkg/url/url.go @@ -1,106 +1,20 @@ -// Package url contains the URL structure. +// Package url is deprecated. package url import ( - "fmt" - "net/url" - "regexp" - "strings" + "github.com/bluenviron/gortsplib/v4/pkg/base" ) // URL is a RTSP URL. // This is basically an HTTP URL with some additional functions to handle // control attributes. -type URL url.URL - -var escapeRegexp = regexp.MustCompile(`^(.+?)://(.*?)@(.*?)/(.*?)$`) +// +// Deprecated: replaced by base.URL +type URL = base.URL // Parse parses a RTSP URL. +// +// Deprecated: replaced by base.ParseURL func Parse(s string) (*URL, error) { - // https://github.com/golang/go/issues/30611 - m := escapeRegexp.FindStringSubmatch(s) - if m != nil { - m[3] = strings.ReplaceAll(m[3], "%25", "%") - m[3] = strings.ReplaceAll(m[3], "%", "%25") - s = m[1] + "://" + m[2] + "@" + m[3] + "/" + m[4] - } - - u, err := url.Parse(s) - if err != nil { - return nil, err - } - - if u.Scheme != "rtsp" && u.Scheme != "rtsps" { - return nil, fmt.Errorf("unsupported scheme '%s'", u.Scheme) - } - - if u.Opaque != "" { - return nil, fmt.Errorf("URLs with opaque data are not supported") - } - - if u.Fragment != "" { - return nil, fmt.Errorf("URLs with fragments are not supported") - } - - return (*URL)(u), nil -} - -// String implements fmt.Stringer. -func (u *URL) String() string { - return (*url.URL)(u).String() -} - -// Clone clones a URL. -func (u *URL) Clone() *URL { - return (*URL)(&url.URL{ - Scheme: u.Scheme, - User: u.User, - Host: u.Host, - Path: u.Path, - RawPath: u.RawPath, - ForceQuery: u.ForceQuery, - RawQuery: u.RawQuery, - }) -} - -// CloneWithoutCredentials clones a URL without its credentials. -func (u *URL) CloneWithoutCredentials() *URL { - return (*URL)(&url.URL{ - Scheme: u.Scheme, - Host: u.Host, - Path: u.Path, - RawPath: u.RawPath, - ForceQuery: u.ForceQuery, - RawQuery: u.RawQuery, - }) -} - -// RTSPPathAndQuery returns the path and query of a RTSP URL. -func (u *URL) RTSPPathAndQuery() (string, bool) { - var pathAndQuery string - if u.RawPath != "" { - pathAndQuery = u.RawPath - } else { - pathAndQuery = u.Path - } - if u.RawQuery != "" { - pathAndQuery += "?" + u.RawQuery - } - - return pathAndQuery, true -} - -// Hostname returns u.Host, stripping any valid port number if present. -// -// If the result is enclosed in square brackets, as literal IPv6 addresses are, -// the square brackets are removed from the result. -func (u *URL) Hostname() string { - return (*url.URL)(u).Hostname() -} - -// Port returns the port part of u.Host, without the leading colon. -// -// If u.Host doesn't contain a valid numeric port, Port returns an empty string. -func (u *URL) Port() string { - return (*url.URL)(u).Port() + return base.ParseURL(s) } diff --git a/server_conn.go b/server_conn.go index 35e65064..64a5cd93 100644 --- a/server_conn.go +++ b/server_conn.go @@ -14,7 +14,6 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/conn" "github.com/bluenviron/gortsplib/v4/pkg/description" "github.com/bluenviron/gortsplib/v4/pkg/liberrors" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) func getSessionID(header base.Header) string { @@ -24,7 +23,7 @@ func getSessionID(header base.Header) string { return "" } -func serverSideDescription(d *description.Session, contentBase *url.URL) *description.Session { +func serverSideDescription(d *description.Session, contentBase *base.URL) *description.Session { out := &description.Session{ Title: d.Title, FECGroups: d.FECGroups, @@ -230,7 +229,7 @@ func (sc *ServerConn) handleRequestInner(req *base.Request) (*base.Response, err }, liberrors.ErrServerInvalidPath{} } - path, query = url.PathSplitQuery(pathAndQuery) + path, query = base.PathSplitQuery(pathAndQuery) } switch req.Method { diff --git a/server_play_test.go b/server_play_test.go index c03616e2..12aeb0a4 100644 --- a/server_play_test.go +++ b/server_play_test.go @@ -23,7 +23,6 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/headers" "github.com/bluenviron/gortsplib/v4/pkg/sdp" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) func uintPtr(v uint) *uint { @@ -1978,7 +1977,7 @@ func TestServerPlayAdditionalInfos(t *testing.T) { require.True(t, strings.HasPrefix(mustParseURL((*rtpInfo)[0].URL).Path, "/teststream/trackID=")) require.Equal(t, &headers.RTPInfo{ &headers.RTPInfoEntry{ - URL: (&url.URL{ + URL: (&base.URL{ Scheme: "rtsp", Host: "localhost:8554", Path: mustParseURL((*rtpInfo)[0].URL).Path, @@ -2008,7 +2007,7 @@ func TestServerPlayAdditionalInfos(t *testing.T) { require.True(t, strings.HasPrefix(mustParseURL((*rtpInfo)[0].URL).Path, "/teststream/trackID=")) require.Equal(t, &headers.RTPInfo{ &headers.RTPInfoEntry{ - URL: (&url.URL{ + URL: (&base.URL{ Scheme: "rtsp", Host: "localhost:8554", Path: mustParseURL((*rtpInfo)[0].URL).Path, @@ -2017,7 +2016,7 @@ func TestServerPlayAdditionalInfos(t *testing.T) { Timestamp: (*rtpInfo)[0].Timestamp, }, &headers.RTPInfoEntry{ - URL: (&url.URL{ + URL: (&base.URL{ Scheme: "rtsp", Host: "localhost:8554", Path: mustParseURL((*rtpInfo)[1].URL).Path, diff --git a/server_session.go b/server_session.go index 862407c6..bfe8163e 100644 --- a/server_session.go +++ b/server_session.go @@ -21,7 +21,6 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/liberrors" "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/bluenviron/gortsplib/v4/pkg/sdp" - "github.com/bluenviron/gortsplib/v4/pkg/url" ) type readFunc func([]byte) @@ -35,7 +34,7 @@ func stringsReverseIndex(s, substr string) int { return -1 } -func serverParseURLForPlay(u *url.URL) (string, string, string, error) { +func serverParseURLForPlay(u *base.URL) (string, string, string, error) { pathAndQuery, ok := u.RTSPPathAndQuery() if !ok { return "", "", "", liberrors.ErrServerInvalidPath{} @@ -47,18 +46,18 @@ func serverParseURLForPlay(u *url.URL) (string, string, string, error) { return "", "", "", liberrors.ErrServerPathNoSlash{} } - path, query := url.PathSplitQuery(pathAndQuery[:len(pathAndQuery)-1]) + path, query := base.PathSplitQuery(pathAndQuery[:len(pathAndQuery)-1]) return path, query, "", nil } var trackID string pathAndQuery, trackID = pathAndQuery[:i], pathAndQuery[i+len("/trackID="):] - path, query := url.PathSplitQuery(pathAndQuery) + path, query := base.PathSplitQuery(pathAndQuery) return path, query, trackID, nil } -func recordBaseURL(u *url.URL, path string, query string) *url.URL { - baseURL := &url.URL{ +func recordBaseURL(u *base.URL, path string, query string) *base.URL { + baseURL := &base.URL{ Scheme: u.Scheme, Host: u.Host, Path: path, @@ -74,7 +73,7 @@ func recordBaseURL(u *url.URL, path string, query string) *url.URL { return baseURL } -func findMediaByURL(medias []*description.Media, baseURL *url.URL, u *url.URL) *description.Media { +func findMediaByURL(medias []*description.Media, baseURL *base.URL, u *base.URL) *description.Media { for _, media := range medias { u1, err := media.URL(baseURL) if err == nil && u1.String() == u.String() { @@ -123,14 +122,14 @@ func generateRTPInfo( setuppedMediasOrdered []*serverSessionMedia, setuppedStream *ServerStream, setuppedPath string, - u *url.URL, + u *base.URL, ) (headers.RTPInfo, bool) { var ri headers.RTPInfo for _, sm := range setuppedMediasOrdered { entry := setuppedStream.rtpInfoEntry(sm.media, now) if entry != nil { - entry.URL = (&url.URL{ + entry.URL = (&base.URL{ Scheme: u.Scheme, Host: u.Host, Path: setuppedPath + "/trackID=" + @@ -526,7 +525,7 @@ func (ss *ServerSession) handleRequestInner(sc *ServerConn, req *base.Request) ( pathAndQuery = strings.TrimSuffix(pathAndQuery, "/") } - path, query = url.PathSplitQuery(pathAndQuery) + path, query = base.PathSplitQuery(pathAndQuery) } switch req.Method {