mirror of
https://github.com/aler9/gortsplib
synced 2025-09-27 03:25:52 +08:00
move url.URL into base.URL (#459)
This commit is contained in:
51
client.go
51
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 {
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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{}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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,
|
||||
|
15
pkg/base/path.go
Normal file
15
pkg/base/path.go
Normal file
@@ -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, ""
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package url
|
||||
package base
|
||||
|
||||
import (
|
||||
"testing"
|
@@ -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)
|
||||
}
|
||||
|
@@ -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
|
||||
|
105
pkg/base/url.go
Normal file
105
pkg/base/url.go
Normal file
@@ -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()
|
||||
}
|
@@ -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",
|
||||
},
|
||||
} {
|
@@ -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",
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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",
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
}
|
||||
|
102
pkg/url/url.go
102
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)
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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,
|
||||
|
@@ -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 {
|
||||
|
Reference in New Issue
Block a user