From 37586b2300a55730866c9deba736c8a6f0bb41ea Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Wed, 19 Jul 2023 13:33:05 +0200 Subject: [PATCH] api: allow to edit properties of path config "all" (#2067) (#2075) --- internal/conf/conf.go | 24 ++++----- internal/conf/path.go | 10 ++-- internal/core/hls_http_server.go | 2 +- internal/core/path.go | 6 +-- internal/core/path_manager.go | 78 ++++++++++++++--------------- internal/core/webrtc_http_server.go | 2 +- mediamtx.yml | 8 +-- 7 files changed, 63 insertions(+), 67 deletions(-) diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 75c9a6b6..e06a5a56 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -77,6 +77,15 @@ func loadFromFile(fpath string, conf *Conf) (bool, error) { return true, nil } +func contains(list []headers.AuthMethod, item headers.AuthMethod) bool { + for _, i := range list { + if i == item { + return true + } + } + return false +} + // Conf is a configuration. type Conf struct { // general @@ -197,15 +206,6 @@ func (conf Conf) Clone() *Conf { return &dest } -func contains(list []headers.AuthMethod, item headers.AuthMethod) bool { - for _, i := range list { - if i == item { - return true - } - } - return false -} - // Check checks the configuration for errors. func (conf *Conf) Check() error { // general @@ -266,12 +266,6 @@ func (conf *Conf) Check() error { conf.Paths = make(map[string]*PathConf) } - // "all" is an alias for "~^.*$" - if _, ok := conf.Paths["all"]; ok { - conf.Paths["~^.*$"] = conf.Paths["all"] - delete(conf.Paths, "all") - } - for _, name := range getSortedKeys(conf.Paths) { pconf := conf.Paths[name] if pconf == nil { diff --git a/internal/conf/path.go b/internal/conf/path.go index e0ae336d..2d9f7430 100644 --- a/internal/conf/path.go +++ b/internal/conf/path.go @@ -119,15 +119,17 @@ type PathConf struct { } func (pconf *PathConf) check(conf *Conf, name string) error { - // normal path - if name == "" || name[0] != '~' { + switch { + case name == "all": + pconf.Regexp = regexp.MustCompile("^.*$") + + case name == "" || name[0] != '~': // normal path err := IsValidPathName(name) if err != nil { return fmt.Errorf("invalid path name '%s': %s", name, err) } - // regular expression path - } else { + default: // regular expression-based path pathRegexp, err := regexp.Compile(name[1:]) if err != nil { return fmt.Errorf("invalid regular expression: %s", name[1:]) diff --git a/internal/core/hls_http_server.go b/internal/core/hls_http_server.go index 9de185cc..729ec5c9 100644 --- a/internal/core/hls_http_server.go +++ b/internal/core/hls_http_server.go @@ -142,7 +142,7 @@ func (s *hlsHTTPServer) onRequest(ctx *gin.Context) { user, pass, hasCredentials := ctx.Request.BasicAuth() - res := s.pathManager.getPathConf(pathGetPathConfReq{ + res := s.pathManager.getConfForPath(pathGetConfForPathReq{ name: dir, publish: false, credentials: authCredentials{ diff --git a/internal/core/path.go b/internal/core/path.go index 718bda81..cad29134 100644 --- a/internal/core/path.go +++ b/internal/core/path.go @@ -83,16 +83,16 @@ type pathPublisherRemoveReq struct { res chan struct{} } -type pathGetPathConfRes struct { +type pathGetConfForPathRes struct { conf *conf.PathConf err error } -type pathGetPathConfReq struct { +type pathGetConfForPathReq struct { name string publish bool credentials authCredentials - res chan pathGetPathConfRes + res chan pathGetConfForPathRes } type pathDescribeRes struct { diff --git a/internal/core/path_manager.go b/internal/core/path_manager.go index ebd33465..249dbbdd 100644 --- a/internal/core/path_manager.go +++ b/internal/core/path_manager.go @@ -30,6 +30,30 @@ func pathConfCanBeUpdated(oldPathConf *conf.PathConf, newPathConf *conf.PathConf return newPathConf.Equal(clone) } +func getConfForPath(pathConfs map[string]*conf.PathConf, name string) (string, *conf.PathConf, []string, error) { + err := conf.IsValidPathName(name) + if err != nil { + return "", nil, nil, fmt.Errorf("invalid path name: %s (%s)", err, name) + } + + // normal path + if pathConf, ok := pathConfs[name]; ok { + return name, pathConf, nil, nil + } + + // regular expression-based path + for pathConfName, pathConf := range pathConfs { + if pathConf.Regexp != nil { + m := pathConf.Regexp.FindStringSubmatch(name) + if m != nil { + return pathConfName, pathConf, m, nil + } + } + } + + return "", nil, nil, fmt.Errorf("path '%s' is not configured", name) +} + type pathManagerHLSManager interface { pathSourceReady(*path) pathSourceNotReady(*path) @@ -64,7 +88,7 @@ type pathManager struct { chPathClose chan *path chPathSourceReady chan *path chPathSourceNotReady chan *path - chPathGetPathConf chan pathGetPathConfReq + chGetConfForPath chan pathGetConfForPathReq chDescribe chan pathDescribeReq chReaderAdd chan pathReaderAddReq chPublisherAdd chan pathPublisherAddReq @@ -108,7 +132,7 @@ func newPathManager( chPathClose: make(chan *path), chPathSourceReady: make(chan *path), chPathSourceNotReady: make(chan *path), - chPathGetPathConf: make(chan pathGetPathConfReq), + chGetConfForPath: make(chan pathGetConfForPathReq), chDescribe: make(chan pathDescribeReq), chReaderAdd: make(chan pathReaderAddReq), chPublisherAdd: make(chan pathPublisherAddReq), @@ -204,24 +228,24 @@ outer: pm.hlsManager.pathSourceNotReady(pa) } - case req := <-pm.chPathGetPathConf: - _, pathConf, _, err := pm.getPathConfInternal(req.name) + case req := <-pm.chGetConfForPath: + _, pathConf, _, err := getConfForPath(pm.pathConfs, req.name) if err != nil { - req.res <- pathGetPathConfRes{err: err} + req.res <- pathGetConfForPathRes{err: err} continue } err = authenticate(pm.externalAuthenticationURL, pm.authMethods, req.name, pathConf, req.publish, req.credentials) if err != nil { - req.res <- pathGetPathConfRes{err: pathErrAuth{wrapped: err}} + req.res <- pathGetConfForPathRes{err: pathErrAuth{wrapped: err}} continue } - req.res <- pathGetPathConfRes{conf: pathConf} + req.res <- pathGetConfForPathRes{conf: pathConf} case req := <-pm.chDescribe: - pathConfName, pathConf, pathMatches, err := pm.getPathConfInternal(req.pathName) + pathConfName, pathConf, pathMatches, err := getConfForPath(pm.pathConfs, req.pathName) if err != nil { req.res <- pathDescribeRes{err: err} continue @@ -241,7 +265,7 @@ outer: req.res <- pathDescribeRes{path: pm.paths[req.pathName]} case req := <-pm.chReaderAdd: - pathConfName, pathConf, pathMatches, err := pm.getPathConfInternal(req.pathName) + pathConfName, pathConf, pathMatches, err := getConfForPath(pm.pathConfs, req.pathName) if err != nil { req.res <- pathReaderSetupPlayRes{err: err} continue @@ -263,7 +287,7 @@ outer: req.res <- pathReaderSetupPlayRes{path: pm.paths[req.pathName]} case req := <-pm.chPublisherAdd: - pathConfName, pathConf, pathMatches, err := pm.getPathConfInternal(req.pathName) + pathConfName, pathConf, pathMatches, err := getConfForPath(pm.pathConfs, req.pathName) if err != nil { req.res <- pathPublisherAnnounceRes{err: err} continue @@ -354,30 +378,6 @@ func (pm *pathManager) removePath(pa *path) { delete(pm.paths, pa.name) } -func (pm *pathManager) getPathConfInternal(name string) (string, *conf.PathConf, []string, error) { - err := conf.IsValidPathName(name) - if err != nil { - return "", nil, nil, fmt.Errorf("invalid path name: %s (%s)", err, name) - } - - // normal path - if pathConf, ok := pm.pathConfs[name]; ok { - return name, pathConf, nil, nil - } - - // regular expression path - for pathConfName, pathConf := range pm.pathConfs { - if pathConf.Regexp != nil { - m := pathConf.Regexp.FindStringSubmatch(name) - if m != nil { - return pathConfName, pathConf, m, nil - } - } - } - - return "", nil, nil, fmt.Errorf("path '%s' is not configured", name) -} - // confReload is called by core. func (pm *pathManager) confReload(pathConfs map[string]*conf.PathConf) { select { @@ -413,15 +413,15 @@ func (pm *pathManager) onPathClose(pa *path) { } } -// getPathConf is called by a reader or publisher. -func (pm *pathManager) getPathConf(req pathGetPathConfReq) pathGetPathConfRes { - req.res = make(chan pathGetPathConfRes) +// getConfForPath is called by a reader or publisher. +func (pm *pathManager) getConfForPath(req pathGetConfForPathReq) pathGetConfForPathRes { + req.res = make(chan pathGetConfForPathRes) select { - case pm.chPathGetPathConf <- req: + case pm.chGetConfForPath <- req: return <-req.res case <-pm.ctx.Done(): - return pathGetPathConfRes{err: fmt.Errorf("terminated")} + return pathGetConfForPathRes{err: fmt.Errorf("terminated")} } } diff --git a/internal/core/webrtc_http_server.go b/internal/core/webrtc_http_server.go index d6f9cdfc..1d2a728b 100644 --- a/internal/core/webrtc_http_server.go +++ b/internal/core/webrtc_http_server.go @@ -293,7 +293,7 @@ func (s *webRTCHTTPServer) onRequest(ctx *gin.Context) { user, pass, hasCredentials := ctx.Request.BasicAuth() - res := s.pathManager.getPathConf(pathGetPathConfReq{ + res := s.pathManager.getConfForPath(pathGetConfForPathReq{ name: dir, publish: publish, credentials: authCredentials{ diff --git a/mediamtx.yml b/mediamtx.yml index 63c84baf..b1fb444c 100644 --- a/mediamtx.yml +++ b/mediamtx.yml @@ -230,10 +230,10 @@ webrtcICETCPMuxAddress: # Path parameters # These settings are path-dependent, and the map key is the name of the path. -# It's possible to use regular expressions by using a tilde as prefix. -# For example, "~^(test1|test2)$" will match both "test1" and "test2". -# For example, "~^prefix" will match all paths that start with "prefix". -# The settings under the path "all" are applied to all paths that do not match +# It's possible to use regular expressions by using a tilde as prefix, +# for example "~^(test1|test2)$" will match both "test1" and "test2", +# for example "~^prefix" will match all paths that start with "prefix". +# Settings under the path "all" are applied to all paths that do not match # another entry. paths: all: