mirror of
https://github.com/bluenviron/mediamtx.git
synced 2026-01-26 21:39:16 -08:00
simplify configuration definitions
This commit is contained in:
parent
a4561a8339
commit
3966ea0664
18 changed files with 232 additions and 251 deletions
|
|
@ -16,15 +16,15 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func mustParseCIDR(v string) net.IPNet {
|
||||
func mustParseCIDR(v string) conf.IPNetwork {
|
||||
_, ne, err := net.ParseCIDR(v)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if ipv4 := ne.IP.To4(); ipv4 != nil {
|
||||
return net.IPNet{IP: ipv4, Mask: ne.Mask[len(ne.Mask)-4 : len(ne.Mask)]}
|
||||
return conf.IPNetwork{IP: ipv4, Mask: ne.Mask[len(ne.Mask)-4 : len(ne.Mask)]}
|
||||
}
|
||||
return *ne
|
||||
return conf.IPNetwork(*ne)
|
||||
}
|
||||
|
||||
func TestAuthInternal(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package conf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/conf/jsonwrapper"
|
||||
|
|
@ -20,11 +19,6 @@ const (
|
|||
AuthActionPprof AuthAction = "pprof"
|
||||
)
|
||||
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (d AuthAction) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(string(d))
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (d *AuthAction) UnmarshalJSON(b []byte) error {
|
||||
var in string
|
||||
|
|
|
|||
9
internal/conf/auth_internal_user.go
Normal file
9
internal/conf/auth_internal_user.go
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package conf
|
||||
|
||||
// AuthInternalUser is an user.
|
||||
type AuthInternalUser struct {
|
||||
User Credential `json:"user"`
|
||||
Pass Credential `json:"pass"`
|
||||
IPs IPNetworks `json:"ips"`
|
||||
Permissions []AuthInternalUserPermission `json:"permissions"`
|
||||
}
|
||||
7
internal/conf/auth_internal_user_permission.go
Normal file
7
internal/conf/auth_internal_user_permission.go
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
package conf
|
||||
|
||||
// AuthInternalUserPermission is a permission of a user.
|
||||
type AuthInternalUserPermission struct {
|
||||
Action AuthAction `json:"action"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
package conf
|
||||
|
||||
// AuthInternalUserPermission is a permission of a user.
|
||||
type AuthInternalUserPermission struct {
|
||||
Action AuthAction `json:"action"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
// AuthInternalUser is an user.
|
||||
type AuthInternalUser struct {
|
||||
User Credential `json:"user"`
|
||||
Pass Credential `json:"pass"`
|
||||
IPs IPNetworks `json:"ips"`
|
||||
Permissions []AuthInternalUserPermission `json:"permissions"`
|
||||
}
|
||||
|
||||
// AuthInternalUsers is a list of AuthInternalUser.
|
||||
type AuthInternalUsers []AuthInternalUser
|
||||
|
||||
// AuthInternalUserPermissions is a list of AuthInternalUserPermission.
|
||||
type AuthInternalUserPermissions []AuthInternalUserPermission
|
||||
|
|
@ -59,6 +59,13 @@ func setAllNilSlicesToEmptyRecursive(rv reflect.Value) {
|
|||
case reflect.Slice:
|
||||
if field.IsNil() {
|
||||
field.Set(reflect.MakeSlice(field.Type(), 0, 0))
|
||||
} else {
|
||||
for j := range field.Len() {
|
||||
elem := field.Index(j)
|
||||
if elem.Kind() == reflect.Pointer || elem.Kind() == reflect.Struct {
|
||||
setAllNilSlicesToEmptyRecursive(elem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Pointer:
|
||||
|
|
@ -110,15 +117,15 @@ func copyStructFields(dest any, source any) {
|
|||
}
|
||||
}
|
||||
|
||||
func mustParseCIDR(v string) net.IPNet {
|
||||
func mustParseCIDR(v string) IPNetwork {
|
||||
_, ne, err := net.ParseCIDR(v)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if ipv4 := ne.IP.To4(); ipv4 != nil {
|
||||
return net.IPNet{IP: ipv4, Mask: ne.Mask[len(ne.Mask)-4 : len(ne.Mask)]}
|
||||
return IPNetwork{IP: ipv4, Mask: ne.Mask[len(ne.Mask)-4 : len(ne.Mask)]}
|
||||
}
|
||||
return *ne
|
||||
return IPNetwork(*ne)
|
||||
}
|
||||
|
||||
func anyPathHasDeprecatedCredentials(pathDefaults Path, paths map[string]*OptionalPath) bool {
|
||||
|
|
@ -198,7 +205,7 @@ type nilLogger struct{}
|
|||
func (nilLogger) Log(_ logger.Level, _ string, _ ...any) {
|
||||
}
|
||||
|
||||
var defaultAuthInternalUsers = AuthInternalUsers{
|
||||
var defaultAuthInternalUsers = []AuthInternalUser{
|
||||
{
|
||||
User: "any",
|
||||
Pass: "",
|
||||
|
|
@ -251,16 +258,16 @@ type Conf struct {
|
|||
RunOnDisconnect string `json:"runOnDisconnect"`
|
||||
|
||||
// Authentication
|
||||
AuthMethod AuthMethod `json:"authMethod"`
|
||||
AuthInternalUsers AuthInternalUsers `json:"authInternalUsers"`
|
||||
AuthHTTPAddress string `json:"authHTTPAddress"`
|
||||
ExternalAuthenticationURL *string `json:"externalAuthenticationURL,omitempty"` // deprecated
|
||||
AuthHTTPExclude AuthInternalUserPermissions `json:"authHTTPExclude"`
|
||||
AuthJWTJWKS string `json:"authJWTJWKS"`
|
||||
AuthJWTJWKSFingerprint string `json:"authJWTJWKSFingerprint"`
|
||||
AuthJWTClaimKey string `json:"authJWTClaimKey"`
|
||||
AuthJWTExclude AuthInternalUserPermissions `json:"authJWTExclude"`
|
||||
AuthJWTInHTTPQuery bool `json:"authJWTInHTTPQuery"`
|
||||
AuthMethod AuthMethod `json:"authMethod"`
|
||||
AuthInternalUsers []AuthInternalUser `json:"authInternalUsers"`
|
||||
AuthHTTPAddress string `json:"authHTTPAddress"`
|
||||
ExternalAuthenticationURL *string `json:"externalAuthenticationURL,omitempty"` // deprecated
|
||||
AuthHTTPExclude []AuthInternalUserPermission `json:"authHTTPExclude"`
|
||||
AuthJWTJWKS string `json:"authJWTJWKS"`
|
||||
AuthJWTJWKSFingerprint string `json:"authJWTJWKSFingerprint"`
|
||||
AuthJWTClaimKey string `json:"authJWTClaimKey"`
|
||||
AuthJWTExclude []AuthInternalUserPermission `json:"authJWTExclude"`
|
||||
AuthJWTInHTTPQuery bool `json:"authJWTInHTTPQuery"`
|
||||
|
||||
// Control API
|
||||
API bool `json:"api"`
|
||||
|
|
@ -357,28 +364,28 @@ type Conf struct {
|
|||
HLSMuxerCloseAfter Duration `json:"hlsMuxerCloseAfter"`
|
||||
|
||||
// WebRTC server
|
||||
WebRTC bool `json:"webrtc"`
|
||||
WebRTCDisable *bool `json:"webrtcDisable,omitempty"` // deprecated
|
||||
WebRTCAddress string `json:"webrtcAddress"`
|
||||
WebRTCEncryption bool `json:"webrtcEncryption"`
|
||||
WebRTCServerKey string `json:"webrtcServerKey"`
|
||||
WebRTCServerCert string `json:"webrtcServerCert"`
|
||||
WebRTCAllowOrigin *string `json:"webrtcAllowOrigin,omitempty"` // deprecated
|
||||
WebRTCAllowOrigins []string `json:"webrtcAllowOrigins"`
|
||||
WebRTCTrustedProxies IPNetworks `json:"webrtcTrustedProxies"`
|
||||
WebRTCLocalUDPAddress string `json:"webrtcLocalUDPAddress"`
|
||||
WebRTCLocalTCPAddress string `json:"webrtcLocalTCPAddress"`
|
||||
WebRTCIPsFromInterfaces bool `json:"webrtcIPsFromInterfaces"`
|
||||
WebRTCIPsFromInterfacesList []string `json:"webrtcIPsFromInterfacesList"`
|
||||
WebRTCAdditionalHosts []string `json:"webrtcAdditionalHosts"`
|
||||
WebRTCICEServers2 WebRTCICEServers `json:"webrtcICEServers2"`
|
||||
WebRTCHandshakeTimeout Duration `json:"webrtcHandshakeTimeout"`
|
||||
WebRTCTrackGatherTimeout Duration `json:"webrtcTrackGatherTimeout"`
|
||||
WebRTCSTUNGatherTimeout Duration `json:"webrtcSTUNGatherTimeout"`
|
||||
WebRTCICEUDPMuxAddress *string `json:"webrtcICEUDPMuxAddress,omitempty"` // deprecated
|
||||
WebRTCICETCPMuxAddress *string `json:"webrtcICETCPMuxAddress,omitempty"` // deprecated
|
||||
WebRTCICEHostNAT1To1IPs *[]string `json:"webrtcICEHostNAT1To1IPs,omitempty"` // deprecated
|
||||
WebRTCICEServers *[]string `json:"webrtcICEServers,omitempty"` // deprecated
|
||||
WebRTC bool `json:"webrtc"`
|
||||
WebRTCDisable *bool `json:"webrtcDisable,omitempty"` // deprecated
|
||||
WebRTCAddress string `json:"webrtcAddress"`
|
||||
WebRTCEncryption bool `json:"webrtcEncryption"`
|
||||
WebRTCServerKey string `json:"webrtcServerKey"`
|
||||
WebRTCServerCert string `json:"webrtcServerCert"`
|
||||
WebRTCAllowOrigin *string `json:"webrtcAllowOrigin,omitempty"` // deprecated
|
||||
WebRTCAllowOrigins []string `json:"webrtcAllowOrigins"`
|
||||
WebRTCTrustedProxies IPNetworks `json:"webrtcTrustedProxies"`
|
||||
WebRTCLocalUDPAddress string `json:"webrtcLocalUDPAddress"`
|
||||
WebRTCLocalTCPAddress string `json:"webrtcLocalTCPAddress"`
|
||||
WebRTCIPsFromInterfaces bool `json:"webrtcIPsFromInterfaces"`
|
||||
WebRTCIPsFromInterfacesList []string `json:"webrtcIPsFromInterfacesList"`
|
||||
WebRTCAdditionalHosts []string `json:"webrtcAdditionalHosts"`
|
||||
WebRTCICEServers2 []WebRTCICEServer `json:"webrtcICEServers2"`
|
||||
WebRTCHandshakeTimeout Duration `json:"webrtcHandshakeTimeout"`
|
||||
WebRTCTrackGatherTimeout Duration `json:"webrtcTrackGatherTimeout"`
|
||||
WebRTCSTUNGatherTimeout Duration `json:"webrtcSTUNGatherTimeout"`
|
||||
WebRTCICEUDPMuxAddress *string `json:"webrtcICEUDPMuxAddress,omitempty"` // deprecated
|
||||
WebRTCICETCPMuxAddress *string `json:"webrtcICETCPMuxAddress,omitempty"` // deprecated
|
||||
WebRTCICEHostNAT1To1IPs *[]string `json:"webrtcICEHostNAT1To1IPs,omitempty"` // deprecated
|
||||
WebRTCICEServers *[]string `json:"webrtcICEServers,omitempty"` // deprecated
|
||||
|
||||
// SRT server
|
||||
SRT bool `json:"srt"`
|
||||
|
|
@ -403,7 +410,7 @@ type Conf struct {
|
|||
func (conf *Conf) setDefaults() {
|
||||
// General
|
||||
conf.LogLevel = LogLevel(logger.Info)
|
||||
conf.LogDestinations = LogDestinations{logger.DestinationStdout}
|
||||
conf.LogDestinations = LogDestinations{LogDestination(logger.DestinationStdout)}
|
||||
conf.LogStructured = false
|
||||
conf.LogFile = "mediamtx.log"
|
||||
conf.SysLogPrefix = "mediamtx"
|
||||
|
|
@ -472,7 +479,7 @@ func (conf *Conf) setDefaults() {
|
|||
conf.MulticastSRTCPPort = 8007
|
||||
conf.RTSPServerKey = "server.key"
|
||||
conf.RTSPServerCert = "server.crt"
|
||||
conf.RTSPAuthMethods = RTSPAuthMethods{auth.VerifyMethodBasic}
|
||||
conf.RTSPAuthMethods = RTSPAuthMethods{RTSPAuthMethod(auth.VerifyMethodBasic)}
|
||||
|
||||
// RTMP server
|
||||
conf.RTMP = true
|
||||
|
|
@ -871,7 +878,7 @@ func (conf *Conf) Validate(l logger.Writer) error {
|
|||
return fmt.Errorf("at least one 'rtspAuthMethods' must be provided")
|
||||
}
|
||||
|
||||
if slices.Contains(conf.RTSPAuthMethods, auth.VerifyMethodDigestMD5) {
|
||||
if slices.Contains(conf.RTSPAuthMethods, RTSPAuthMethod(auth.VerifyMethodDigestMD5)) {
|
||||
if conf.AuthMethod != AuthMethodInternal {
|
||||
return fmt.Errorf("when RTSP digest is enabled, the only supported auth method is 'internal'")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ func TestConfDeprecatedAuth(t *testing.T) {
|
|||
conf, _, err := Load(tmpf, nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, AuthInternalUsers{
|
||||
require.Equal(t, []AuthInternalUser{
|
||||
{
|
||||
User: "any",
|
||||
Permissions: []AuthInternalUserPermission{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package conf
|
|||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
|
@ -28,11 +27,6 @@ func sha256Base64(in string) string {
|
|||
// Credential is a parameter that is used as username or password.
|
||||
type Credential string
|
||||
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (d Credential) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(string(d))
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (d *Credential) UnmarshalJSON(b []byte) error {
|
||||
var in string
|
||||
|
|
|
|||
|
|
@ -7,14 +7,6 @@ import (
|
|||
)
|
||||
|
||||
func TestCredential(t *testing.T) {
|
||||
t.Run("MarshalJSON", func(t *testing.T) {
|
||||
cred := Credential("password")
|
||||
expectedJSON := []byte(`"password"`)
|
||||
actualJSON, err := cred.MarshalJSON()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expectedJSON, actualJSON)
|
||||
})
|
||||
|
||||
t.Run("UnmarshalJSON", func(t *testing.T) {
|
||||
expectedCred := Credential("password")
|
||||
jsonData := []byte(`"password"`)
|
||||
|
|
|
|||
55
internal/conf/ip_network.go
Normal file
55
internal/conf/ip_network.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package conf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/conf/jsonwrapper"
|
||||
)
|
||||
|
||||
// IPNetwork represents an IP network.
|
||||
type IPNetwork net.IPNet
|
||||
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (n IPNetwork) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(n.String())
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (n *IPNetwork) UnmarshalJSON(b []byte) error {
|
||||
var t string
|
||||
if err := jsonwrapper.Unmarshal(b, &t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, ipnet, err := net.ParseCIDR(t); err == nil {
|
||||
if ipv4 := ipnet.IP.To4(); ipv4 != nil {
|
||||
*n = IPNetwork{IP: ipv4, Mask: ipnet.Mask[len(ipnet.Mask)-4 : len(ipnet.Mask)]}
|
||||
} else {
|
||||
*n = IPNetwork(*ipnet)
|
||||
}
|
||||
} else if ip := net.ParseIP(t); ip != nil {
|
||||
if ipv4 := ip.To4(); ipv4 != nil {
|
||||
*n = IPNetwork{IP: ipv4, Mask: net.CIDRMask(32, 32)}
|
||||
} else {
|
||||
*n = IPNetwork{IP: ip, Mask: net.CIDRMask(128, 128)}
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("unable to parse IP/CIDR '%s'", t)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (n IPNetwork) String() string {
|
||||
ipnet := net.IPNet(n)
|
||||
return ipnet.String()
|
||||
}
|
||||
|
||||
// Contains checks whether the IP is part of the network.
|
||||
func (n IPNetwork) Contains(ip net.IP) bool {
|
||||
ipnet := net.IPNet(n)
|
||||
return ipnet.Contains(ip)
|
||||
}
|
||||
|
|
@ -2,68 +2,19 @@ package conf
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/conf/jsonwrapper"
|
||||
)
|
||||
|
||||
// IPNetworks is a parameter that contains a list of IP networks.
|
||||
type IPNetworks []net.IPNet
|
||||
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (d IPNetworks) MarshalJSON() ([]byte, error) {
|
||||
out := make([]string, len(d))
|
||||
|
||||
for i, v := range d {
|
||||
out[i] = v.String()
|
||||
}
|
||||
|
||||
sort.Strings(out)
|
||||
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (d *IPNetworks) UnmarshalJSON(b []byte) error {
|
||||
var in []string
|
||||
if err := jsonwrapper.Unmarshal(b, &in); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*d = nil
|
||||
|
||||
if len(in) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, t := range in {
|
||||
if _, ipnet, err := net.ParseCIDR(t); err == nil {
|
||||
if ipv4 := ipnet.IP.To4(); ipv4 != nil {
|
||||
*d = append(*d, net.IPNet{IP: ipv4, Mask: ipnet.Mask[len(ipnet.Mask)-4 : len(ipnet.Mask)]})
|
||||
} else {
|
||||
*d = append(*d, *ipnet)
|
||||
}
|
||||
} else if ip := net.ParseIP(t); ip != nil {
|
||||
if ipv4 := ip.To4(); ipv4 != nil {
|
||||
*d = append(*d, net.IPNet{IP: ipv4, Mask: net.CIDRMask(32, 32)})
|
||||
} else {
|
||||
*d = append(*d, net.IPNet{IP: ip, Mask: net.CIDRMask(128, 128)})
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("unable to parse IP/CIDR '%s'", t)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
type IPNetworks []IPNetwork
|
||||
|
||||
// UnmarshalEnv implements env.Unmarshaler.
|
||||
func (d *IPNetworks) UnmarshalEnv(_ string, v string) error {
|
||||
byts, _ := json.Marshal(strings.Split(v, ","))
|
||||
return d.UnmarshalJSON(byts)
|
||||
return jsonwrapper.Unmarshal(byts, d)
|
||||
}
|
||||
|
||||
// ToTrustedProxies converts IPNetworks into a string slice for SetTrustedProxies.
|
||||
|
|
|
|||
|
|
@ -3,83 +3,48 @@ package conf
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/conf/jsonwrapper"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
)
|
||||
|
||||
// LogDestinations is the logDestionations parameter.
|
||||
type LogDestinations []logger.Destination
|
||||
// LogDestination represents a log destination.
|
||||
type LogDestination logger.Destination
|
||||
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (d LogDestinations) MarshalJSON() ([]byte, error) {
|
||||
out := make([]string, len(d))
|
||||
i := 0
|
||||
func (d LogDestination) MarshalJSON() ([]byte, error) {
|
||||
switch d {
|
||||
case LogDestination(logger.DestinationStdout):
|
||||
return json.Marshal("stdout")
|
||||
|
||||
for _, p := range d {
|
||||
var v string
|
||||
case LogDestination(logger.DestinationFile):
|
||||
return json.Marshal("file")
|
||||
|
||||
switch p {
|
||||
case logger.DestinationStdout:
|
||||
v = "stdout"
|
||||
|
||||
case logger.DestinationFile:
|
||||
v = "file"
|
||||
|
||||
default:
|
||||
v = "syslog"
|
||||
}
|
||||
|
||||
out[i] = v
|
||||
i++
|
||||
default:
|
||||
return json.Marshal("syslog")
|
||||
}
|
||||
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
func (d *LogDestinations) contains(v logger.Destination) bool {
|
||||
return slices.Contains(*d, v)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (d *LogDestinations) UnmarshalJSON(b []byte) error {
|
||||
var in []string
|
||||
func (d *LogDestination) UnmarshalJSON(b []byte) error {
|
||||
var in string
|
||||
if err := jsonwrapper.Unmarshal(b, &in); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*d = nil
|
||||
switch in {
|
||||
case "stdout":
|
||||
*d = LogDestination(logger.DestinationStdout)
|
||||
|
||||
for _, dest := range in {
|
||||
var v logger.Destination
|
||||
switch dest {
|
||||
case "stdout":
|
||||
v = logger.DestinationStdout
|
||||
case "file":
|
||||
*d = LogDestination(logger.DestinationFile)
|
||||
|
||||
case "file":
|
||||
v = logger.DestinationFile
|
||||
case "syslog":
|
||||
*d = LogDestination(logger.DestinationSyslog)
|
||||
|
||||
case "syslog":
|
||||
v = logger.DestinationSyslog
|
||||
|
||||
default:
|
||||
return fmt.Errorf("invalid log destination: %s", dest)
|
||||
}
|
||||
|
||||
if d.contains(v) {
|
||||
return fmt.Errorf("log destination set twice")
|
||||
}
|
||||
|
||||
*d = append(*d, v)
|
||||
default:
|
||||
return fmt.Errorf("invalid log destination: %s", in)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalEnv implements env.Unmarshaler.
|
||||
func (d *LogDestinations) UnmarshalEnv(_ string, v string) error {
|
||||
byts, _ := json.Marshal(strings.Split(v, ","))
|
||||
return d.UnmarshalJSON(byts)
|
||||
}
|
||||
|
|
|
|||
27
internal/conf/log_destinations.go
Normal file
27
internal/conf/log_destinations.go
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package conf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/conf/jsonwrapper"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
)
|
||||
|
||||
// LogDestinations is the logDestionations parameter.
|
||||
type LogDestinations []LogDestination
|
||||
|
||||
// UnmarshalEnv implements env.Unmarshaler.
|
||||
func (d *LogDestinations) UnmarshalEnv(_ string, v string) error {
|
||||
byts, _ := json.Marshal(strings.Split(v, ","))
|
||||
return jsonwrapper.Unmarshal(byts, d)
|
||||
}
|
||||
|
||||
// ToDestinations converts to logger.Destination slice.
|
||||
func (d LogDestinations) ToDestinations() []logger.Destination {
|
||||
out := make([]logger.Destination, len(d))
|
||||
for i, v := range d {
|
||||
out[i] = logger.Destination(v)
|
||||
}
|
||||
return out
|
||||
}
|
||||
44
internal/conf/rtsp_auth_method.go
Normal file
44
internal/conf/rtsp_auth_method.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package conf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/auth"
|
||||
"github.com/bluenviron/mediamtx/internal/conf/jsonwrapper"
|
||||
)
|
||||
|
||||
// RTSPAuthMethod represents an RTSP authentication method.
|
||||
type RTSPAuthMethod auth.VerifyMethod
|
||||
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (d RTSPAuthMethod) MarshalJSON() ([]byte, error) {
|
||||
switch d {
|
||||
case RTSPAuthMethod(auth.VerifyMethodBasic):
|
||||
return json.Marshal("basic")
|
||||
|
||||
default:
|
||||
return json.Marshal("digest")
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (d *RTSPAuthMethod) UnmarshalJSON(b []byte) error {
|
||||
var in string
|
||||
if err := jsonwrapper.Unmarshal(b, &in); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch in {
|
||||
case "basic":
|
||||
*d = RTSPAuthMethod(auth.VerifyMethodBasic)
|
||||
|
||||
case "digest":
|
||||
*d = RTSPAuthMethod(auth.VerifyMethodDigestMD5)
|
||||
|
||||
default:
|
||||
return fmt.Errorf("invalid authentication method: '%s'", in)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -2,8 +2,6 @@ package conf
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/auth"
|
||||
|
|
@ -11,54 +9,19 @@ import (
|
|||
)
|
||||
|
||||
// RTSPAuthMethods is the rtspAuthMethods parameter.
|
||||
type RTSPAuthMethods []auth.VerifyMethod
|
||||
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (d RTSPAuthMethods) MarshalJSON() ([]byte, error) {
|
||||
out := make([]string, len(d))
|
||||
|
||||
for i, v := range d {
|
||||
switch v {
|
||||
case auth.VerifyMethodBasic:
|
||||
out[i] = "basic"
|
||||
|
||||
default:
|
||||
out[i] = "digest"
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(out)
|
||||
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (d *RTSPAuthMethods) UnmarshalJSON(b []byte) error {
|
||||
var in []string
|
||||
if err := jsonwrapper.Unmarshal(b, &in); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*d = nil
|
||||
|
||||
for _, v := range in {
|
||||
switch v {
|
||||
case "basic":
|
||||
*d = append(*d, auth.VerifyMethodBasic)
|
||||
|
||||
case "digest":
|
||||
*d = append(*d, auth.VerifyMethodDigestMD5)
|
||||
|
||||
default:
|
||||
return fmt.Errorf("invalid authentication method: '%s'", v)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
type RTSPAuthMethods []RTSPAuthMethod
|
||||
|
||||
// UnmarshalEnv implements env.Unmarshaler.
|
||||
func (d *RTSPAuthMethods) UnmarshalEnv(_ string, v string) error {
|
||||
byts, _ := json.Marshal(strings.Split(v, ","))
|
||||
return d.UnmarshalJSON(byts)
|
||||
return jsonwrapper.Unmarshal(byts, d)
|
||||
}
|
||||
|
||||
// ToAuthMethods converts to auth.VerifyMethod slice.
|
||||
func (d RTSPAuthMethods) ToAuthMethods() []auth.VerifyMethod {
|
||||
out := make([]auth.VerifyMethod, len(d))
|
||||
for i, v := range d {
|
||||
out[i] = auth.VerifyMethod(v)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,3 @@ type WebRTCICEServer struct {
|
|||
Password string `json:"password"`
|
||||
ClientOnly bool `json:"clientOnly"`
|
||||
}
|
||||
|
||||
// WebRTCICEServers is a list of WebRTCICEServer.
|
||||
type WebRTCICEServers []WebRTCICEServer
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ func (p *Core) createResources(initial bool) error {
|
|||
if p.logger == nil {
|
||||
i := &logger.Logger{
|
||||
Level: logger.Level(p.conf.LogLevel),
|
||||
Destinations: p.conf.LogDestinations,
|
||||
Destinations: p.conf.LogDestinations.ToDestinations(),
|
||||
Structured: p.conf.LogStructured,
|
||||
File: p.conf.LogFile,
|
||||
SysLogPrefix: p.conf.SysLogPrefix,
|
||||
|
|
@ -451,7 +451,7 @@ func (p *Core) createResources(initial bool) error {
|
|||
|
||||
i := &rtsp.Server{
|
||||
Address: p.conf.RTSPAddress,
|
||||
AuthMethods: p.conf.RTSPAuthMethods,
|
||||
AuthMethods: p.conf.RTSPAuthMethods.ToAuthMethods(),
|
||||
UDPReadBufferSize: udpReadBufferSize,
|
||||
ReadTimeout: p.conf.ReadTimeout,
|
||||
WriteTimeout: p.conf.WriteTimeout,
|
||||
|
|
@ -493,7 +493,7 @@ func (p *Core) createResources(initial bool) error {
|
|||
|
||||
i := &rtsp.Server{
|
||||
Address: p.conf.RTSPSAddress,
|
||||
AuthMethods: p.conf.RTSPAuthMethods,
|
||||
AuthMethods: p.conf.RTSPAuthMethods.ToAuthMethods(),
|
||||
UDPReadBufferSize: udpReadBufferSize,
|
||||
ReadTimeout: p.conf.ReadTimeout,
|
||||
WriteTimeout: p.conf.WriteTimeout,
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/auth"
|
||||
"github.com/bluenviron/mediamtx/internal/conf"
|
||||
"github.com/bluenviron/mediamtx/internal/defs"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
|
@ -73,7 +70,7 @@ func fillProperty(t *testing.T, rt reflect.Type, existing openAPIProperty) openA
|
|||
|
||||
case rt == reflect.TypeOf(time.Time{}) ||
|
||||
rt == reflect.TypeOf(conf.Duration(0)) ||
|
||||
rt == reflect.TypeOf(net.IPNet{}) ||
|
||||
rt == reflect.TypeOf(conf.IPNetwork{}) ||
|
||||
rt == reflect.TypeOf(conf.Credential("")) ||
|
||||
rt == reflect.TypeOf(conf.RecordFormat(0)) ||
|
||||
rt == reflect.TypeOf(conf.AuthAction("")) ||
|
||||
|
|
@ -83,8 +80,8 @@ func fillProperty(t *testing.T, rt reflect.Type, existing openAPIProperty) openA
|
|||
rt == reflect.TypeOf(conf.RTSPRangeType(0)) ||
|
||||
rt == reflect.TypeOf(conf.LogLevel(0)) ||
|
||||
rt == reflect.TypeOf(conf.AuthMethod(0)) ||
|
||||
rt == reflect.TypeOf(logger.Destination(0)) ||
|
||||
rt == reflect.TypeOf(auth.VerifyMethod(0)) ||
|
||||
rt == reflect.TypeOf(conf.LogDestination(0)) ||
|
||||
rt == reflect.TypeOf(conf.RTSPAuthMethod(0)) ||
|
||||
rt == reflect.TypeOf(conf.HLSVariant(0)) ||
|
||||
rt == reflect.TypeOf(defs.APIRTMPConnState("")) ||
|
||||
rt == reflect.TypeOf(defs.APIWebRTCSessionState("")) ||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue