mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 23:26:54 +08:00
rewrite extraction of control attribute
This commit is contained in:
@@ -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] != '?' {
|
||||||
|
@@ -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,
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user