Browse Source

move api, metrics and pprof into dedicated packages (#2843)

pull/2844/head
Alessandro Ros 2 years ago committed by GitHub
parent
commit
1341421412
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 290
      internal/api/api.go
  2. 39
      internal/api/api_test.go
  3. 34
      internal/core/api_test.go
  4. 103
      internal/core/core.go
  5. 4
      internal/core/path.go
  6. 16
      internal/core/path_manager.go
  7. 2
      internal/core/path_manager_test.go
  8. 76
      internal/metrics/metrics.go
  9. 36
      internal/pprof/pprof.go

290
internal/core/api.go → internal/api/api.go

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
package core
// Package api contains the API server.
package api
import (
"encoding/json"
@ -97,17 +98,20 @@ func paramName(ctx *gin.Context) (string, bool) { @@ -97,17 +98,20 @@ func paramName(ctx *gin.Context) (string, bool) {
return name[1:], true
}
type apiPathManager interface {
apiPathsList() (*defs.APIPathList, error)
apiPathsGet(string) (*defs.APIPath, error)
// PathManager contains methods used by the API and Metrics server.
type PathManager interface {
APIPathsList() (*defs.APIPathList, error)
APIPathsGet(string) (*defs.APIPath, error)
}
type apiHLSServer interface {
// HLSServer contains methods used by the API and Metrics server.
type HLSServer interface {
APIMuxersList() (*defs.APIHLSMuxerList, error)
APIMuxersGet(string) (*defs.APIHLSMuxer, error)
}
type apiRTSPServer interface {
// RTSPServer contains methods used by the API and Metrics server.
type RTSPServer interface {
APIConnsList() (*defs.APIRTSPConnsList, error)
APIConnsGet(uuid.UUID) (*defs.APIRTSPConn, error)
APISessionsList() (*defs.APIRTSPSessionList, error)
@ -115,19 +119,22 @@ type apiRTSPServer interface { @@ -115,19 +119,22 @@ type apiRTSPServer interface {
APISessionsKick(uuid.UUID) error
}
type apiRTMPServer interface {
// RTMPServer contains methods used by the API and Metrics server.
type RTMPServer interface {
APIConnsList() (*defs.APIRTMPConnList, error)
APIConnsGet(uuid.UUID) (*defs.APIRTMPConn, error)
APIConnsKick(uuid.UUID) error
}
type apiSRTServer interface {
// SRTServer contains methods used by the API and Metrics server.
type SRTServer interface {
APIConnsList() (*defs.APISRTConnList, error)
APIConnsGet(uuid.UUID) (*defs.APISRTConn, error)
APIConnsKick(uuid.UUID) error
}
type apiWebRTCServer interface {
// WebRTCServer contains methods used by the API and Metrics server.
type WebRTCServer interface {
APISessionsList() (*defs.APIWebRTCSessionList, error)
APISessionsGet(uuid.UUID) (*defs.APIWebRTCSession, error)
APISessionsKick(uuid.UUID) error
@ -135,52 +142,30 @@ type apiWebRTCServer interface { @@ -135,52 +142,30 @@ type apiWebRTCServer interface {
type apiParent interface {
logger.Writer
apiConfigSet(conf *conf.Conf)
}
type api struct {
conf *conf.Conf
pathManager apiPathManager
rtspServer apiRTSPServer
rtspsServer apiRTSPServer
rtmpServer apiRTMPServer
rtmpsServer apiRTMPServer
hlsManager apiHLSServer
webRTCServer apiWebRTCServer
srtServer apiSRTServer
parent apiParent
APIConfigSet(conf *conf.Conf)
}
// API is an API server.
type API struct {
Address string
ReadTimeout conf.StringDuration
Conf *conf.Conf
PathManager PathManager
RTSPServer RTSPServer
RTSPSServer RTSPServer
RTMPServer RTMPServer
RTMPSServer RTMPServer
HLSServer HLSServer
WebRTCServer WebRTCServer
SRTServer SRTServer
Parent apiParent
httpServer *httpserv.WrappedServer
mutex sync.Mutex
}
func newAPI(
address string,
readTimeout conf.StringDuration,
conf *conf.Conf,
pathManager apiPathManager,
rtspServer apiRTSPServer,
rtspsServer apiRTSPServer,
rtmpServer apiRTMPServer,
rtmpsServer apiRTMPServer,
hlsManager apiHLSServer,
webRTCServer apiWebRTCServer,
srtServer apiSRTServer,
parent apiParent,
) (*api, error) {
a := &api{
conf: conf,
pathManager: pathManager,
rtspServer: rtspServer,
rtspsServer: rtspsServer,
rtmpServer: rtmpServer,
rtmpsServer: rtmpsServer,
hlsManager: hlsManager,
webRTCServer: webRTCServer,
srtServer: srtServer,
parent: parent,
}
// Initialize initializes API.
func (a *API) Initialize() error {
router := gin.New()
router.SetTrustedProxies(nil) //nolint:errcheck
@ -202,12 +187,12 @@ func newAPI( @@ -202,12 +187,12 @@ func newAPI(
group.GET("/v3/paths/list", a.onPathsList)
group.GET("/v3/paths/get/*name", a.onPathsGet)
if !interfaceIsEmpty(a.hlsManager) {
if !interfaceIsEmpty(a.HLSServer) {
group.GET("/v3/hlsmuxers/list", a.onHLSMuxersList)
group.GET("/v3/hlsmuxers/get/*name", a.onHLSMuxersGet)
}
if !interfaceIsEmpty(a.rtspServer) {
if !interfaceIsEmpty(a.RTSPServer) {
group.GET("/v3/rtspconns/list", a.onRTSPConnsList)
group.GET("/v3/rtspconns/get/:id", a.onRTSPConnsGet)
group.GET("/v3/rtspsessions/list", a.onRTSPSessionsList)
@ -215,7 +200,7 @@ func newAPI( @@ -215,7 +200,7 @@ func newAPI(
group.POST("/v3/rtspsessions/kick/:id", a.onRTSPSessionsKick)
}
if !interfaceIsEmpty(a.rtspsServer) {
if !interfaceIsEmpty(a.RTSPSServer) {
group.GET("/v3/rtspsconns/list", a.onRTSPSConnsList)
group.GET("/v3/rtspsconns/get/:id", a.onRTSPSConnsGet)
group.GET("/v3/rtspssessions/list", a.onRTSPSSessionsList)
@ -223,63 +208,64 @@ func newAPI( @@ -223,63 +208,64 @@ func newAPI(
group.POST("/v3/rtspssessions/kick/:id", a.onRTSPSSessionsKick)
}
if !interfaceIsEmpty(a.rtmpServer) {
if !interfaceIsEmpty(a.RTMPServer) {
group.GET("/v3/rtmpconns/list", a.onRTMPConnsList)
group.GET("/v3/rtmpconns/get/:id", a.onRTMPConnsGet)
group.POST("/v3/rtmpconns/kick/:id", a.onRTMPConnsKick)
}
if !interfaceIsEmpty(a.rtmpsServer) {
if !interfaceIsEmpty(a.RTMPSServer) {
group.GET("/v3/rtmpsconns/list", a.onRTMPSConnsList)
group.GET("/v3/rtmpsconns/get/:id", a.onRTMPSConnsGet)
group.POST("/v3/rtmpsconns/kick/:id", a.onRTMPSConnsKick)
}
if !interfaceIsEmpty(a.webRTCServer) {
if !interfaceIsEmpty(a.WebRTCServer) {
group.GET("/v3/webrtcsessions/list", a.onWebRTCSessionsList)
group.GET("/v3/webrtcsessions/get/:id", a.onWebRTCSessionsGet)
group.POST("/v3/webrtcsessions/kick/:id", a.onWebRTCSessionsKick)
}
if !interfaceIsEmpty(a.srtServer) {
if !interfaceIsEmpty(a.SRTServer) {
group.GET("/v3/srtconns/list", a.onSRTConnsList)
group.GET("/v3/srtconns/get/:id", a.onSRTConnsGet)
group.POST("/v3/srtconns/kick/:id", a.onSRTConnsKick)
}
network, address := restrictnetwork.Restrict("tcp", address)
network, address := restrictnetwork.Restrict("tcp", a.Address)
var err error
a.httpServer, err = httpserv.NewWrappedServer(
network,
address,
time.Duration(readTimeout),
time.Duration(a.ReadTimeout),
"",
"",
router,
a,
)
if err != nil {
return nil, err
return err
}
a.Log(logger.Info, "listener opened on "+address)
return a, nil
return nil
}
func (a *api) close() {
// Close closes the API.
func (a *API) Close() {
a.Log(logger.Info, "listener is closing")
a.httpServer.Close()
}
// Log implements logger.Writer.
func (a *api) Log(level logger.Level, format string, args ...interface{}) {
a.parent.Log(level, "[API] "+format, args...)
func (a *API) Log(level logger.Level, format string, args ...interface{}) {
a.Parent.Log(level, "[API] "+format, args...)
}
// error coming from something the user inserted into the request.
func (a *api) writeError(ctx *gin.Context, status int, err error) {
func (a *API) writeError(ctx *gin.Context, status int, err error) {
// show error in logs
a.Log(logger.Error, err.Error())
@ -289,15 +275,15 @@ func (a *api) writeError(ctx *gin.Context, status int, err error) { @@ -289,15 +275,15 @@ func (a *api) writeError(ctx *gin.Context, status int, err error) {
})
}
func (a *api) onConfigGlobalGet(ctx *gin.Context) {
func (a *API) onConfigGlobalGet(ctx *gin.Context) {
a.mutex.Lock()
c := a.conf
c := a.Conf
a.mutex.Unlock()
ctx.JSON(http.StatusOK, c.Global())
}
func (a *api) onConfigGlobalPatch(ctx *gin.Context) {
func (a *API) onConfigGlobalPatch(ctx *gin.Context) {
var c conf.OptionalGlobal
err := json.NewDecoder(ctx.Request.Body).Decode(&c)
if err != nil {
@ -308,7 +294,7 @@ func (a *api) onConfigGlobalPatch(ctx *gin.Context) { @@ -308,7 +294,7 @@ func (a *api) onConfigGlobalPatch(ctx *gin.Context) {
a.mutex.Lock()
defer a.mutex.Unlock()
newConf := a.conf.Clone()
newConf := a.Conf.Clone()
newConf.PatchGlobal(&c)
@ -318,24 +304,24 @@ func (a *api) onConfigGlobalPatch(ctx *gin.Context) { @@ -318,24 +304,24 @@ func (a *api) onConfigGlobalPatch(ctx *gin.Context) {
return
}
a.conf = newConf
a.Conf = newConf
// since reloading the configuration can cause the shutdown of the API,
// call it in a goroutine
go a.parent.apiConfigSet(newConf)
go a.Parent.APIConfigSet(newConf)
ctx.Status(http.StatusOK)
}
func (a *api) onConfigPathDefaultsGet(ctx *gin.Context) {
func (a *API) onConfigPathDefaultsGet(ctx *gin.Context) {
a.mutex.Lock()
c := a.conf
c := a.Conf
a.mutex.Unlock()
ctx.JSON(http.StatusOK, c.PathDefaults)
}
func (a *api) onConfigPathDefaultsPatch(ctx *gin.Context) {
func (a *API) onConfigPathDefaultsPatch(ctx *gin.Context) {
var p conf.OptionalPath
err := json.NewDecoder(ctx.Request.Body).Decode(&p)
if err != nil {
@ -346,7 +332,7 @@ func (a *api) onConfigPathDefaultsPatch(ctx *gin.Context) { @@ -346,7 +332,7 @@ func (a *api) onConfigPathDefaultsPatch(ctx *gin.Context) {
a.mutex.Lock()
defer a.mutex.Unlock()
newConf := a.conf.Clone()
newConf := a.Conf.Clone()
newConf.PatchPathDefaults(&p)
@ -356,15 +342,15 @@ func (a *api) onConfigPathDefaultsPatch(ctx *gin.Context) { @@ -356,15 +342,15 @@ func (a *api) onConfigPathDefaultsPatch(ctx *gin.Context) {
return
}
a.conf = newConf
a.parent.apiConfigSet(newConf)
a.Conf = newConf
a.Parent.APIConfigSet(newConf)
ctx.Status(http.StatusOK)
}
func (a *api) onConfigPathsList(ctx *gin.Context) {
func (a *API) onConfigPathsList(ctx *gin.Context) {
a.mutex.Lock()
c := a.conf
c := a.Conf
a.mutex.Unlock()
data := &defs.APIPathConfList{
@ -386,7 +372,7 @@ func (a *api) onConfigPathsList(ctx *gin.Context) { @@ -386,7 +372,7 @@ func (a *api) onConfigPathsList(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onConfigPathsGet(ctx *gin.Context) {
func (a *API) onConfigPathsGet(ctx *gin.Context) {
name, ok := paramName(ctx)
if !ok {
a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name"))
@ -394,7 +380,7 @@ func (a *api) onConfigPathsGet(ctx *gin.Context) { @@ -394,7 +380,7 @@ func (a *api) onConfigPathsGet(ctx *gin.Context) {
}
a.mutex.Lock()
c := a.conf
c := a.Conf
a.mutex.Unlock()
p, ok := c.Paths[name]
@ -406,7 +392,7 @@ func (a *api) onConfigPathsGet(ctx *gin.Context) { @@ -406,7 +392,7 @@ func (a *api) onConfigPathsGet(ctx *gin.Context) {
ctx.JSON(http.StatusOK, p)
}
func (a *api) onConfigPathsAdd(ctx *gin.Context) { //nolint:dupl
func (a *API) onConfigPathsAdd(ctx *gin.Context) { //nolint:dupl
name, ok := paramName(ctx)
if !ok {
a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name"))
@ -423,7 +409,7 @@ func (a *api) onConfigPathsAdd(ctx *gin.Context) { //nolint:dupl @@ -423,7 +409,7 @@ func (a *api) onConfigPathsAdd(ctx *gin.Context) { //nolint:dupl
a.mutex.Lock()
defer a.mutex.Unlock()
newConf := a.conf.Clone()
newConf := a.Conf.Clone()
err = newConf.AddPath(name, &p)
if err != nil {
@ -437,13 +423,13 @@ func (a *api) onConfigPathsAdd(ctx *gin.Context) { //nolint:dupl @@ -437,13 +423,13 @@ func (a *api) onConfigPathsAdd(ctx *gin.Context) { //nolint:dupl
return
}
a.conf = newConf
a.parent.apiConfigSet(newConf)
a.Conf = newConf
a.Parent.APIConfigSet(newConf)
ctx.Status(http.StatusOK)
}
func (a *api) onConfigPathsPatch(ctx *gin.Context) { //nolint:dupl
func (a *API) onConfigPathsPatch(ctx *gin.Context) { //nolint:dupl
name, ok := paramName(ctx)
if !ok {
a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name"))
@ -460,7 +446,7 @@ func (a *api) onConfigPathsPatch(ctx *gin.Context) { //nolint:dupl @@ -460,7 +446,7 @@ func (a *api) onConfigPathsPatch(ctx *gin.Context) { //nolint:dupl
a.mutex.Lock()
defer a.mutex.Unlock()
newConf := a.conf.Clone()
newConf := a.Conf.Clone()
err = newConf.PatchPath(name, &p)
if err != nil {
@ -474,13 +460,13 @@ func (a *api) onConfigPathsPatch(ctx *gin.Context) { //nolint:dupl @@ -474,13 +460,13 @@ func (a *api) onConfigPathsPatch(ctx *gin.Context) { //nolint:dupl
return
}
a.conf = newConf
a.parent.apiConfigSet(newConf)
a.Conf = newConf
a.Parent.APIConfigSet(newConf)
ctx.Status(http.StatusOK)
}
func (a *api) onConfigPathsReplace(ctx *gin.Context) { //nolint:dupl
func (a *API) onConfigPathsReplace(ctx *gin.Context) { //nolint:dupl
name, ok := paramName(ctx)
if !ok {
a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name"))
@ -497,7 +483,7 @@ func (a *api) onConfigPathsReplace(ctx *gin.Context) { //nolint:dupl @@ -497,7 +483,7 @@ func (a *api) onConfigPathsReplace(ctx *gin.Context) { //nolint:dupl
a.mutex.Lock()
defer a.mutex.Unlock()
newConf := a.conf.Clone()
newConf := a.Conf.Clone()
err = newConf.ReplacePath(name, &p)
if err != nil {
@ -511,13 +497,13 @@ func (a *api) onConfigPathsReplace(ctx *gin.Context) { //nolint:dupl @@ -511,13 +497,13 @@ func (a *api) onConfigPathsReplace(ctx *gin.Context) { //nolint:dupl
return
}
a.conf = newConf
a.parent.apiConfigSet(newConf)
a.Conf = newConf
a.Parent.APIConfigSet(newConf)
ctx.Status(http.StatusOK)
}
func (a *api) onConfigPathsDelete(ctx *gin.Context) {
func (a *API) onConfigPathsDelete(ctx *gin.Context) {
name, ok := paramName(ctx)
if !ok {
a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name"))
@ -527,7 +513,7 @@ func (a *api) onConfigPathsDelete(ctx *gin.Context) { @@ -527,7 +513,7 @@ func (a *api) onConfigPathsDelete(ctx *gin.Context) {
a.mutex.Lock()
defer a.mutex.Unlock()
newConf := a.conf.Clone()
newConf := a.Conf.Clone()
err := newConf.RemovePath(name)
if err != nil {
@ -541,14 +527,14 @@ func (a *api) onConfigPathsDelete(ctx *gin.Context) { @@ -541,14 +527,14 @@ func (a *api) onConfigPathsDelete(ctx *gin.Context) {
return
}
a.conf = newConf
a.parent.apiConfigSet(newConf)
a.Conf = newConf
a.Parent.APIConfigSet(newConf)
ctx.Status(http.StatusOK)
}
func (a *api) onPathsList(ctx *gin.Context) {
data, err := a.pathManager.apiPathsList()
func (a *API) onPathsList(ctx *gin.Context) {
data, err := a.PathManager.APIPathsList()
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -565,14 +551,14 @@ func (a *api) onPathsList(ctx *gin.Context) { @@ -565,14 +551,14 @@ func (a *api) onPathsList(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onPathsGet(ctx *gin.Context) {
func (a *API) onPathsGet(ctx *gin.Context) {
name, ok := paramName(ctx)
if !ok {
a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name"))
return
}
data, err := a.pathManager.apiPathsGet(name)
data, err := a.PathManager.APIPathsGet(name)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -581,8 +567,8 @@ func (a *api) onPathsGet(ctx *gin.Context) { @@ -581,8 +567,8 @@ func (a *api) onPathsGet(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTSPConnsList(ctx *gin.Context) {
data, err := a.rtspServer.APIConnsList()
func (a *API) onRTSPConnsList(ctx *gin.Context) {
data, err := a.RTSPServer.APIConnsList()
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -599,14 +585,14 @@ func (a *api) onRTSPConnsList(ctx *gin.Context) { @@ -599,14 +585,14 @@ func (a *api) onRTSPConnsList(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTSPConnsGet(ctx *gin.Context) {
func (a *API) onRTSPConnsGet(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
data, err := a.rtspServer.APIConnsGet(uuid)
data, err := a.RTSPServer.APIConnsGet(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -615,8 +601,8 @@ func (a *api) onRTSPConnsGet(ctx *gin.Context) { @@ -615,8 +601,8 @@ func (a *api) onRTSPConnsGet(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTSPSessionsList(ctx *gin.Context) {
data, err := a.rtspServer.APISessionsList()
func (a *API) onRTSPSessionsList(ctx *gin.Context) {
data, err := a.RTSPServer.APISessionsList()
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -633,14 +619,14 @@ func (a *api) onRTSPSessionsList(ctx *gin.Context) { @@ -633,14 +619,14 @@ func (a *api) onRTSPSessionsList(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTSPSessionsGet(ctx *gin.Context) {
func (a *API) onRTSPSessionsGet(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
data, err := a.rtspServer.APISessionsGet(uuid)
data, err := a.RTSPServer.APISessionsGet(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -649,14 +635,14 @@ func (a *api) onRTSPSessionsGet(ctx *gin.Context) { @@ -649,14 +635,14 @@ func (a *api) onRTSPSessionsGet(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTSPSessionsKick(ctx *gin.Context) {
func (a *API) onRTSPSessionsKick(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
err = a.rtspServer.APISessionsKick(uuid)
err = a.RTSPServer.APISessionsKick(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -665,8 +651,8 @@ func (a *api) onRTSPSessionsKick(ctx *gin.Context) { @@ -665,8 +651,8 @@ func (a *api) onRTSPSessionsKick(ctx *gin.Context) {
ctx.Status(http.StatusOK)
}
func (a *api) onRTSPSConnsList(ctx *gin.Context) {
data, err := a.rtspsServer.APIConnsList()
func (a *API) onRTSPSConnsList(ctx *gin.Context) {
data, err := a.RTSPSServer.APIConnsList()
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -683,14 +669,14 @@ func (a *api) onRTSPSConnsList(ctx *gin.Context) { @@ -683,14 +669,14 @@ func (a *api) onRTSPSConnsList(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTSPSConnsGet(ctx *gin.Context) {
func (a *API) onRTSPSConnsGet(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
data, err := a.rtspsServer.APIConnsGet(uuid)
data, err := a.RTSPSServer.APIConnsGet(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -699,8 +685,8 @@ func (a *api) onRTSPSConnsGet(ctx *gin.Context) { @@ -699,8 +685,8 @@ func (a *api) onRTSPSConnsGet(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTSPSSessionsList(ctx *gin.Context) {
data, err := a.rtspsServer.APISessionsList()
func (a *API) onRTSPSSessionsList(ctx *gin.Context) {
data, err := a.RTSPSServer.APISessionsList()
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -717,14 +703,14 @@ func (a *api) onRTSPSSessionsList(ctx *gin.Context) { @@ -717,14 +703,14 @@ func (a *api) onRTSPSSessionsList(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTSPSSessionsGet(ctx *gin.Context) {
func (a *API) onRTSPSSessionsGet(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
data, err := a.rtspsServer.APISessionsGet(uuid)
data, err := a.RTSPSServer.APISessionsGet(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -733,14 +719,14 @@ func (a *api) onRTSPSSessionsGet(ctx *gin.Context) { @@ -733,14 +719,14 @@ func (a *api) onRTSPSSessionsGet(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTSPSSessionsKick(ctx *gin.Context) {
func (a *API) onRTSPSSessionsKick(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
err = a.rtspsServer.APISessionsKick(uuid)
err = a.RTSPSServer.APISessionsKick(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -749,8 +735,8 @@ func (a *api) onRTSPSSessionsKick(ctx *gin.Context) { @@ -749,8 +735,8 @@ func (a *api) onRTSPSSessionsKick(ctx *gin.Context) {
ctx.Status(http.StatusOK)
}
func (a *api) onRTMPConnsList(ctx *gin.Context) {
data, err := a.rtmpServer.APIConnsList()
func (a *API) onRTMPConnsList(ctx *gin.Context) {
data, err := a.RTMPServer.APIConnsList()
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -767,14 +753,14 @@ func (a *api) onRTMPConnsList(ctx *gin.Context) { @@ -767,14 +753,14 @@ func (a *api) onRTMPConnsList(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTMPConnsGet(ctx *gin.Context) {
func (a *API) onRTMPConnsGet(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
data, err := a.rtmpServer.APIConnsGet(uuid)
data, err := a.RTMPServer.APIConnsGet(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -783,14 +769,14 @@ func (a *api) onRTMPConnsGet(ctx *gin.Context) { @@ -783,14 +769,14 @@ func (a *api) onRTMPConnsGet(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTMPConnsKick(ctx *gin.Context) {
func (a *API) onRTMPConnsKick(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
err = a.rtmpServer.APIConnsKick(uuid)
err = a.RTMPServer.APIConnsKick(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -799,8 +785,8 @@ func (a *api) onRTMPConnsKick(ctx *gin.Context) { @@ -799,8 +785,8 @@ func (a *api) onRTMPConnsKick(ctx *gin.Context) {
ctx.Status(http.StatusOK)
}
func (a *api) onRTMPSConnsList(ctx *gin.Context) {
data, err := a.rtmpsServer.APIConnsList()
func (a *API) onRTMPSConnsList(ctx *gin.Context) {
data, err := a.RTMPSServer.APIConnsList()
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -817,14 +803,14 @@ func (a *api) onRTMPSConnsList(ctx *gin.Context) { @@ -817,14 +803,14 @@ func (a *api) onRTMPSConnsList(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTMPSConnsGet(ctx *gin.Context) {
func (a *API) onRTMPSConnsGet(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
data, err := a.rtmpsServer.APIConnsGet(uuid)
data, err := a.RTMPSServer.APIConnsGet(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -833,14 +819,14 @@ func (a *api) onRTMPSConnsGet(ctx *gin.Context) { @@ -833,14 +819,14 @@ func (a *api) onRTMPSConnsGet(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onRTMPSConnsKick(ctx *gin.Context) {
func (a *API) onRTMPSConnsKick(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
err = a.rtmpsServer.APIConnsKick(uuid)
err = a.RTMPSServer.APIConnsKick(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -849,8 +835,8 @@ func (a *api) onRTMPSConnsKick(ctx *gin.Context) { @@ -849,8 +835,8 @@ func (a *api) onRTMPSConnsKick(ctx *gin.Context) {
ctx.Status(http.StatusOK)
}
func (a *api) onHLSMuxersList(ctx *gin.Context) {
data, err := a.hlsManager.APIMuxersList()
func (a *API) onHLSMuxersList(ctx *gin.Context) {
data, err := a.HLSServer.APIMuxersList()
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -867,14 +853,14 @@ func (a *api) onHLSMuxersList(ctx *gin.Context) { @@ -867,14 +853,14 @@ func (a *api) onHLSMuxersList(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onHLSMuxersGet(ctx *gin.Context) {
func (a *API) onHLSMuxersGet(ctx *gin.Context) {
name, ok := paramName(ctx)
if !ok {
a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name"))
return
}
data, err := a.hlsManager.APIMuxersGet(name)
data, err := a.HLSServer.APIMuxersGet(name)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -883,8 +869,8 @@ func (a *api) onHLSMuxersGet(ctx *gin.Context) { @@ -883,8 +869,8 @@ func (a *api) onHLSMuxersGet(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onWebRTCSessionsList(ctx *gin.Context) {
data, err := a.webRTCServer.APISessionsList()
func (a *API) onWebRTCSessionsList(ctx *gin.Context) {
data, err := a.WebRTCServer.APISessionsList()
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -901,14 +887,14 @@ func (a *api) onWebRTCSessionsList(ctx *gin.Context) { @@ -901,14 +887,14 @@ func (a *api) onWebRTCSessionsList(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onWebRTCSessionsGet(ctx *gin.Context) {
func (a *API) onWebRTCSessionsGet(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
data, err := a.webRTCServer.APISessionsGet(uuid)
data, err := a.WebRTCServer.APISessionsGet(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -917,14 +903,14 @@ func (a *api) onWebRTCSessionsGet(ctx *gin.Context) { @@ -917,14 +903,14 @@ func (a *api) onWebRTCSessionsGet(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onWebRTCSessionsKick(ctx *gin.Context) {
func (a *API) onWebRTCSessionsKick(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
err = a.webRTCServer.APISessionsKick(uuid)
err = a.WebRTCServer.APISessionsKick(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -933,8 +919,8 @@ func (a *api) onWebRTCSessionsKick(ctx *gin.Context) { @@ -933,8 +919,8 @@ func (a *api) onWebRTCSessionsKick(ctx *gin.Context) {
ctx.Status(http.StatusOK)
}
func (a *api) onSRTConnsList(ctx *gin.Context) {
data, err := a.srtServer.APIConnsList()
func (a *API) onSRTConnsList(ctx *gin.Context) {
data, err := a.SRTServer.APIConnsList()
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -951,14 +937,14 @@ func (a *api) onSRTConnsList(ctx *gin.Context) { @@ -951,14 +937,14 @@ func (a *api) onSRTConnsList(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onSRTConnsGet(ctx *gin.Context) {
func (a *API) onSRTConnsGet(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
data, err := a.srtServer.APIConnsGet(uuid)
data, err := a.SRTServer.APIConnsGet(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -967,14 +953,14 @@ func (a *api) onSRTConnsGet(ctx *gin.Context) { @@ -967,14 +953,14 @@ func (a *api) onSRTConnsGet(ctx *gin.Context) {
ctx.JSON(http.StatusOK, data)
}
func (a *api) onSRTConnsKick(ctx *gin.Context) {
func (a *API) onSRTConnsKick(ctx *gin.Context) {
uuid, err := uuid.Parse(ctx.Param("id"))
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
}
err = a.srtServer.APIConnsKick(uuid)
err = a.SRTServer.APIConnsKick(uuid)
if err != nil {
a.writeError(ctx, http.StatusInternalServerError, err)
return
@ -983,9 +969,9 @@ func (a *api) onSRTConnsKick(ctx *gin.Context) { @@ -983,9 +969,9 @@ func (a *api) onSRTConnsKick(ctx *gin.Context) {
ctx.Status(http.StatusOK)
}
// confReload is called by core.
func (a *api) confReload(conf *conf.Conf) {
// ReloadConf is called by core.
func (a *API) ReloadConf(conf *conf.Conf) {
a.mutex.Lock()
defer a.mutex.Unlock()
a.conf = conf
a.Conf = conf
}

39
internal/api/api_test.go

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
package api
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestPaginate(t *testing.T) {
items := make([]int, 5)
for i := 0; i < 5; i++ {
items[i] = i
}
pageCount, err := paginate(&items, "1", "1")
require.NoError(t, err)
require.Equal(t, 5, pageCount)
require.Equal(t, []int{1}, items)
items = make([]int, 5)
for i := 0; i < 5; i++ {
items[i] = i
}
pageCount, err = paginate(&items, "3", "2")
require.NoError(t, err)
require.Equal(t, 2, pageCount)
require.Equal(t, []int{}, items)
items = make([]int, 6)
for i := 0; i < 6; i++ {
items[i] = i
}
pageCount, err = paginate(&items, "4", "1")
require.NoError(t, err)
require.Equal(t, 2, pageCount)
require.Equal(t, []int{4, 5}, items)
}

34
internal/core/api_test.go

@ -20,7 +20,7 @@ import ( @@ -20,7 +20,7 @@ import (
"github.com/bluenviron/gortsplib/v4/pkg/format"
"github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
"github.com/bluenviron/mediacommon/pkg/formats/mpegts"
"github.com/datarhei/gosrt"
srt "github.com/datarhei/gosrt"
"github.com/google/uuid"
"github.com/pion/rtp"
"github.com/stretchr/testify/require"
@ -102,38 +102,6 @@ func httpRequest(t *testing.T, hc *http.Client, method string, ur string, in int @@ -102,38 +102,6 @@ func httpRequest(t *testing.T, hc *http.Client, method string, ur string, in int
require.NoError(t, err)
}
func TestPagination(t *testing.T) {
items := make([]int, 5)
for i := 0; i < 5; i++ {
items[i] = i
}
pageCount, err := paginate(&items, "1", "1")
require.NoError(t, err)
require.Equal(t, 5, pageCount)
require.Equal(t, []int{1}, items)
items = make([]int, 5)
for i := 0; i < 5; i++ {
items[i] = i
}
pageCount, err = paginate(&items, "3", "2")
require.NoError(t, err)
require.Equal(t, 2, pageCount)
require.Equal(t, []int{}, items)
items = make([]int, 6)
for i := 0; i < 6; i++ {
items[i] = i
}
pageCount, err = paginate(&items, "4", "1")
require.NoError(t, err)
require.Equal(t, 2, pageCount)
require.Equal(t, []int{4, 5}, items)
}
func TestAPIConfigGlobalGet(t *testing.T) {
p, ok := newInstance("api: yes\n")
require.Equal(t, true, ok)

103
internal/core/core.go

@ -16,10 +16,13 @@ import ( @@ -16,10 +16,13 @@ import (
"github.com/bluenviron/gortsplib/v4"
"github.com/gin-gonic/gin"
"github.com/bluenviron/mediamtx/internal/api"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/confwatcher"
"github.com/bluenviron/mediamtx/internal/externalcmd"
"github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/metrics"
"github.com/bluenviron/mediamtx/internal/pprof"
"github.com/bluenviron/mediamtx/internal/record"
"github.com/bluenviron/mediamtx/internal/rlimit"
"github.com/bluenviron/mediamtx/internal/servers/hls"
@ -84,8 +87,8 @@ type Core struct { @@ -84,8 +87,8 @@ type Core struct {
conf *conf.Conf
logger *logger.Logger
externalCmdPool *externalcmd.Pool
metrics *metrics
pprof *pprof
metrics *metrics.Metrics
pprof *pprof.PPROF
recordCleaner *record.Cleaner
pathManager *pathManager
rtspServer *rtsp.Server
@ -95,7 +98,7 @@ type Core struct { @@ -95,7 +98,7 @@ type Core struct {
hlsServer *hls.Server
webRTCServer *webrtc.Server
srtServer *srt.Server
api *api
api *api.API
confWatcher *confwatcher.ConfWatcher
// in
@ -275,12 +278,12 @@ func (p *Core) createResources(initial bool) error { @@ -275,12 +278,12 @@ func (p *Core) createResources(initial bool) error {
if p.conf.Metrics &&
p.metrics == nil {
p.metrics = &metrics{
p.metrics = &metrics.Metrics{
Address: p.conf.MetricsAddress,
ReadTimeout: p.conf.ReadTimeout,
Parent: p,
}
err = p.metrics.initialize()
err := p.metrics.Initialize()
if err != nil {
return err
}
@ -288,11 +291,12 @@ func (p *Core) createResources(initial bool) error { @@ -288,11 +291,12 @@ func (p *Core) createResources(initial bool) error {
if p.conf.PPROF &&
p.pprof == nil {
p.pprof, err = newPPROF(
p.conf.PPROFAddress,
p.conf.ReadTimeout,
p,
)
p.pprof = &pprof.PPROF{
Address: p.conf.PPROFAddress,
ReadTimeout: p.conf.ReadTimeout,
Parent: p,
}
err := p.pprof.Initialize()
if err != nil {
return err
}
@ -324,7 +328,7 @@ func (p *Core) createResources(initial bool) error { @@ -324,7 +328,7 @@ func (p *Core) createResources(initial bool) error {
)
if p.metrics != nil {
p.metrics.setPathManager(p.pathManager)
p.metrics.SetPathManager(p.pathManager)
}
}
@ -366,7 +370,7 @@ func (p *Core) createResources(initial bool) error { @@ -366,7 +370,7 @@ func (p *Core) createResources(initial bool) error {
}
if p.metrics != nil {
p.metrics.setRTSPServer(p.rtspServer)
p.metrics.SetRTSPServer(p.rtspServer)
}
}
@ -405,7 +409,7 @@ func (p *Core) createResources(initial bool) error { @@ -405,7 +409,7 @@ func (p *Core) createResources(initial bool) error {
}
if p.metrics != nil {
p.metrics.setRTSPSServer(p.rtspsServer)
p.metrics.SetRTSPSServer(p.rtspsServer)
}
}
@ -435,7 +439,7 @@ func (p *Core) createResources(initial bool) error { @@ -435,7 +439,7 @@ func (p *Core) createResources(initial bool) error {
}
if p.metrics != nil {
p.metrics.setRTMPServer(p.rtmpServer)
p.metrics.SetRTMPServer(p.rtmpServer)
}
}
@ -465,7 +469,7 @@ func (p *Core) createResources(initial bool) error { @@ -465,7 +469,7 @@ func (p *Core) createResources(initial bool) error {
}
if p.metrics != nil {
p.metrics.setRTMPSServer(p.rtmpsServer)
p.metrics.SetRTMPSServer(p.rtmpsServer)
}
}
@ -499,7 +503,7 @@ func (p *Core) createResources(initial bool) error { @@ -499,7 +503,7 @@ func (p *Core) createResources(initial bool) error {
p.pathManager.setHLSServer(p.hlsServer)
if p.metrics != nil {
p.metrics.setHLSServer(p.hlsServer)
p.metrics.SetHLSServer(p.hlsServer)
}
}
@ -524,14 +528,14 @@ func (p *Core) createResources(initial bool) error { @@ -524,14 +528,14 @@ func (p *Core) createResources(initial bool) error {
PathManager: p.pathManager,
Parent: p,
}
err = p.webRTCServer.Initialize()
err := p.webRTCServer.Initialize()
if err != nil {
p.webRTCServer = nil
return err
}
if p.metrics != nil {
p.metrics.setWebRTCServer(p.webRTCServer)
p.metrics.SetWebRTCServer(p.webRTCServer)
}
}
@ -551,32 +555,33 @@ func (p *Core) createResources(initial bool) error { @@ -551,32 +555,33 @@ func (p *Core) createResources(initial bool) error {
PathManager: p.pathManager,
Parent: p,
}
err = p.srtServer.Initialize()
err := p.srtServer.Initialize()
if err != nil {
return err
}
if p.metrics != nil {
p.metrics.setSRTServer(p.srtServer)
p.metrics.SetSRTServer(p.srtServer)
}
}
if p.conf.API &&
p.api == nil {
p.api, err = newAPI(
p.conf.APIAddress,
p.conf.ReadTimeout,
p.conf,
p.pathManager,
p.rtspServer,
p.rtspsServer,
p.rtmpServer,
p.rtmpsServer,
p.hlsServer,
p.webRTCServer,
p.srtServer,
p,
)
p.api = &api.API{
Address: p.conf.APIAddress,
ReadTimeout: p.conf.ReadTimeout,
Conf: p.conf,
PathManager: p.pathManager,
RTSPServer: p.rtspServer,
RTSPSServer: p.rtspsServer,
RTMPServer: p.rtmpServer,
RTMPSServer: p.rtmpsServer,
HLSServer: p.hlsServer,
WebRTCServer: p.webRTCServer,
SRTServer: p.srtServer,
Parent: p,
}
err := p.api.Initialize()
if err != nil {
return err
}
@ -626,7 +631,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { @@ -626,7 +631,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
closeMetrics ||
closeLogger
if !closePathManager && !reflect.DeepEqual(newConf.Paths, p.conf.Paths) {
p.pathManager.confReload(newConf.Paths)
p.pathManager.ReloadConf(newConf.Paths)
}
closeRTSPServer := newConf == nil ||
@ -779,16 +784,16 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { @@ -779,16 +784,16 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
if p.api != nil {
if closeAPI {
p.api.close()
p.api.Close()
p.api = nil
} else if !calledByAPI { // avoid a loop
p.api.confReload(newConf)
p.api.ReloadConf(newConf)
}
}
if closeSRTServer && p.srtServer != nil {
if p.metrics != nil {
p.metrics.setSRTServer(nil)
p.metrics.SetSRTServer(nil)
}
p.srtServer.Close()
@ -797,7 +802,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { @@ -797,7 +802,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
if closeWebRTCServer && p.webRTCServer != nil {
if p.metrics != nil {
p.metrics.setWebRTCServer(nil)
p.metrics.SetWebRTCServer(nil)
}
p.webRTCServer.Close()
@ -806,7 +811,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { @@ -806,7 +811,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
if closeHLSServer && p.hlsServer != nil {
if p.metrics != nil {
p.metrics.setHLSServer(nil)
p.metrics.SetHLSServer(nil)
}
p.pathManager.setHLSServer(nil)
@ -817,7 +822,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { @@ -817,7 +822,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
if closeRTMPSServer && p.rtmpsServer != nil {
if p.metrics != nil {
p.metrics.setRTMPSServer(nil)
p.metrics.SetRTMPSServer(nil)
}
p.rtmpsServer.Close()
@ -826,7 +831,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { @@ -826,7 +831,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
if closeRTMPServer && p.rtmpServer != nil {
if p.metrics != nil {
p.metrics.setRTMPServer(nil)
p.metrics.SetRTMPServer(nil)
}
p.rtmpServer.Close()
@ -835,7 +840,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { @@ -835,7 +840,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
if closeRTSPSServer && p.rtspsServer != nil {
if p.metrics != nil {
p.metrics.setRTSPSServer(nil)
p.metrics.SetRTSPSServer(nil)
}
p.rtspsServer.Close()
@ -844,7 +849,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { @@ -844,7 +849,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
if closeRTSPServer && p.rtspServer != nil {
if p.metrics != nil {
p.metrics.setRTSPServer(nil)
p.metrics.SetRTSPServer(nil)
}
p.rtspServer.Close()
@ -853,7 +858,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { @@ -853,7 +858,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
if closePathManager && p.pathManager != nil {
if p.metrics != nil {
p.metrics.setPathManager(nil)
p.metrics.SetPathManager(nil)
}
p.pathManager.close()
@ -866,12 +871,12 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { @@ -866,12 +871,12 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
}
if closePPROF && p.pprof != nil {
p.pprof.close()
p.pprof.Close()
p.pprof = nil
}
if closeMetrics && p.metrics != nil {
p.metrics.close()
p.metrics.Close()
p.metrics = nil
}
@ -892,8 +897,8 @@ func (p *Core) reloadConf(newConf *conf.Conf, calledByAPI bool) error { @@ -892,8 +897,8 @@ func (p *Core) reloadConf(newConf *conf.Conf, calledByAPI bool) error {
return p.createResources(false)
}
// apiConfigSet is called by api.
func (p *Core) apiConfigSet(conf *conf.Conf) {
// APIConfigSet is called by api.
func (p *Core) APIConfigSet(conf *conf.Conf) {
select {
case p.chAPIConfigSet <- conf:
case <-p.ctx.Done():

4
internal/core/path.go

@ -1019,8 +1019,8 @@ func (pa *path) RemoveReader(req defs.PathRemoveReaderReq) { @@ -1019,8 +1019,8 @@ func (pa *path) RemoveReader(req defs.PathRemoveReaderReq) {
}
}
// apiPathsGet is called by api.
func (pa *path) apiPathsGet(req pathAPIPathsGetReq) (*defs.APIPath, error) {
// APIPathsGet is called by api.
func (pa *path) APIPathsGet(req pathAPIPathsGetReq) (*defs.APIPath, error) {
req.res = make(chan pathAPIPathsGetRes)
select {
case pa.chAPIPathsGet <- req:

16
internal/core/path_manager.go

@ -433,8 +433,8 @@ func (pm *pathManager) removePath(pa *path) { @@ -433,8 +433,8 @@ func (pm *pathManager) removePath(pa *path) {
delete(pm.paths, pa.name)
}
// confReload is called by core.
func (pm *pathManager) confReload(pathConfs map[string]*conf.Path) {
// ReloadConf is called by core.
func (pm *pathManager) ReloadConf(pathConfs map[string]*conf.Path) {
select {
case pm.chReloadConf <- pathConfs:
case <-pm.ctx.Done():
@ -545,8 +545,8 @@ func (pm *pathManager) setHLSServer(s pathManagerHLSServer) { @@ -545,8 +545,8 @@ func (pm *pathManager) setHLSServer(s pathManagerHLSServer) {
}
}
// apiPathsList is called by api.
func (pm *pathManager) apiPathsList() (*defs.APIPathList, error) {
// APIPathsList is called by api.
func (pm *pathManager) APIPathsList() (*defs.APIPathList, error) {
req := pathAPIPathsListReq{
res: make(chan pathAPIPathsListRes),
}
@ -560,7 +560,7 @@ func (pm *pathManager) apiPathsList() (*defs.APIPathList, error) { @@ -560,7 +560,7 @@ func (pm *pathManager) apiPathsList() (*defs.APIPathList, error) {
}
for _, pa := range res.paths {
item, err := pa.apiPathsGet(pathAPIPathsGetReq{})
item, err := pa.APIPathsGet(pathAPIPathsGetReq{})
if err == nil {
res.data.Items = append(res.data.Items, item)
}
@ -577,8 +577,8 @@ func (pm *pathManager) apiPathsList() (*defs.APIPathList, error) { @@ -577,8 +577,8 @@ func (pm *pathManager) apiPathsList() (*defs.APIPathList, error) {
}
}
// apiPathsGet is called by api.
func (pm *pathManager) apiPathsGet(name string) (*defs.APIPath, error) {
// APIPathsGet is called by api.
func (pm *pathManager) APIPathsGet(name string) (*defs.APIPath, error) {
req := pathAPIPathsGetReq{
name: name,
res: make(chan pathAPIPathsGetRes),
@ -591,7 +591,7 @@ func (pm *pathManager) apiPathsGet(name string) (*defs.APIPath, error) { @@ -591,7 +591,7 @@ func (pm *pathManager) apiPathsGet(name string) (*defs.APIPath, error) {
return nil, res.err
}
data, err := res.path.apiPathsGet(req)
data, err := res.path.APIPathsGet(req)
return data, err
case <-pm.ctx.Done():

2
internal/core/path_manager_test.go

@ -78,7 +78,7 @@ func TestPathAutoDeletion(t *testing.T) { @@ -78,7 +78,7 @@ func TestPathAutoDeletion(t *testing.T) {
}
}()
data, err := p.pathManager.apiPathsList()
data, err := p.pathManager.APIPathsList()
require.NoError(t, err)
require.Equal(t, 0, len(data.Items))

76
internal/core/metrics.go → internal/metrics/metrics.go

@ -1,20 +1,27 @@ @@ -1,20 +1,27 @@
package core
// Package metrics contains the metrics provider.
package metrics
import (
"io"
"net/http"
"reflect"
"strconv"
"sync"
"time"
"github.com/gin-gonic/gin"
"github.com/bluenviron/mediamtx/internal/api"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/protocols/httpserv"
"github.com/bluenviron/mediamtx/internal/restrictnetwork"
)
func interfaceIsEmpty(i interface{}) bool {
return reflect.ValueOf(i).Kind() != reflect.Ptr || reflect.ValueOf(i).IsNil()
}
func metric(key string, tags string, value int64) string {
return key + tags + " " + strconv.FormatInt(value, 10) + "\n"
}
@ -23,24 +30,26 @@ type metricsParent interface { @@ -23,24 +30,26 @@ type metricsParent interface {
logger.Writer
}
type metrics struct {
// Metrics is a metrics provider.
type Metrics struct {
Address string
ReadTimeout conf.StringDuration
Parent metricsParent
httpServer *httpserv.WrappedServer
mutex sync.Mutex
pathManager apiPathManager
rtspServer apiRTSPServer
rtspsServer apiRTSPServer
rtmpServer apiRTMPServer
rtmpsServer apiRTMPServer
srtServer apiSRTServer
hlsManager apiHLSServer
webRTCServer apiWebRTCServer
}
func (m *metrics) initialize() error {
pathManager api.PathManager
rtspServer api.RTSPServer
rtspsServer api.RTSPServer
rtmpServer api.RTMPServer
rtmpsServer api.RTMPServer
srtServer api.SRTServer
hlsManager api.HLSServer
webRTCServer api.WebRTCServer
}
// Initialize initializes metrics.
func (m *Metrics) Initialize() error {
router := gin.New()
router.SetTrustedProxies(nil) //nolint:errcheck
@ -67,20 +76,21 @@ func (m *metrics) initialize() error { @@ -67,20 +76,21 @@ func (m *metrics) initialize() error {
return nil
}
func (m *metrics) close() {
// Close closes Metrics.
func (m *Metrics) Close() {
m.Log(logger.Info, "listener is closing")
m.httpServer.Close()
}
// Log implements logger.Writer.
func (m *metrics) Log(level logger.Level, format string, args ...interface{}) {
func (m *Metrics) Log(level logger.Level, format string, args ...interface{}) {
m.Parent.Log(level, "[metrics] "+format, args...)
}
func (m *metrics) onMetrics(ctx *gin.Context) {
func (m *Metrics) onMetrics(ctx *gin.Context) {
out := ""
data, err := m.pathManager.apiPathsList()
data, err := m.pathManager.APIPathsList()
if err == nil && len(data.Items) != 0 {
for _, i := range data.Items {
var state string
@ -249,57 +259,57 @@ func (m *metrics) onMetrics(ctx *gin.Context) { @@ -249,57 +259,57 @@ func (m *metrics) onMetrics(ctx *gin.Context) {
io.WriteString(ctx.Writer, out) //nolint:errcheck
}
// setPathManager is called by core.
func (m *metrics) setPathManager(s apiPathManager) {
// SetPathManager is called by core.
func (m *Metrics) SetPathManager(s api.PathManager) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.pathManager = s
}
// setHLSServer is called by core.
func (m *metrics) setHLSServer(s apiHLSServer) {
// SetHLSServer is called by core.
func (m *Metrics) SetHLSServer(s api.HLSServer) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.hlsManager = s
}
// setRTSPServer is called by core.
func (m *metrics) setRTSPServer(s apiRTSPServer) {
// SetRTSPServer is called by core.
func (m *Metrics) SetRTSPServer(s api.RTSPServer) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.rtspServer = s
}
// setRTSPSServer is called by core.
func (m *metrics) setRTSPSServer(s apiRTSPServer) {
// SetRTSPSServer is called by core.
func (m *Metrics) SetRTSPSServer(s api.RTSPServer) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.rtspsServer = s
}
// setRTMPServer is called by core.
func (m *metrics) setRTMPServer(s apiRTMPServer) {
// SetRTMPServer is called by core.
func (m *Metrics) SetRTMPServer(s api.RTMPServer) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.rtmpServer = s
}
// setRTMPSServer is called by core.
func (m *metrics) setRTMPSServer(s apiRTMPServer) {
// SetRTMPSServer is called by core.
func (m *Metrics) SetRTMPSServer(s api.RTMPServer) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.rtmpsServer = s
}
// setSRTServer is called by core.
func (m *metrics) setSRTServer(s apiSRTServer) {
// SetSRTServer is called by core.
func (m *Metrics) SetSRTServer(s api.SRTServer) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.srtServer = s
}
// setWebRTCServer is called by core.
func (m *metrics) setWebRTCServer(s apiWebRTCServer) {
// SetWebRTCServer is called by core.
func (m *Metrics) SetWebRTCServer(s api.WebRTCServer) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.webRTCServer = s

36
internal/core/pprof.go → internal/pprof/pprof.go

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
package core
// Package pprof contains a pprof exporter.
package pprof
import (
"net/http"
@ -17,48 +18,45 @@ type pprofParent interface { @@ -17,48 +18,45 @@ type pprofParent interface {
logger.Writer
}
type pprof struct {
parent pprofParent
// PPROF is a pprof exporter.
type PPROF struct {
Address string
ReadTimeout conf.StringDuration
Parent pprofParent
httpServer *httpserv.WrappedServer
}
func newPPROF(
address string,
readTimeout conf.StringDuration,
parent pprofParent,
) (*pprof, error) {
pp := &pprof{
parent: parent,
}
network, address := restrictnetwork.Restrict("tcp", address)
// Initialize initializes PPROF.
func (pp *PPROF) Initialize() error {
network, address := restrictnetwork.Restrict("tcp", pp.Address)
var err error
pp.httpServer, err = httpserv.NewWrappedServer(
network,
address,
time.Duration(readTimeout),
time.Duration(pp.ReadTimeout),
"",
"",
http.DefaultServeMux,
pp,
)
if err != nil {
return nil, err
return err
}
pp.Log(logger.Info, "listener opened on "+address)
return pp, nil
return nil
}
func (pp *pprof) close() {
// Close closes PPROF.
func (pp *PPROF) Close() {
pp.Log(logger.Info, "listener is closing")
pp.httpServer.Close()
}
// Log implements logger.Writer.
func (pp *pprof) Log(level logger.Level, format string, args ...interface{}) {
pp.parent.Log(level, "[pprof] "+format, args...)
func (pp *PPROF) Log(level logger.Level, format string, args ...interface{}) {
pp.Parent.Log(level, "[pprof] "+format, args...)
}
Loading…
Cancel
Save