mirror of
https://github.com/aler9/gortsplib
synced 2025-10-06 15:46:51 +08:00
move headers into dedicated folder
This commit is contained in:
11
auth.go
11
auth.go
@@ -10,14 +10,3 @@ func md5Hex(in string) string {
|
||||
h.Write([]byte(in))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// AuthMethod is an authentication method.
|
||||
type AuthMethod int
|
||||
|
||||
const (
|
||||
// Basic authentication method
|
||||
Basic AuthMethod = iota
|
||||
|
||||
// Digest authentication method
|
||||
Digest
|
||||
)
|
||||
|
12
auth_test.go
12
auth_test.go
@@ -7,23 +7,24 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aler9/gortsplib/base"
|
||||
"github.com/aler9/gortsplib/headers"
|
||||
)
|
||||
|
||||
var casesAuth = []struct {
|
||||
name string
|
||||
methods []AuthMethod
|
||||
methods []headers.AuthMethod
|
||||
}{
|
||||
{
|
||||
"basic",
|
||||
[]AuthMethod{Basic},
|
||||
[]headers.AuthMethod{headers.AuthBasic},
|
||||
},
|
||||
{
|
||||
"digest",
|
||||
[]AuthMethod{Digest},
|
||||
[]headers.AuthMethod{headers.AuthDigest},
|
||||
},
|
||||
{
|
||||
"both",
|
||||
[]AuthMethod{Basic, Digest},
|
||||
[]headers.AuthMethod{headers.AuthBasic, headers.AuthDigest},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -46,7 +47,8 @@ func TestAuthMethods(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAuthBasePath(t *testing.T) {
|
||||
authServer := NewAuthServer("testuser", "testpass", []AuthMethod{Basic, Digest})
|
||||
authServer := NewAuthServer("testuser", "testpass",
|
||||
[]headers.AuthMethod{headers.AuthBasic, headers.AuthDigest})
|
||||
wwwAuthenticate := authServer.GenerateHeader()
|
||||
|
||||
ac, err := newAuthClient(wwwAuthenticate, "testuser", "testpass")
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/aler9/gortsplib/base"
|
||||
"github.com/aler9/gortsplib/headers"
|
||||
)
|
||||
|
||||
// authClient is an object that helps a client to send its credentials to a
|
||||
@@ -14,7 +15,7 @@ import (
|
||||
type authClient struct {
|
||||
user string
|
||||
pass string
|
||||
method AuthMethod
|
||||
method headers.AuthMethod
|
||||
realm string
|
||||
nonce string
|
||||
}
|
||||
@@ -31,7 +32,7 @@ func newAuthClient(v base.HeaderValue, user string, pass string) (*authClient, e
|
||||
}
|
||||
return ""
|
||||
}(); headerAuthDigest != "" {
|
||||
auth, err := ReadHeaderAuth(base.HeaderValue{headerAuthDigest})
|
||||
auth, err := headers.ReadAuth(base.HeaderValue{headerAuthDigest})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -47,7 +48,7 @@ func newAuthClient(v base.HeaderValue, user string, pass string) (*authClient, e
|
||||
return &authClient{
|
||||
user: user,
|
||||
pass: pass,
|
||||
method: Digest,
|
||||
method: headers.AuthDigest,
|
||||
realm: *auth.Realm,
|
||||
nonce: *auth.Nonce,
|
||||
}, nil
|
||||
@@ -61,7 +62,7 @@ func newAuthClient(v base.HeaderValue, user string, pass string) (*authClient, e
|
||||
}
|
||||
return ""
|
||||
}(); headerAuthBasic != "" {
|
||||
auth, err := ReadHeaderAuth(base.HeaderValue{headerAuthBasic})
|
||||
auth, err := headers.ReadAuth(base.HeaderValue{headerAuthBasic})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -73,7 +74,7 @@ func newAuthClient(v base.HeaderValue, user string, pass string) (*authClient, e
|
||||
return &authClient{
|
||||
user: user,
|
||||
pass: pass,
|
||||
method: Basic,
|
||||
method: headers.AuthBasic,
|
||||
realm: *auth.Realm,
|
||||
}, nil
|
||||
}
|
||||
@@ -85,17 +86,17 @@ func newAuthClient(v base.HeaderValue, user string, pass string) (*authClient, e
|
||||
// the given method and url.
|
||||
func (ac *authClient) GenerateHeader(method base.Method, ur *url.URL) base.HeaderValue {
|
||||
switch ac.method {
|
||||
case Basic:
|
||||
case headers.AuthBasic:
|
||||
response := base64.StdEncoding.EncodeToString([]byte(ac.user + ":" + ac.pass))
|
||||
|
||||
return base.HeaderValue{"Basic " + response}
|
||||
|
||||
case Digest:
|
||||
case headers.AuthDigest:
|
||||
response := md5Hex(md5Hex(ac.user+":"+ac.realm+":"+ac.pass) + ":" +
|
||||
ac.nonce + ":" + md5Hex(string(method)+":"+ur.String()))
|
||||
|
||||
return (&HeaderAuth{
|
||||
Method: Digest,
|
||||
return (&headers.Auth{
|
||||
Method: headers.AuthDigest,
|
||||
Username: &ac.user,
|
||||
Realm: &ac.realm,
|
||||
Nonce: &ac.nonce,
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/aler9/gortsplib/base"
|
||||
"github.com/aler9/gortsplib/headers"
|
||||
)
|
||||
|
||||
// AuthServer is an object that helps a server to validate the credentials of
|
||||
@@ -16,16 +17,16 @@ import (
|
||||
type AuthServer struct {
|
||||
user string
|
||||
pass string
|
||||
methods []AuthMethod
|
||||
methods []headers.AuthMethod
|
||||
realm string
|
||||
nonce string
|
||||
}
|
||||
|
||||
// NewAuthServer allocates an AuthServer.
|
||||
// If methods is nil, the Basic and Digest methods are used.
|
||||
func NewAuthServer(user string, pass string, methods []AuthMethod) *AuthServer {
|
||||
func NewAuthServer(user string, pass string, methods []headers.AuthMethod) *AuthServer {
|
||||
if methods == nil {
|
||||
methods = []AuthMethod{Basic, Digest}
|
||||
methods = []headers.AuthMethod{headers.AuthBasic, headers.AuthDigest}
|
||||
}
|
||||
|
||||
nonceByts := make([]byte, 16)
|
||||
@@ -46,15 +47,15 @@ func (as *AuthServer) GenerateHeader() base.HeaderValue {
|
||||
var ret base.HeaderValue
|
||||
for _, m := range as.methods {
|
||||
switch m {
|
||||
case Basic:
|
||||
ret = append(ret, (&HeaderAuth{
|
||||
Method: Basic,
|
||||
case headers.AuthBasic:
|
||||
ret = append(ret, (&headers.Auth{
|
||||
Method: headers.AuthBasic,
|
||||
Realm: &as.realm,
|
||||
}).Write()...)
|
||||
|
||||
case Digest:
|
||||
ret = append(ret, (&HeaderAuth{
|
||||
Method: Digest,
|
||||
case headers.AuthDigest:
|
||||
ret = append(ret, (&headers.Auth{
|
||||
Method: headers.AuthDigest,
|
||||
Realm: &as.realm,
|
||||
Nonce: &as.nonce,
|
||||
}).Write()...)
|
||||
@@ -85,7 +86,7 @@ func (as *AuthServer) ValidateHeader(v base.HeaderValue, method base.Method, ur
|
||||
}
|
||||
|
||||
} else if strings.HasPrefix(v0, "Digest ") {
|
||||
auth, err := ReadHeaderAuth(base.HeaderValue{v0})
|
||||
auth, err := headers.ReadAuth(base.HeaderValue{v0})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aler9/gortsplib/base"
|
||||
"github.com/aler9/gortsplib/headers"
|
||||
"github.com/aler9/gortsplib/rtcpreceiver"
|
||||
)
|
||||
|
||||
@@ -297,7 +298,7 @@ func (c *ConnClient) Do(req *base.Request) (*base.Response, error) {
|
||||
|
||||
// get session from response
|
||||
if v, ok := res.Header["Session"]; ok {
|
||||
sx, err := ReadHeaderSession(v)
|
||||
sx, err := headers.ReadSession(v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse session header: %s", err)
|
||||
}
|
||||
@@ -448,7 +449,7 @@ func (c *ConnClient) urlForTrack(baseUrl *url.URL, mode SetupMode, track *Track)
|
||||
return u
|
||||
}
|
||||
|
||||
func (c *ConnClient) setup(u *url.URL, mode SetupMode, track *Track, ht *HeaderTransport) (*base.Response, error) {
|
||||
func (c *ConnClient) setup(u *url.URL, mode SetupMode, track *Track, ht *headers.Transport) (*base.Response, error) {
|
||||
res, err := c.Do(&base.Request{
|
||||
Method: base.SETUP,
|
||||
Url: c.urlForTrack(u, mode, track),
|
||||
@@ -533,7 +534,7 @@ func (c *ConnClient) SetupUDP(u *url.URL, mode SetupMode, track *Track, rtpPort
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := c.setup(u, mode, track, &HeaderTransport{
|
||||
res, err := c.setup(u, mode, track, &headers.Transport{
|
||||
Protocol: StreamProtocolUDP,
|
||||
Cast: func() *StreamCast {
|
||||
ret := StreamUnicast
|
||||
@@ -556,7 +557,7 @@ func (c *ConnClient) SetupUDP(u *url.URL, mode SetupMode, track *Track, rtpPort
|
||||
return nil, err
|
||||
}
|
||||
|
||||
th, err := ReadHeaderTransport(res.Header["Transport"])
|
||||
th, err := headers.ReadTransport(res.Header["Transport"])
|
||||
if err != nil {
|
||||
rtpListener.close()
|
||||
rtcpListener.close()
|
||||
@@ -608,7 +609,7 @@ func (c *ConnClient) SetupTCP(u *url.URL, mode SetupMode, track *Track) (*base.R
|
||||
}
|
||||
|
||||
interleavedIds := [2]int{(track.Id * 2), (track.Id * 2) + 1}
|
||||
res, err := c.setup(u, mode, track, &HeaderTransport{
|
||||
res, err := c.setup(u, mode, track, &headers.Transport{
|
||||
Protocol: StreamProtocolTCP,
|
||||
Cast: func() *StreamCast {
|
||||
ret := StreamUnicast
|
||||
@@ -629,7 +630,7 @@ func (c *ConnClient) SetupTCP(u *url.URL, mode SetupMode, track *Track) (*base.R
|
||||
return nil, err
|
||||
}
|
||||
|
||||
th, err := ReadHeaderTransport(res.Header["Transport"])
|
||||
th, err := headers.ReadTransport(res.Header["Transport"])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("transport header: %s", err)
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
package gortsplib
|
||||
// Package headers contains various RTSP headers.
|
||||
package headers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -7,8 +8,19 @@ import (
|
||||
"github.com/aler9/gortsplib/base"
|
||||
)
|
||||
|
||||
// HeaderAuth is an Authenticate or a WWWW-Authenticate header.
|
||||
type HeaderAuth struct {
|
||||
// AuthMethod is an authentication method.
|
||||
type AuthMethod int
|
||||
|
||||
const (
|
||||
// AuthBasic is the Basic authentication method
|
||||
AuthBasic AuthMethod = iota
|
||||
|
||||
// AuthDigest is the Digest authentication method
|
||||
AuthDigest
|
||||
)
|
||||
|
||||
// Auth is an Authenticate or a WWWW-Authenticate header.
|
||||
type Auth struct {
|
||||
// authentication method
|
||||
Method AuthMethod
|
||||
|
||||
@@ -67,8 +79,8 @@ func findValue(v0 string) (string, string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadHeaderAuth parses an Authenticate or a WWW-Authenticate header.
|
||||
func ReadHeaderAuth(v base.HeaderValue) (*HeaderAuth, error) {
|
||||
// ReadAuth parses an Authenticate or a WWW-Authenticate header.
|
||||
func ReadAuth(v base.HeaderValue) (*Auth, error) {
|
||||
if len(v) == 0 {
|
||||
return nil, fmt.Errorf("value not provided")
|
||||
}
|
||||
@@ -77,7 +89,7 @@ func ReadHeaderAuth(v base.HeaderValue) (*HeaderAuth, error) {
|
||||
return nil, fmt.Errorf("value provided multiple times (%v)", v)
|
||||
}
|
||||
|
||||
ha := &HeaderAuth{}
|
||||
ha := &Auth{}
|
||||
|
||||
v0 := v[0]
|
||||
|
||||
@@ -88,10 +100,10 @@ func ReadHeaderAuth(v base.HeaderValue) (*HeaderAuth, error) {
|
||||
|
||||
switch v0[:i] {
|
||||
case "Basic":
|
||||
ha.Method = Basic
|
||||
ha.Method = AuthBasic
|
||||
|
||||
case "Digest":
|
||||
ha.Method = Digest
|
||||
ha.Method = AuthDigest
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid method (%s)", v0[:i])
|
||||
@@ -156,14 +168,14 @@ func ReadHeaderAuth(v base.HeaderValue) (*HeaderAuth, error) {
|
||||
}
|
||||
|
||||
// Write encodes an Authenticate or a WWW-Authenticate header.
|
||||
func (ha *HeaderAuth) Write() base.HeaderValue {
|
||||
func (ha *Auth) Write() base.HeaderValue {
|
||||
ret := ""
|
||||
|
||||
switch ha.Method {
|
||||
case Basic:
|
||||
case AuthBasic:
|
||||
ret += "Basic"
|
||||
|
||||
case Digest:
|
||||
case AuthDigest:
|
||||
ret += "Digest"
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package gortsplib
|
||||
package headers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -8,18 +8,18 @@ import (
|
||||
"github.com/aler9/gortsplib/base"
|
||||
)
|
||||
|
||||
var casesHeaderAuth = []struct {
|
||||
var casesAuth = []struct {
|
||||
name string
|
||||
vin base.HeaderValue
|
||||
vout base.HeaderValue
|
||||
h *HeaderAuth
|
||||
h *Auth
|
||||
}{
|
||||
{
|
||||
"basic",
|
||||
base.HeaderValue{`Basic realm="4419b63f5e51"`},
|
||||
base.HeaderValue{`Basic realm="4419b63f5e51"`},
|
||||
&HeaderAuth{
|
||||
Method: Basic,
|
||||
&Auth{
|
||||
Method: AuthBasic,
|
||||
Realm: func() *string {
|
||||
v := "4419b63f5e51"
|
||||
return &v
|
||||
@@ -30,8 +30,8 @@ var casesHeaderAuth = []struct {
|
||||
"digest request 1",
|
||||
base.HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale="FALSE"`},
|
||||
base.HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale="FALSE"`},
|
||||
&HeaderAuth{
|
||||
Method: Digest,
|
||||
&Auth{
|
||||
Method: AuthDigest,
|
||||
Realm: func() *string {
|
||||
v := "4419b63f5e51"
|
||||
return &v
|
||||
@@ -50,8 +50,8 @@ var casesHeaderAuth = []struct {
|
||||
"digest request 2",
|
||||
base.HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale=FALSE`},
|
||||
base.HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale="FALSE"`},
|
||||
&HeaderAuth{
|
||||
Method: Digest,
|
||||
&Auth{
|
||||
Method: AuthDigest,
|
||||
Realm: func() *string {
|
||||
v := "4419b63f5e51"
|
||||
return &v
|
||||
@@ -70,8 +70,8 @@ var casesHeaderAuth = []struct {
|
||||
"digest request 3",
|
||||
base.HeaderValue{`Digest realm="4419b63f5e51",nonce="133767111917411116111311118211673010032", stale="FALSE"`},
|
||||
base.HeaderValue{`Digest realm="4419b63f5e51", nonce="133767111917411116111311118211673010032", stale="FALSE"`},
|
||||
&HeaderAuth{
|
||||
Method: Digest,
|
||||
&Auth{
|
||||
Method: AuthDigest,
|
||||
Realm: func() *string {
|
||||
v := "4419b63f5e51"
|
||||
return &v
|
||||
@@ -90,8 +90,8 @@ var casesHeaderAuth = []struct {
|
||||
"digest response generic",
|
||||
base.HeaderValue{`Digest username="aa", realm="bb", nonce="cc", uri="dd", response="ee"`},
|
||||
base.HeaderValue{`Digest username="aa", realm="bb", nonce="cc", uri="dd", response="ee"`},
|
||||
&HeaderAuth{
|
||||
Method: Digest,
|
||||
&Auth{
|
||||
Method: AuthDigest,
|
||||
Username: func() *string {
|
||||
v := "aa"
|
||||
return &v
|
||||
@@ -118,8 +118,8 @@ var casesHeaderAuth = []struct {
|
||||
"digest response with empty field",
|
||||
base.HeaderValue{`Digest username="", realm="IPCAM", nonce="5d17cd12b9fa8a85ac5ceef0926ea5a6", uri="rtsp://localhost:8554/mystream", response="c072ae90eb4a27f4cdcb90d62266b2a1"`},
|
||||
base.HeaderValue{`Digest username="", realm="IPCAM", nonce="5d17cd12b9fa8a85ac5ceef0926ea5a6", uri="rtsp://localhost:8554/mystream", response="c072ae90eb4a27f4cdcb90d62266b2a1"`},
|
||||
&HeaderAuth{
|
||||
Method: Digest,
|
||||
&Auth{
|
||||
Method: AuthDigest,
|
||||
Username: func() *string {
|
||||
v := ""
|
||||
return &v
|
||||
@@ -146,8 +146,8 @@ var casesHeaderAuth = []struct {
|
||||
"digest response with no spaces and additional fields",
|
||||
base.HeaderValue{`Digest realm="Please log in with a valid username",nonce="752a62306daf32b401a41004555c7663",opaque="",stale=FALSE,algorithm=MD5`},
|
||||
base.HeaderValue{`Digest realm="Please log in with a valid username", nonce="752a62306daf32b401a41004555c7663", opaque="", stale="FALSE", algorithm="MD5"`},
|
||||
&HeaderAuth{
|
||||
Method: Digest,
|
||||
&Auth{
|
||||
Method: AuthDigest,
|
||||
Realm: func() *string {
|
||||
v := "Please log in with a valid username"
|
||||
return &v
|
||||
@@ -172,18 +172,18 @@ var casesHeaderAuth = []struct {
|
||||
},
|
||||
}
|
||||
|
||||
func TestHeaderAuthRead(t *testing.T) {
|
||||
for _, c := range casesHeaderAuth {
|
||||
func TestAuthRead(t *testing.T) {
|
||||
for _, c := range casesAuth {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
req, err := ReadHeaderAuth(c.vin)
|
||||
req, err := ReadAuth(c.vin)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, c.h, req)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeaderAuthWrite(t *testing.T) {
|
||||
for _, c := range casesHeaderAuth {
|
||||
func TestAuthWrite(t *testing.T) {
|
||||
for _, c := range casesAuth {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
req := c.h.Write()
|
||||
require.Equal(t, c.vout, req)
|
@@ -1,4 +1,4 @@
|
||||
package gortsplib
|
||||
package headers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"github.com/aler9/gortsplib/base"
|
||||
)
|
||||
|
||||
// HeaderSession is a Session header.
|
||||
type HeaderSession struct {
|
||||
// Session is a Session header.
|
||||
type Session struct {
|
||||
// session id
|
||||
Session string
|
||||
|
||||
@@ -17,8 +17,8 @@ type HeaderSession struct {
|
||||
Timeout *uint
|
||||
}
|
||||
|
||||
// ReadHeaderSession parses a Session header.
|
||||
func ReadHeaderSession(v base.HeaderValue) (*HeaderSession, error) {
|
||||
// ReadSession parses a Session header.
|
||||
func ReadSession(v base.HeaderValue) (*Session, error) {
|
||||
if len(v) == 0 {
|
||||
return nil, fmt.Errorf("value not provided")
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func ReadHeaderSession(v base.HeaderValue) (*HeaderSession, error) {
|
||||
return nil, fmt.Errorf("invalid value (%v)", v)
|
||||
}
|
||||
|
||||
hs := &HeaderSession{}
|
||||
hs := &Session{}
|
||||
|
||||
hs.Session = parts[0]
|
||||
|
||||
@@ -63,7 +63,7 @@ func ReadHeaderSession(v base.HeaderValue) (*HeaderSession, error) {
|
||||
}
|
||||
|
||||
// Write encodes a Session header
|
||||
func (hs *HeaderSession) Write() base.HeaderValue {
|
||||
func (hs *Session) Write() base.HeaderValue {
|
||||
val := hs.Session
|
||||
|
||||
if hs.Timeout != nil {
|
@@ -1,4 +1,4 @@
|
||||
package gortsplib
|
||||
package headers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -8,17 +8,17 @@ import (
|
||||
"github.com/aler9/gortsplib/base"
|
||||
)
|
||||
|
||||
var casesHeaderSession = []struct {
|
||||
var casesSession = []struct {
|
||||
name string
|
||||
vin base.HeaderValue
|
||||
vout base.HeaderValue
|
||||
h *HeaderSession
|
||||
h *Session
|
||||
}{
|
||||
{
|
||||
"base",
|
||||
base.HeaderValue{`A3eqwsafq3rFASqew`},
|
||||
base.HeaderValue{`A3eqwsafq3rFASqew`},
|
||||
&HeaderSession{
|
||||
&Session{
|
||||
Session: "A3eqwsafq3rFASqew",
|
||||
},
|
||||
},
|
||||
@@ -26,7 +26,7 @@ var casesHeaderSession = []struct {
|
||||
"with timeout",
|
||||
base.HeaderValue{`A3eqwsafq3rFASqew;timeout=47`},
|
||||
base.HeaderValue{`A3eqwsafq3rFASqew;timeout=47`},
|
||||
&HeaderSession{
|
||||
&Session{
|
||||
Session: "A3eqwsafq3rFASqew",
|
||||
Timeout: func() *uint {
|
||||
v := uint(47)
|
||||
@@ -38,7 +38,7 @@ var casesHeaderSession = []struct {
|
||||
"with timeout and space",
|
||||
base.HeaderValue{`A3eqwsafq3rFASqew; timeout=47`},
|
||||
base.HeaderValue{`A3eqwsafq3rFASqew;timeout=47`},
|
||||
&HeaderSession{
|
||||
&Session{
|
||||
Session: "A3eqwsafq3rFASqew",
|
||||
Timeout: func() *uint {
|
||||
v := uint(47)
|
||||
@@ -48,18 +48,18 @@ var casesHeaderSession = []struct {
|
||||
},
|
||||
}
|
||||
|
||||
func TestHeaderSessionRead(t *testing.T) {
|
||||
for _, c := range casesHeaderSession {
|
||||
func TestSessionRead(t *testing.T) {
|
||||
for _, c := range casesSession {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
req, err := ReadHeaderSession(c.vin)
|
||||
req, err := ReadSession(c.vin)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, c.h, req)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeaderSessionWrite(t *testing.T) {
|
||||
for _, c := range casesHeaderSession {
|
||||
func TestSessionWrite(t *testing.T) {
|
||||
for _, c := range casesSession {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
req := c.h.Write()
|
||||
require.Equal(t, c.vout, req)
|
@@ -1,4 +1,4 @@
|
||||
package gortsplib
|
||||
package headers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -8,8 +8,54 @@ import (
|
||||
"github.com/aler9/gortsplib/base"
|
||||
)
|
||||
|
||||
// HeaderTransport is a Transport header.
|
||||
type HeaderTransport struct {
|
||||
// StreamProtocol is the protocol of a stream.
|
||||
type StreamProtocol int
|
||||
|
||||
const (
|
||||
// StreamProtocolUDP means that the stream uses the UDP protocol
|
||||
StreamProtocolUDP StreamProtocol = iota
|
||||
|
||||
// StreamProtocolTCP means that the stream uses the TCP protocol
|
||||
StreamProtocolTCP
|
||||
)
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (sp StreamProtocol) String() string {
|
||||
switch sp {
|
||||
case StreamProtocolUDP:
|
||||
return "udp"
|
||||
|
||||
case StreamProtocolTCP:
|
||||
return "tcp"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// StreamCast is the cast method of a stream.
|
||||
type StreamCast int
|
||||
|
||||
const (
|
||||
// StreamUnicast means that the stream is unicasted
|
||||
StreamUnicast StreamCast = iota
|
||||
|
||||
// StreamMulticast means that the stream is multicasted
|
||||
StreamMulticast
|
||||
)
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (sc StreamCast) String() string {
|
||||
switch sc {
|
||||
case StreamUnicast:
|
||||
return "unicast"
|
||||
|
||||
case StreamMulticast:
|
||||
return "multicast"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// Transport is a Transport header.
|
||||
type Transport struct {
|
||||
// protocol of the stream
|
||||
Protocol StreamProtocol
|
||||
|
||||
@@ -57,8 +103,8 @@ func parsePorts(val string) (*[2]int, error) {
|
||||
return &[2]int{int(port1), int(port2)}, nil
|
||||
}
|
||||
|
||||
// ReadHeaderTransport parses a Transport header.
|
||||
func ReadHeaderTransport(v base.HeaderValue) (*HeaderTransport, error) {
|
||||
// ReadTransport parses a Transport header.
|
||||
func ReadTransport(v base.HeaderValue) (*Transport, error) {
|
||||
if len(v) == 0 {
|
||||
return nil, fmt.Errorf("value not provided")
|
||||
}
|
||||
@@ -67,7 +113,7 @@ func ReadHeaderTransport(v base.HeaderValue) (*HeaderTransport, error) {
|
||||
return nil, fmt.Errorf("value provided multiple times (%v)", v)
|
||||
}
|
||||
|
||||
ht := &HeaderTransport{}
|
||||
ht := &Transport{}
|
||||
|
||||
parts := strings.Split(v[0], ";")
|
||||
if len(parts) == 0 {
|
||||
@@ -153,7 +199,7 @@ func ReadHeaderTransport(v base.HeaderValue) (*HeaderTransport, error) {
|
||||
}
|
||||
|
||||
// Write encodes a Transport header
|
||||
func (ht *HeaderTransport) Write() base.HeaderValue {
|
||||
func (ht *Transport) Write() base.HeaderValue {
|
||||
var vals []string
|
||||
|
||||
if ht.Protocol == StreamProtocolUDP {
|
@@ -1,4 +1,4 @@
|
||||
package gortsplib
|
||||
package headers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -8,17 +8,17 @@ import (
|
||||
"github.com/aler9/gortsplib/base"
|
||||
)
|
||||
|
||||
var casesHeaderTransport = []struct {
|
||||
var casesTransport = []struct {
|
||||
name string
|
||||
vin base.HeaderValue
|
||||
vout base.HeaderValue
|
||||
h *HeaderTransport
|
||||
h *Transport
|
||||
}{
|
||||
{
|
||||
"udp unicast play request",
|
||||
base.HeaderValue{`RTP/AVP;unicast;client_port=3456-3457;mode="PLAY"`},
|
||||
base.HeaderValue{`RTP/AVP;unicast;client_port=3456-3457;mode=play`},
|
||||
&HeaderTransport{
|
||||
&Transport{
|
||||
Protocol: StreamProtocolUDP,
|
||||
Cast: func() *StreamCast {
|
||||
v := StreamUnicast
|
||||
@@ -35,7 +35,7 @@ var casesHeaderTransport = []struct {
|
||||
"udp unicast play response",
|
||||
base.HeaderValue{`RTP/AVP/UDP;unicast;client_port=3056-3057;server_port=5000-5001`},
|
||||
base.HeaderValue{`RTP/AVP;unicast;client_port=3056-3057;server_port=5000-5001`},
|
||||
&HeaderTransport{
|
||||
&Transport{
|
||||
Protocol: StreamProtocolUDP,
|
||||
Cast: func() *StreamCast {
|
||||
v := StreamUnicast
|
||||
@@ -49,7 +49,7 @@ var casesHeaderTransport = []struct {
|
||||
"udp multicast play request / response",
|
||||
base.HeaderValue{`RTP/AVP;multicast;destination=225.219.201.15;port=7000-7001;ttl=127`},
|
||||
base.HeaderValue{`RTP/AVP;multicast`},
|
||||
&HeaderTransport{
|
||||
&Transport{
|
||||
Protocol: StreamProtocolUDP,
|
||||
Cast: func() *StreamCast {
|
||||
v := StreamMulticast
|
||||
@@ -70,25 +70,25 @@ var casesHeaderTransport = []struct {
|
||||
"tcp play request / response",
|
||||
base.HeaderValue{`RTP/AVP/TCP;interleaved=0-1`},
|
||||
base.HeaderValue{`RTP/AVP/TCP;interleaved=0-1`},
|
||||
&HeaderTransport{
|
||||
&Transport{
|
||||
Protocol: StreamProtocolTCP,
|
||||
InterleavedIds: &[2]int{0, 1},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestHeaderTransportRead(t *testing.T) {
|
||||
for _, c := range casesHeaderTransport {
|
||||
func TestTransportRead(t *testing.T) {
|
||||
for _, c := range casesTransport {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
req, err := ReadHeaderTransport(c.vin)
|
||||
req, err := ReadTransport(c.vin)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, c.h, req)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeaderTransportWrite(t *testing.T) {
|
||||
for _, c := range casesHeaderTransport {
|
||||
func TestTransportWrite(t *testing.T) {
|
||||
for _, c := range casesTransport {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
req := c.h.Write()
|
||||
require.Equal(t, c.vout, req)
|
37
utils.go
37
utils.go
@@ -2,54 +2,31 @@ package gortsplib
|
||||
|
||||
import (
|
||||
"github.com/aler9/gortsplib/base"
|
||||
"github.com/aler9/gortsplib/headers"
|
||||
)
|
||||
|
||||
// StreamProtocol is the protocol of a stream.
|
||||
type StreamProtocol int
|
||||
type StreamProtocol = headers.StreamProtocol
|
||||
|
||||
const (
|
||||
// StreamProtocolUDP means that the stream uses the UDP protocol
|
||||
StreamProtocolUDP StreamProtocol = iota
|
||||
StreamProtocolUDP = headers.StreamProtocolUDP
|
||||
|
||||
// StreamProtocolTCP means that the stream uses the TCP protocol
|
||||
StreamProtocolTCP
|
||||
StreamProtocolTCP = headers.StreamProtocolTCP
|
||||
)
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (sp StreamProtocol) String() string {
|
||||
switch sp {
|
||||
case StreamProtocolUDP:
|
||||
return "udp"
|
||||
|
||||
case StreamProtocolTCP:
|
||||
return "tcp"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// StreamCast is the cast method of a stream.
|
||||
type StreamCast int
|
||||
type StreamCast = headers.StreamCast
|
||||
|
||||
const (
|
||||
// StreamUnicast means that the stream is unicasted
|
||||
StreamUnicast StreamCast = iota
|
||||
StreamUnicast = headers.StreamUnicast
|
||||
|
||||
// StreamMulticast means that the stream is multicasted
|
||||
StreamMulticast
|
||||
StreamMulticast = headers.StreamMulticast
|
||||
)
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (sc StreamCast) String() string {
|
||||
switch sc {
|
||||
case StreamUnicast:
|
||||
return "unicast"
|
||||
|
||||
case StreamMulticast:
|
||||
return "multicast"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// StreamType is the stream type.
|
||||
type StreamType = base.StreamType
|
||||
|
||||
|
Reference in New Issue
Block a user