diff --git a/internal/conf/conf.go b/internal/conf/conf.go index a71121ec..5ac60012 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -525,6 +525,13 @@ func (conf *Conf) Validate(l logger.Writer) error { l = &nilLogger{} } + // General (deprecated params) + + if conf.ReadBufferCount != nil { + l.Log(logger.Warn, "parameter 'readBufferCount' is deprecated and has been replaced with 'writeQueueSize'") + conf.WriteQueueSize = *conf.ReadBufferCount + } + // General if conf.ReadTimeout <= 0 { @@ -535,11 +542,6 @@ func (conf *Conf) Validate(l logger.Writer) error { return fmt.Errorf("'writeTimeout' must be greater than zero") } - if conf.ReadBufferCount != nil { - l.Log(logger.Warn, "parameter 'readBufferCount' is deprecated and has been replaced with 'writeQueueSize'") - conf.WriteQueueSize = *conf.ReadBufferCount - } - if (conf.WriteQueueSize & (conf.WriteQueueSize - 1)) != 0 { return fmt.Errorf("'writeQueueSize' must be a power of two") } @@ -548,7 +550,7 @@ func (conf *Conf) Validate(l logger.Writer) error { return fmt.Errorf("'udpMaxPayloadSize' must be less than 1472") } - // Authentication + // Authentication (deprecated params) if conf.ExternalAuthenticationURL != nil { l.Log(logger.Warn, "parameter 'externalAuthenticationURL' is deprecated "+ @@ -557,18 +559,6 @@ func (conf *Conf) Validate(l logger.Writer) error { conf.AuthHTTPAddress = *conf.ExternalAuthenticationURL } - if conf.AuthHTTPAddress != "" && - !strings.HasPrefix(conf.AuthHTTPAddress, "http://") && - !strings.HasPrefix(conf.AuthHTTPAddress, "https://") { - return fmt.Errorf("'externalAuthenticationURL' must be a HTTP URL") - } - - if conf.AuthJWTJWKS != "" && - !strings.HasPrefix(conf.AuthJWTJWKS, "http://") && - !strings.HasPrefix(conf.AuthJWTJWKS, "https://") { - return fmt.Errorf("'authJWTJWKS' must be a HTTP URL") - } - deprecatedCredentialsMode := false if anyPathHasDeprecatedCredentials(conf.PathDefaults, conf.OptionalPaths) { l.Log(logger.Warn, "you are using one or more authentication-related deprecated parameters "+ @@ -608,50 +598,97 @@ func (conf *Conf) Validate(l logger.Writer) error { deprecatedCredentialsMode = true } + // Authentication + switch conf.AuthMethod { case AuthMethodHTTP: if conf.AuthHTTPAddress == "" { return fmt.Errorf("'authHTTPAddress' is empty") } + if conf.AuthHTTPAddress != "" && + !strings.HasPrefix(conf.AuthHTTPAddress, "http://") && + !strings.HasPrefix(conf.AuthHTTPAddress, "https://") { + return fmt.Errorf("'externalAuthenticationURL' must be a HTTP URL") + } + case AuthMethodJWT: if conf.AuthJWTJWKS == "" { return fmt.Errorf("'authJWTJWKS' is empty") } + + if conf.AuthJWTJWKS != "" && + !strings.HasPrefix(conf.AuthJWTJWKS, "http://") && + !strings.HasPrefix(conf.AuthJWTJWKS, "https://") { + return fmt.Errorf("'authJWTJWKS' must be a HTTP URL") + } + if conf.AuthJWTClaimKey == "" { return fmt.Errorf("'authJWTClaimKey' is empty") } } - // Control API + // Control API (deprecated params) if conf.APIAllowOrigin != nil { l.Log(logger.Warn, "parameter 'apiAllowOrigin' is deprecated and has been replaced with 'apiAllowOrigins'") conf.APIAllowOrigins = []string{*conf.APIAllowOrigin} } - // Metrics + // Control API + + if conf.API { + if conf.APIAddress == "" { + return fmt.Errorf("'apiAddress' must be set when API is enabled") + } + } + + // Metrics (deprecated params) if conf.MetricsAllowOrigin != nil { l.Log(logger.Warn, "parameter 'metricsAllowOrigin' is deprecated and has been replaced with 'metricsAllowOrigins'") conf.MetricsAllowOrigins = []string{*conf.MetricsAllowOrigin} } - // PPROF + // Metrics + + if conf.Metrics { + if conf.MetricsAddress == "" { + return fmt.Errorf("'metricsAddress' must be set when metrics are enabled") + } + } + + // PPROF (deprecated params) if conf.PPROFAllowOrigin != nil { l.Log(logger.Warn, "parameter 'pprofAllowOrigin' is deprecated and has been replaced with 'pprofAllowOrigins'") conf.PPROFAllowOrigins = []string{*conf.PPROFAllowOrigin} } - // Playback + // PPROF + + if conf.PPROF { + if conf.PPROFAddress == "" { + return fmt.Errorf("'pprofAddress' must be set when pprof is enabled") + } + } + + // Playback (deprecated params) if conf.PlaybackAllowOrigin != nil { l.Log(logger.Warn, "parameter 'playbackAllowOrigin' is deprecated and has been replaced with 'playbackAllowOrigins'") conf.PlaybackAllowOrigins = []string{*conf.PlaybackAllowOrigin} } - // RTSP server + // Playback + + if conf.Playback { + if conf.PlaybackAddress == "" { + return fmt.Errorf("'playbackAddress' must be set when playback is enabled") + } + } + + // RTSP server (deprecated params) if conf.RTSPDisable != nil { l.Log(logger.Warn, "parameter 'rtspDisabled' is deprecated and has been replaced with 'rtsp'") @@ -673,17 +710,6 @@ func (conf *Conf) Validate(l logger.Writer) error { conf.RTSPAuthMethods = *conf.AuthMethods } - if slices.Contains(conf.RTSPAuthMethods, auth.VerifyMethodDigestMD5) { - if conf.AuthMethod != AuthMethodInternal { - return fmt.Errorf("when RTSP digest is enabled, the only supported auth method is 'internal'") - } - for _, user := range conf.AuthInternalUsers { - if user.User.IsHashed() || user.Pass.IsHashed() { - return fmt.Errorf("when RTSP digest is enabled, hashed credentials cannot be used") - } - } - } - if conf.ServerCert != nil { l.Log(logger.Warn, "parameter 'serverCert' is deprecated and has been replaced with 'rtspServerCert'") conf.RTSPServerCert = *conf.ServerCert @@ -694,18 +720,103 @@ func (conf *Conf) Validate(l logger.Writer) error { conf.RTSPServerKey = *conf.ServerKey } - if len(conf.RTSPAuthMethods) == 0 { - return fmt.Errorf("at least one 'rtspAuthMethods' must be provided") + // RTSP server + + if conf.RTSP { + if conf.RTSPEncryption == EncryptionNo || conf.RTSPEncryption == EncryptionOptional { + if conf.RTSPAddress == "" { + return fmt.Errorf("'rtspAddress' must be set when RTSP is enabled and RTSP encryption is 'no' or 'optional'") + } + + if _, ok := conf.RTSPTransports[gortsplib.ProtocolUDP]; ok { + if conf.RTPAddress == "" { + return fmt.Errorf("'rtpAddress' must be set when UDP is enabled and RTSP encryption is 'no' or 'optional'") + } + if conf.RTCPAddress == "" { + return fmt.Errorf("'rtcpAddress' must be set when UDP is enabled and RTSP encryption is 'no' or 'optional'") + } + } + + if _, ok := conf.RTSPTransports[gortsplib.ProtocolUDPMulticast]; ok { + if conf.MulticastIPRange == "" { + return fmt.Errorf("'multicastIPRange' must be set when UDP multicast is enabled" + + " and RTSP encryption is 'no' or 'optional'") + } + if conf.MulticastRTPPort == 0 { + return fmt.Errorf("'multicastRTPPort' must be set when UDP multicast is enabled" + + " and RTSP encryption is 'no' or 'optional'") + } + if conf.MulticastRTCPPort == 0 { + return fmt.Errorf("'multicastRTCPPort' must be set when UDP multicast is enabled" + + " and RTSP encryption is 'no' or 'optional'") + } + } + } + + if conf.RTSPEncryption == EncryptionOptional || conf.RTSPEncryption == EncryptionStrict { + if conf.RTSPSAddress == "" { + return fmt.Errorf("'rtspsAddress' must be set when RTSP is enabled and RTSP encryption is 'optional' or 'strict'") + } + + if _, ok := conf.RTSPTransports[gortsplib.ProtocolUDP]; ok { + if conf.SRTPAddress == "" { + return fmt.Errorf("'srtpAddress' must be set when UDP is enabled" + + " and RTSP encryption is 'optional' or 'strict'") + } + if conf.SRTCPAddress == "" { + return fmt.Errorf("'srtcpAddress' must be set when UDP is enabled" + + " and RTSP encryption is 'optional' or 'strict'") + } + } + + if _, ok := conf.RTSPTransports[gortsplib.ProtocolUDPMulticast]; ok { + if conf.MulticastIPRange == "" { + return fmt.Errorf("'multicastIPRange' must be set when UDP multicast is enabled" + + " and RTSP encryption is 'optional' or 'strict'") + } + if conf.MulticastSRTPPort == 0 { + return fmt.Errorf("'multicastSRTPPort' must be set when UDP multicast is enabled" + + " and RTSP encryption is 'optional' or 'strict'") + } + if conf.MulticastSRTCPPort == 0 { + return fmt.Errorf("'multicastSRTCPPort' must be set when UDP multicast is enabled" + + " and RTSP encryption is 'optional' or 'strict'") + } + } + } + + if len(conf.RTSPAuthMethods) == 0 { + return fmt.Errorf("at least one 'rtspAuthMethods' must be provided") + } + + if slices.Contains(conf.RTSPAuthMethods, auth.VerifyMethodDigestMD5) { + if conf.AuthMethod != AuthMethodInternal { + return fmt.Errorf("when RTSP digest is enabled, the only supported auth method is 'internal'") + } + for _, user := range conf.AuthInternalUsers { + if user.User.IsHashed() || user.Pass.IsHashed() { + return fmt.Errorf("when RTSP digest is enabled, hashed credentials cannot be used") + } + } + } } - // RTMP + // RTMP (deprecated params) if conf.RTMPDisable != nil { l.Log(logger.Warn, "parameter 'rtmpDisabled' is deprecated and has been replaced with 'rtmp'") conf.RTMP = !*conf.RTMPDisable } - // HLS + // RTMP + + if conf.RTMP { + if conf.RTMPAddress == "" { + return fmt.Errorf("'rtmpAddress' must be set when RTMP is enabled") + } + } + + // HLS (deprecated params) if conf.HLSDisable != nil { l.Log(logger.Warn, "parameter 'hlsDisable' is deprecated and has been replaced with 'hls'") @@ -717,7 +828,15 @@ func (conf *Conf) Validate(l logger.Writer) error { conf.HLSAllowOrigins = []string{*conf.HLSAllowOrigin} } - // WebRTC + // HLS + + if conf.HLS { + if conf.HLSAddress == "" { + return fmt.Errorf("'hlsAddress' must be set when HLS is enabled") + } + } + + // WebRTC (deprecated params) if conf.WebRTCDisable != nil { l.Log(logger.Warn, "parameter 'webrtcDisable' is deprecated and has been replaced with 'webrtc'") @@ -762,32 +881,40 @@ func (conf *Conf) Validate(l logger.Writer) error { } } - for _, server := range conf.WebRTCICEServers2 { - if !strings.HasPrefix(server.URL, "stun:") && - !strings.HasPrefix(server.URL, "turn:") && - !strings.HasPrefix(server.URL, "turns:") { - return fmt.Errorf("invalid ICE server: '%s'", server.URL) - } - } - - if conf.WebRTCLocalUDPAddress == "" && - conf.WebRTCLocalTCPAddress == "" && - len(conf.WebRTCICEServers2) == 0 { - return fmt.Errorf("at least one between 'webrtcLocalUDPAddress'," + - " 'webrtcLocalTCPAddress' or 'webrtcICEServers2' must be filled") - } - - if conf.WebRTCLocalUDPAddress != "" || conf.WebRTCLocalTCPAddress != "" { - if !conf.WebRTCIPsFromInterfaces && len(conf.WebRTCAdditionalHosts) == 0 { - return fmt.Errorf("at least one between 'webrtcIPsFromInterfaces' or 'webrtcAdditionalHosts' must be filled") - } - } - if conf.WebRTCAllowOrigin != nil { l.Log(logger.Warn, "parameter 'webrtcAllowOrigin' is deprecated and has been replaced with 'webrtcAllowOrigins'") conf.WebRTCAllowOrigins = []string{*conf.WebRTCAllowOrigin} } + // WebRTC + + if conf.WebRTC { + if conf.WebRTCAddress == "" { + return fmt.Errorf("'webrtcAddress' must be set when WebRTC is enabled") + } + + for _, server := range conf.WebRTCICEServers2 { + if !strings.HasPrefix(server.URL, "stun:") && + !strings.HasPrefix(server.URL, "turn:") && + !strings.HasPrefix(server.URL, "turns:") { + return fmt.Errorf("invalid ICE server: '%s'", server.URL) + } + } + + if conf.WebRTCLocalUDPAddress == "" && + conf.WebRTCLocalTCPAddress == "" && + len(conf.WebRTCICEServers2) == 0 { + return fmt.Errorf("at least one between 'webrtcLocalUDPAddress'," + + " 'webrtcLocalTCPAddress' or 'webrtcICEServers2' must be filled") + } + + if conf.WebRTCLocalUDPAddress != "" || conf.WebRTCLocalTCPAddress != "" { + if !conf.WebRTCIPsFromInterfaces && len(conf.WebRTCAdditionalHosts) == 0 { + return fmt.Errorf("at least one between 'webrtcIPsFromInterfaces' or 'webrtcAdditionalHosts' must be filled") + } + } + } + // Record (deprecated) if conf.Record != nil { @@ -826,6 +953,8 @@ func (conf *Conf) Validate(l logger.Writer) error { conf.PathDefaults.RecordDeleteAfter = *conf.RecordDeleteAfter } + // paths + hasAllOthers := false for name := range conf.OptionalPaths { if name == "all" || name == "all_others" || name == "~^.*$" { diff --git a/internal/conf/conf_test.go b/internal/conf/conf_test.go index 8534087b..1ae06eab 100644 --- a/internal/conf/conf_test.go +++ b/internal/conf/conf_test.go @@ -356,6 +356,20 @@ func TestConfErrors(t *testing.T) { " ~^.*$:\n", `all_others, all and '~^.*$' are aliases`, }, + { + "jwt jwks empty", + "authMethod: jwt\n" + + "authJWTJWKS: \"\"\n" + + "authJWTClaimKey: test", + "'authJWTJWKS' is empty", + }, + { + "invalid jwt jwks url", + "authMethod: jwt\n" + + "authJWTJWKS: ftp://invalid\n" + + "authJWTClaimKey: test", + "'authJWTJWKS' must be a HTTP URL", + }, { "jwt claim key empty", "authMethod: jwt\n" + @@ -363,11 +377,40 @@ func TestConfErrors(t *testing.T) { "authJWTClaimKey: \"\"", "'authJWTClaimKey' is empty", }, + { + "http auth address empty", + "authMethod: http\n" + + "authHTTPAddress: \"\"", + "'authHTTPAddress' is empty", + }, + { + "invalid http auth address", + "authMethod: http\n" + + "authHTTPAddress: ftp://invalid", + "'externalAuthenticationURL' must be a HTTP URL", + }, { "invalid rtsp auth methods", "rtspAuthMethods: []", "at least one 'rtspAuthMethods' must be provided", }, + { + "rtsp digest with non-internal auth", + "authMethod: http\n" + + "authHTTPAddress: http://localhost:9000\n" + + "rtspAuthMethods: [digest]\n", + "when RTSP digest is enabled, the only supported auth method is 'internal'", + }, + { + "rtsp digest with hashed credentials", + "rtspAuthMethods: [digest]\n" + + "authInternalUsers:\n" + + "- user: sha256:test\n" + + " pass: test\n" + + " permissions:\n" + + " - action: publish\n", + "when RTSP digest is enabled, hashed credentials cannot be used", + }, { "invalid fallback", "paths:\n" + @@ -438,6 +481,252 @@ func TestConfErrors(t *testing.T) { " recordDeleteAfter: 20m\n", `'recordDeleteAfter' cannot be lower than 'recordSegmentDuration'`, }, + { + "missing rtpAddress with UDP and no encryption", + "rtspEncryption: \"no\"\n" + + "rtspTransports: [udp]\n" + + "rtpAddress: ''\n", + "'rtpAddress' must be set when UDP is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing rtcpAddress with UDP and no encryption", + "rtspEncryption: \"no\"\n" + + "rtspTransports: [udp]\n" + + "rtpAddress: ':8000'\n" + + "rtcpAddress: ''\n", + "'rtcpAddress' must be set when UDP is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing rtpAddress with UDP and optional encryption", + "rtspEncryption: optional\n" + + "rtspTransports: [udp]\n" + + "rtpAddress: ''\n", + "'rtpAddress' must be set when UDP is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing rtcpAddress with UDP and optional encryption", + "rtspEncryption: optional\n" + + "rtspTransports: [udp]\n" + + "rtpAddress: ':8000'\n" + + "rtcpAddress: ''\n", + "'rtcpAddress' must be set when UDP is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing multicastIPRange with UDP multicast and no encryption", + "rtspEncryption: \"no\"\n" + + "rtspTransports: [multicast]\n" + + "multicastIPRange: ''\n", + "'multicastIPRange' must be set when UDP multicast is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing multicastRTPPort with UDP multicast and no encryption", + "rtspEncryption: \"no\"\n" + + "rtspTransports: [multicast]\n" + + "multicastIPRange: '224.1.0.0/16'\n" + + "multicastRTPPort: 0\n", + "'multicastRTPPort' must be set when UDP multicast is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing multicastRTCPPort with UDP multicast and no encryption", + "rtspEncryption: \"no\"\n" + + "rtspTransports: [multicast]\n" + + "multicastIPRange: '224.1.0.0/16'\n" + + "multicastRTPPort: 8002\n" + + "multicastRTCPPort: 0\n", + "'multicastRTCPPort' must be set when UDP multicast is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing multicastIPRange with UDP multicast and optional encryption", + "rtspEncryption: optional\n" + + "rtspTransports: [multicast]\n" + + "multicastIPRange: ''\n", + "'multicastIPRange' must be set when UDP multicast is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing multicastRTPPort with UDP multicast and optional encryption", + "rtspEncryption: optional\n" + + "rtspTransports: [multicast]\n" + + "multicastIPRange: '224.1.0.0/16'\n" + + "multicastRTPPort: 0\n", + "'multicastRTPPort' must be set when UDP multicast is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing multicastRTCPPort with UDP multicast and optional encryption", + "rtspEncryption: optional\n" + + "rtspTransports: [multicast]\n" + + "multicastIPRange: '224.1.0.0/16'\n" + + "multicastRTPPort: 8002\n" + + "multicastRTCPPort: 0\n", + "'multicastRTCPPort' must be set when UDP multicast is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing srtpAddress with UDP and optional encryption", + "rtspEncryption: optional\n" + + "rtspTransports: [udp]\n" + + "rtpAddress: ':8000'\n" + + "rtcpAddress: ':8001'\n" + + "srtpAddress: ''\n", + "'srtpAddress' must be set when UDP is enabled and RTSP encryption is 'optional' or 'strict'", + }, + { + "missing srtcpAddress with UDP and optional encryption", + "rtspEncryption: optional\n" + + "rtspTransports: [udp]\n" + + "rtpAddress: ':8000'\n" + + "rtcpAddress: ':8001'\n" + + "srtpAddress: ':8004'\n" + + "srtcpAddress: ''\n", + "'srtcpAddress' must be set when UDP is enabled and RTSP encryption is 'optional' or 'strict'", + }, + { + "missing srtpAddress with UDP and strict encryption", + "rtspEncryption: strict\n" + + "rtspTransports: [udp]\n" + + "srtpAddress: ''\n", + "'srtpAddress' must be set when UDP is enabled and RTSP encryption is 'optional' or 'strict'", + }, + { + "missing srtcpAddress with UDP and strict encryption", + "rtspEncryption: strict\n" + + "rtspTransports: [udp]\n" + + "srtpAddress: ':8004'\n" + + "srtcpAddress: ''\n", + "'srtcpAddress' must be set when UDP is enabled and RTSP encryption is 'optional' or 'strict'", + }, + { + "missing multicastIPRange with UDP multicast and optional encryption second check", + "rtspEncryption: optional\n" + + "rtspTransports: [multicast]\n" + + "rtpAddress: ':8000'\n" + + "rtcpAddress: ':8001'\n" + + "multicastIPRange: ''\n", + "'multicastIPRange' must be set when UDP multicast is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing multicastSRTPPort with UDP multicast and optional encryption", + "rtspEncryption: optional\n" + + "rtspTransports: [multicast]\n" + + "rtpAddress: ':8000'\n" + + "rtcpAddress: ':8001'\n" + + "multicastIPRange: '224.1.0.0/16'\n" + + "multicastRTPPort: 8002\n" + + "multicastRTCPPort: 8003\n" + + "srtpAddress: ':8004'\n" + + "srtcpAddress: ':8005'\n" + + "multicastSRTPPort: 0\n", + "'multicastSRTPPort' must be set when UDP multicast is enabled and RTSP encryption is 'optional' or 'strict'", + }, + { + "missing multicastSRTCPPort with UDP multicast and optional encryption", + "rtspEncryption: optional\n" + + "rtspTransports: [multicast]\n" + + "rtpAddress: ':8000'\n" + + "rtcpAddress: ':8001'\n" + + "multicastIPRange: '224.1.0.0/16'\n" + + "multicastRTPPort: 8002\n" + + "multicastRTCPPort: 8003\n" + + "srtpAddress: ':8004'\n" + + "srtcpAddress: ':8005'\n" + + "multicastSRTPPort: 8006\n" + + "multicastSRTCPPort: 0\n", + "'multicastSRTCPPort' must be set when UDP multicast is enabled and RTSP encryption is 'optional' or 'strict'", + }, + { + "missing multicastIPRange with UDP multicast and strict encryption", + "rtspEncryption: strict\n" + + "rtspTransports: [multicast]\n" + + "multicastIPRange: ''\n", + "'multicastIPRange' must be set when UDP multicast is enabled and RTSP encryption is 'optional' or 'strict'", + }, + { + "missing multicastSRTPPort with UDP multicast and strict encryption", + "rtspEncryption: strict\n" + + "rtspTransports: [multicast]\n" + + "multicastIPRange: '224.1.0.0/16'\n" + + "multicastSRTPPort: 0\n", + "'multicastSRTPPort' must be set when UDP multicast is enabled and RTSP encryption is 'optional' or 'strict'", + }, + { + "missing multicastSRTCPPort with UDP multicast and strict encryption", + "rtspEncryption: strict\n" + + "rtspTransports: [multicast]\n" + + "multicastIPRange: '224.1.0.0/16'\n" + + "multicastSRTPPort: 8006\n" + + "multicastSRTCPPort: 0\n", + "'multicastSRTCPPort' must be set when UDP multicast is enabled and RTSP encryption is 'optional' or 'strict'", + }, + { + "missing rtspAddress with RTSP enabled and no encryption", + "rtsp: yes\n" + + "rtspEncryption: \"no\"\n" + + "rtspAddress: ''\n", + "'rtspAddress' must be set when RTSP is enabled and RTSP encryption is 'no' or 'optional'", + }, + { + "missing rtspsAddress with RTSP enabled and strict encryption", + "rtsp: yes\n" + + "rtspEncryption: strict\n" + + "rtspsAddress: ''\n", + "'rtspsAddress' must be set when RTSP is enabled and RTSP encryption is 'optional' or 'strict'", + }, + { + "missing rtmpAddress with RTMP enabled", + "rtmp: yes\n" + + "rtmpAddress: ''\n", + "'rtmpAddress' must be set when RTMP is enabled", + }, + { + "missing hlsAddress with HLS enabled", + "hls: yes\n" + + "hlsAddress: ''\n", + "'hlsAddress' must be set when HLS is enabled", + }, + { + "missing webrtcAddress with WebRTC enabled", + "webrtc: yes\n" + + "webrtcAddress: ''\n", + "'webrtcAddress' must be set when WebRTC is enabled", + }, + { + "webrtc missing local addresses and ice servers", + "webrtc: yes\n" + + "webrtcLocalUDPAddress: ''\n" + + "webrtcLocalTCPAddress: ''\n" + + "webrtcICEServers2: []\n", + "at least one between 'webrtcLocalUDPAddress', 'webrtcLocalTCPAddress' or 'webrtcICEServers2' must be filled", + }, + { + "webrtc missing ips config", + "webrtc: yes\n" + + "webrtcLocalUDPAddress: ':8189'\n" + + "webrtcIPsFromInterfaces: false\n" + + "webrtcAdditionalHosts: []\n", + "at least one between 'webrtcIPsFromInterfaces' or 'webrtcAdditionalHosts' must be filled", + }, + { + "missing apiAddress with API enabled", + "api: yes\n" + + "apiAddress: ''\n", + "'apiAddress' must be set when API is enabled", + }, + { + "missing metricsAddress with metrics enabled", + "metrics: yes\n" + + "metricsAddress: ''\n", + "'metricsAddress' must be set when metrics are enabled", + }, + { + "missing pprofAddress with pprof enabled", + "pprof: yes\n" + + "pprofAddress: ''\n", + "'pprofAddress' must be set when pprof is enabled", + }, + { + "missing playbackAddress with playback enabled", + "playback: yes\n" + + "playbackAddress: ''\n", + "'playbackAddress' must be set when playback is enabled", + }, } { t.Run(ca.name, func(t *testing.T) { tmpf, err := createTempFile([]byte(ca.conf)) diff --git a/internal/core/core.go b/internal/core/core.go index 06277194..19956949 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -17,7 +17,6 @@ import ( "time" "github.com/alecthomas/kong" - "github.com/bluenviron/gortsplib/v5" "github.com/gin-gonic/gin" "github.com/bluenviron/mediamtx/internal/api" @@ -445,9 +444,6 @@ func (p *Core) createResources(initial bool) error { (p.conf.RTSPEncryption == conf.EncryptionNo || p.conf.RTSPEncryption == conf.EncryptionOptional) && p.rtspServer == nil { - _, useUDP := p.conf.RTSPTransports[gortsplib.ProtocolUDP] - _, useMulticast := p.conf.RTSPTransports[gortsplib.ProtocolUDPMulticast] - udpReadBufferSize := p.conf.UDPReadBufferSize if p.conf.RTSPUDPReadBufferSize != nil { udpReadBufferSize = *p.conf.RTSPUDPReadBufferSize @@ -460,8 +456,7 @@ func (p *Core) createResources(initial bool) error { ReadTimeout: p.conf.ReadTimeout, WriteTimeout: p.conf.WriteTimeout, WriteQueueSize: p.conf.WriteQueueSize, - UseUDP: useUDP, - UseMulticast: useMulticast, + RTSPTransports: p.conf.RTSPTransports, RTPAddress: p.conf.RTPAddress, RTCPAddress: p.conf.RTCPAddress, MulticastIPRange: p.conf.MulticastIPRange, @@ -491,9 +486,6 @@ func (p *Core) createResources(initial bool) error { (p.conf.RTSPEncryption == conf.EncryptionStrict || p.conf.RTSPEncryption == conf.EncryptionOptional) && p.rtspsServer == nil { - _, useUDP := p.conf.RTSPTransports[gortsplib.ProtocolUDP] - _, useMulticast := p.conf.RTSPTransports[gortsplib.ProtocolUDPMulticast] - udpReadBufferSize := p.conf.UDPReadBufferSize if p.conf.RTSPUDPReadBufferSize != nil { udpReadBufferSize = *p.conf.RTSPUDPReadBufferSize @@ -506,8 +498,7 @@ func (p *Core) createResources(initial bool) error { ReadTimeout: p.conf.ReadTimeout, WriteTimeout: p.conf.WriteTimeout, WriteQueueSize: p.conf.WriteQueueSize, - UseUDP: useUDP, - UseMulticast: useMulticast, + RTSPTransports: p.conf.RTSPTransports, RTPAddress: p.conf.SRTPAddress, RTCPAddress: p.conf.SRTCPAddress, MulticastIPRange: p.conf.MulticastIPRange, diff --git a/internal/servers/rtsp/server.go b/internal/servers/rtsp/server.go index 0d403ce2..d21eb4d1 100644 --- a/internal/servers/rtsp/server.go +++ b/internal/servers/rtsp/server.go @@ -94,8 +94,7 @@ type Server struct { ReadTimeout conf.Duration WriteTimeout conf.Duration WriteQueueSize int - UseUDP bool - UseMulticast bool + RTSPTransports conf.RTSPTransports RTPAddress string RTCPAddress string MulticastIPRange string @@ -141,12 +140,12 @@ func (s *Server) Initialize() error { AuthMethods: s.AuthMethods, } - if s.UseUDP { + if _, ok := s.RTSPTransports[gortsplib.ProtocolUDP]; ok { s.srv.UDPRTPAddress = s.RTPAddress s.srv.UDPRTCPAddress = s.RTCPAddress } - if s.UseMulticast { + if _, ok := s.RTSPTransports[gortsplib.ProtocolUDPMulticast]; ok { s.srv.MulticastIPRange = s.MulticastIPRange s.srv.MulticastRTPPort = s.MulticastRTPPort s.srv.MulticastRTCPPort = s.MulticastRTCPPort