mirror of
https://github.com/aler9/rtsp-simple-server
synced 2025-10-05 07:36:57 +08:00
api: decode durations from strings instead of numbers
This allows to use human-readable durations with the API, for instance: "5s" instead of 5000000000
This commit is contained in:
@@ -26,9 +26,9 @@ components:
|
|||||||
logFile:
|
logFile:
|
||||||
type: string
|
type: string
|
||||||
readTimeout:
|
readTimeout:
|
||||||
type: integer
|
type: string
|
||||||
writeTimeout:
|
writeTimeout:
|
||||||
type: integer
|
type: string
|
||||||
readBufferCount:
|
readBufferCount:
|
||||||
type: integer
|
type: integer
|
||||||
api:
|
api:
|
||||||
@@ -98,7 +98,7 @@ components:
|
|||||||
hlsSegmentCount:
|
hlsSegmentCount:
|
||||||
type: integer
|
type: integer
|
||||||
hlsSegmentDuration:
|
hlsSegmentDuration:
|
||||||
type: integer
|
type: string
|
||||||
hlsAllowOrigin:
|
hlsAllowOrigin:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
@@ -122,9 +122,9 @@ components:
|
|||||||
sourceOnDemand:
|
sourceOnDemand:
|
||||||
type: boolean
|
type: boolean
|
||||||
sourceOnDemandStartTimeout:
|
sourceOnDemandStartTimeout:
|
||||||
type: integer
|
type: string
|
||||||
sourceOnDemandCloseAfter:
|
sourceOnDemandCloseAfter:
|
||||||
type: integer
|
type: string
|
||||||
sourceRedirect:
|
sourceRedirect:
|
||||||
type: string
|
type: string
|
||||||
disablePublisherOverride:
|
disablePublisherOverride:
|
||||||
@@ -160,9 +160,9 @@ components:
|
|||||||
runOnDemandRestart:
|
runOnDemandRestart:
|
||||||
type: boolean
|
type: boolean
|
||||||
runOnDemandStartTimeout:
|
runOnDemandStartTimeout:
|
||||||
type: integer
|
type: string
|
||||||
runOnDemandCloseAfter:
|
runOnDemandCloseAfter:
|
||||||
type: integer
|
type: string
|
||||||
runOnPublish:
|
runOnPublish:
|
||||||
type: string
|
type: string
|
||||||
runOnPublishRestart:
|
runOnPublishRestart:
|
||||||
|
@@ -61,8 +61,8 @@ type Conf struct {
|
|||||||
LogDestinations []string `yaml:"logDestinations" json:"logDestinations"`
|
LogDestinations []string `yaml:"logDestinations" json:"logDestinations"`
|
||||||
LogDestinationsParsed map[logger.Destination]struct{} `yaml:"-" json:"-"`
|
LogDestinationsParsed map[logger.Destination]struct{} `yaml:"-" json:"-"`
|
||||||
LogFile string `yaml:"logFile" json:"logFile"`
|
LogFile string `yaml:"logFile" json:"logFile"`
|
||||||
ReadTimeout time.Duration `yaml:"readTimeout" json:"readTimeout"`
|
ReadTimeout StringDuration `yaml:"readTimeout" json:"readTimeout"`
|
||||||
WriteTimeout time.Duration `yaml:"writeTimeout" json:"writeTimeout"`
|
WriteTimeout StringDuration `yaml:"writeTimeout" json:"writeTimeout"`
|
||||||
ReadBufferCount int `yaml:"readBufferCount" json:"readBufferCount"`
|
ReadBufferCount int `yaml:"readBufferCount" json:"readBufferCount"`
|
||||||
API bool `yaml:"api" json:"api"`
|
API bool `yaml:"api" json:"api"`
|
||||||
APIAddress string `yaml:"apiAddress" json:"apiAddress"`
|
APIAddress string `yaml:"apiAddress" json:"apiAddress"`
|
||||||
@@ -97,12 +97,12 @@ type Conf struct {
|
|||||||
RTMPAddress string `yaml:"rtmpAddress" json:"rtmpAddress"`
|
RTMPAddress string `yaml:"rtmpAddress" json:"rtmpAddress"`
|
||||||
|
|
||||||
// hls
|
// hls
|
||||||
HLSDisable bool `yaml:"hlsDisable" json:"hlsDisable"`
|
HLSDisable bool `yaml:"hlsDisable" json:"hlsDisable"`
|
||||||
HLSAddress string `yaml:"hlsAddress" json:"hlsAddress"`
|
HLSAddress string `yaml:"hlsAddress" json:"hlsAddress"`
|
||||||
HLSAlwaysRemux bool `yaml:"hlsAlwaysRemux" json:"hlsAlwaysRemux"`
|
HLSAlwaysRemux bool `yaml:"hlsAlwaysRemux" json:"hlsAlwaysRemux"`
|
||||||
HLSSegmentCount int `yaml:"hlsSegmentCount" json:"hlsSegmentCount"`
|
HLSSegmentCount int `yaml:"hlsSegmentCount" json:"hlsSegmentCount"`
|
||||||
HLSSegmentDuration time.Duration `yaml:"hlsSegmentDuration" json:"hlsSegmentDuration"`
|
HLSSegmentDuration StringDuration `yaml:"hlsSegmentDuration" json:"hlsSegmentDuration"`
|
||||||
HLSAllowOrigin string `yaml:"hlsAllowOrigin" json:"hlsAllowOrigin"`
|
HLSAllowOrigin string `yaml:"hlsAllowOrigin" json:"hlsAllowOrigin"`
|
||||||
|
|
||||||
// paths
|
// paths
|
||||||
Paths map[string]*PathConf `yaml:"paths" json:"paths"`
|
Paths map[string]*PathConf `yaml:"paths" json:"paths"`
|
||||||
@@ -201,10 +201,10 @@ func (conf *Conf) CheckAndFillMissing() error {
|
|||||||
conf.LogFile = "rtsp-simple-server.log"
|
conf.LogFile = "rtsp-simple-server.log"
|
||||||
}
|
}
|
||||||
if conf.ReadTimeout == 0 {
|
if conf.ReadTimeout == 0 {
|
||||||
conf.ReadTimeout = 10 * time.Second
|
conf.ReadTimeout = 10 * StringDuration(time.Second)
|
||||||
}
|
}
|
||||||
if conf.WriteTimeout == 0 {
|
if conf.WriteTimeout == 0 {
|
||||||
conf.WriteTimeout = 10 * time.Second
|
conf.WriteTimeout = 10 * StringDuration(time.Second)
|
||||||
}
|
}
|
||||||
if conf.ReadBufferCount == 0 {
|
if conf.ReadBufferCount == 0 {
|
||||||
conf.ReadBufferCount = 512
|
conf.ReadBufferCount = 512
|
||||||
@@ -322,7 +322,7 @@ func (conf *Conf) CheckAndFillMissing() error {
|
|||||||
conf.HLSSegmentCount = 3
|
conf.HLSSegmentCount = 3
|
||||||
}
|
}
|
||||||
if conf.HLSSegmentDuration == 0 {
|
if conf.HLSSegmentDuration == 0 {
|
||||||
conf.HLSSegmentDuration = 1 * time.Second
|
conf.HLSSegmentDuration = 1 * StringDuration(time.Second)
|
||||||
}
|
}
|
||||||
if conf.HLSAllowOrigin == "" {
|
if conf.HLSAllowOrigin == "" {
|
||||||
conf.HLSAllowOrigin = "*"
|
conf.HLSAllowOrigin = "*"
|
||||||
|
@@ -28,7 +28,32 @@ func writeTempFile(byts []byte) (string, error) {
|
|||||||
return tmpf.Name(), nil
|
return tmpf.Name(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWithFileAndEnv(t *testing.T) {
|
func TestConfFromFile(t *testing.T) {
|
||||||
|
tmpf, err := writeTempFile([]byte(`
|
||||||
|
paths:
|
||||||
|
cam1:
|
||||||
|
runOnDemandStartTimeout: 5s
|
||||||
|
`))
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer os.Remove(tmpf)
|
||||||
|
|
||||||
|
conf, hasFile, err := Load(tmpf)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, true, hasFile)
|
||||||
|
|
||||||
|
pa, ok := conf.Paths["cam1"]
|
||||||
|
require.Equal(t, true, ok)
|
||||||
|
require.Equal(t, &PathConf{
|
||||||
|
Source: "publisher",
|
||||||
|
SourceProtocol: "",
|
||||||
|
SourceOnDemandStartTimeout: 10 * StringDuration(time.Second),
|
||||||
|
SourceOnDemandCloseAfter: 10 * StringDuration(time.Second),
|
||||||
|
RunOnDemandStartTimeout: 5 * StringDuration(time.Second),
|
||||||
|
RunOnDemandCloseAfter: 10 * StringDuration(time.Second),
|
||||||
|
}, pa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfFromFileAndEnv(t *testing.T) {
|
||||||
os.Setenv("RTSP_PATHS_CAM1_SOURCE", "rtsp://testing")
|
os.Setenv("RTSP_PATHS_CAM1_SOURCE", "rtsp://testing")
|
||||||
defer os.Unsetenv("RTSP_PATHS_CAM1_SOURCE")
|
defer os.Unsetenv("RTSP_PATHS_CAM1_SOURCE")
|
||||||
|
|
||||||
@@ -45,14 +70,14 @@ func TestWithFileAndEnv(t *testing.T) {
|
|||||||
require.Equal(t, &PathConf{
|
require.Equal(t, &PathConf{
|
||||||
Source: "rtsp://testing",
|
Source: "rtsp://testing",
|
||||||
SourceProtocol: "automatic",
|
SourceProtocol: "automatic",
|
||||||
SourceOnDemandStartTimeout: 10 * time.Second,
|
SourceOnDemandStartTimeout: 10 * StringDuration(time.Second),
|
||||||
SourceOnDemandCloseAfter: 10 * time.Second,
|
SourceOnDemandCloseAfter: 10 * StringDuration(time.Second),
|
||||||
RunOnDemandStartTimeout: 10 * time.Second,
|
RunOnDemandStartTimeout: 10 * StringDuration(time.Second),
|
||||||
RunOnDemandCloseAfter: 10 * time.Second,
|
RunOnDemandCloseAfter: 10 * StringDuration(time.Second),
|
||||||
}, pa)
|
}, pa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWithEnvOnly(t *testing.T) {
|
func TestConfFromEnvOnly(t *testing.T) {
|
||||||
os.Setenv("RTSP_PATHS_CAM1_SOURCE", "rtsp://testing")
|
os.Setenv("RTSP_PATHS_CAM1_SOURCE", "rtsp://testing")
|
||||||
defer os.Unsetenv("RTSP_PATHS_CAM1_SOURCE")
|
defer os.Unsetenv("RTSP_PATHS_CAM1_SOURCE")
|
||||||
|
|
||||||
@@ -65,14 +90,14 @@ func TestWithEnvOnly(t *testing.T) {
|
|||||||
require.Equal(t, &PathConf{
|
require.Equal(t, &PathConf{
|
||||||
Source: "rtsp://testing",
|
Source: "rtsp://testing",
|
||||||
SourceProtocol: "automatic",
|
SourceProtocol: "automatic",
|
||||||
SourceOnDemandStartTimeout: 10 * time.Second,
|
SourceOnDemandStartTimeout: 10 * StringDuration(time.Second),
|
||||||
SourceOnDemandCloseAfter: 10 * time.Second,
|
SourceOnDemandCloseAfter: 10 * StringDuration(time.Second),
|
||||||
RunOnDemandStartTimeout: 10 * time.Second,
|
RunOnDemandStartTimeout: 10 * StringDuration(time.Second),
|
||||||
RunOnDemandCloseAfter: 10 * time.Second,
|
RunOnDemandCloseAfter: 10 * StringDuration(time.Second),
|
||||||
}, pa)
|
}, pa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEncryption(t *testing.T) {
|
func TestConfEncryption(t *testing.T) {
|
||||||
key := "testing123testin"
|
key := "testing123testin"
|
||||||
plaintext := `
|
plaintext := `
|
||||||
paths:
|
paths:
|
||||||
|
@@ -12,13 +12,13 @@ import (
|
|||||||
func loadEnvInternal(env map[string]string, prefix string, rv reflect.Value) error {
|
func loadEnvInternal(env map[string]string, prefix string, rv reflect.Value) error {
|
||||||
rt := rv.Type()
|
rt := rv.Type()
|
||||||
|
|
||||||
if rt == reflect.TypeOf(time.Duration(0)) {
|
if rt == reflect.TypeOf(StringDuration(0)) {
|
||||||
if ev, ok := env[prefix]; ok {
|
if ev, ok := env[prefix]; ok {
|
||||||
d, err := time.ParseDuration(ev)
|
d, err := time.ParseDuration(ev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s: %s", prefix, err)
|
return fmt.Errorf("%s: %s", prefix, err)
|
||||||
}
|
}
|
||||||
rv.Set(reflect.ValueOf(d))
|
rv.Set(reflect.ValueOf(StringDuration(d)))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,7 @@ type testStruct struct {
|
|||||||
MyBool bool
|
MyBool bool
|
||||||
|
|
||||||
// duration
|
// duration
|
||||||
MyDuration time.Duration
|
MyDuration StringDuration
|
||||||
|
|
||||||
// slice
|
// slice
|
||||||
MySlice []string
|
MySlice []string
|
||||||
@@ -61,7 +61,7 @@ func TestEnvironment(t *testing.T) {
|
|||||||
require.Equal(t, "testcontent", s.MyString)
|
require.Equal(t, "testcontent", s.MyString)
|
||||||
require.Equal(t, 123, s.MyInt)
|
require.Equal(t, 123, s.MyInt)
|
||||||
require.Equal(t, true, s.MyBool)
|
require.Equal(t, true, s.MyBool)
|
||||||
require.Equal(t, 22*time.Second, s.MyDuration)
|
require.Equal(t, 22*StringDuration(time.Second), s.MyDuration)
|
||||||
require.Equal(t, []string{"el1", "el2"}, s.MySlice)
|
require.Equal(t, []string{"el1", "el2"}, s.MySlice)
|
||||||
|
|
||||||
_, ok := s.MyMap["mykey"]
|
_, ok := s.MyMap["mykey"]
|
||||||
|
@@ -75,8 +75,8 @@ type PathConf struct {
|
|||||||
SourceAnyPortEnable bool `yaml:"sourceAnyPortEnable" json:"sourceAnyPortEnable"`
|
SourceAnyPortEnable bool `yaml:"sourceAnyPortEnable" json:"sourceAnyPortEnable"`
|
||||||
SourceFingerprint string `yaml:"sourceFingerprint" json:"sourceFingerprint"`
|
SourceFingerprint string `yaml:"sourceFingerprint" json:"sourceFingerprint"`
|
||||||
SourceOnDemand bool `yaml:"sourceOnDemand" json:"sourceOnDemand"`
|
SourceOnDemand bool `yaml:"sourceOnDemand" json:"sourceOnDemand"`
|
||||||
SourceOnDemandStartTimeout time.Duration `yaml:"sourceOnDemandStartTimeout" json:"sourceOnDemandStartTimeout"` //nolint:lll
|
SourceOnDemandStartTimeout StringDuration `yaml:"sourceOnDemandStartTimeout" json:"sourceOnDemandStartTimeout"` //nolint:lll
|
||||||
SourceOnDemandCloseAfter time.Duration `yaml:"sourceOnDemandCloseAfter" json:"sourceOnDemandCloseAfter"`
|
SourceOnDemandCloseAfter StringDuration `yaml:"sourceOnDemandCloseAfter" json:"sourceOnDemandCloseAfter"`
|
||||||
SourceRedirect string `yaml:"sourceRedirect" json:"sourceRedirect"`
|
SourceRedirect string `yaml:"sourceRedirect" json:"sourceRedirect"`
|
||||||
DisablePublisherOverride bool `yaml:"disablePublisherOverride" json:"disablePublisherOverride"`
|
DisablePublisherOverride bool `yaml:"disablePublisherOverride" json:"disablePublisherOverride"`
|
||||||
Fallback string `yaml:"fallback" json:"fallback"`
|
Fallback string `yaml:"fallback" json:"fallback"`
|
||||||
@@ -92,16 +92,16 @@ type PathConf struct {
|
|||||||
ReadIPsParsed []interface{} `yaml:"-" json:"-"`
|
ReadIPsParsed []interface{} `yaml:"-" json:"-"`
|
||||||
|
|
||||||
// custom commands
|
// custom commands
|
||||||
RunOnInit string `yaml:"runOnInit" json:"runOnInit"`
|
RunOnInit string `yaml:"runOnInit" json:"runOnInit"`
|
||||||
RunOnInitRestart bool `yaml:"runOnInitRestart" json:"runOnInitRestart"`
|
RunOnInitRestart bool `yaml:"runOnInitRestart" json:"runOnInitRestart"`
|
||||||
RunOnDemand string `yaml:"runOnDemand" json:"runOnDemand"`
|
RunOnDemand string `yaml:"runOnDemand" json:"runOnDemand"`
|
||||||
RunOnDemandRestart bool `yaml:"runOnDemandRestart" json:"runOnDemandRestart"`
|
RunOnDemandRestart bool `yaml:"runOnDemandRestart" json:"runOnDemandRestart"`
|
||||||
RunOnDemandStartTimeout time.Duration `yaml:"runOnDemandStartTimeout" json:"runOnDemandStartTimeout"`
|
RunOnDemandStartTimeout StringDuration `yaml:"runOnDemandStartTimeout" json:"runOnDemandStartTimeout"`
|
||||||
RunOnDemandCloseAfter time.Duration `yaml:"runOnDemandCloseAfter" json:"runOnDemandCloseAfter"`
|
RunOnDemandCloseAfter StringDuration `yaml:"runOnDemandCloseAfter" json:"runOnDemandCloseAfter"`
|
||||||
RunOnPublish string `yaml:"runOnPublish" json:"runOnPublish"`
|
RunOnPublish string `yaml:"runOnPublish" json:"runOnPublish"`
|
||||||
RunOnPublishRestart bool `yaml:"runOnPublishRestart" json:"runOnPublishRestart"`
|
RunOnPublishRestart bool `yaml:"runOnPublishRestart" json:"runOnPublishRestart"`
|
||||||
RunOnRead string `yaml:"runOnRead" json:"runOnRead"`
|
RunOnRead string `yaml:"runOnRead" json:"runOnRead"`
|
||||||
RunOnReadRestart bool `yaml:"runOnReadRestart" json:"runOnReadRestart"`
|
RunOnReadRestart bool `yaml:"runOnReadRestart" json:"runOnReadRestart"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pconf *PathConf) checkAndFillMissing(name string) error {
|
func (pconf *PathConf) checkAndFillMissing(name string) error {
|
||||||
@@ -236,11 +236,11 @@ func (pconf *PathConf) checkAndFillMissing(name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pconf.SourceOnDemandStartTimeout == 0 {
|
if pconf.SourceOnDemandStartTimeout == 0 {
|
||||||
pconf.SourceOnDemandStartTimeout = 10 * time.Second
|
pconf.SourceOnDemandStartTimeout = 10 * StringDuration(time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pconf.SourceOnDemandCloseAfter == 0 {
|
if pconf.SourceOnDemandCloseAfter == 0 {
|
||||||
pconf.SourceOnDemandCloseAfter = 10 * time.Second
|
pconf.SourceOnDemandCloseAfter = 10 * StringDuration(time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pconf.Fallback != "" {
|
if pconf.Fallback != "" {
|
||||||
@@ -337,11 +337,11 @@ func (pconf *PathConf) checkAndFillMissing(name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pconf.RunOnDemandStartTimeout == 0 {
|
if pconf.RunOnDemandStartTimeout == 0 {
|
||||||
pconf.RunOnDemandStartTimeout = 10 * time.Second
|
pconf.RunOnDemandStartTimeout = 10 * StringDuration(time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pconf.RunOnDemandCloseAfter == 0 {
|
if pconf.RunOnDemandCloseAfter == 0 {
|
||||||
pconf.RunOnDemandCloseAfter = 10 * time.Second
|
pconf.RunOnDemandCloseAfter = 10 * StringDuration(time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
65
internal/conf/stringduration.go
Normal file
65
internal/conf/stringduration.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StringDuration is a duration that is unmarshaled from a string.
|
||||||
|
// Durations are normally unmarshaled from numbers.
|
||||||
|
type StringDuration time.Duration
|
||||||
|
|
||||||
|
// MarshalJSON marshals a StringDuration into a string.
|
||||||
|
func (d StringDuration) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(time.Duration(d).String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals a StringDuration from a string.
|
||||||
|
func (d *StringDuration) UnmarshalJSON(b []byte) error {
|
||||||
|
var v interface{}
|
||||||
|
if err := json.Unmarshal(b, &v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
value, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("invalid duration")
|
||||||
|
}
|
||||||
|
|
||||||
|
du, err := time.ParseDuration(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*d = StringDuration(du)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalYAML marshals a StringDuration into a string.
|
||||||
|
func (d StringDuration) MarshalYAML() ([]byte, error) {
|
||||||
|
return yaml.Marshal(time.Duration(d).String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalYAML unmarshals a StringDuration from a string.
|
||||||
|
func (d *StringDuration) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
var v interface{}
|
||||||
|
if err := unmarshal(&v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
value, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("invalid duration")
|
||||||
|
}
|
||||||
|
|
||||||
|
du, err := time.ParseDuration(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*d = StringDuration(du)
|
||||||
|
return nil
|
||||||
|
}
|
@@ -10,7 +10,6 @@ import (
|
|||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
@@ -47,20 +46,20 @@ func cloneStruct(dest interface{}, source interface{}) {
|
|||||||
func loadConfData(ctx *gin.Context) (interface{}, error) {
|
func loadConfData(ctx *gin.Context) (interface{}, error) {
|
||||||
var in struct {
|
var in struct {
|
||||||
// general
|
// general
|
||||||
LogLevel *string `json:"logLevel"`
|
LogLevel *string `json:"logLevel"`
|
||||||
LogDestinations *[]string `json:"logDestinations"`
|
LogDestinations *[]string `json:"logDestinations"`
|
||||||
LogFile *string `json:"logFile"`
|
LogFile *string `json:"logFile"`
|
||||||
ReadTimeout *time.Duration `json:"readTimeout"`
|
ReadTimeout *conf.StringDuration `json:"readTimeout"`
|
||||||
WriteTimeout *time.Duration `json:"writeTimeout"`
|
WriteTimeout *conf.StringDuration `json:"writeTimeout"`
|
||||||
ReadBufferCount *int `json:"readBufferCount"`
|
ReadBufferCount *int `json:"readBufferCount"`
|
||||||
API *bool `json:"api"`
|
API *bool `json:"api"`
|
||||||
APIAddress *string `json:"apiAddress"`
|
APIAddress *string `json:"apiAddress"`
|
||||||
Metrics *bool `json:"metrics"`
|
Metrics *bool `json:"metrics"`
|
||||||
MetricsAddress *string `json:"metricsAddress"`
|
MetricsAddress *string `json:"metricsAddress"`
|
||||||
PPROF *bool `json:"pprof"`
|
PPROF *bool `json:"pprof"`
|
||||||
PPROFAddress *string `json:"pprofAddress"`
|
PPROFAddress *string `json:"pprofAddress"`
|
||||||
RunOnConnect *string `json:"runOnConnect"`
|
RunOnConnect *string `json:"runOnConnect"`
|
||||||
RunOnConnectRestart *bool `json:"runOnConnectRestart"`
|
RunOnConnectRestart *bool `json:"runOnConnectRestart"`
|
||||||
|
|
||||||
// rtsp
|
// rtsp
|
||||||
RTSPDisable *bool `json:"rtspDisable"`
|
RTSPDisable *bool `json:"rtspDisable"`
|
||||||
@@ -83,12 +82,12 @@ func loadConfData(ctx *gin.Context) (interface{}, error) {
|
|||||||
RTMPAddress *string `json:"rtmpAddress"`
|
RTMPAddress *string `json:"rtmpAddress"`
|
||||||
|
|
||||||
// hls
|
// hls
|
||||||
HLSDisable *bool `json:"hlsDisable"`
|
HLSDisable *bool `json:"hlsDisable"`
|
||||||
HLSAddress *string `json:"hlsAddress"`
|
HLSAddress *string `json:"hlsAddress"`
|
||||||
HLSAlwaysRemux *bool `json:"hlsAlwaysRemux"`
|
HLSAlwaysRemux *bool `json:"hlsAlwaysRemux"`
|
||||||
HLSSegmentCount *int `json:"hlsSegmentCount"`
|
HLSSegmentCount *int `json:"hlsSegmentCount"`
|
||||||
HLSSegmentDuration *time.Duration `json:"hlsSegmentDuration"`
|
HLSSegmentDuration *conf.StringDuration `json:"hlsSegmentDuration"`
|
||||||
HLSAllowOrigin *string `json:"hlsAllowOrigin"`
|
HLSAllowOrigin *string `json:"hlsAllowOrigin"`
|
||||||
}
|
}
|
||||||
err := json.NewDecoder(ctx.Request.Body).Decode(&in)
|
err := json.NewDecoder(ctx.Request.Body).Decode(&in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -101,16 +100,16 @@ func loadConfData(ctx *gin.Context) (interface{}, error) {
|
|||||||
func loadConfPathData(ctx *gin.Context) (interface{}, error) {
|
func loadConfPathData(ctx *gin.Context) (interface{}, error) {
|
||||||
var in struct {
|
var in struct {
|
||||||
// source
|
// source
|
||||||
Source *string `json:"source"`
|
Source *string `json:"source"`
|
||||||
SourceProtocol *string `json:"sourceProtocol"`
|
SourceProtocol *string `json:"sourceProtocol"`
|
||||||
SourceAnyPortEnable *bool `json:"sourceAnyPortEnable"`
|
SourceAnyPortEnable *bool `json:"sourceAnyPortEnable"`
|
||||||
SourceFingerprint *string `json:"sourceFingerprint"`
|
SourceFingerprint *string `json:"sourceFingerprint"`
|
||||||
SourceOnDemand *bool `json:"sourceOnDemand"`
|
SourceOnDemand *bool `json:"sourceOnDemand"`
|
||||||
SourceOnDemandStartTimeout *time.Duration `json:"sourceOnDemandStartTimeout"`
|
SourceOnDemandStartTimeout *conf.StringDuration `json:"sourceOnDemandStartTimeout"`
|
||||||
SourceOnDemandCloseAfter *time.Duration `json:"sourceOnDemandCloseAfter"`
|
SourceOnDemandCloseAfter *conf.StringDuration `json:"sourceOnDemandCloseAfter"`
|
||||||
SourceRedirect *string `json:"sourceRedirect"`
|
SourceRedirect *string `json:"sourceRedirect"`
|
||||||
DisablePublisherOverride *bool `json:"disablePublisherOverride"`
|
DisablePublisherOverride *bool `json:"disablePublisherOverride"`
|
||||||
Fallback *string `json:"fallback"`
|
Fallback *string `json:"fallback"`
|
||||||
|
|
||||||
// authentication
|
// authentication
|
||||||
PublishUser *string `json:"publishUser"`
|
PublishUser *string `json:"publishUser"`
|
||||||
@@ -121,16 +120,16 @@ func loadConfPathData(ctx *gin.Context) (interface{}, error) {
|
|||||||
ReadIPs *[]string `json:"readIPs"`
|
ReadIPs *[]string `json:"readIPs"`
|
||||||
|
|
||||||
// custom commands
|
// custom commands
|
||||||
RunOnInit *string `json:"runOnInit"`
|
RunOnInit *string `json:"runOnInit"`
|
||||||
RunOnInitRestart *bool `json:"runOnInitRestart"`
|
RunOnInitRestart *bool `json:"runOnInitRestart"`
|
||||||
RunOnDemand *string `json:"runOnDemand"`
|
RunOnDemand *string `json:"runOnDemand"`
|
||||||
RunOnDemandRestart *bool `json:"runOnDemandRestart"`
|
RunOnDemandRestart *bool `json:"runOnDemandRestart"`
|
||||||
RunOnDemandStartTimeout *time.Duration `json:"runOnDemandStartTimeout"`
|
RunOnDemandStartTimeout *conf.StringDuration `json:"runOnDemandStartTimeout"`
|
||||||
RunOnDemandCloseAfter *time.Duration `json:"runOnDemandCloseAfter"`
|
RunOnDemandCloseAfter *conf.StringDuration `json:"runOnDemandCloseAfter"`
|
||||||
RunOnPublish *string `json:"runOnPublish"`
|
RunOnPublish *string `json:"runOnPublish"`
|
||||||
RunOnPublishRestart *bool `json:"runOnPublishRestart"`
|
RunOnPublishRestart *bool `json:"runOnPublishRestart"`
|
||||||
RunOnRead *string `json:"runOnRead"`
|
RunOnRead *string `json:"runOnRead"`
|
||||||
RunOnReadRestart *bool `json:"runOnReadRestart"`
|
RunOnReadRestart *bool `json:"runOnReadRestart"`
|
||||||
}
|
}
|
||||||
err := json.NewDecoder(ctx.Request.Body).Decode(&in)
|
err := json.NewDecoder(ctx.Request.Body).Decode(&in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -71,6 +71,7 @@ func TestAPIConfigSet(t *testing.T) {
|
|||||||
|
|
||||||
err := httpRequest(http.MethodPost, "http://localhost:9997/v1/config/set", map[string]interface{}{
|
err := httpRequest(http.MethodPost, "http://localhost:9997/v1/config/set", map[string]interface{}{
|
||||||
"rtmpDisable": true,
|
"rtmpDisable": true,
|
||||||
|
"readTimeout": "7s",
|
||||||
}, nil)
|
}, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@@ -80,6 +81,7 @@ func TestAPIConfigSet(t *testing.T) {
|
|||||||
err = httpRequest(http.MethodGet, "http://localhost:9997/v1/config/get", nil, &out)
|
err = httpRequest(http.MethodGet, "http://localhost:9997/v1/config/get", nil, &out)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, true, out["rtmpDisable"])
|
require.Equal(t, true, out["rtmpDisable"])
|
||||||
|
require.Equal(t, "7s", out["readTimeout"])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPIConfigPathsAdd(t *testing.T) {
|
func TestAPIConfigPathsAdd(t *testing.T) {
|
||||||
|
@@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/aler9/gortsplib/pkg/rtph264"
|
"github.com/aler9/gortsplib/pkg/rtph264"
|
||||||
"github.com/pion/rtp"
|
"github.com/pion/rtp"
|
||||||
|
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/conf"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/hls"
|
"github.com/aler9/rtsp-simple-server/internal/hls"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/logger"
|
"github.com/aler9/rtsp-simple-server/internal/logger"
|
||||||
)
|
)
|
||||||
@@ -117,7 +118,7 @@ type hlsMuxerParent interface {
|
|||||||
type hlsMuxer struct {
|
type hlsMuxer struct {
|
||||||
hlsAlwaysRemux bool
|
hlsAlwaysRemux bool
|
||||||
hlsSegmentCount int
|
hlsSegmentCount int
|
||||||
hlsSegmentDuration time.Duration
|
hlsSegmentDuration conf.StringDuration
|
||||||
readBufferCount int
|
readBufferCount int
|
||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
pathName string
|
pathName string
|
||||||
@@ -140,7 +141,7 @@ func newHLSMuxer(
|
|||||||
parentCtx context.Context,
|
parentCtx context.Context,
|
||||||
hlsAlwaysRemux bool,
|
hlsAlwaysRemux bool,
|
||||||
hlsSegmentCount int,
|
hlsSegmentCount int,
|
||||||
hlsSegmentDuration time.Duration,
|
hlsSegmentDuration conf.StringDuration,
|
||||||
readBufferCount int,
|
readBufferCount int,
|
||||||
wg *sync.WaitGroup,
|
wg *sync.WaitGroup,
|
||||||
pathName string,
|
pathName string,
|
||||||
@@ -300,7 +301,7 @@ func (r *hlsMuxer) runInner(innerCtx context.Context, innerReady chan struct{})
|
|||||||
var err error
|
var err error
|
||||||
r.muxer, err = hls.NewMuxer(
|
r.muxer, err = hls.NewMuxer(
|
||||||
r.hlsSegmentCount,
|
r.hlsSegmentCount,
|
||||||
r.hlsSegmentDuration,
|
time.Duration(r.hlsSegmentDuration),
|
||||||
videoTrack,
|
videoTrack,
|
||||||
audioTrack,
|
audioTrack,
|
||||||
)
|
)
|
||||||
|
@@ -8,8 +8,8 @@ import (
|
|||||||
gopath "path"
|
gopath "path"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/conf"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/logger"
|
"github.com/aler9/rtsp-simple-server/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ type hlsServerParent interface {
|
|||||||
type hlsServer struct {
|
type hlsServer struct {
|
||||||
hlsAlwaysRemux bool
|
hlsAlwaysRemux bool
|
||||||
hlsSegmentCount int
|
hlsSegmentCount int
|
||||||
hlsSegmentDuration time.Duration
|
hlsSegmentDuration conf.StringDuration
|
||||||
hlsAllowOrigin string
|
hlsAllowOrigin string
|
||||||
readBufferCount int
|
readBufferCount int
|
||||||
pathManager *pathManager
|
pathManager *pathManager
|
||||||
@@ -43,7 +43,7 @@ func newHLSServer(
|
|||||||
address string,
|
address string,
|
||||||
hlsAlwaysRemux bool,
|
hlsAlwaysRemux bool,
|
||||||
hlsSegmentCount int,
|
hlsSegmentCount int,
|
||||||
hlsSegmentDuration time.Duration,
|
hlsSegmentDuration conf.StringDuration,
|
||||||
hlsAllowOrigin string,
|
hlsAllowOrigin string,
|
||||||
readBufferCount int,
|
readBufferCount int,
|
||||||
pathManager *pathManager,
|
pathManager *pathManager,
|
||||||
|
@@ -182,8 +182,8 @@ type pathPublisherPauseReq struct {
|
|||||||
|
|
||||||
type path struct {
|
type path struct {
|
||||||
rtspAddress string
|
rtspAddress string
|
||||||
readTimeout time.Duration
|
readTimeout conf.StringDuration
|
||||||
writeTimeout time.Duration
|
writeTimeout conf.StringDuration
|
||||||
readBufferCount int
|
readBufferCount int
|
||||||
readBufferSize int
|
readBufferSize int
|
||||||
confName string
|
confName string
|
||||||
@@ -226,8 +226,8 @@ type path struct {
|
|||||||
func newPath(
|
func newPath(
|
||||||
parentCtx context.Context,
|
parentCtx context.Context,
|
||||||
rtspAddress string,
|
rtspAddress string,
|
||||||
readTimeout time.Duration,
|
readTimeout conf.StringDuration,
|
||||||
writeTimeout time.Duration,
|
writeTimeout conf.StringDuration,
|
||||||
readBufferCount int,
|
readBufferCount int,
|
||||||
readBufferSize int,
|
readBufferSize int,
|
||||||
confName string,
|
confName string,
|
||||||
@@ -478,7 +478,7 @@ func (pa *path) onDemandStartSource() {
|
|||||||
pa.onDemandReadyTimer.Stop()
|
pa.onDemandReadyTimer.Stop()
|
||||||
if pa.hasStaticSource() {
|
if pa.hasStaticSource() {
|
||||||
pa.staticSourceCreate()
|
pa.staticSourceCreate()
|
||||||
pa.onDemandReadyTimer = time.NewTimer(pa.conf.SourceOnDemandStartTimeout)
|
pa.onDemandReadyTimer = time.NewTimer(time.Duration(pa.conf.SourceOnDemandStartTimeout))
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
pa.Log(logger.Info, "on demand command started")
|
pa.Log(logger.Info, "on demand command started")
|
||||||
@@ -487,7 +487,7 @@ func (pa *path) onDemandStartSource() {
|
|||||||
Path: pa.name,
|
Path: pa.name,
|
||||||
Port: port,
|
Port: port,
|
||||||
})
|
})
|
||||||
pa.onDemandReadyTimer = time.NewTimer(pa.conf.RunOnDemandStartTimeout)
|
pa.onDemandReadyTimer = time.NewTimer(time.Duration(pa.conf.RunOnDemandStartTimeout))
|
||||||
}
|
}
|
||||||
|
|
||||||
pa.onDemandState = pathOnDemandStateWaitingReady
|
pa.onDemandState = pathOnDemandStateWaitingReady
|
||||||
@@ -496,9 +496,9 @@ func (pa *path) onDemandStartSource() {
|
|||||||
func (pa *path) onDemandScheduleClose() {
|
func (pa *path) onDemandScheduleClose() {
|
||||||
pa.onDemandCloseTimer.Stop()
|
pa.onDemandCloseTimer.Stop()
|
||||||
if pa.hasStaticSource() {
|
if pa.hasStaticSource() {
|
||||||
pa.onDemandCloseTimer = time.NewTimer(pa.conf.SourceOnDemandCloseAfter)
|
pa.onDemandCloseTimer = time.NewTimer(time.Duration(pa.conf.SourceOnDemandCloseAfter))
|
||||||
} else {
|
} else {
|
||||||
pa.onDemandCloseTimer = time.NewTimer(pa.conf.RunOnDemandCloseAfter)
|
pa.onDemandCloseTimer = time.NewTimer(time.Duration(pa.conf.RunOnDemandCloseAfter))
|
||||||
}
|
}
|
||||||
|
|
||||||
pa.onDemandState = pathOnDemandStateClosing
|
pa.onDemandState = pathOnDemandStateClosing
|
||||||
|
@@ -5,7 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
|
|
||||||
@@ -23,8 +22,8 @@ type pathManagerParent interface {
|
|||||||
|
|
||||||
type pathManager struct {
|
type pathManager struct {
|
||||||
rtspAddress string
|
rtspAddress string
|
||||||
readTimeout time.Duration
|
readTimeout conf.StringDuration
|
||||||
writeTimeout time.Duration
|
writeTimeout conf.StringDuration
|
||||||
readBufferCount int
|
readBufferCount int
|
||||||
readBufferSize int
|
readBufferSize int
|
||||||
pathConfs map[string]*conf.PathConf
|
pathConfs map[string]*conf.PathConf
|
||||||
@@ -52,8 +51,8 @@ type pathManager struct {
|
|||||||
func newPathManager(
|
func newPathManager(
|
||||||
parentCtx context.Context,
|
parentCtx context.Context,
|
||||||
rtspAddress string,
|
rtspAddress string,
|
||||||
readTimeout time.Duration,
|
readTimeout conf.StringDuration,
|
||||||
writeTimeout time.Duration,
|
writeTimeout conf.StringDuration,
|
||||||
readBufferCount int,
|
readBufferCount int,
|
||||||
readBufferSize int,
|
readBufferSize int,
|
||||||
pathConfs map[string]*conf.PathConf,
|
pathConfs map[string]*conf.PathConf,
|
||||||
|
@@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/notedit/rtmp/av"
|
"github.com/notedit/rtmp/av"
|
||||||
"github.com/pion/rtp"
|
"github.com/pion/rtp"
|
||||||
|
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/conf"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/externalcmd"
|
"github.com/aler9/rtsp-simple-server/internal/externalcmd"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/logger"
|
"github.com/aler9/rtsp-simple-server/internal/logger"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/rtcpsenderset"
|
"github.com/aler9/rtsp-simple-server/internal/rtcpsenderset"
|
||||||
@@ -55,8 +56,8 @@ type rtmpConnParent interface {
|
|||||||
type rtmpConn struct {
|
type rtmpConn struct {
|
||||||
id string
|
id string
|
||||||
rtspAddress string
|
rtspAddress string
|
||||||
readTimeout time.Duration
|
readTimeout conf.StringDuration
|
||||||
writeTimeout time.Duration
|
writeTimeout conf.StringDuration
|
||||||
readBufferCount int
|
readBufferCount int
|
||||||
runOnConnect string
|
runOnConnect string
|
||||||
runOnConnectRestart bool
|
runOnConnectRestart bool
|
||||||
@@ -77,8 +78,8 @@ func newRTMPConn(
|
|||||||
parentCtx context.Context,
|
parentCtx context.Context,
|
||||||
id string,
|
id string,
|
||||||
rtspAddress string,
|
rtspAddress string,
|
||||||
readTimeout time.Duration,
|
readTimeout conf.StringDuration,
|
||||||
writeTimeout time.Duration,
|
writeTimeout conf.StringDuration,
|
||||||
readBufferCount int,
|
readBufferCount int,
|
||||||
runOnConnect string,
|
runOnConnect string,
|
||||||
runOnConnectRestart bool,
|
runOnConnectRestart bool,
|
||||||
@@ -184,8 +185,8 @@ func (c *rtmpConn) runInner(ctx context.Context) error {
|
|||||||
c.conn.NetConn().Close()
|
c.conn.NetConn().Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
c.conn.NetConn().SetReadDeadline(time.Now().Add(c.readTimeout))
|
c.conn.NetConn().SetReadDeadline(time.Now().Add(time.Duration(c.readTimeout)))
|
||||||
c.conn.NetConn().SetWriteDeadline(time.Now().Add(c.writeTimeout))
|
c.conn.NetConn().SetWriteDeadline(time.Now().Add(time.Duration(c.writeTimeout)))
|
||||||
err := c.conn.ServerHandshake()
|
err := c.conn.ServerHandshake()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -262,7 +263,7 @@ func (c *rtmpConn) runRead(ctx context.Context) error {
|
|||||||
return fmt.Errorf("the stream doesn't contain an H264 track or an AAC track")
|
return fmt.Errorf("the stream doesn't contain an H264 track or an AAC track")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.conn.NetConn().SetWriteDeadline(time.Now().Add(c.writeTimeout))
|
c.conn.NetConn().SetWriteDeadline(time.Now().Add(time.Duration(c.writeTimeout)))
|
||||||
c.conn.WriteMetadata(videoTrack, audioTrack)
|
c.conn.WriteMetadata(videoTrack, audioTrack)
|
||||||
|
|
||||||
c.ringBuffer = ringbuffer.New(uint64(c.readBufferCount))
|
c.ringBuffer = ringbuffer.New(uint64(c.readBufferCount))
|
||||||
@@ -351,7 +352,7 @@ func (c *rtmpConn) runRead(ctx context.Context) error {
|
|||||||
pts -= videoStartPTS
|
pts -= videoStartPTS
|
||||||
dts := videoDTSEst.Feed(pts)
|
dts := videoDTSEst.Feed(pts)
|
||||||
|
|
||||||
c.conn.NetConn().SetWriteDeadline(time.Now().Add(c.writeTimeout))
|
c.conn.NetConn().SetWriteDeadline(time.Now().Add(time.Duration(c.writeTimeout)))
|
||||||
err = c.conn.WritePacket(av.Packet{
|
err = c.conn.WritePacket(av.Packet{
|
||||||
Type: av.H264,
|
Type: av.H264,
|
||||||
Data: data,
|
Data: data,
|
||||||
@@ -391,7 +392,7 @@ func (c *rtmpConn) runRead(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, au := range aus {
|
for _, au := range aus {
|
||||||
c.conn.NetConn().SetWriteDeadline(time.Now().Add(c.writeTimeout))
|
c.conn.NetConn().SetWriteDeadline(time.Now().Add(time.Duration(c.writeTimeout)))
|
||||||
err := c.conn.WritePacket(av.Packet{
|
err := c.conn.WritePacket(av.Packet{
|
||||||
Type: av.AAC,
|
Type: av.AAC,
|
||||||
Data: au,
|
Data: au,
|
||||||
@@ -408,7 +409,7 @@ func (c *rtmpConn) runRead(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *rtmpConn) runPublish(ctx context.Context) error {
|
func (c *rtmpConn) runPublish(ctx context.Context) error {
|
||||||
c.conn.NetConn().SetReadDeadline(time.Now().Add(c.readTimeout))
|
c.conn.NetConn().SetReadDeadline(time.Now().Add(time.Duration(c.readTimeout)))
|
||||||
videoTrack, audioTrack, err := c.conn.ReadMetadata()
|
videoTrack, audioTrack, err := c.conn.ReadMetadata()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -483,7 +484,7 @@ func (c *rtmpConn) runPublish(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
c.conn.NetConn().SetReadDeadline(time.Now().Add(c.readTimeout))
|
c.conn.NetConn().SetReadDeadline(time.Now().Add(time.Duration(c.readTimeout)))
|
||||||
pkt, err := c.conn.ReadPacket()
|
pkt, err := c.conn.ReadPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -8,10 +8,10 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/aler9/gortsplib"
|
"github.com/aler9/gortsplib"
|
||||||
|
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/conf"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/logger"
|
"github.com/aler9/rtsp-simple-server/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,8 +20,8 @@ type rtmpServerParent interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type rtmpServer struct {
|
type rtmpServer struct {
|
||||||
readTimeout time.Duration
|
readTimeout conf.StringDuration
|
||||||
writeTimeout time.Duration
|
writeTimeout conf.StringDuration
|
||||||
readBufferCount int
|
readBufferCount int
|
||||||
rtspAddress string
|
rtspAddress string
|
||||||
runOnConnect string
|
runOnConnect string
|
||||||
@@ -45,8 +45,8 @@ type rtmpServer struct {
|
|||||||
func newRTMPServer(
|
func newRTMPServer(
|
||||||
parentCtx context.Context,
|
parentCtx context.Context,
|
||||||
address string,
|
address string,
|
||||||
readTimeout time.Duration,
|
readTimeout conf.StringDuration,
|
||||||
writeTimeout time.Duration,
|
writeTimeout conf.StringDuration,
|
||||||
readBufferCount int,
|
readBufferCount int,
|
||||||
rtspAddress string,
|
rtspAddress string,
|
||||||
runOnConnect string,
|
runOnConnect string,
|
||||||
|
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/aler9/gortsplib/pkg/rtph264"
|
"github.com/aler9/gortsplib/pkg/rtph264"
|
||||||
"github.com/notedit/rtmp/av"
|
"github.com/notedit/rtmp/av"
|
||||||
|
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/conf"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/logger"
|
"github.com/aler9/rtsp-simple-server/internal/logger"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/rtcpsenderset"
|
"github.com/aler9/rtsp-simple-server/internal/rtcpsenderset"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/rtmp"
|
"github.com/aler9/rtsp-simple-server/internal/rtmp"
|
||||||
@@ -29,8 +30,8 @@ type rtmpSourceParent interface {
|
|||||||
|
|
||||||
type rtmpSource struct {
|
type rtmpSource struct {
|
||||||
ur string
|
ur string
|
||||||
readTimeout time.Duration
|
readTimeout conf.StringDuration
|
||||||
writeTimeout time.Duration
|
writeTimeout conf.StringDuration
|
||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
parent rtmpSourceParent
|
parent rtmpSourceParent
|
||||||
|
|
||||||
@@ -41,8 +42,8 @@ type rtmpSource struct {
|
|||||||
func newRTMPSource(
|
func newRTMPSource(
|
||||||
parentCtx context.Context,
|
parentCtx context.Context,
|
||||||
ur string,
|
ur string,
|
||||||
readTimeout time.Duration,
|
readTimeout conf.StringDuration,
|
||||||
writeTimeout time.Duration,
|
writeTimeout conf.StringDuration,
|
||||||
wg *sync.WaitGroup,
|
wg *sync.WaitGroup,
|
||||||
parent rtmpSourceParent) *rtmpSource {
|
parent rtmpSourceParent) *rtmpSource {
|
||||||
ctx, ctxCancel := context.WithCancel(parentCtx)
|
ctx, ctxCancel := context.WithCancel(parentCtx)
|
||||||
@@ -103,7 +104,7 @@ func (s *rtmpSource) runInner() bool {
|
|||||||
runErr <- func() error {
|
runErr <- func() error {
|
||||||
s.log(logger.Debug, "connecting")
|
s.log(logger.Debug, "connecting")
|
||||||
|
|
||||||
ctx2, cancel2 := context.WithTimeout(innerCtx, s.readTimeout)
|
ctx2, cancel2 := context.WithTimeout(innerCtx, time.Duration(s.readTimeout))
|
||||||
defer cancel2()
|
defer cancel2()
|
||||||
|
|
||||||
conn, err := rtmp.DialContext(ctx2, s.ur)
|
conn, err := rtmp.DialContext(ctx2, s.ur)
|
||||||
@@ -114,8 +115,8 @@ func (s *rtmpSource) runInner() bool {
|
|||||||
readDone := make(chan error)
|
readDone := make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
readDone <- func() error {
|
readDone <- func() error {
|
||||||
conn.NetConn().SetReadDeadline(time.Now().Add(s.readTimeout))
|
conn.NetConn().SetReadDeadline(time.Now().Add(time.Duration(s.readTimeout)))
|
||||||
conn.NetConn().SetWriteDeadline(time.Now().Add(s.writeTimeout))
|
conn.NetConn().SetWriteDeadline(time.Now().Add(time.Duration(s.writeTimeout)))
|
||||||
err = conn.ClientHandshake()
|
err = conn.ClientHandshake()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -123,7 +124,7 @@ func (s *rtmpSource) runInner() bool {
|
|||||||
|
|
||||||
conn.NetConn().SetWriteDeadline(time.Time{})
|
conn.NetConn().SetWriteDeadline(time.Time{})
|
||||||
|
|
||||||
conn.NetConn().SetReadDeadline(time.Now().Add(s.readTimeout))
|
conn.NetConn().SetReadDeadline(time.Now().Add(time.Duration(s.readTimeout)))
|
||||||
videoTrack, audioTrack, err := conn.ReadMetadata()
|
videoTrack, audioTrack, err := conn.ReadMetadata()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -171,7 +172,7 @@ func (s *rtmpSource) runInner() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
conn.NetConn().SetReadDeadline(time.Now().Add(s.readTimeout))
|
conn.NetConn().SetReadDeadline(time.Now().Add(time.Duration(s.readTimeout)))
|
||||||
pkt, err := conn.ReadPacket()
|
pkt, err := conn.ReadPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/aler9/gortsplib/pkg/headers"
|
"github.com/aler9/gortsplib/pkg/headers"
|
||||||
"github.com/aler9/gortsplib/pkg/liberrors"
|
"github.com/aler9/gortsplib/pkg/liberrors"
|
||||||
|
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/conf"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/externalcmd"
|
"github.com/aler9/rtsp-simple-server/internal/externalcmd"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/logger"
|
"github.com/aler9/rtsp-simple-server/internal/logger"
|
||||||
)
|
)
|
||||||
@@ -37,7 +38,7 @@ type rtspConnParent interface {
|
|||||||
type rtspConn struct {
|
type rtspConn struct {
|
||||||
rtspAddress string
|
rtspAddress string
|
||||||
authMethods []headers.AuthMethod
|
authMethods []headers.AuthMethod
|
||||||
readTimeout time.Duration
|
readTimeout conf.StringDuration
|
||||||
runOnConnect string
|
runOnConnect string
|
||||||
runOnConnectRestart bool
|
runOnConnectRestart bool
|
||||||
pathManager *pathManager
|
pathManager *pathManager
|
||||||
@@ -54,7 +55,7 @@ type rtspConn struct {
|
|||||||
func newRTSPConn(
|
func newRTSPConn(
|
||||||
rtspAddress string,
|
rtspAddress string,
|
||||||
authMethods []headers.AuthMethod,
|
authMethods []headers.AuthMethod,
|
||||||
readTimeout time.Duration,
|
readTimeout conf.StringDuration,
|
||||||
runOnConnect string,
|
runOnConnect string,
|
||||||
runOnConnectRestart bool,
|
runOnConnectRestart bool,
|
||||||
pathManager *pathManager,
|
pathManager *pathManager,
|
||||||
|
@@ -24,7 +24,7 @@ type rtspServerParent interface {
|
|||||||
|
|
||||||
type rtspServer struct {
|
type rtspServer struct {
|
||||||
authMethods []headers.AuthMethod
|
authMethods []headers.AuthMethod
|
||||||
readTimeout time.Duration
|
readTimeout conf.StringDuration
|
||||||
isTLS bool
|
isTLS bool
|
||||||
rtspAddress string
|
rtspAddress string
|
||||||
protocols map[conf.Protocol]struct{}
|
protocols map[conf.Protocol]struct{}
|
||||||
@@ -47,8 +47,8 @@ func newRTSPServer(
|
|||||||
parentCtx context.Context,
|
parentCtx context.Context,
|
||||||
address string,
|
address string,
|
||||||
authMethods []headers.AuthMethod,
|
authMethods []headers.AuthMethod,
|
||||||
readTimeout time.Duration,
|
readTimeout conf.StringDuration,
|
||||||
writeTimeout time.Duration,
|
writeTimeout conf.StringDuration,
|
||||||
readBufferCount int,
|
readBufferCount int,
|
||||||
readBufferSize int,
|
readBufferSize int,
|
||||||
useUDP bool,
|
useUDP bool,
|
||||||
@@ -87,8 +87,8 @@ func newRTSPServer(
|
|||||||
|
|
||||||
s.srv = &gortsplib.Server{
|
s.srv = &gortsplib.Server{
|
||||||
Handler: s,
|
Handler: s,
|
||||||
ReadTimeout: readTimeout,
|
ReadTimeout: time.Duration(readTimeout),
|
||||||
WriteTimeout: writeTimeout,
|
WriteTimeout: time.Duration(writeTimeout),
|
||||||
ReadBufferCount: readBufferCount,
|
ReadBufferCount: readBufferCount,
|
||||||
ReadBufferSize: readBufferSize,
|
ReadBufferSize: readBufferSize,
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/aler9/gortsplib"
|
"github.com/aler9/gortsplib"
|
||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
|
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/conf"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/logger"
|
"github.com/aler9/rtsp-simple-server/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -31,8 +32,8 @@ type rtspSource struct {
|
|||||||
proto *gortsplib.ClientProtocol
|
proto *gortsplib.ClientProtocol
|
||||||
anyPortEnable bool
|
anyPortEnable bool
|
||||||
fingerprint string
|
fingerprint string
|
||||||
readTimeout time.Duration
|
readTimeout conf.StringDuration
|
||||||
writeTimeout time.Duration
|
writeTimeout conf.StringDuration
|
||||||
readBufferCount int
|
readBufferCount int
|
||||||
readBufferSize int
|
readBufferSize int
|
||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
@@ -48,8 +49,8 @@ func newRTSPSource(
|
|||||||
proto *gortsplib.ClientProtocol,
|
proto *gortsplib.ClientProtocol,
|
||||||
anyPortEnable bool,
|
anyPortEnable bool,
|
||||||
fingerprint string,
|
fingerprint string,
|
||||||
readTimeout time.Duration,
|
readTimeout conf.StringDuration,
|
||||||
writeTimeout time.Duration,
|
writeTimeout conf.StringDuration,
|
||||||
readBufferCount int,
|
readBufferCount int,
|
||||||
readBufferSize int,
|
readBufferSize int,
|
||||||
wg *sync.WaitGroup,
|
wg *sync.WaitGroup,
|
||||||
@@ -134,8 +135,8 @@ func (s *rtspSource) runInner() bool {
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ReadTimeout: s.readTimeout,
|
ReadTimeout: time.Duration(s.readTimeout),
|
||||||
WriteTimeout: s.writeTimeout,
|
WriteTimeout: time.Duration(s.writeTimeout),
|
||||||
ReadBufferCount: s.readBufferCount,
|
ReadBufferCount: s.readBufferCount,
|
||||||
ReadBufferSize: s.readBufferSize,
|
ReadBufferSize: s.readBufferSize,
|
||||||
AnyPortEnable: s.anyPortEnable,
|
AnyPortEnable: s.anyPortEnable,
|
||||||
|
Reference in New Issue
Block a user