From 558d1c38185488c61f64da51f088d7e608157bd3 Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Wed, 17 Sep 2025 22:18:21 +0200 Subject: [PATCH] api: add tunnel and profile to RTSP conns and sessions (#4985) --- api/openapi.yaml | 5 +++++ go.mod | 2 +- go.sum | 4 ++-- internal/core/api_test.go | 9 ++++++--- internal/defs/api.go | 2 ++ internal/servers/rtsp/conn.go | 13 +++++++++++++ internal/servers/rtsp/session.go | 19 +++++++++++++++++++ internal/testapidocs/apidocs_test.go | 6 ++++++ 8 files changed, 54 insertions(+), 6 deletions(-) diff --git a/api/openapi.yaml b/api/openapi.yaml index f7190c3f..3193fce8 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -746,6 +746,8 @@ components: session: type: string nullable: true + tunnel: + type: string RTSPConnList: type: object @@ -780,6 +782,9 @@ components: transport: type: string nullable: true + profile: + type: string + nullable: true bytesReceived: type: integer format: int64 diff --git a/go.mod b/go.mod index 51e7b7f0..069f3dcf 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/asticode/go-astits v1.13.0 github.com/bluenviron/gohlslib/v2 v2.2.3 github.com/bluenviron/gortmplib v0.0.0-20250916095243-72b6eaffb6a4 - github.com/bluenviron/gortsplib/v5 v5.0.0-20250916102828-1616c8c63415 + github.com/bluenviron/gortsplib/v5 v5.0.0-20250917174653-288b637b2301 github.com/bluenviron/mediacommon/v2 v2.4.2 github.com/datarhei/gosrt v0.9.0 github.com/fsnotify/fsnotify v1.9.0 diff --git a/go.sum b/go.sum index 4a8d8715..938a0a7e 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/bluenviron/gohlslib/v2 v2.2.3 h1:1R/Jnh1kNR9UB09KAX6xjS2GcdKFRLuPd9wM github.com/bluenviron/gohlslib/v2 v2.2.3/go.mod h1:z4Viks+Mdgcl7OcOVJ1fgSmuUwCCJBxYJPLN49n7Vnw= github.com/bluenviron/gortmplib v0.0.0-20250916095243-72b6eaffb6a4 h1:ZDsCiFpmOoEy2eWcJBEhV8jb0sA9MxO/BzYmyrmm4hE= github.com/bluenviron/gortmplib v0.0.0-20250916095243-72b6eaffb6a4/go.mod h1:73VbUEJLkaixSRPRI/imEkVRkBccvR1GKrd6SUOdkrQ= -github.com/bluenviron/gortsplib/v5 v5.0.0-20250916102828-1616c8c63415 h1:FErClZLSuXkZEPfIsAtD4DH6CKmQ6z7gtod1eHi4Efg= -github.com/bluenviron/gortsplib/v5 v5.0.0-20250916102828-1616c8c63415/go.mod h1:un/XrjuE+yaglJw4Fd75OUXowPxioaHHqNOUC28byFA= +github.com/bluenviron/gortsplib/v5 v5.0.0-20250917174653-288b637b2301 h1:dLEqNi4/uTN6lUM3djwWXhO0uqs9/TbRSg4AfDOJjH8= +github.com/bluenviron/gortsplib/v5 v5.0.0-20250917174653-288b637b2301/go.mod h1:zp5tDI2tkjVMgyWiy+B2tRQowqYq/GwHjdAdYFQAxrU= github.com/bluenviron/mediacommon/v2 v2.4.2 h1:rggs61nTaqPcR1+RhlIE8/nDqfF5PO57QxpxBzSFfrw= github.com/bluenviron/mediacommon/v2 v2.4.2/go.mod h1:zy1fODPuS/kBd93ftgJS1Jhvjq7LFWfAo32KP7By9AE= github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= diff --git a/internal/core/api_test.go b/internal/core/api_test.go index 6e80f199..d93242b9 100644 --- a/internal/core/api_test.go +++ b/internal/core/api_test.go @@ -367,8 +367,7 @@ func TestAPIProtocolListGet(t *testing.T) { switch ca { case "rtsps conns", "rtsps sessions": - conf += "rtspTransports: [tcp]\n" + - "rtspEncryption: strict\n" + + conf += "rtspEncryption: strict\n" + "rtspServerCert: " + serverCertFpath + "\n" + "rtspServerKey: " + serverKeyFpath + "\n" @@ -621,6 +620,7 @@ func TestAPIProtocolListGet(t *testing.T) { "id": out1.(map[string]interface{})["items"].([]interface{})[0].(map[string]interface{})["id"], "remoteAddr": out1.(map[string]interface{})["items"].([]interface{})[0].(map[string]interface{})["remoteAddr"], "session": out1.(map[string]interface{})["items"].([]interface{})[0].(map[string]interface{})["session"], + "tunnel": "none", }, }, }, out1) @@ -640,6 +640,7 @@ func TestAPIProtocolListGet(t *testing.T) { "remoteAddr": out1.(map[string]interface{})["items"].([]interface{})[0].(map[string]interface{})["remoteAddr"], "state": "publish", "transport": "UDP", + "profile": "AVP", "rtpPacketsReceived": float64(0), "rtpPacketsSent": float64(0), "rtpPacketsLost": float64(0), @@ -664,6 +665,7 @@ func TestAPIProtocolListGet(t *testing.T) { "id": out1.(map[string]interface{})["items"].([]interface{})[0].(map[string]interface{})["id"], "remoteAddr": out1.(map[string]interface{})["items"].([]interface{})[0].(map[string]interface{})["remoteAddr"], "session": out1.(map[string]interface{})["items"].([]interface{})[0].(map[string]interface{})["session"], + "tunnel": "none", }, }, }, out1) @@ -682,7 +684,8 @@ func TestAPIProtocolListGet(t *testing.T) { "query": "key=val", "remoteAddr": out1.(map[string]interface{})["items"].([]interface{})[0].(map[string]interface{})["remoteAddr"], "state": "publish", - "transport": "TCP", + "transport": "UDP", + "profile": "SAVP", "rtpPacketsReceived": float64(0), "rtpPacketsSent": float64(0), "rtpPacketsLost": float64(0), diff --git a/internal/defs/api.go b/internal/defs/api.go index 86aca7e8..11abf500 100644 --- a/internal/defs/api.go +++ b/internal/defs/api.go @@ -140,6 +140,7 @@ type APIRTSPConn struct { BytesReceived uint64 `json:"bytesReceived"` BytesSent uint64 `json:"bytesSent"` Session *uuid.UUID `json:"session"` + Tunnel string `json:"tunnel"` } // APIRTSPConnsList is a list of RTSP connections. @@ -168,6 +169,7 @@ type APIRTSPSession struct { Path string `json:"path"` Query string `json:"query"` Transport *string `json:"transport"` + Profile *string `json:"profile"` BytesReceived uint64 `json:"bytesReceived"` BytesSent uint64 `json:"bytesSent"` RTPPacketsReceived uint64 `json:"rtpPacketsReceived"` diff --git a/internal/servers/rtsp/conn.go b/internal/servers/rtsp/conn.go index bf18e025..9c5e6c0b 100644 --- a/internal/servers/rtsp/conn.go +++ b/internal/servers/rtsp/conn.go @@ -43,6 +43,18 @@ func credentialsProvided(req *base.Request) bool { return err == nil && auth.Username != "" } +func tunnelLabel(t gortsplib.Tunnel) string { + switch t { + case gortsplib.TunnelHTTP: + return "http" + case gortsplib.TunnelWebSocket: + return "websocket" + case gortsplib.TunnelNone: + return "none" + } + return "unknown" +} + type connParent interface { logger.Writer findSessionByRSessionUnsafe(rsession *gortsplib.ServerSession) *session @@ -229,5 +241,6 @@ func (c *conn) apiItem() *defs.APIRTSPConn { } return nil }(), + Tunnel: tunnelLabel(c.rconn.Transport().Tunnel), } } diff --git a/internal/servers/rtsp/session.go b/internal/servers/rtsp/session.go index e1cd5065..11384ac9 100644 --- a/internal/servers/rtsp/session.go +++ b/internal/servers/rtsp/session.go @@ -11,6 +11,7 @@ import ( "github.com/bluenviron/gortsplib/v5" rtspauth "github.com/bluenviron/gortsplib/v5/pkg/auth" "github.com/bluenviron/gortsplib/v5/pkg/base" + "github.com/bluenviron/gortsplib/v5/pkg/headers" "github.com/google/uuid" "github.com/bluenviron/mediamtx/internal/auth" @@ -24,6 +25,16 @@ import ( "github.com/bluenviron/mediamtx/internal/stream" ) +func profileLabel(p headers.TransportProfile) string { + switch p { + case headers.TransportProfileSAVP: + return "SAVP" + case headers.TransportProfileAVP: + return "AVP" + } + return "unknown" +} + type session struct { isTLS bool transports conf.RTSPTransports @@ -408,6 +419,14 @@ func (s *session) apiItem() *defs.APIRTSPSession { v := transport.Protocol.String() return &v }(), + Profile: func() *string { + transport := s.rsession.Transport() + if transport == nil { + return nil + } + v := profileLabel(transport.Profile) + return &v + }(), BytesReceived: stats.BytesReceived, BytesSent: stats.BytesSent, RTPPacketsReceived: stats.RTPPacketsReceived, diff --git a/internal/testapidocs/apidocs_test.go b/internal/testapidocs/apidocs_test.go index c8c991e8..2831a7b4 100644 --- a/internal/testapidocs/apidocs_test.go +++ b/internal/testapidocs/apidocs_test.go @@ -157,6 +157,12 @@ func TestAPIDocs(t *testing.T) { case sf.Type == reflect.TypeOf(""): content2.Properties[js] = openAPIProperty{Type: "string"} + case sf.Type == reflect.PointerTo(reflect.TypeOf("")): + content2.Properties[js] = openAPIProperty{ + Type: "string", + Nullable: true, + } + case sf.Type == reflect.TypeOf(int(0)): content2.Properties[js] = openAPIProperty{Type: "integer", Format: "int64"}