mirror of
				https://github.com/aler9/gortsplib
				synced 2025-10-31 10:36:26 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			222 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Package headers contains various RTSP headers.
 | |
| package headers
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/aler9/gortsplib/base"
 | |
| )
 | |
| 
 | |
| // 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
 | |
| 
 | |
| 	// (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
 | |
| }
 | |
| 
 | |
| 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++
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // 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")
 | |
| 	}
 | |
| 
 | |
| 	if len(v) > 1 {
 | |
| 		return nil, fmt.Errorf("value provided multiple times (%v)", v)
 | |
| 	}
 | |
| 
 | |
| 	ha := &Auth{}
 | |
| 
 | |
| 	v0 := v[0]
 | |
| 
 | |
| 	i := strings.IndexByte(v0, ' ')
 | |
| 	if i < 0 {
 | |
| 		return nil, fmt.Errorf("unable to find method (%s)", v0)
 | |
| 	}
 | |
| 
 | |
| 	switch v0[:i] {
 | |
| 	case "Basic":
 | |
| 		ha.Method = AuthBasic
 | |
| 
 | |
| 	case "Digest":
 | |
| 		ha.Method = AuthDigest
 | |
| 
 | |
| 	default:
 | |
| 		return nil, fmt.Errorf("invalid method (%s)", v0[:i])
 | |
| 	}
 | |
| 	v0 = v0[i+1:]
 | |
| 
 | |
| 	for len(v0) > 0 {
 | |
| 		i := strings.IndexByte(v0, '=')
 | |
| 		if i < 0 {
 | |
| 			return nil, fmt.Errorf("unable to find key (%s)", v0)
 | |
| 		}
 | |
| 		var key string
 | |
| 		key, v0 = v0[:i], v0[i+1:]
 | |
| 
 | |
| 		var val string
 | |
| 		var err error
 | |
| 		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
 | |
| }
 | |
| 
 | |
| // Write encodes an Authenticate or a WWW-Authenticate header.
 | |
| func (ha *Auth) Write() base.HeaderValue {
 | |
| 	ret := ""
 | |
| 
 | |
| 	switch ha.Method {
 | |
| 	case AuthBasic:
 | |
| 		ret += "Basic"
 | |
| 
 | |
| 	case AuthDigest:
 | |
| 		ret += "Digest"
 | |
| 	}
 | |
| 
 | |
| 	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 base.HeaderValue{ret}
 | |
| }
 | 
