mirror of
https://github.com/aler9/gortsplib
synced 2025-10-08 00:20:05 +08:00
HeaderAuth: use struct instead of map for storing
This commit is contained in:
73
auth.go
73
auth.go
@@ -64,19 +64,15 @@ func (as *AuthServer) GenerateHeader() HeaderValue {
|
|||||||
switch m {
|
switch m {
|
||||||
case Basic:
|
case Basic:
|
||||||
ret = append(ret, (&HeaderAuth{
|
ret = append(ret, (&HeaderAuth{
|
||||||
Prefix: "Basic",
|
Method: Basic,
|
||||||
Values: map[string]string{
|
Realm: &as.realm,
|
||||||
"realm": as.realm,
|
|
||||||
},
|
|
||||||
}).Write()...)
|
}).Write()...)
|
||||||
|
|
||||||
case Digest:
|
case Digest:
|
||||||
ret = append(ret, (&HeaderAuth{
|
ret = append(ret, (&HeaderAuth{
|
||||||
Prefix: "Digest",
|
Method: Digest,
|
||||||
Values: map[string]string{
|
Realm: &as.realm,
|
||||||
"realm": as.realm,
|
Nonce: &as.nonce,
|
||||||
"nonce": as.nonce,
|
|
||||||
},
|
|
||||||
}).Write()...)
|
}).Write()...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,46 +106,41 @@ func (as *AuthServer) ValidateHeader(v HeaderValue, method Method, ur *url.URL)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
inRealm, ok := auth.Values["realm"]
|
if auth.Realm == nil {
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("realm not provided")
|
return fmt.Errorf("realm not provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
inNonce, ok := auth.Values["nonce"]
|
if auth.Nonce == nil {
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("nonce not provided")
|
return fmt.Errorf("nonce not provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
inUsername, ok := auth.Values["username"]
|
if auth.Username == nil {
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("username not provided")
|
return fmt.Errorf("username not provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
inUri, ok := auth.Values["uri"]
|
if auth.URI == nil {
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("uri not provided")
|
return fmt.Errorf("uri not provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
inResponse, ok := auth.Values["response"]
|
if auth.Response == nil {
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("response not provided")
|
return fmt.Errorf("response not provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
if inNonce != as.nonce {
|
if *auth.Nonce != as.nonce {
|
||||||
return fmt.Errorf("wrong nonce")
|
return fmt.Errorf("wrong nonce")
|
||||||
}
|
}
|
||||||
|
|
||||||
if inRealm != as.realm {
|
if *auth.Realm != as.realm {
|
||||||
return fmt.Errorf("wrong realm")
|
return fmt.Errorf("wrong realm")
|
||||||
}
|
}
|
||||||
|
|
||||||
if inUsername != as.user {
|
if *auth.Username != as.user {
|
||||||
return fmt.Errorf("wrong username")
|
return fmt.Errorf("wrong username")
|
||||||
}
|
}
|
||||||
|
|
||||||
uri := ur.String()
|
uri := ur.String()
|
||||||
|
|
||||||
if inUri != uri {
|
if *auth.URI != uri {
|
||||||
// VLC strips the subpath
|
// VLC strips the subpath
|
||||||
newUrl := *ur
|
newUrl := *ur
|
||||||
newUrl.Path = func() string {
|
newUrl.Path = func() string {
|
||||||
@@ -163,7 +154,7 @@ func (as *AuthServer) ValidateHeader(v HeaderValue, method Method, ur *url.URL)
|
|||||||
}()
|
}()
|
||||||
uri = newUrl.String()
|
uri = newUrl.String()
|
||||||
|
|
||||||
if inUri != uri {
|
if *auth.URI != uri {
|
||||||
return fmt.Errorf("wrong url")
|
return fmt.Errorf("wrong url")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,7 +162,7 @@ func (as *AuthServer) ValidateHeader(v HeaderValue, method Method, ur *url.URL)
|
|||||||
response := md5Hex(md5Hex(as.user+":"+as.realm+":"+as.pass) +
|
response := md5Hex(md5Hex(as.user+":"+as.realm+":"+as.pass) +
|
||||||
":" + as.nonce + ":" + md5Hex(string(method)+":"+uri))
|
":" + as.nonce + ":" + md5Hex(string(method)+":"+uri))
|
||||||
|
|
||||||
if inResponse != response {
|
if *auth.Response != response {
|
||||||
return fmt.Errorf("wrong response")
|
return fmt.Errorf("wrong response")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,13 +200,11 @@ func newAuthClient(v HeaderValue, user string, pass string) (*authClient, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
realm, ok := auth.Values["realm"]
|
if auth.Realm == nil {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("realm not provided")
|
return nil, fmt.Errorf("realm not provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
nonce, ok := auth.Values["nonce"]
|
if auth.Nonce == nil {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("nonce not provided")
|
return nil, fmt.Errorf("nonce not provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,8 +212,8 @@ func newAuthClient(v HeaderValue, user string, pass string) (*authClient, error)
|
|||||||
user: user,
|
user: user,
|
||||||
pass: pass,
|
pass: pass,
|
||||||
method: Digest,
|
method: Digest,
|
||||||
realm: realm,
|
realm: *auth.Realm,
|
||||||
nonce: nonce,
|
nonce: *auth.Nonce,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,8 +230,7 @@ func newAuthClient(v HeaderValue, user string, pass string) (*authClient, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
realm, ok := auth.Values["realm"]
|
if auth.Realm == nil {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("realm not provided")
|
return nil, fmt.Errorf("realm not provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +238,7 @@ func newAuthClient(v HeaderValue, user string, pass string) (*authClient, error)
|
|||||||
user: user,
|
user: user,
|
||||||
pass: pass,
|
pass: pass,
|
||||||
method: Basic,
|
method: Basic,
|
||||||
realm: realm,
|
realm: *auth.Realm,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,14 +259,15 @@ func (ac *authClient) GenerateHeader(method Method, ur *url.URL) HeaderValue {
|
|||||||
ac.nonce + ":" + md5Hex(string(method)+":"+ur.String()))
|
ac.nonce + ":" + md5Hex(string(method)+":"+ur.String()))
|
||||||
|
|
||||||
return (&HeaderAuth{
|
return (&HeaderAuth{
|
||||||
Prefix: "Digest",
|
Method: Digest,
|
||||||
Values: map[string]string{
|
Username: &ac.user,
|
||||||
"username": ac.user,
|
Realm: &ac.realm,
|
||||||
"realm": ac.realm,
|
Nonce: &ac.nonce,
|
||||||
"nonce": ac.nonce,
|
URI: func() *string {
|
||||||
"uri": ur.String(),
|
v := ur.String()
|
||||||
"response": response,
|
return &v
|
||||||
},
|
}(),
|
||||||
|
Response: &response,
|
||||||
}).Write()
|
}).Write()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
220
header-auth.go
220
header-auth.go
@@ -2,18 +2,68 @@ package gortsplib
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HeaderAuth is an Authenticate or a WWWW-Authenticate header.
|
// HeaderAuth is an Authenticate or a WWWW-Authenticate header.
|
||||||
type HeaderAuth struct {
|
type HeaderAuth struct {
|
||||||
Prefix string
|
// authentication method
|
||||||
Values map[string]string
|
Method AuthMethod
|
||||||
|
|
||||||
|
// (optional) username
|
||||||
|
Username *string
|
||||||
|
|
||||||
|
// (optional) realm
|
||||||
|
Realm *string
|
||||||
|
|
||||||
|
// (optional) nonce
|
||||||
|
Nonce *string
|
||||||
|
|
||||||
|
// (optional) uri
|
||||||
|
URI *string
|
||||||
|
|
||||||
|
// (optional) response
|
||||||
|
Response *string
|
||||||
|
|
||||||
|
// (optional) opaque
|
||||||
|
Opaque *string
|
||||||
|
|
||||||
|
// (optional) stale
|
||||||
|
Stale *string
|
||||||
|
|
||||||
|
// (optional) algorithm
|
||||||
|
Algorithm *string
|
||||||
}
|
}
|
||||||
|
|
||||||
var regHeaderAuthKeyValue = regexp.MustCompile("^([a-z]+)=(\"(.*?)\"|([a-zA-Z0-9]+))(, *|$)")
|
func findValue(v0 string) (string, string, error) {
|
||||||
|
if v0 == "" {
|
||||||
|
return "", "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if v0[0] == '"' {
|
||||||
|
i := 1
|
||||||
|
for {
|
||||||
|
if i >= len(v0) {
|
||||||
|
return "", "", fmt.Errorf("apices not closed (%v)", v0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v0[i] == '"' {
|
||||||
|
return v0[1:i], v0[i+1:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
if i >= len(v0) || v0[i] == ',' {
|
||||||
|
return v0[:i], v0[i:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ReadHeaderAuth parses an Authenticate or a WWW-Authenticate header.
|
// ReadHeaderAuth parses an Authenticate or a WWW-Authenticate header.
|
||||||
func ReadHeaderAuth(v HeaderValue) (*HeaderAuth, error) {
|
func ReadHeaderAuth(v HeaderValue) (*HeaderAuth, error) {
|
||||||
@@ -25,28 +75,79 @@ func ReadHeaderAuth(v HeaderValue) (*HeaderAuth, error) {
|
|||||||
return nil, fmt.Errorf("value provided multiple times (%v)", v)
|
return nil, fmt.Errorf("value provided multiple times (%v)", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
ha := &HeaderAuth{
|
ha := &HeaderAuth{}
|
||||||
Values: make(map[string]string),
|
|
||||||
}
|
|
||||||
|
|
||||||
v0 := v[0]
|
v0 := v[0]
|
||||||
|
|
||||||
i := strings.IndexByte(v[0], ' ')
|
i := strings.IndexByte(v0, ' ')
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
return nil, fmt.Errorf("unable to find prefix (%s)", v0)
|
return nil, fmt.Errorf("unable to find method (%s)", v0)
|
||||||
}
|
}
|
||||||
ha.Prefix, v0 = v0[:i], v0[i+1:]
|
|
||||||
|
switch v0[:i] {
|
||||||
|
case "Basic":
|
||||||
|
ha.Method = Basic
|
||||||
|
|
||||||
|
case "Digest":
|
||||||
|
ha.Method = Digest
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid method (%s)", v0[:i])
|
||||||
|
}
|
||||||
|
v0 = v0[i+1:]
|
||||||
|
|
||||||
for len(v0) > 0 {
|
for len(v0) > 0 {
|
||||||
m := regHeaderAuthKeyValue.FindStringSubmatch(v0)
|
i := strings.IndexByte(v0, '=')
|
||||||
if m == nil {
|
if i < 0 {
|
||||||
return nil, fmt.Errorf("unable to parse key-value (%s)", v0)
|
return nil, fmt.Errorf("unable to find key (%s)", v0)
|
||||||
}
|
}
|
||||||
v0 = v0[len(m[0]):]
|
var key string
|
||||||
|
key, v0 = v0[:i], v0[i+1:]
|
||||||
|
|
||||||
m[2] = strings.TrimPrefix(m[2], "\"")
|
var val string
|
||||||
m[2] = strings.TrimSuffix(m[2], "\"")
|
var err error
|
||||||
ha.Values[m[1]] = m[2]
|
val, v0, err = findValue(v0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch key {
|
||||||
|
case "username":
|
||||||
|
ha.Username = &val
|
||||||
|
|
||||||
|
case "realm":
|
||||||
|
ha.Realm = &val
|
||||||
|
|
||||||
|
case "nonce":
|
||||||
|
ha.Nonce = &val
|
||||||
|
|
||||||
|
case "uri":
|
||||||
|
ha.URI = &val
|
||||||
|
|
||||||
|
case "response":
|
||||||
|
ha.Response = &val
|
||||||
|
|
||||||
|
case "opaque":
|
||||||
|
ha.Opaque = &val
|
||||||
|
|
||||||
|
case "stale":
|
||||||
|
ha.Stale = &val
|
||||||
|
|
||||||
|
case "algorithm":
|
||||||
|
ha.Algorithm = &val
|
||||||
|
|
||||||
|
// ignore non-standard keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip comma
|
||||||
|
if len(v0) > 0 && v0[0] == ',' {
|
||||||
|
v0 = v0[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip spaces
|
||||||
|
for len(v0) > 0 && v0[0] == ' ' {
|
||||||
|
v0 = v0[1:]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ha, nil
|
return ha, nil
|
||||||
@@ -54,48 +155,53 @@ func ReadHeaderAuth(v HeaderValue) (*HeaderAuth, error) {
|
|||||||
|
|
||||||
// Write encodes an Authenticate or a WWW-Authenticate header.
|
// Write encodes an Authenticate or a WWW-Authenticate header.
|
||||||
func (ha *HeaderAuth) Write() HeaderValue {
|
func (ha *HeaderAuth) Write() HeaderValue {
|
||||||
ret := ha.Prefix + " "
|
ret := ""
|
||||||
|
|
||||||
// follow a specific order, otherwise some clients/servers do not work correctly
|
switch ha.Method {
|
||||||
var sortedKeys []string
|
case Basic:
|
||||||
for key := range ha.Values {
|
ret += "Basic"
|
||||||
sortedKeys = append(sortedKeys, key)
|
|
||||||
}
|
|
||||||
score := func(v string) int {
|
|
||||||
switch v {
|
|
||||||
case "username":
|
|
||||||
return 0
|
|
||||||
case "realm":
|
|
||||||
return 1
|
|
||||||
case "nonce":
|
|
||||||
return 2
|
|
||||||
case "uri":
|
|
||||||
return 3
|
|
||||||
case "response":
|
|
||||||
return 4
|
|
||||||
case "opaque":
|
|
||||||
return 5
|
|
||||||
case "stale":
|
|
||||||
return 6
|
|
||||||
case "algorithm":
|
|
||||||
return 7
|
|
||||||
}
|
|
||||||
return 8
|
|
||||||
}
|
|
||||||
sort.Slice(sortedKeys, func(a, b int) bool {
|
|
||||||
sa := score(sortedKeys[a])
|
|
||||||
sb := score(sortedKeys[b])
|
|
||||||
if sa != sb {
|
|
||||||
return sa < sb
|
|
||||||
}
|
|
||||||
return a < b
|
|
||||||
})
|
|
||||||
|
|
||||||
var tmp []string
|
case Digest:
|
||||||
for _, key := range sortedKeys {
|
ret += "Digest"
|
||||||
tmp = append(tmp, key+"=\""+ha.Values[key]+"\"")
|
|
||||||
}
|
}
|
||||||
ret += strings.Join(tmp, ", ")
|
|
||||||
|
ret += " "
|
||||||
|
|
||||||
|
var vals []string
|
||||||
|
|
||||||
|
if ha.Username != nil {
|
||||||
|
vals = append(vals, "username=\""+*ha.Username+"\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ha.Realm != nil {
|
||||||
|
vals = append(vals, "realm=\""+*ha.Realm+"\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ha.Nonce != nil {
|
||||||
|
vals = append(vals, "nonce=\""+*ha.Nonce+"\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ha.URI != nil {
|
||||||
|
vals = append(vals, "uri=\""+*ha.URI+"\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ha.Response != nil {
|
||||||
|
vals = append(vals, "response=\""+*ha.Response+"\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ha.Opaque != nil {
|
||||||
|
vals = append(vals, "opaque=\""+*ha.Opaque+"\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ha.Stale != nil {
|
||||||
|
vals = append(vals, "stale=\""+*ha.Stale+"\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ha.Algorithm != nil {
|
||||||
|
vals = append(vals, "algorithm=\""+*ha.Algorithm+"\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += strings.Join(vals, ", ")
|
||||||
|
|
||||||
return HeaderValue{ret}
|
return HeaderValue{ret}
|
||||||
}
|
}
|
||||||
|
@@ -17,10 +17,11 @@ var casesHeaderAuth = []struct {
|
|||||||
HeaderValue{`Basic realm="4419b63f5e51"`},
|
HeaderValue{`Basic realm="4419b63f5e51"`},
|
||||||
HeaderValue{`Basic realm="4419b63f5e51"`},
|
HeaderValue{`Basic realm="4419b63f5e51"`},
|
||||||
&HeaderAuth{
|
&HeaderAuth{
|
||||||
Prefix: "Basic",
|
Method: Basic,
|
||||||
Values: map[string]string{
|
Realm: func() *string {
|
||||||
"realm": "4419b63f5e51",
|
v := "4419b63f5e51"
|
||||||
},
|
return &v
|
||||||
|
}(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -28,12 +29,19 @@ var casesHeaderAuth = []struct {
|
|||||||
HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale="FALSE"`},
|
HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale="FALSE"`},
|
||||||
HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale="FALSE"`},
|
HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale="FALSE"`},
|
||||||
&HeaderAuth{
|
&HeaderAuth{
|
||||||
Prefix: "Digest",
|
Method: Digest,
|
||||||
Values: map[string]string{
|
Realm: func() *string {
|
||||||
"realm": "4419b63f5e51",
|
v := "4419b63f5e51"
|
||||||
"nonce": "8b84a3b789283a8bea8da7fa7d41f08b",
|
return &v
|
||||||
"stale": "FALSE",
|
}(),
|
||||||
},
|
Nonce: func() *string {
|
||||||
|
v := "8b84a3b789283a8bea8da7fa7d41f08b"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
|
Stale: func() *string {
|
||||||
|
v := "FALSE"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -41,12 +49,19 @@ var casesHeaderAuth = []struct {
|
|||||||
HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale=FALSE`},
|
HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale=FALSE`},
|
||||||
HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale="FALSE"`},
|
HeaderValue{`Digest realm="4419b63f5e51", nonce="8b84a3b789283a8bea8da7fa7d41f08b", stale="FALSE"`},
|
||||||
&HeaderAuth{
|
&HeaderAuth{
|
||||||
Prefix: "Digest",
|
Method: Digest,
|
||||||
Values: map[string]string{
|
Realm: func() *string {
|
||||||
"realm": "4419b63f5e51",
|
v := "4419b63f5e51"
|
||||||
"nonce": "8b84a3b789283a8bea8da7fa7d41f08b",
|
return &v
|
||||||
"stale": "FALSE",
|
}(),
|
||||||
},
|
Nonce: func() *string {
|
||||||
|
v := "8b84a3b789283a8bea8da7fa7d41f08b"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
|
Stale: func() *string {
|
||||||
|
v := "FALSE"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -54,12 +69,19 @@ var casesHeaderAuth = []struct {
|
|||||||
HeaderValue{`Digest realm="4419b63f5e51",nonce="133767111917411116111311118211673010032", stale="FALSE"`},
|
HeaderValue{`Digest realm="4419b63f5e51",nonce="133767111917411116111311118211673010032", stale="FALSE"`},
|
||||||
HeaderValue{`Digest realm="4419b63f5e51", nonce="133767111917411116111311118211673010032", stale="FALSE"`},
|
HeaderValue{`Digest realm="4419b63f5e51", nonce="133767111917411116111311118211673010032", stale="FALSE"`},
|
||||||
&HeaderAuth{
|
&HeaderAuth{
|
||||||
Prefix: "Digest",
|
Method: Digest,
|
||||||
Values: map[string]string{
|
Realm: func() *string {
|
||||||
"realm": "4419b63f5e51",
|
v := "4419b63f5e51"
|
||||||
"nonce": "133767111917411116111311118211673010032",
|
return &v
|
||||||
"stale": "FALSE",
|
}(),
|
||||||
},
|
Nonce: func() *string {
|
||||||
|
v := "133767111917411116111311118211673010032"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
|
Stale: func() *string {
|
||||||
|
v := "FALSE"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -67,14 +89,27 @@ var casesHeaderAuth = []struct {
|
|||||||
HeaderValue{`Digest username="aa", realm="bb", nonce="cc", uri="dd", response="ee"`},
|
HeaderValue{`Digest username="aa", realm="bb", nonce="cc", uri="dd", response="ee"`},
|
||||||
HeaderValue{`Digest username="aa", realm="bb", nonce="cc", uri="dd", response="ee"`},
|
HeaderValue{`Digest username="aa", realm="bb", nonce="cc", uri="dd", response="ee"`},
|
||||||
&HeaderAuth{
|
&HeaderAuth{
|
||||||
Prefix: "Digest",
|
Method: Digest,
|
||||||
Values: map[string]string{
|
Username: func() *string {
|
||||||
"username": "aa",
|
v := "aa"
|
||||||
"realm": "bb",
|
return &v
|
||||||
"nonce": "cc",
|
}(),
|
||||||
"uri": "dd",
|
Realm: func() *string {
|
||||||
"response": "ee",
|
v := "bb"
|
||||||
},
|
return &v
|
||||||
|
}(),
|
||||||
|
Nonce: func() *string {
|
||||||
|
v := "cc"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
|
URI: func() *string {
|
||||||
|
v := "dd"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
|
Response: func() *string {
|
||||||
|
v := "ee"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -82,14 +117,27 @@ var casesHeaderAuth = []struct {
|
|||||||
HeaderValue{`Digest username="", realm="IPCAM", nonce="5d17cd12b9fa8a85ac5ceef0926ea5a6", uri="rtsp://localhost:8554/mystream", response="c072ae90eb4a27f4cdcb90d62266b2a1"`},
|
HeaderValue{`Digest username="", realm="IPCAM", nonce="5d17cd12b9fa8a85ac5ceef0926ea5a6", uri="rtsp://localhost:8554/mystream", response="c072ae90eb4a27f4cdcb90d62266b2a1"`},
|
||||||
HeaderValue{`Digest username="", realm="IPCAM", nonce="5d17cd12b9fa8a85ac5ceef0926ea5a6", uri="rtsp://localhost:8554/mystream", response="c072ae90eb4a27f4cdcb90d62266b2a1"`},
|
HeaderValue{`Digest username="", realm="IPCAM", nonce="5d17cd12b9fa8a85ac5ceef0926ea5a6", uri="rtsp://localhost:8554/mystream", response="c072ae90eb4a27f4cdcb90d62266b2a1"`},
|
||||||
&HeaderAuth{
|
&HeaderAuth{
|
||||||
Prefix: "Digest",
|
Method: Digest,
|
||||||
Values: map[string]string{
|
Username: func() *string {
|
||||||
"username": "",
|
v := ""
|
||||||
"realm": "IPCAM",
|
return &v
|
||||||
"nonce": "5d17cd12b9fa8a85ac5ceef0926ea5a6",
|
}(),
|
||||||
"uri": "rtsp://localhost:8554/mystream",
|
Realm: func() *string {
|
||||||
"response": "c072ae90eb4a27f4cdcb90d62266b2a1",
|
v := "IPCAM"
|
||||||
},
|
return &v
|
||||||
|
}(),
|
||||||
|
Nonce: func() *string {
|
||||||
|
v := "5d17cd12b9fa8a85ac5ceef0926ea5a6"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
|
URI: func() *string {
|
||||||
|
v := "rtsp://localhost:8554/mystream"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
|
Response: func() *string {
|
||||||
|
v := "c072ae90eb4a27f4cdcb90d62266b2a1"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -97,14 +145,27 @@ var casesHeaderAuth = []struct {
|
|||||||
HeaderValue{`Digest realm="Please log in with a valid username",nonce="752a62306daf32b401a41004555c7663",opaque="",stale=FALSE,algorithm=MD5`},
|
HeaderValue{`Digest realm="Please log in with a valid username",nonce="752a62306daf32b401a41004555c7663",opaque="",stale=FALSE,algorithm=MD5`},
|
||||||
HeaderValue{`Digest realm="Please log in with a valid username", nonce="752a62306daf32b401a41004555c7663", opaque="", stale="FALSE", algorithm="MD5"`},
|
HeaderValue{`Digest realm="Please log in with a valid username", nonce="752a62306daf32b401a41004555c7663", opaque="", stale="FALSE", algorithm="MD5"`},
|
||||||
&HeaderAuth{
|
&HeaderAuth{
|
||||||
Prefix: "Digest",
|
Method: Digest,
|
||||||
Values: map[string]string{
|
Realm: func() *string {
|
||||||
"realm": "Please log in with a valid username",
|
v := "Please log in with a valid username"
|
||||||
"nonce": "752a62306daf32b401a41004555c7663",
|
return &v
|
||||||
"opaque": "",
|
}(),
|
||||||
"stale": "FALSE",
|
Nonce: func() *string {
|
||||||
"algorithm": "MD5",
|
v := "752a62306daf32b401a41004555c7663"
|
||||||
},
|
return &v
|
||||||
|
}(),
|
||||||
|
Opaque: func() *string {
|
||||||
|
v := ""
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
|
Stale: func() *string {
|
||||||
|
v := "FALSE"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
|
Algorithm: func() *string {
|
||||||
|
v := "MD5"
|
||||||
|
return &v
|
||||||
|
}(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@@ -75,15 +75,14 @@ func ReadHeaderTransport(v HeaderValue) (*HeaderTransport, error) {
|
|||||||
switch parts[0] {
|
switch parts[0] {
|
||||||
case "RTP/AVP", "RTP/AVP/UDP":
|
case "RTP/AVP", "RTP/AVP/UDP":
|
||||||
ht.Protocol = StreamProtocolUDP
|
ht.Protocol = StreamProtocolUDP
|
||||||
parts = parts[1:]
|
|
||||||
|
|
||||||
case "RTP/AVP/TCP":
|
case "RTP/AVP/TCP":
|
||||||
ht.Protocol = StreamProtocolTCP
|
ht.Protocol = StreamProtocolTCP
|
||||||
parts = parts[1:]
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid protocol (%v)", v)
|
return nil, fmt.Errorf("invalid protocol (%v)", v)
|
||||||
}
|
}
|
||||||
|
parts = parts[1:]
|
||||||
|
|
||||||
switch parts[0] {
|
switch parts[0] {
|
||||||
case "unicast":
|
case "unicast":
|
||||||
@@ -144,6 +143,8 @@ func ReadHeaderTransport(v HeaderValue) (*HeaderTransport, error) {
|
|||||||
v = strings.TrimSuffix(v, "\"")
|
v = strings.TrimSuffix(v, "\"")
|
||||||
ht.Mode = &v
|
ht.Mode = &v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore non-standard keys
|
||||||
}
|
}
|
||||||
|
|
||||||
return ht, nil
|
return ht, nil
|
||||||
|
Reference in New Issue
Block a user