mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 15:16:51 +08:00
rewrite extraction of control attribute
This commit is contained in:
@@ -3,8 +3,46 @@ package base
|
||||
import (
|
||||
"fmt"
|
||||
"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.
|
||||
// This is basically an HTTP URL with some additional functions to handle
|
||||
// control attributes.
|
||||
@@ -67,19 +105,12 @@ func (u *URL) CloneWithoutCredentials() *URL {
|
||||
|
||||
// RTSPPath returns the path of a RTSP URL.
|
||||
func (u *URL) RTSPPath() (string, bool) {
|
||||
var path string
|
||||
if u.RawPath != "" {
|
||||
path = u.RawPath
|
||||
} else {
|
||||
path = u.Path
|
||||
}
|
||||
|
||||
// remove leading slash
|
||||
if len(path) == 0 || path[0] != '/' {
|
||||
pathAndQuery, ok := u.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
path = path[1:]
|
||||
|
||||
path, _ := PathSplitQuery(pathAndQuery)
|
||||
return path, true
|
||||
}
|
||||
|
||||
@@ -104,19 +135,6 @@ func (u *URL) RTSPPathAndQuery() (string, bool) {
|
||||
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.
|
||||
func (u *URL) AddControlAttribute(controlPath string) {
|
||||
if controlPath[0] != '?' {
|
||||
|
@@ -170,15 +170,24 @@ func (ts *testServ) handleConn(conn *ServerConn) {
|
||||
}
|
||||
|
||||
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() {
|
||||
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" {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
|
@@ -6,7 +6,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -500,23 +499,10 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
||||
|
||||
trackID, err := func() (int, error) {
|
||||
if th.Mode == nil || *th.Mode == headers.TransportModePlay {
|
||||
i := strings.Index(pathAndQuery, "/trackID=")
|
||||
|
||||
// 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 {
|
||||
trackID, _, ok := base.PathSplitControlAttribute(pathAndQuery)
|
||||
if !ok {
|
||||
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
|
||||
}
|
||||
|
Reference in New Issue
Block a user