rewrite extraction of control attribute

This commit is contained in:
aler9
2021-01-19 14:28:46 +01:00
parent af60046380
commit 039d69ba42
3 changed files with 59 additions and 46 deletions

View File

@@ -3,8 +3,46 @@ package base
import ( import (
"fmt" "fmt"
"net/url" "net/url"
"strconv"
) )
func stringsReverseIndex(s, substr string) int {
for i := len(s) - 1 - len(substr); i >= 0; i-- {
if s[i:i+len(substr)] == substr {
return i
}
}
return -1
}
// PathSplitControlAttribute splits a path and query from a control attribute.
func PathSplitControlAttribute(pathAndQuery string) (int, string, bool) {
i := stringsReverseIndex(pathAndQuery, "/trackID=")
// URL doesn't contain trackID - we assume it's track 0
if i < 0 {
return 0, pathAndQuery, true
}
tmp, err := strconv.ParseInt(pathAndQuery[i+len("/trackID="):], 10, 64)
if err != nil || tmp < 0 {
return 0, "", false
}
trackID := int(tmp)
return trackID, pathAndQuery[:i], true
}
// PathSplitQuery splits a path from a query.
func PathSplitQuery(pathAndQuery string) (string, string) {
i := stringsReverseIndex(pathAndQuery, "?")
if i >= 0 {
return pathAndQuery[:i], pathAndQuery[i:]
}
return pathAndQuery, ""
}
// URL is a RTSP URL. // URL is a RTSP URL.
// This is basically an HTTP URL with some additional functions to handle // This is basically an HTTP URL with some additional functions to handle
// control attributes. // control attributes.
@@ -67,19 +105,12 @@ func (u *URL) CloneWithoutCredentials() *URL {
// RTSPPath returns the path of a RTSP URL. // RTSPPath returns the path of a RTSP URL.
func (u *URL) RTSPPath() (string, bool) { func (u *URL) RTSPPath() (string, bool) {
var path string pathAndQuery, ok := u.RTSPPathAndQuery()
if u.RawPath != "" { if !ok {
path = u.RawPath
} else {
path = u.Path
}
// remove leading slash
if len(path) == 0 || path[0] != '/' {
return "", false return "", false
} }
path = path[1:]
path, _ := PathSplitQuery(pathAndQuery)
return path, true return path, true
} }
@@ -104,19 +135,6 @@ func (u *URL) RTSPPathAndQuery() (string, bool) {
return pathAndQuery, true return pathAndQuery, true
} }
// SetRTSPPathAndQuery sets the path and query of a RTSP URL.
func (u *URL) SetRTSPPathAndQuery(pathAndQuery string) {
nu1 := &URL{
Scheme: u.Scheme,
Opaque: u.Opaque,
User: u.User,
Host: u.Host,
Path: "/",
}
nu2, _ := ParseURL(nu1.String() + pathAndQuery)
*u = *nu2
}
// AddControlAttribute adds a control attribute to a RTSP url. // AddControlAttribute adds a control attribute to a RTSP url.
func (u *URL) AddControlAttribute(controlPath string) { func (u *URL) AddControlAttribute(controlPath string) {
if controlPath[0] != '?' { if controlPath[0] != '?' {

View File

@@ -170,15 +170,24 @@ func (ts *testServ) handleConn(conn *ServerConn) {
} }
onSetup := func(req *base.Request, th *headers.Transport, trackID int) (*base.Response, error) { onSetup := func(req *base.Request, th *headers.Transport, trackID int) (*base.Response, error) {
reqPath, ok := req.URL.RTSPPath()
if !ok {
return &base.Response{
StatusCode: base.StatusBadRequest,
}, fmt.Errorf("invalid path (%s)", req.URL)
}
switch conn.State() { switch conn.State() {
case ServerConnStateInitial, ServerConnStatePrePlay: case ServerConnStateInitial, ServerConnStatePrePlay:
pathAndQuery, ok := req.URL.RTSPPathAndQuery()
if !ok {
return &base.Response{
StatusCode: base.StatusBadRequest,
}, fmt.Errorf("invalid path (%s)", req.URL)
}
_, pathAndQuery, ok = base.PathSplitControlAttribute(pathAndQuery)
if !ok {
return &base.Response{
StatusCode: base.StatusBadRequest,
}, fmt.Errorf("invalid path (%s)", req.URL)
}
reqPath, _ := base.PathSplitQuery(pathAndQuery)
if reqPath != "teststream" { if reqPath != "teststream" {
return &base.Response{ return &base.Response{
StatusCode: base.StatusBadRequest, StatusCode: base.StatusBadRequest,

View File

@@ -6,7 +6,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"strconv"
"strings" "strings"
"sync/atomic" "sync/atomic"
"time" "time"
@@ -500,23 +499,10 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
trackID, err := func() (int, error) { trackID, err := func() (int, error) {
if th.Mode == nil || *th.Mode == headers.TransportModePlay { if th.Mode == nil || *th.Mode == headers.TransportModePlay {
i := strings.Index(pathAndQuery, "/trackID=") trackID, _, ok := base.PathSplitControlAttribute(pathAndQuery)
if !ok {
// URL doesn't contain trackID - we assume it's track 0
if i < 0 {
return 0, nil
}
tmp, err := strconv.ParseInt(pathAndQuery[i+len("/trackID="):], 10, 64)
if err != nil || tmp < 0 {
return 0, fmt.Errorf("invalid track (%s)", pathAndQuery) return 0, fmt.Errorf("invalid track (%s)", pathAndQuery)
} }
trackID := int(tmp)
// remove track ID from path
nu := req.URL.Clone()
nu.SetRTSPPathAndQuery(pathAndQuery[:i])
req.URL = nu
return trackID, nil return trackID, nil
} }