|
|
|
|
@ -15,26 +15,6 @@ import (
@@ -15,26 +15,6 @@ import (
|
|
|
|
|
"github.com/aler9/rtsp-simple-server/internal/logger" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// Encryption is an encryption policy.
|
|
|
|
|
type Encryption int |
|
|
|
|
|
|
|
|
|
// encryption policies.
|
|
|
|
|
const ( |
|
|
|
|
EncryptionNo Encryption = iota |
|
|
|
|
EncryptionOptional |
|
|
|
|
EncryptionStrict |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// Protocol is a RTSP protocol
|
|
|
|
|
type Protocol int |
|
|
|
|
|
|
|
|
|
// RTSP protocols.
|
|
|
|
|
const ( |
|
|
|
|
ProtocolUDP Protocol = iota |
|
|
|
|
ProtocolMulticast |
|
|
|
|
ProtocolTCP |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
func decrypt(key string, byts []byte) ([]byte, error) { |
|
|
|
|
enc, err := base64.StdEncoding.DecodeString(string(byts)) |
|
|
|
|
if err != nil { |
|
|
|
|
@ -121,41 +101,36 @@ func loadFromFile(fpath string, conf *Conf) (bool, error) {
@@ -121,41 +101,36 @@ func loadFromFile(fpath string, conf *Conf) (bool, error) {
|
|
|
|
|
// Conf is a configuration.
|
|
|
|
|
type Conf struct { |
|
|
|
|
// general
|
|
|
|
|
LogLevel string `json:"logLevel"` |
|
|
|
|
LogLevelParsed logger.Level `json:"-"` |
|
|
|
|
LogDestinations []string `json:"logDestinations"` |
|
|
|
|
LogDestinationsParsed map[logger.Destination]struct{} `json:"-"` |
|
|
|
|
LogFile string `json:"logFile"` |
|
|
|
|
ReadTimeout StringDuration `json:"readTimeout"` |
|
|
|
|
WriteTimeout StringDuration `json:"writeTimeout"` |
|
|
|
|
ReadBufferCount int `json:"readBufferCount"` |
|
|
|
|
API bool `json:"api"` |
|
|
|
|
APIAddress string `json:"apiAddress"` |
|
|
|
|
Metrics bool `json:"metrics"` |
|
|
|
|
MetricsAddress string `json:"metricsAddress"` |
|
|
|
|
PPROF bool `json:"pprof"` |
|
|
|
|
PPROFAddress string `json:"pprofAddress"` |
|
|
|
|
RunOnConnect string `json:"runOnConnect"` |
|
|
|
|
RunOnConnectRestart bool `json:"runOnConnectRestart"` |
|
|
|
|
LogLevel LogLevel `json:"logLevel"` |
|
|
|
|
LogDestinations LogDestinations `json:"logDestinations"` |
|
|
|
|
LogFile string `json:"logFile"` |
|
|
|
|
ReadTimeout StringDuration `json:"readTimeout"` |
|
|
|
|
WriteTimeout StringDuration `json:"writeTimeout"` |
|
|
|
|
ReadBufferCount int `json:"readBufferCount"` |
|
|
|
|
API bool `json:"api"` |
|
|
|
|
APIAddress string `json:"apiAddress"` |
|
|
|
|
Metrics bool `json:"metrics"` |
|
|
|
|
MetricsAddress string `json:"metricsAddress"` |
|
|
|
|
PPROF bool `json:"pprof"` |
|
|
|
|
PPROFAddress string `json:"pprofAddress"` |
|
|
|
|
RunOnConnect string `json:"runOnConnect"` |
|
|
|
|
RunOnConnectRestart bool `json:"runOnConnectRestart"` |
|
|
|
|
|
|
|
|
|
// RTSP
|
|
|
|
|
RTSPDisable bool `json:"rtspDisable"` |
|
|
|
|
Protocols []string `json:"protocols"` |
|
|
|
|
ProtocolsParsed map[Protocol]struct{} `json:"-"` |
|
|
|
|
Encryption string `json:"encryption"` |
|
|
|
|
EncryptionParsed Encryption `json:"-"` |
|
|
|
|
RTSPAddress string `json:"rtspAddress"` |
|
|
|
|
RTSPSAddress string `json:"rtspsAddress"` |
|
|
|
|
RTPAddress string `json:"rtpAddress"` |
|
|
|
|
RTCPAddress string `json:"rtcpAddress"` |
|
|
|
|
MulticastIPRange string `json:"multicastIPRange"` |
|
|
|
|
MulticastRTPPort int `json:"multicastRTPPort"` |
|
|
|
|
MulticastRTCPPort int `json:"multicastRTCPPort"` |
|
|
|
|
ServerKey string `json:"serverKey"` |
|
|
|
|
ServerCert string `json:"serverCert"` |
|
|
|
|
AuthMethods []string `json:"authMethods"` |
|
|
|
|
AuthMethodsParsed []headers.AuthMethod `json:"-"` |
|
|
|
|
ReadBufferSize int `json:"readBufferSize"` |
|
|
|
|
RTSPDisable bool `json:"rtspDisable"` |
|
|
|
|
Protocols Protocols `json:"protocols"` |
|
|
|
|
Encryption Encryption `json:"encryption"` |
|
|
|
|
RTSPAddress string `json:"rtspAddress"` |
|
|
|
|
RTSPSAddress string `json:"rtspsAddress"` |
|
|
|
|
RTPAddress string `json:"rtpAddress"` |
|
|
|
|
RTCPAddress string `json:"rtcpAddress"` |
|
|
|
|
MulticastIPRange string `json:"multicastIPRange"` |
|
|
|
|
MulticastRTPPort int `json:"multicastRTPPort"` |
|
|
|
|
MulticastRTCPPort int `json:"multicastRTCPPort"` |
|
|
|
|
ServerKey string `json:"serverKey"` |
|
|
|
|
ServerCert string `json:"serverCert"` |
|
|
|
|
AuthMethods AuthMethods `json:"authMethods"` |
|
|
|
|
ReadBufferSize int `json:"readBufferSize"` |
|
|
|
|
|
|
|
|
|
// RTMP
|
|
|
|
|
RTMPDisable bool `json:"rtmpDisable"` |
|
|
|
|
@ -197,52 +172,26 @@ func Load(fpath string) (*Conf, bool, error) {
@@ -197,52 +172,26 @@ func Load(fpath string) (*Conf, bool, error) {
|
|
|
|
|
|
|
|
|
|
// CheckAndFillMissing checks the configuration for errors and fills missing fields.
|
|
|
|
|
func (conf *Conf) CheckAndFillMissing() error { |
|
|
|
|
if conf.LogLevel == "" { |
|
|
|
|
conf.LogLevel = "info" |
|
|
|
|
} |
|
|
|
|
switch conf.LogLevel { |
|
|
|
|
case "warn": |
|
|
|
|
conf.LogLevelParsed = logger.Warn |
|
|
|
|
|
|
|
|
|
case "info": |
|
|
|
|
conf.LogLevelParsed = logger.Info |
|
|
|
|
|
|
|
|
|
case "debug": |
|
|
|
|
conf.LogLevelParsed = logger.Debug |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
return fmt.Errorf("unsupported log level: %s", conf.LogLevel) |
|
|
|
|
if conf.LogLevel == 0 { |
|
|
|
|
conf.LogLevel = LogLevel(logger.Info) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(conf.LogDestinations) == 0 { |
|
|
|
|
conf.LogDestinations = []string{"stdout"} |
|
|
|
|
} |
|
|
|
|
conf.LogDestinationsParsed = make(map[logger.Destination]struct{}) |
|
|
|
|
for _, dest := range conf.LogDestinations { |
|
|
|
|
switch dest { |
|
|
|
|
case "stdout": |
|
|
|
|
conf.LogDestinationsParsed[logger.DestinationStdout] = struct{}{} |
|
|
|
|
|
|
|
|
|
case "file": |
|
|
|
|
conf.LogDestinationsParsed[logger.DestinationFile] = struct{}{} |
|
|
|
|
|
|
|
|
|
case "syslog": |
|
|
|
|
conf.LogDestinationsParsed[logger.DestinationSyslog] = struct{}{} |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
return fmt.Errorf("unsupported log destination: %s", dest) |
|
|
|
|
} |
|
|
|
|
conf.LogDestinations = LogDestinations{logger.DestinationStdout: {}} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.LogFile == "" { |
|
|
|
|
conf.LogFile = "rtsp-simple-server.log" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.ReadTimeout == 0 { |
|
|
|
|
conf.ReadTimeout = 10 * StringDuration(time.Second) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.WriteTimeout == 0 { |
|
|
|
|
conf.WriteTimeout = 10 * StringDuration(time.Second) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.ReadBufferCount == 0 { |
|
|
|
|
conf.ReadBufferCount = 512 |
|
|
|
|
} |
|
|
|
|
@ -260,67 +209,43 @@ func (conf *Conf) CheckAndFillMissing() error {
@@ -260,67 +209,43 @@ func (conf *Conf) CheckAndFillMissing() error {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(conf.Protocols) == 0 { |
|
|
|
|
conf.Protocols = []string{"udp", "multicast", "tcp"} |
|
|
|
|
} |
|
|
|
|
conf.ProtocolsParsed = make(map[Protocol]struct{}) |
|
|
|
|
for _, proto := range conf.Protocols { |
|
|
|
|
switch proto { |
|
|
|
|
case "udp": |
|
|
|
|
conf.ProtocolsParsed[ProtocolUDP] = struct{}{} |
|
|
|
|
|
|
|
|
|
case "multicast": |
|
|
|
|
conf.ProtocolsParsed[ProtocolMulticast] = struct{}{} |
|
|
|
|
|
|
|
|
|
case "tcp": |
|
|
|
|
conf.ProtocolsParsed[ProtocolTCP] = struct{}{} |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
return fmt.Errorf("unsupported protocol: %s", proto) |
|
|
|
|
conf.Protocols = Protocols{ |
|
|
|
|
ProtocolUDP: {}, |
|
|
|
|
ProtocolMulticast: {}, |
|
|
|
|
ProtocolTCP: {}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if len(conf.ProtocolsParsed) == 0 { |
|
|
|
|
return fmt.Errorf("no protocols provided") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.Encryption == "" { |
|
|
|
|
conf.Encryption = "no" |
|
|
|
|
} |
|
|
|
|
switch conf.Encryption { |
|
|
|
|
case "no", "false": |
|
|
|
|
conf.EncryptionParsed = EncryptionNo |
|
|
|
|
|
|
|
|
|
case "optional": |
|
|
|
|
conf.EncryptionParsed = EncryptionOptional |
|
|
|
|
|
|
|
|
|
case "strict", "yes", "true": |
|
|
|
|
conf.EncryptionParsed = EncryptionStrict |
|
|
|
|
|
|
|
|
|
if _, ok := conf.ProtocolsParsed[ProtocolUDP]; ok { |
|
|
|
|
return fmt.Errorf("encryption can't be used with the UDP stream protocol") |
|
|
|
|
if conf.Encryption == EncryptionStrict { |
|
|
|
|
if _, ok := conf.Protocols[ProtocolUDP]; ok { |
|
|
|
|
return fmt.Errorf("strict encryption can't be used with the UDP stream protocol") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
return fmt.Errorf("unsupported encryption value: '%s'", conf.Encryption) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.RTSPAddress == "" { |
|
|
|
|
conf.RTSPAddress = ":8554" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.RTSPSAddress == "" { |
|
|
|
|
conf.RTSPSAddress = ":8555" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.RTPAddress == "" { |
|
|
|
|
conf.RTPAddress = ":8000" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.RTCPAddress == "" { |
|
|
|
|
conf.RTCPAddress = ":8001" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.MulticastIPRange == "" { |
|
|
|
|
conf.MulticastIPRange = "224.1.0.0/16" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.MulticastRTPPort == 0 { |
|
|
|
|
conf.MulticastRTPPort = 8002 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.MulticastRTCPPort == 0 { |
|
|
|
|
conf.MulticastRTCPPort = 8003 |
|
|
|
|
} |
|
|
|
|
@ -328,24 +253,13 @@ func (conf *Conf) CheckAndFillMissing() error {
@@ -328,24 +253,13 @@ func (conf *Conf) CheckAndFillMissing() error {
|
|
|
|
|
if conf.ServerKey == "" { |
|
|
|
|
conf.ServerKey = "server.key" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.ServerCert == "" { |
|
|
|
|
conf.ServerCert = "server.crt" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(conf.AuthMethods) == 0 { |
|
|
|
|
conf.AuthMethods = []string{"basic", "digest"} |
|
|
|
|
} |
|
|
|
|
for _, method := range conf.AuthMethods { |
|
|
|
|
switch method { |
|
|
|
|
case "basic": |
|
|
|
|
conf.AuthMethodsParsed = append(conf.AuthMethodsParsed, headers.AuthBasic) |
|
|
|
|
|
|
|
|
|
case "digest": |
|
|
|
|
conf.AuthMethodsParsed = append(conf.AuthMethodsParsed, headers.AuthDigest) |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
return fmt.Errorf("unsupported authentication method: %s", method) |
|
|
|
|
} |
|
|
|
|
conf.AuthMethods = AuthMethods{headers.AuthBasic, headers.AuthDigest} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.RTMPAddress == "" { |
|
|
|
|
@ -355,12 +269,15 @@ func (conf *Conf) CheckAndFillMissing() error {
@@ -355,12 +269,15 @@ func (conf *Conf) CheckAndFillMissing() error {
|
|
|
|
|
if conf.HLSAddress == "" { |
|
|
|
|
conf.HLSAddress = ":8888" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.HLSSegmentCount == 0 { |
|
|
|
|
conf.HLSSegmentCount = 3 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.HLSSegmentDuration == 0 { |
|
|
|
|
conf.HLSSegmentDuration = 1 * StringDuration(time.Second) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if conf.HLSAllowOrigin == "" { |
|
|
|
|
conf.HLSAllowOrigin = "*" |
|
|
|
|
} |
|
|
|
|
|