From b49acb1e00a73cb2b91c41edda93003a5b9ed252 Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Thu, 2 Jan 2025 12:44:15 +0100 Subject: [PATCH] accept durations expressed as days (i.e. '1d') (#4094) --- internal/api/api.go | 2 +- internal/api/api_test.go | 34 +++--- internal/conf/conf.go | 66 ++++++------ internal/conf/conf_test.go | 10 +- internal/conf/duration.go | 101 ++++++++++++++++++ internal/conf/duration_test.go | 56 ++++++++++ internal/conf/path.go | 74 ++++++------- internal/conf/string_duration.go | 36 ------- internal/core/path.go | 4 +- internal/core/path_manager.go | 4 +- internal/core/static_source_handler.go | 4 +- internal/metrics/metrics.go | 2 +- internal/metrics/metrics_test.go | 2 +- internal/playback/on_get_test.go | 6 +- internal/playback/on_list_test.go | 4 +- internal/playback/server.go | 2 +- internal/playback/server_test.go | 2 +- internal/pprof/pprof.go | 2 +- internal/pprof/pprof_test.go | 4 +- internal/protocols/webrtc/peer_connection.go | 4 +- .../protocols/webrtc/peer_connection_test.go | 12 +-- internal/protocols/webrtc/to_stream_test.go | 8 +- internal/protocols/whip/client.go | 8 +- internal/recordcleaner/cleaner_test.go | 6 +- internal/servers/hls/http_server.go | 2 +- internal/servers/hls/muxer.go | 6 +- internal/servers/hls/muxer_instance.go | 4 +- internal/servers/hls/server.go | 8 +- internal/servers/hls/server_test.go | 26 ++--- internal/servers/rtmp/conn.go | 4 +- internal/servers/rtmp/server.go | 4 +- internal/servers/rtmp/server_test.go | 8 +- internal/servers/rtsp/conn.go | 2 +- internal/servers/rtsp/server.go | 4 +- internal/servers/rtsp/server_test.go | 8 +- internal/servers/srt/conn.go | 4 +- internal/servers/srt/server.go | 4 +- internal/servers/srt/server_test.go | 8 +- internal/servers/webrtc/http_server.go | 2 +- internal/servers/webrtc/server.go | 6 +- internal/servers/webrtc/server_test.go | 30 +++--- internal/staticsources/hls/source.go | 2 +- internal/staticsources/rtmp/source.go | 4 +- internal/staticsources/rtmp/source_test.go | 8 +- internal/staticsources/rtsp/source.go | 4 +- internal/staticsources/rtsp/source_test.go | 16 +-- internal/staticsources/srt/source.go | 2 +- internal/staticsources/srt/source_test.go | 2 +- internal/staticsources/udp/source.go | 2 +- internal/staticsources/udp/source_test.go | 2 +- internal/staticsources/webrtc/source.go | 2 +- internal/staticsources/webrtc/source_test.go | 6 +- mediamtx.yml | 2 +- 53 files changed, 378 insertions(+), 257 deletions(-) create mode 100644 internal/conf/duration.go create mode 100644 internal/conf/duration_test.go delete mode 100644 internal/conf/string_duration.go diff --git a/internal/api/api.go b/internal/api/api.go index 147b69c27b2..2f9dfbfbde6 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -136,7 +136,7 @@ type API struct { ServerCert string AllowOrigin string TrustedProxies conf.IPNetworks - ReadTimeout conf.StringDuration + ReadTimeout conf.Duration Conf *conf.Conf AuthManager apiAuthManager PathManager PathManager diff --git a/internal/api/api_test.go b/internal/api/api_test.go index 481a2662b92..86b41e42e90 100644 --- a/internal/api/api_test.go +++ b/internal/api/api_test.go @@ -77,7 +77,7 @@ func TestPreflightRequest(t *testing.T) { api := API{ Address: "localhost:9997", AllowOrigin: "*", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), AuthManager: test.NilAuthManager, Parent: &testParent{}, } @@ -115,7 +115,7 @@ func TestConfigGlobalGet(t *testing.T) { api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -138,7 +138,7 @@ func TestConfigGlobalPatch(t *testing.T) { api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -174,7 +174,7 @@ func TestConfigGlobalPatchUnknownField(t *testing.T) { //nolint:dupl api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -211,7 +211,7 @@ func TestConfigPathDefaultsGet(t *testing.T) { api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -234,7 +234,7 @@ func TestConfigPathDefaultsPatch(t *testing.T) { api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -271,7 +271,7 @@ func TestConfigPathsList(t *testing.T) { api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -313,7 +313,7 @@ func TestConfigPathsGet(t *testing.T) { api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -337,7 +337,7 @@ func TestConfigPathsAdd(t *testing.T) { api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -371,7 +371,7 @@ func TestConfigPathsAddUnknownField(t *testing.T) { //nolint:dupl api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -408,7 +408,7 @@ func TestConfigPathsPatch(t *testing.T) { //nolint:dupl api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -448,7 +448,7 @@ func TestConfigPathsReplace(t *testing.T) { //nolint:dupl api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -488,7 +488,7 @@ func TestConfigPathsReplaceNonExisting(t *testing.T) { //nolint:dupl api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -520,7 +520,7 @@ func TestConfigPathsDelete(t *testing.T) { api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -565,7 +565,7 @@ func TestRecordingsList(t *testing.T) { api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -634,7 +634,7 @@ func TestRecordingsGet(t *testing.T) { api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, @@ -683,7 +683,7 @@ func TestRecordingsDeleteSegment(t *testing.T) { api := API{ Address: "localhost:9997", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Conf: cnf, AuthManager: test.NilAuthManager, Parent: &testParent{}, diff --git a/internal/conf/conf.go b/internal/conf/conf.go index f2eca4b14f1..bc1e13c2a20 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -161,8 +161,8 @@ type Conf struct { LogLevel LogLevel `json:"logLevel"` LogDestinations LogDestinations `json:"logDestinations"` LogFile string `json:"logFile"` - ReadTimeout StringDuration `json:"readTimeout"` - WriteTimeout StringDuration `json:"writeTimeout"` + ReadTimeout Duration `json:"readTimeout"` + WriteTimeout Duration `json:"writeTimeout"` ReadBufferCount *int `json:"readBufferCount,omitempty"` // deprecated WriteQueueSize int `json:"writeQueueSize"` UDPMaxPayloadSize int `json:"udpMaxPayloadSize"` @@ -246,22 +246,22 @@ type Conf struct { RTMPServerCert string `json:"rtmpServerCert"` // HLS server - HLS bool `json:"hls"` - HLSDisable *bool `json:"hlsDisable,omitempty"` // deprecated - HLSAddress string `json:"hlsAddress"` - HLSEncryption bool `json:"hlsEncryption"` - HLSServerKey string `json:"hlsServerKey"` - HLSServerCert string `json:"hlsServerCert"` - HLSAllowOrigin string `json:"hlsAllowOrigin"` - HLSTrustedProxies IPNetworks `json:"hlsTrustedProxies"` - HLSAlwaysRemux bool `json:"hlsAlwaysRemux"` - HLSVariant HLSVariant `json:"hlsVariant"` - HLSSegmentCount int `json:"hlsSegmentCount"` - HLSSegmentDuration StringDuration `json:"hlsSegmentDuration"` - HLSPartDuration StringDuration `json:"hlsPartDuration"` - HLSSegmentMaxSize StringSize `json:"hlsSegmentMaxSize"` - HLSDirectory string `json:"hlsDirectory"` - HLSMuxerCloseAfter StringDuration `json:"hlsMuxerCloseAfter"` + HLS bool `json:"hls"` + HLSDisable *bool `json:"hlsDisable,omitempty"` // deprecated + HLSAddress string `json:"hlsAddress"` + HLSEncryption bool `json:"hlsEncryption"` + HLSServerKey string `json:"hlsServerKey"` + HLSServerCert string `json:"hlsServerCert"` + HLSAllowOrigin string `json:"hlsAllowOrigin"` + HLSTrustedProxies IPNetworks `json:"hlsTrustedProxies"` + HLSAlwaysRemux bool `json:"hlsAlwaysRemux"` + HLSVariant HLSVariant `json:"hlsVariant"` + HLSSegmentCount int `json:"hlsSegmentCount"` + HLSSegmentDuration Duration `json:"hlsSegmentDuration"` + HLSPartDuration Duration `json:"hlsPartDuration"` + HLSSegmentMaxSize StringSize `json:"hlsSegmentMaxSize"` + HLSDirectory string `json:"hlsDirectory"` + HLSMuxerCloseAfter Duration `json:"hlsMuxerCloseAfter"` // WebRTC server WebRTC bool `json:"webrtc"` @@ -278,8 +278,8 @@ type Conf struct { WebRTCIPsFromInterfacesList []string `json:"webrtcIPsFromInterfacesList"` WebRTCAdditionalHosts []string `json:"webrtcAdditionalHosts"` WebRTCICEServers2 WebRTCICEServers `json:"webrtcICEServers2"` - WebRTCHandshakeTimeout StringDuration `json:"webrtcHandshakeTimeout"` - WebRTCTrackGatherTimeout StringDuration `json:"webrtcTrackGatherTimeout"` + WebRTCHandshakeTimeout Duration `json:"webrtcHandshakeTimeout"` + WebRTCTrackGatherTimeout Duration `json:"webrtcTrackGatherTimeout"` WebRTCICEUDPMuxAddress *string `json:"webrtcICEUDPMuxAddress,omitempty"` // deprecated WebRTCICETCPMuxAddress *string `json:"webrtcICETCPMuxAddress,omitempty"` // deprecated WebRTCICEHostNAT1To1IPs *[]string `json:"webrtcICEHostNAT1To1IPs,omitempty"` // deprecated @@ -290,12 +290,12 @@ type Conf struct { SRTAddress string `json:"srtAddress"` // Record (deprecated) - Record *bool `json:"record,omitempty"` // deprecated - RecordPath *string `json:"recordPath,omitempty"` // deprecated - RecordFormat *RecordFormat `json:"recordFormat,omitempty"` // deprecated - RecordPartDuration *StringDuration `json:"recordPartDuration,omitempty"` // deprecated - RecordSegmentDuration *StringDuration `json:"recordSegmentDuration,omitempty"` // deprecated - RecordDeleteAfter *StringDuration `json:"recordDeleteAfter,omitempty"` // deprecated + Record *bool `json:"record,omitempty"` // deprecated + RecordPath *string `json:"recordPath,omitempty"` // deprecated + RecordFormat *RecordFormat `json:"recordFormat,omitempty"` // deprecated + RecordPartDuration *Duration `json:"recordPartDuration,omitempty"` // deprecated + RecordSegmentDuration *Duration `json:"recordSegmentDuration,omitempty"` // deprecated + RecordDeleteAfter *Duration `json:"recordDeleteAfter,omitempty"` // deprecated // Path defaults PathDefaults Path `json:"pathDefaults"` @@ -310,8 +310,8 @@ func (conf *Conf) setDefaults() { conf.LogLevel = LogLevel(logger.Info) conf.LogDestinations = LogDestinations{logger.DestinationStdout} conf.LogFile = "mediamtx.log" - conf.ReadTimeout = 10 * StringDuration(time.Second) - conf.WriteTimeout = 10 * StringDuration(time.Second) + conf.ReadTimeout = 10 * Duration(time.Second) + conf.WriteTimeout = 10 * Duration(time.Second) conf.WriteQueueSize = 512 conf.UDPMaxPayloadSize = 1472 @@ -387,10 +387,10 @@ func (conf *Conf) setDefaults() { conf.HLSAllowOrigin = "*" conf.HLSVariant = HLSVariant(gohlslib.MuxerVariantLowLatency) conf.HLSSegmentCount = 7 - conf.HLSSegmentDuration = 1 * StringDuration(time.Second) - conf.HLSPartDuration = 200 * StringDuration(time.Millisecond) + conf.HLSSegmentDuration = 1 * Duration(time.Second) + conf.HLSPartDuration = 200 * Duration(time.Millisecond) conf.HLSSegmentMaxSize = 50 * 1024 * 1024 - conf.HLSMuxerCloseAfter = 60 * StringDuration(time.Second) + conf.HLSMuxerCloseAfter = 60 * Duration(time.Second) // WebRTC server conf.WebRTC = true @@ -403,8 +403,8 @@ func (conf *Conf) setDefaults() { conf.WebRTCIPsFromInterfacesList = []string{} conf.WebRTCAdditionalHosts = []string{} conf.WebRTCICEServers2 = []WebRTCICEServer{} - conf.WebRTCHandshakeTimeout = 10 * StringDuration(time.Second) - conf.WebRTCTrackGatherTimeout = 2 * StringDuration(time.Second) + conf.WebRTCHandshakeTimeout = 10 * Duration(time.Second) + conf.WebRTCTrackGatherTimeout = 2 * Duration(time.Second) // SRT server conf.SRT = true diff --git a/internal/conf/conf_test.go b/internal/conf/conf_test.go index 1d71a827720..e2fd9abca5f 100644 --- a/internal/conf/conf_test.go +++ b/internal/conf/conf_test.go @@ -50,11 +50,11 @@ func TestConfFromFile(t *testing.T) { require.Equal(t, &Path{ Name: "cam1", Source: "publisher", - SourceOnDemandStartTimeout: 10 * StringDuration(time.Second), - SourceOnDemandCloseAfter: 10 * StringDuration(time.Second), + SourceOnDemandStartTimeout: 10 * Duration(time.Second), + SourceOnDemandCloseAfter: 10 * Duration(time.Second), RecordPath: "./recordings/%path/%Y-%m-%d_%H-%M-%S-%f", RecordFormat: RecordFormatFMP4, - RecordPartDuration: StringDuration(1 * time.Second), + RecordPartDuration: Duration(1 * time.Second), RecordSegmentDuration: 3600000000000, RecordDeleteAfter: 86400000000000, OverridePublisher: true, @@ -78,8 +78,8 @@ func TestConfFromFile(t *testing.T) { RPICameraBitrate: 5000000, RPICameraProfile: "main", RPICameraLevel: "4.1", - RunOnDemandStartTimeout: 5 * StringDuration(time.Second), - RunOnDemandCloseAfter: 10 * StringDuration(time.Second), + RunOnDemandStartTimeout: 5 * Duration(time.Second), + RunOnDemandCloseAfter: 10 * Duration(time.Second), }, pa) }() diff --git a/internal/conf/duration.go b/internal/conf/duration.go new file mode 100644 index 00000000000..389826352b9 --- /dev/null +++ b/internal/conf/duration.go @@ -0,0 +1,101 @@ +package conf + +import ( + "encoding/json" + "regexp" + "strconv" + "time" +) + +var reDays = regexp.MustCompile("^(-?[0-9]+)d") + +// Duration is a duration. It differs from the standard duration in these ways: +// - it is unmarshaled/marshaled from/to a string (instead of a number) +// - it supports days +type Duration time.Duration + +func (d Duration) marshalInternal() string { + negative := false + if d < 0 { + negative = true + d = -d + } + + day := Duration(86400 * time.Second) + days := d / day + nonDays := d % day + + ret := "" + if negative { + ret += "-" + } + + if days > 0 { + ret += strconv.FormatInt(int64(days), 10) + "d" + } + + if nonDays != 0 { + ret += time.Duration(nonDays).String() + } + + return ret +} + +// MarshalJSON implements json.Marshaler. +func (d Duration) MarshalJSON() ([]byte, error) { + return json.Marshal(d.marshalInternal()) +} + +func (d *Duration) unmarshalInternal(in string) error { + negative := false + days := int64(0) + + m := reDays.FindStringSubmatch(in) + if m != nil { + days, _ = strconv.ParseInt(m[1], 10, 64) + if days < 0 { + negative = true + days = -days + } + + in = in[len(m[0]):] + } + + var nonDays time.Duration + + if len(in) != 0 { + var err error + nonDays, err = time.ParseDuration(in) + if err != nil { + return err + } + } + + nonDays += time.Duration(days) * 24 * time.Hour + if negative { + nonDays = -nonDays + } + + *d = Duration(nonDays) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (d *Duration) UnmarshalJSON(b []byte) error { + var in string + if err := json.Unmarshal(b, &in); err != nil { + return err + } + + err := d.unmarshalInternal(in) + if err != nil { + return err + } + + return nil +} + +// UnmarshalEnv implements env.Unmarshaler. +func (d *Duration) UnmarshalEnv(_ string, v string) error { + return d.UnmarshalJSON([]byte(`"` + v + `"`)) +} diff --git a/internal/conf/duration_test.go b/internal/conf/duration_test.go new file mode 100644 index 00000000000..b8b383d1c8d --- /dev/null +++ b/internal/conf/duration_test.go @@ -0,0 +1,56 @@ +package conf + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +var casesDuration = []struct { + name string + dec Duration + enc string +}{ + { + "standard", + Duration(13456 * time.Second), + `"3h44m16s"`, + }, + { + "days", + Duration(50 * 13456 * time.Second), + `"7d18h53m20s"`, + }, + { + "days negative", + Duration(-50 * 13456 * time.Second), + `"-7d18h53m20s"`, + }, + { + "days even", + Duration(7 * 24 * time.Hour), + `"7d"`, + }, +} + +func TestDurationUnmarshal(t *testing.T) { + for _, ca := range casesDuration { + t.Run(ca.name, func(t *testing.T) { + var dec Duration + err := dec.UnmarshalJSON([]byte(ca.enc)) + require.NoError(t, err) + require.Equal(t, ca.dec, dec) + }) + } +} + +func TestDurationMarshal(t *testing.T) { + for _, ca := range casesDuration { + t.Run(ca.name, func(t *testing.T) { + enc, err := ca.dec.MarshalJSON() + require.NoError(t, err) + require.Equal(t, ca.enc, string(enc)) + }) + } +} diff --git a/internal/conf/path.go b/internal/conf/path.go index 36d4ec3a80c..a83ff64894b 100644 --- a/internal/conf/path.go +++ b/internal/conf/path.go @@ -88,23 +88,23 @@ type Path struct { Name string `json:"name"` // filled by Check() // General - Source string `json:"source"` - SourceFingerprint string `json:"sourceFingerprint"` - SourceOnDemand bool `json:"sourceOnDemand"` - SourceOnDemandStartTimeout StringDuration `json:"sourceOnDemandStartTimeout"` - SourceOnDemandCloseAfter StringDuration `json:"sourceOnDemandCloseAfter"` - MaxReaders int `json:"maxReaders"` - SRTReadPassphrase string `json:"srtReadPassphrase"` - Fallback string `json:"fallback"` + Source string `json:"source"` + SourceFingerprint string `json:"sourceFingerprint"` + SourceOnDemand bool `json:"sourceOnDemand"` + SourceOnDemandStartTimeout Duration `json:"sourceOnDemandStartTimeout"` + SourceOnDemandCloseAfter Duration `json:"sourceOnDemandCloseAfter"` + MaxReaders int `json:"maxReaders"` + SRTReadPassphrase string `json:"srtReadPassphrase"` + Fallback string `json:"fallback"` // Record - Record bool `json:"record"` - Playback *bool `json:"playback,omitempty"` // deprecated - RecordPath string `json:"recordPath"` - RecordFormat RecordFormat `json:"recordFormat"` - RecordPartDuration StringDuration `json:"recordPartDuration"` - RecordSegmentDuration StringDuration `json:"recordSegmentDuration"` - RecordDeleteAfter StringDuration `json:"recordDeleteAfter"` + Record bool `json:"record"` + Playback *bool `json:"playback,omitempty"` // deprecated + RecordPath string `json:"recordPath"` + RecordFormat RecordFormat `json:"recordFormat"` + RecordPartDuration Duration `json:"recordPartDuration"` + RecordSegmentDuration Duration `json:"recordSegmentDuration"` + RecordDeleteAfter Duration `json:"recordDeleteAfter"` // Authentication (deprecated) PublishUser *Credential `json:"publishUser,omitempty"` // deprecated @@ -168,35 +168,35 @@ type Path struct { RPICameraLevel string `json:"rpiCameraLevel"` // Hooks - RunOnInit string `json:"runOnInit"` - RunOnInitRestart bool `json:"runOnInitRestart"` - RunOnDemand string `json:"runOnDemand"` - RunOnDemandRestart bool `json:"runOnDemandRestart"` - RunOnDemandStartTimeout StringDuration `json:"runOnDemandStartTimeout"` - RunOnDemandCloseAfter StringDuration `json:"runOnDemandCloseAfter"` - RunOnUnDemand string `json:"runOnUnDemand"` - RunOnReady string `json:"runOnReady"` - RunOnReadyRestart bool `json:"runOnReadyRestart"` - RunOnNotReady string `json:"runOnNotReady"` - RunOnRead string `json:"runOnRead"` - RunOnReadRestart bool `json:"runOnReadRestart"` - RunOnUnread string `json:"runOnUnread"` - RunOnRecordSegmentCreate string `json:"runOnRecordSegmentCreate"` - RunOnRecordSegmentComplete string `json:"runOnRecordSegmentComplete"` + RunOnInit string `json:"runOnInit"` + RunOnInitRestart bool `json:"runOnInitRestart"` + RunOnDemand string `json:"runOnDemand"` + RunOnDemandRestart bool `json:"runOnDemandRestart"` + RunOnDemandStartTimeout Duration `json:"runOnDemandStartTimeout"` + RunOnDemandCloseAfter Duration `json:"runOnDemandCloseAfter"` + RunOnUnDemand string `json:"runOnUnDemand"` + RunOnReady string `json:"runOnReady"` + RunOnReadyRestart bool `json:"runOnReadyRestart"` + RunOnNotReady string `json:"runOnNotReady"` + RunOnRead string `json:"runOnRead"` + RunOnReadRestart bool `json:"runOnReadRestart"` + RunOnUnread string `json:"runOnUnread"` + RunOnRecordSegmentCreate string `json:"runOnRecordSegmentCreate"` + RunOnRecordSegmentComplete string `json:"runOnRecordSegmentComplete"` } func (pconf *Path) setDefaults() { // General pconf.Source = "publisher" - pconf.SourceOnDemandStartTimeout = 10 * StringDuration(time.Second) - pconf.SourceOnDemandCloseAfter = 10 * StringDuration(time.Second) + pconf.SourceOnDemandStartTimeout = 10 * Duration(time.Second) + pconf.SourceOnDemandCloseAfter = 10 * Duration(time.Second) // Record pconf.RecordPath = "./recordings/%path/%Y-%m-%d_%H-%M-%S-%f" pconf.RecordFormat = RecordFormatFMP4 - pconf.RecordPartDuration = StringDuration(1 * time.Second) - pconf.RecordSegmentDuration = 3600 * StringDuration(time.Second) - pconf.RecordDeleteAfter = 24 * 3600 * StringDuration(time.Second) + pconf.RecordPartDuration = Duration(1 * time.Second) + pconf.RecordSegmentDuration = 3600 * Duration(time.Second) + pconf.RecordDeleteAfter = 24 * 3600 * Duration(time.Second) // Publisher source pconf.OverridePublisher = true @@ -224,8 +224,8 @@ func (pconf *Path) setDefaults() { pconf.RPICameraLevel = "4.1" // Hooks - pconf.RunOnDemandStartTimeout = 10 * StringDuration(time.Second) - pconf.RunOnDemandCloseAfter = 10 * StringDuration(time.Second) + pconf.RunOnDemandStartTimeout = 10 * Duration(time.Second) + pconf.RunOnDemandCloseAfter = 10 * Duration(time.Second) } func newPath(defaults *Path, partial *OptionalPath) *Path { diff --git a/internal/conf/string_duration.go b/internal/conf/string_duration.go deleted file mode 100644 index 57e6dbaae40..00000000000 --- a/internal/conf/string_duration.go +++ /dev/null @@ -1,36 +0,0 @@ -package conf - -import ( - "encoding/json" - "time" -) - -// StringDuration is a duration that is unmarshaled from a string. -// Durations are normally unmarshaled from numbers. -type StringDuration time.Duration - -// MarshalJSON implements json.Marshaler. -func (d StringDuration) MarshalJSON() ([]byte, error) { - return json.Marshal(time.Duration(d).String()) -} - -// UnmarshalJSON implements json.Unmarshaler. -func (d *StringDuration) UnmarshalJSON(b []byte) error { - var in string - if err := json.Unmarshal(b, &in); err != nil { - return err - } - - du, err := time.ParseDuration(in) - if err != nil { - return err - } - *d = StringDuration(du) - - return nil -} - -// UnmarshalEnv implements env.Unmarshaler. -func (d *StringDuration) UnmarshalEnv(_ string, v string) error { - return d.UnmarshalJSON([]byte(`"` + v + `"`)) -} diff --git a/internal/core/path.go b/internal/core/path.go index 4eeae3a4a15..b214be66748 100644 --- a/internal/core/path.go +++ b/internal/core/path.go @@ -67,8 +67,8 @@ type path struct { parentCtx context.Context logLevel conf.LogLevel rtspAddress string - readTimeout conf.StringDuration - writeTimeout conf.StringDuration + readTimeout conf.Duration + writeTimeout conf.Duration writeQueueSize int udpMaxPayloadSize int conf *conf.Path diff --git a/internal/core/path_manager.go b/internal/core/path_manager.go index a3495864f3a..bbd1bb7b0a3 100644 --- a/internal/core/path_manager.go +++ b/internal/core/path_manager.go @@ -52,8 +52,8 @@ type pathManager struct { logLevel conf.LogLevel authManager *auth.Manager rtspAddress string - readTimeout conf.StringDuration - writeTimeout conf.StringDuration + readTimeout conf.Duration + writeTimeout conf.Duration writeQueueSize int udpMaxPayloadSize int pathConfs map[string]*conf.Path diff --git a/internal/core/static_source_handler.go b/internal/core/static_source_handler.go index adec4f5b789..395da818a38 100644 --- a/internal/core/static_source_handler.go +++ b/internal/core/static_source_handler.go @@ -45,8 +45,8 @@ type staticSourceHandlerParent interface { type staticSourceHandler struct { conf *conf.Path logLevel conf.LogLevel - readTimeout conf.StringDuration - writeTimeout conf.StringDuration + readTimeout conf.Duration + writeTimeout conf.Duration writeQueueSize int matches []string parent staticSourceHandlerParent diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index 2177ae41065..1c0110db798 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -48,7 +48,7 @@ type Metrics struct { ServerCert string AllowOrigin string TrustedProxies conf.IPNetworks - ReadTimeout conf.StringDuration + ReadTimeout conf.Duration AuthManager metricsAuthManager Parent metricsParent diff --git a/internal/metrics/metrics_test.go b/internal/metrics/metrics_test.go index 7bd3099d980..ef5611e16c2 100644 --- a/internal/metrics/metrics_test.go +++ b/internal/metrics/metrics_test.go @@ -15,7 +15,7 @@ func TestPreflightRequest(t *testing.T) { api := Metrics{ Address: "localhost:9998", AllowOrigin: "*", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), AuthManager: test.NilAuthManager, Parent: test.NilLogger, } diff --git a/internal/playback/on_get_test.go b/internal/playback/on_get_test.go index 38a39797bdb..09196652b95 100644 --- a/internal/playback/on_get_test.go +++ b/internal/playback/on_get_test.go @@ -231,7 +231,7 @@ func TestOnGet(t *testing.T) { s := &Server{ Address: "127.0.0.1:9996", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), PathConfs: map[string]*conf.Path{ "mypath": { Name: "mypath", @@ -505,7 +505,7 @@ func TestOnGetDifferentInit(t *testing.T) { s := &Server{ Address: "127.0.0.1:9996", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), PathConfs: map[string]*conf.Path{ "mypath": { Name: "mypath", @@ -581,7 +581,7 @@ func TestOnGetNTPCompensation(t *testing.T) { s := &Server{ Address: "127.0.0.1:9996", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), PathConfs: map[string]*conf.Path{ "mypath": { Name: "mypath", diff --git a/internal/playback/on_list_test.go b/internal/playback/on_list_test.go index 006b676adf7..9cabc935b49 100644 --- a/internal/playback/on_list_test.go +++ b/internal/playback/on_list_test.go @@ -28,7 +28,7 @@ func TestOnListUnfiltered(t *testing.T) { s := &Server{ Address: "127.0.0.1:9996", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), PathConfs: map[string]*conf.Path{ "mypath": { Name: "mypath", @@ -157,7 +157,7 @@ func TestOnListDifferentInit(t *testing.T) { s := &Server{ Address: "127.0.0.1:9996", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), PathConfs: map[string]*conf.Path{ "mypath": { Name: "mypath", diff --git a/internal/playback/server.go b/internal/playback/server.go index a5c7f22615c..7874e49d40c 100644 --- a/internal/playback/server.go +++ b/internal/playback/server.go @@ -27,7 +27,7 @@ type Server struct { ServerCert string AllowOrigin string TrustedProxies conf.IPNetworks - ReadTimeout conf.StringDuration + ReadTimeout conf.Duration PathConfs map[string]*conf.Path AuthManager serverAuthManager Parent logger.Writer diff --git a/internal/playback/server_test.go b/internal/playback/server_test.go index 9fb905c657e..5c03a4c32ba 100644 --- a/internal/playback/server_test.go +++ b/internal/playback/server_test.go @@ -15,7 +15,7 @@ func TestPreflightRequest(t *testing.T) { s := &Server{ Address: "127.0.0.1:9996", AllowOrigin: "*", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Parent: test.NilLogger, } err := s.Initialize() diff --git a/internal/pprof/pprof.go b/internal/pprof/pprof.go index 6575778974f..1cd93b570c7 100644 --- a/internal/pprof/pprof.go +++ b/internal/pprof/pprof.go @@ -32,7 +32,7 @@ type PPROF struct { ServerCert string AllowOrigin string TrustedProxies conf.IPNetworks - ReadTimeout conf.StringDuration + ReadTimeout conf.Duration AuthManager pprofAuthManager Parent pprofParent diff --git a/internal/pprof/pprof_test.go b/internal/pprof/pprof_test.go index 16cb16f43d4..05817be166a 100644 --- a/internal/pprof/pprof_test.go +++ b/internal/pprof/pprof_test.go @@ -15,7 +15,7 @@ func TestPreflightRequest(t *testing.T) { s := &PPROF{ Address: "127.0.0.1:9999", AllowOrigin: "*", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Parent: test.NilLogger, } err := s.Initialize() @@ -51,7 +51,7 @@ func TestPprof(t *testing.T) { s := &PPROF{ Address: "127.0.0.1:9999", AllowOrigin: "*", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), AuthManager: test.NilAuthManager, Parent: test.NilLogger, } diff --git a/internal/protocols/webrtc/peer_connection.go b/internal/protocols/webrtc/peer_connection.go index 6ac441e4b0d..afe3c85f1bc 100644 --- a/internal/protocols/webrtc/peer_connection.go +++ b/internal/protocols/webrtc/peer_connection.go @@ -72,8 +72,8 @@ type PeerConnection struct { ICEServers []webrtc.ICEServer ICEUDPMux ice.UDPMux ICETCPMux ice.TCPMux - HandshakeTimeout conf.StringDuration - TrackGatherTimeout conf.StringDuration + HandshakeTimeout conf.Duration + TrackGatherTimeout conf.Duration LocalRandomUDP bool IPsFromInterfaces bool IPsFromInterfacesList []string diff --git a/internal/protocols/webrtc/peer_connection_test.go b/internal/protocols/webrtc/peer_connection_test.go index 72b5a084570..e43397f16c0 100644 --- a/internal/protocols/webrtc/peer_connection_test.go +++ b/internal/protocols/webrtc/peer_connection_test.go @@ -14,8 +14,8 @@ import ( func TestPeerConnectionCloseImmediately(t *testing.T) { pc := &PeerConnection{ - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), LocalRandomUDP: true, IPsFromInterfaces: true, Publish: false, @@ -37,8 +37,8 @@ func TestPeerConnectionCloseImmediately(t *testing.T) { // test that an audio codec is present regardless of the fact that an audio track is. func TestPeerConnectionFallbackCodecs(t *testing.T) { pc1 := &PeerConnection{ - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), LocalRandomUDP: true, IPsFromInterfaces: true, Publish: false, @@ -49,8 +49,8 @@ func TestPeerConnectionFallbackCodecs(t *testing.T) { defer pc1.Close() pc2 := &PeerConnection{ - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), LocalRandomUDP: true, IPsFromInterfaces: true, Publish: true, diff --git a/internal/protocols/webrtc/to_stream_test.go b/internal/protocols/webrtc/to_stream_test.go index 6a7c0e4b4c4..56f484c3d5d 100644 --- a/internal/protocols/webrtc/to_stream_test.go +++ b/internal/protocols/webrtc/to_stream_test.go @@ -336,8 +336,8 @@ func TestToStream(t *testing.T) { for _, ca := range toFromStreamCases { t.Run(ca.name, func(t *testing.T) { pc1 := &PeerConnection{ - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), LocalRandomUDP: true, IPsFromInterfaces: true, Publish: true, @@ -351,8 +351,8 @@ func TestToStream(t *testing.T) { defer pc1.Close() pc2 := &PeerConnection{ - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), LocalRandomUDP: true, IPsFromInterfaces: true, Publish: false, diff --git a/internal/protocols/whip/client.go b/internal/protocols/whip/client.go index 824e88dcde9..80ccbd4260f 100644 --- a/internal/protocols/whip/client.go +++ b/internal/protocols/whip/client.go @@ -46,8 +46,8 @@ func (c *Client) Publish( c.pc = &webrtc.PeerConnection{ ICEServers: iceServers, - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), LocalRandomUDP: true, IPsFromInterfaces: true, Publish: true, @@ -122,8 +122,8 @@ func (c *Client) Read(ctx context.Context) ([]*webrtc.IncomingTrack, error) { c.pc = &webrtc.PeerConnection{ ICEServers: iceServers, - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), LocalRandomUDP: true, IPsFromInterfaces: true, Publish: false, diff --git a/internal/recordcleaner/cleaner_test.go b/internal/recordcleaner/cleaner_test.go index fd5e4ac0adc..ac9ece6dc6f 100644 --- a/internal/recordcleaner/cleaner_test.go +++ b/internal/recordcleaner/cleaner_test.go @@ -39,7 +39,7 @@ func TestCleaner(t *testing.T) { Regexp: regexp.MustCompile("^.*$"), RecordPath: filepath.Join(dir, specialChars+"_%path/%Y-%m-%d_%H-%M-%S-%f"), RecordFormat: conf.RecordFormatFMP4, - RecordDeleteAfter: conf.StringDuration(10 * time.Second), + RecordDeleteAfter: conf.Duration(10 * time.Second), }, }, Parent: test.NilLogger, @@ -83,13 +83,13 @@ func TestCleanerMultipleEntriesSamePath(t *testing.T) { Name: "path1", RecordPath: filepath.Join(dir, "%path/%Y-%m-%d_%H-%M-%S-%f"), RecordFormat: conf.RecordFormatFMP4, - RecordDeleteAfter: conf.StringDuration(10 * time.Second), + RecordDeleteAfter: conf.Duration(10 * time.Second), }, "path2": { Name: "path2", RecordPath: filepath.Join(dir, "%path/%Y-%m-%d_%H-%M-%S-%f"), RecordFormat: conf.RecordFormatFMP4, - RecordDeleteAfter: conf.StringDuration(10 * 24 * time.Hour), + RecordDeleteAfter: conf.Duration(10 * 24 * time.Hour), }, }, Parent: test.NilLogger, diff --git a/internal/servers/hls/http_server.go b/internal/servers/hls/http_server.go index a73d79ffbc5..df122a1e317 100644 --- a/internal/servers/hls/http_server.go +++ b/internal/servers/hls/http_server.go @@ -42,7 +42,7 @@ type httpServer struct { serverCert string allowOrigin string trustedProxies conf.IPNetworks - readTimeout conf.StringDuration + readTimeout conf.Duration pathManager serverPathManager parent *Server diff --git a/internal/servers/hls/muxer.go b/internal/servers/hls/muxer.go index c445321b412..5614843e702 100644 --- a/internal/servers/hls/muxer.go +++ b/internal/servers/hls/muxer.go @@ -50,11 +50,11 @@ type muxer struct { remoteAddr string variant conf.HLSVariant segmentCount int - segmentDuration conf.StringDuration - partDuration conf.StringDuration + segmentDuration conf.Duration + partDuration conf.Duration segmentMaxSize conf.StringSize directory string - closeAfter conf.StringDuration + closeAfter conf.Duration wg *sync.WaitGroup pathName string pathManager serverPathManager diff --git a/internal/servers/hls/muxer_instance.go b/internal/servers/hls/muxer_instance.go index b37d207a313..14f8f057f9f 100644 --- a/internal/servers/hls/muxer_instance.go +++ b/internal/servers/hls/muxer_instance.go @@ -17,8 +17,8 @@ import ( type muxerInstance struct { variant conf.HLSVariant segmentCount int - segmentDuration conf.StringDuration - partDuration conf.StringDuration + segmentDuration conf.Duration + partDuration conf.Duration segmentMaxSize conf.StringSize directory string pathName string diff --git a/internal/servers/hls/server.go b/internal/servers/hls/server.go index 7b6e530085c..5f81413c404 100644 --- a/internal/servers/hls/server.go +++ b/internal/servers/hls/server.go @@ -69,12 +69,12 @@ type Server struct { AlwaysRemux bool Variant conf.HLSVariant SegmentCount int - SegmentDuration conf.StringDuration - PartDuration conf.StringDuration + SegmentDuration conf.Duration + PartDuration conf.Duration SegmentMaxSize conf.StringSize Directory string - ReadTimeout conf.StringDuration - MuxerCloseAfter conf.StringDuration + ReadTimeout conf.Duration + MuxerCloseAfter conf.Duration PathManager serverPathManager Parent serverParent diff --git a/internal/servers/hls/server_test.go b/internal/servers/hls/server_test.go index 4d19dd26e20..70ee9331040 100644 --- a/internal/servers/hls/server_test.go +++ b/internal/servers/hls/server_test.go @@ -65,7 +65,7 @@ func TestPreflightRequest(t *testing.T) { s := &Server{ Address: "127.0.0.1:8888", AllowOrigin: "*", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Parent: test.NilLogger, } err := s.Initialize() @@ -122,13 +122,13 @@ func TestServerNotFound(t *testing.T) { AlwaysRemux: ca == "always remux on", Variant: conf.HLSVariant(gohlslib.MuxerVariantMPEGTS), SegmentCount: 7, - SegmentDuration: conf.StringDuration(1 * time.Second), - PartDuration: conf.StringDuration(200 * time.Millisecond), + SegmentDuration: conf.Duration(1 * time.Second), + PartDuration: conf.Duration(200 * time.Millisecond), SegmentMaxSize: 50 * 1024 * 1024, AllowOrigin: "", TrustedProxies: conf.IPNetworks{}, Directory: "", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), PathManager: pm, Parent: test.NilLogger, } @@ -195,13 +195,13 @@ func TestServerRead(t *testing.T) { AlwaysRemux: false, Variant: conf.HLSVariant(gohlslib.MuxerVariantMPEGTS), SegmentCount: 7, - SegmentDuration: conf.StringDuration(1 * time.Second), - PartDuration: conf.StringDuration(200 * time.Millisecond), + SegmentDuration: conf.Duration(1 * time.Second), + PartDuration: conf.Duration(200 * time.Millisecond), SegmentMaxSize: 50 * 1024 * 1024, AllowOrigin: "", TrustedProxies: conf.IPNetworks{}, Directory: "", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), PathManager: pm, Parent: test.NilLogger, } @@ -290,13 +290,13 @@ func TestServerRead(t *testing.T) { AlwaysRemux: true, Variant: conf.HLSVariant(gohlslib.MuxerVariantMPEGTS), SegmentCount: 7, - SegmentDuration: conf.StringDuration(1 * time.Second), - PartDuration: conf.StringDuration(200 * time.Millisecond), + SegmentDuration: conf.Duration(1 * time.Second), + PartDuration: conf.Duration(200 * time.Millisecond), SegmentMaxSize: 50 * 1024 * 1024, AllowOrigin: "", TrustedProxies: conf.IPNetworks{}, Directory: "", - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), PathManager: pm, Parent: test.NilLogger, } @@ -385,13 +385,13 @@ func TestDirectory(t *testing.T) { AlwaysRemux: true, Variant: conf.HLSVariant(gohlslib.MuxerVariantMPEGTS), SegmentCount: 7, - SegmentDuration: conf.StringDuration(1 * time.Second), - PartDuration: conf.StringDuration(200 * time.Millisecond), + SegmentDuration: conf.Duration(1 * time.Second), + PartDuration: conf.Duration(200 * time.Millisecond), SegmentMaxSize: 50 * 1024 * 1024, AllowOrigin: "", TrustedProxies: conf.IPNetworks{}, Directory: filepath.Join(dir, "mydir"), - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), PathManager: pm, Parent: test.NilLogger, } diff --git a/internal/servers/rtmp/conn.go b/internal/servers/rtmp/conn.go index 310bddcb0d9..4295f8ac684 100644 --- a/internal/servers/rtmp/conn.go +++ b/internal/servers/rtmp/conn.go @@ -42,8 +42,8 @@ type conn struct { parentCtx context.Context isTLS bool rtspAddress string - readTimeout conf.StringDuration - writeTimeout conf.StringDuration + readTimeout conf.Duration + writeTimeout conf.Duration runOnConnect string runOnConnectRestart bool runOnDisconnect string diff --git a/internal/servers/rtmp/server.go b/internal/servers/rtmp/server.go index 8d954bcbd10..86edfe53226 100644 --- a/internal/servers/rtmp/server.go +++ b/internal/servers/rtmp/server.go @@ -64,8 +64,8 @@ type serverParent interface { // Server is a RTMP server. type Server struct { Address string - ReadTimeout conf.StringDuration - WriteTimeout conf.StringDuration + ReadTimeout conf.Duration + WriteTimeout conf.Duration IsTLS bool ServerCert string ServerKey string diff --git a/internal/servers/rtmp/server_test.go b/internal/servers/rtmp/server_test.go index 32623bc4918..c98429ea43a 100644 --- a/internal/servers/rtmp/server_test.go +++ b/internal/servers/rtmp/server_test.go @@ -109,8 +109,8 @@ func TestServerPublish(t *testing.T) { s := &Server{ Address: "127.0.0.1:1935", - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), IsTLS: encrypt == "tls", ServerCert: serverCertFpath, ServerKey: serverKeyFpath, @@ -220,8 +220,8 @@ func TestServerRead(t *testing.T) { s := &Server{ Address: "127.0.0.1:1935", - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), IsTLS: encrypt == "tls", ServerCert: serverCertFpath, ServerKey: serverKeyFpath, diff --git a/internal/servers/rtsp/conn.go b/internal/servers/rtsp/conn.go index 216083dd4ad..675208f35df 100644 --- a/internal/servers/rtsp/conn.go +++ b/internal/servers/rtsp/conn.go @@ -32,7 +32,7 @@ type conn struct { isTLS bool rtspAddress string authMethods []rtspauth.ValidateMethod - readTimeout conf.StringDuration + readTimeout conf.Duration runOnConnect string runOnConnectRestart bool runOnDisconnect string diff --git a/internal/servers/rtsp/server.go b/internal/servers/rtsp/server.go index d8b81558ab7..c3482ec3cd2 100644 --- a/internal/servers/rtsp/server.go +++ b/internal/servers/rtsp/server.go @@ -61,8 +61,8 @@ type serverParent interface { type Server struct { Address string AuthMethods []auth.ValidateMethod - ReadTimeout conf.StringDuration - WriteTimeout conf.StringDuration + ReadTimeout conf.Duration + WriteTimeout conf.Duration WriteQueueSize int UseUDP bool UseMulticast bool diff --git a/internal/servers/rtsp/server_test.go b/internal/servers/rtsp/server_test.go index 8348beeb2ae..c594776a695 100644 --- a/internal/servers/rtsp/server_test.go +++ b/internal/servers/rtsp/server_test.go @@ -94,8 +94,8 @@ func TestServerPublish(t *testing.T) { s := &Server{ Address: "127.0.0.1:8557", AuthMethods: []auth.ValidateMethod{auth.ValidateMethodBasic}, - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), WriteQueueSize: 512, UseUDP: false, UseMulticast: false, @@ -188,8 +188,8 @@ func TestServerRead(t *testing.T) { s := &Server{ Address: "127.0.0.1:8557", AuthMethods: []auth.ValidateMethod{auth.ValidateMethodBasic}, - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), WriteQueueSize: 512, UseUDP: false, UseMulticast: false, diff --git a/internal/servers/srt/conn.go b/internal/servers/srt/conn.go index bc665e5b06a..9e169e91963 100644 --- a/internal/servers/srt/conn.go +++ b/internal/servers/srt/conn.go @@ -51,8 +51,8 @@ const ( type conn struct { parentCtx context.Context rtspAddress string - readTimeout conf.StringDuration - writeTimeout conf.StringDuration + readTimeout conf.Duration + writeTimeout conf.Duration udpMaxPayloadSize int connReq srt.ConnRequest runOnConnect string diff --git a/internal/servers/srt/server.go b/internal/servers/srt/server.go index e5a2e6b5cc3..8bc6bbe4910 100644 --- a/internal/servers/srt/server.go +++ b/internal/servers/srt/server.go @@ -67,8 +67,8 @@ type serverParent interface { type Server struct { Address string RTSPAddress string - ReadTimeout conf.StringDuration - WriteTimeout conf.StringDuration + ReadTimeout conf.Duration + WriteTimeout conf.Duration UDPMaxPayloadSize int RunOnConnect string RunOnConnectRestart bool diff --git a/internal/servers/srt/server_test.go b/internal/servers/srt/server_test.go index 04c40561796..5e05cb14a56 100644 --- a/internal/servers/srt/server_test.go +++ b/internal/servers/srt/server_test.go @@ -91,8 +91,8 @@ func TestServerPublish(t *testing.T) { s := &Server{ Address: "127.0.0.1:8890", RTSPAddress: "", - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), UDPMaxPayloadSize: 1472, RunOnConnect: "", RunOnConnectRestart: false, @@ -192,8 +192,8 @@ func TestServerRead(t *testing.T) { s := &Server{ Address: "127.0.0.1:8890", RTSPAddress: "", - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), UDPMaxPayloadSize: 1472, RunOnConnect: "", RunOnConnectRestart: false, diff --git a/internal/servers/webrtc/http_server.go b/internal/servers/webrtc/http_server.go index c4258e78877..e2bac5f3639 100644 --- a/internal/servers/webrtc/http_server.go +++ b/internal/servers/webrtc/http_server.go @@ -79,7 +79,7 @@ type httpServer struct { serverCert string allowOrigin string trustedProxies conf.IPNetworks - readTimeout conf.StringDuration + readTimeout conf.Duration pathManager serverPathManager parent *Server diff --git a/internal/servers/webrtc/server.go b/internal/servers/webrtc/server.go index 5d0fd0f5663..cd829487281 100644 --- a/internal/servers/webrtc/server.go +++ b/internal/servers/webrtc/server.go @@ -181,15 +181,15 @@ type Server struct { ServerCert string AllowOrigin string TrustedProxies conf.IPNetworks - ReadTimeout conf.StringDuration + ReadTimeout conf.Duration LocalUDPAddress string LocalTCPAddress string IPsFromInterfaces bool IPsFromInterfacesList []string AdditionalHosts []string ICEServers []conf.WebRTCICEServer - HandshakeTimeout conf.StringDuration - TrackGatherTimeout conf.StringDuration + HandshakeTimeout conf.Duration + TrackGatherTimeout conf.Duration ExternalCmdPool *externalcmd.Pool PathManager serverPathManager Parent serverParent diff --git a/internal/servers/webrtc/server_test.go b/internal/servers/webrtc/server_test.go index 4da99c46104..03d03f829af 100644 --- a/internal/servers/webrtc/server_test.go +++ b/internal/servers/webrtc/server_test.go @@ -108,15 +108,15 @@ func initializeTestServer(t *testing.T) *Server { ServerCert: "", AllowOrigin: "*", TrustedProxies: conf.IPNetworks{}, - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), LocalUDPAddress: "127.0.0.1:8887", LocalTCPAddress: "127.0.0.1:8887", IPsFromInterfaces: true, IPsFromInterfacesList: []string{}, AdditionalHosts: []string{}, ICEServers: []conf.WebRTCICEServer{}, - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), ExternalCmdPool: nil, PathManager: pm, Parent: test.NilLogger, @@ -192,7 +192,7 @@ func TestServerOptionsICEServer(t *testing.T) { ServerCert: "", AllowOrigin: "", TrustedProxies: conf.IPNetworks{}, - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), LocalUDPAddress: "127.0.0.1:8887", LocalTCPAddress: "127.0.0.1:8887", IPsFromInterfaces: true, @@ -203,8 +203,8 @@ func TestServerOptionsICEServer(t *testing.T) { Username: "myuser", Password: "mypass", }}, - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), ExternalCmdPool: nil, PathManager: pathManager, Parent: test.NilLogger, @@ -260,15 +260,15 @@ func TestServerPublish(t *testing.T) { ServerCert: "", AllowOrigin: "", TrustedProxies: conf.IPNetworks{}, - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), LocalUDPAddress: "127.0.0.1:8887", LocalTCPAddress: "127.0.0.1:8887", IPsFromInterfaces: true, IPsFromInterfacesList: []string{}, AdditionalHosts: []string{}, ICEServers: []conf.WebRTCICEServer{}, - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), ExternalCmdPool: nil, PathManager: pathManager, Parent: test.NilLogger, @@ -541,15 +541,15 @@ func TestServerRead(t *testing.T) { ServerCert: "", AllowOrigin: "", TrustedProxies: conf.IPNetworks{}, - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), LocalUDPAddress: "127.0.0.1:8887", LocalTCPAddress: "127.0.0.1:8887", IPsFromInterfaces: true, IPsFromInterfacesList: []string{}, AdditionalHosts: []string{}, ICEServers: []conf.WebRTCICEServer{}, - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), ExternalCmdPool: nil, PathManager: pathManager, Parent: test.NilLogger, @@ -629,15 +629,15 @@ func TestServerReadNotFound(t *testing.T) { ServerCert: "", AllowOrigin: "", TrustedProxies: conf.IPNetworks{}, - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), LocalUDPAddress: "127.0.0.1:8887", LocalTCPAddress: "127.0.0.1:8887", IPsFromInterfaces: true, IPsFromInterfacesList: []string{}, AdditionalHosts: []string{}, ICEServers: []conf.WebRTCICEServer{}, - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), ExternalCmdPool: nil, PathManager: pm, Parent: test.NilLogger, diff --git a/internal/staticsources/hls/source.go b/internal/staticsources/hls/source.go index da6765d233e..54da37a6827 100644 --- a/internal/staticsources/hls/source.go +++ b/internal/staticsources/hls/source.go @@ -18,7 +18,7 @@ import ( // Source is a HLS static source. type Source struct { - ReadTimeout conf.StringDuration + ReadTimeout conf.Duration Parent defs.StaticSourceParent } diff --git a/internal/staticsources/rtmp/source.go b/internal/staticsources/rtmp/source.go index 900308b49d1..2a1de34cc2b 100644 --- a/internal/staticsources/rtmp/source.go +++ b/internal/staticsources/rtmp/source.go @@ -21,8 +21,8 @@ import ( // Source is a RTMP static source. type Source struct { - ReadTimeout conf.StringDuration - WriteTimeout conf.StringDuration + ReadTimeout conf.Duration + WriteTimeout conf.Duration Parent defs.StaticSourceParent } diff --git a/internal/staticsources/rtmp/source_test.go b/internal/staticsources/rtmp/source_test.go index 7e749238597..15ccbcb8792 100644 --- a/internal/staticsources/rtmp/source_test.go +++ b/internal/staticsources/rtmp/source_test.go @@ -67,8 +67,8 @@ func TestSource(t *testing.T) { te = test.NewSourceTester( func(p defs.StaticSourceParent) defs.StaticSource { return &Source{ - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), Parent: p, } }, @@ -79,8 +79,8 @@ func TestSource(t *testing.T) { te = test.NewSourceTester( func(p defs.StaticSourceParent) defs.StaticSource { return &Source{ - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), Parent: p, } }, diff --git a/internal/staticsources/rtsp/source.go b/internal/staticsources/rtsp/source.go index 1c161bb61a0..545343a0d9e 100644 --- a/internal/staticsources/rtsp/source.go +++ b/internal/staticsources/rtsp/source.go @@ -62,8 +62,8 @@ func createRangeHeader(cnf *conf.Path) (*headers.Range, error) { // Source is a RTSP static source. type Source struct { - ReadTimeout conf.StringDuration - WriteTimeout conf.StringDuration + ReadTimeout conf.Duration + WriteTimeout conf.Duration WriteQueueSize int Parent defs.StaticSourceParent } diff --git a/internal/staticsources/rtsp/source_test.go b/internal/staticsources/rtsp/source_test.go index 10494e28ac2..b3b4a971b57 100644 --- a/internal/staticsources/rtsp/source_test.go +++ b/internal/staticsources/rtsp/source_test.go @@ -138,8 +138,8 @@ func TestSource(t *testing.T) { te = test.NewSourceTester( func(p defs.StaticSourceParent) defs.StaticSource { return &Source{ - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), WriteQueueSize: 2048, Parent: p, } @@ -153,8 +153,8 @@ func TestSource(t *testing.T) { te = test.NewSourceTester( func(p defs.StaticSourceParent) defs.StaticSource { return &Source{ - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), WriteQueueSize: 2048, Parent: p, } @@ -241,8 +241,8 @@ func TestRTSPSourceNoPassword(t *testing.T) { te := test.NewSourceTester( func(p defs.StaticSourceParent) defs.StaticSource { return &Source{ - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), WriteQueueSize: 2048, Parent: p, } @@ -338,8 +338,8 @@ func TestRTSPSourceRange(t *testing.T) { te := test.NewSourceTester( func(p defs.StaticSourceParent) defs.StaticSource { return &Source{ - ReadTimeout: conf.StringDuration(10 * time.Second), - WriteTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), WriteQueueSize: 2048, Parent: p, } diff --git a/internal/staticsources/srt/source.go b/internal/staticsources/srt/source.go index 1c6c6faf15c..6458619baf1 100644 --- a/internal/staticsources/srt/source.go +++ b/internal/staticsources/srt/source.go @@ -17,7 +17,7 @@ import ( // Source is a SRT static source. type Source struct { - ReadTimeout conf.StringDuration + ReadTimeout conf.Duration Parent defs.StaticSourceParent } diff --git a/internal/staticsources/srt/source_test.go b/internal/staticsources/srt/source_test.go index 230aeeb3469..0f43d3385e1 100644 --- a/internal/staticsources/srt/source_test.go +++ b/internal/staticsources/srt/source_test.go @@ -54,7 +54,7 @@ func TestSource(t *testing.T) { te := test.NewSourceTester( func(p defs.StaticSourceParent) defs.StaticSource { return &Source{ - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Parent: p, } }, diff --git a/internal/staticsources/udp/source.go b/internal/staticsources/udp/source.go index 2a7aa32308f..88f0d4a3fa8 100644 --- a/internal/staticsources/udp/source.go +++ b/internal/staticsources/udp/source.go @@ -45,7 +45,7 @@ type packetConn interface { // Source is a UDP static source. type Source struct { - ReadTimeout conf.StringDuration + ReadTimeout conf.Duration Parent defs.StaticSourceParent } diff --git a/internal/staticsources/udp/source_test.go b/internal/staticsources/udp/source_test.go index fa64dc7ed42..f1b63a61c95 100644 --- a/internal/staticsources/udp/source_test.go +++ b/internal/staticsources/udp/source_test.go @@ -18,7 +18,7 @@ func TestSource(t *testing.T) { te := test.NewSourceTester( func(p defs.StaticSourceParent) defs.StaticSource { return &Source{ - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Parent: p, } }, diff --git a/internal/staticsources/webrtc/source.go b/internal/staticsources/webrtc/source.go index f8720f7b083..aa6817ce9d2 100644 --- a/internal/staticsources/webrtc/source.go +++ b/internal/staticsources/webrtc/source.go @@ -20,7 +20,7 @@ import ( // Source is a WebRTC static source. type Source struct { - ReadTimeout conf.StringDuration + ReadTimeout conf.Duration Parent defs.StaticSourceParent } diff --git a/internal/staticsources/webrtc/source_test.go b/internal/staticsources/webrtc/source_test.go index 7458fb727e8..a5992d67b71 100644 --- a/internal/staticsources/webrtc/source_test.go +++ b/internal/staticsources/webrtc/source_test.go @@ -39,8 +39,8 @@ func TestSource(t *testing.T) { LocalRandomUDP: true, IPsFromInterfaces: true, Publish: true, - HandshakeTimeout: conf.StringDuration(10 * time.Second), - TrackGatherTimeout: conf.StringDuration(2 * time.Second), + HandshakeTimeout: conf.Duration(10 * time.Second), + TrackGatherTimeout: conf.Duration(2 * time.Second), OutgoingTracks: outgoingTracks, Log: test.NilLogger, } @@ -125,7 +125,7 @@ func TestSource(t *testing.T) { te := test.NewSourceTester( func(p defs.StaticSourceParent) defs.StaticSource { return &Source{ - ReadTimeout: conf.StringDuration(10 * time.Second), + ReadTimeout: conf.Duration(10 * time.Second), Parent: p, } }, diff --git a/mediamtx.yml b/mediamtx.yml index 33c14189353..c184238278b 100644 --- a/mediamtx.yml +++ b/mediamtx.yml @@ -469,7 +469,7 @@ pathDefaults: recordSegmentDuration: 1h # Delete segments after this timespan. # Set to 0s to disable automatic deletion. - recordDeleteAfter: 24h + recordDeleteAfter: 1d ############################################### # Default path settings -> Publisher source (when source is "publisher")