From 5eef89a0157437fb3f96818dd2a12e3a9a3913de Mon Sep 17 00:00:00 2001 From: andrew-ld <43882924+andrew-ld@users.noreply.github.com> Date: Thu, 22 Dec 2022 10:22:16 +0100 Subject: [PATCH 01/13] add webrtcp static tcp mux port --- Dockerfile | 8 +++++++ internal/conf/conf.go | 21 +++++++++------- internal/core/core.go | 2 ++ internal/core/webrtc_conn.go | 44 +++++++++++++++++++++++++++++++--- internal/core/webrtc_server.go | 19 +++++++++++++++ 5 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000000..e46b969c0a7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM golang:alpine as builder +WORKDIR /build +COPY . . +RUN go build + +FROM alpine:latest +COPY --from=builder /build/rtsp-simple-server / +CMD ["/rtsp-simple-server"] diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 7a3aab0252c..871ff258cae 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -224,14 +224,16 @@ type Conf struct { HLSTrustedProxies IPsOrCIDRs `json:"hlsTrustedProxies"` // WebRTC - WebRTCDisable bool `json:"webrtcDisable"` - WebRTCAddress string `json:"webrtcAddress"` - WebRTCEncryption bool `json:"webrtcEncryption"` - WebRTCServerKey string `json:"webrtcServerKey"` - WebRTCServerCert string `json:"webrtcServerCert"` - WebRTCAllowOrigin string `json:"webrtcAllowOrigin"` - WebRTCTrustedProxies IPsOrCIDRs `json:"webrtcTrustedProxies"` - WebRTCICEServers []string `json:"webrtcICEServers"` + WebRTCDisable bool `json:"webrtcDisable"` + WebRTCAddress string `json:"webrtcAddress"` + WebRTCEncryption bool `json:"webrtcEncryption"` + WebRTCServerKey string `json:"webrtcServerKey"` + WebRTCServerCert string `json:"webrtcServerCert"` + WebRTCAllowOrigin string `json:"webrtcAllowOrigin"` + WebRTCTrustedProxies IPsOrCIDRs `json:"webrtcTrustedProxies"` + WebRTCICEServers []string `json:"webrtcICEServers"` + WebRTCICETCPMuxEnable bool `json:"webRTCICETCPMuxEnable"` + WebRTCICETCPMuxAddress string `json:"webRTCICETCPMuxAddress"` // paths Paths map[string]*PathConf `json:"paths"` @@ -412,6 +414,9 @@ func (conf *Conf) CheckAndFillMissing() error { if conf.WebRTCICEServers == nil { conf.WebRTCICEServers = []string{"stun:stun.l.google.com:19302"} } + if conf.WebRTCICETCPMuxAddress == "" { + conf.WebRTCICETCPMuxAddress = "127.0.0.1:9996" + } // do not add automatically "all", since user may want to // initialize all paths through API or hot reloading. diff --git a/internal/core/core.go b/internal/core/core.go index 51f3e58b262..1904af57f78 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -413,6 +413,8 @@ func (p *Core) createResources(initial bool) error { p.pathManager, p.metrics, p, + p.conf.WebRTCICETCPMuxEnable, + p.conf.WebRTCICETCPMuxAddress, ) if err != nil { return err diff --git a/internal/core/webrtc_conn.go b/internal/core/webrtc_conn.go index 7f0b2843eaf..f80c598e519 100644 --- a/internal/core/webrtc_conn.go +++ b/internal/core/webrtc_conn.go @@ -24,6 +24,8 @@ import ( "github.com/aler9/gortsplib/v2/pkg/ringbuffer" "github.com/google/uuid" "github.com/gorilla/websocket" + "github.com/pion/ice/v2" + "github.com/pion/interceptor" "github.com/pion/webrtc/v3" "github.com/aler9/rtsp-simple-server/internal/conf" @@ -75,6 +77,8 @@ type webRTCConn struct { created time.Time curPC *webrtc.PeerConnection mutex sync.RWMutex + + iceTcpMux ice.TCPMux } func newWebRTCConn( @@ -86,6 +90,7 @@ func newWebRTCConn( wg *sync.WaitGroup, pathManager webRTCConnPathManager, parent webRTCConnParent, + iceTcpMux ice.TCPMux, ) *webRTCConn { ctx, ctxCancel := context.WithCancel(parentCtx) @@ -101,6 +106,7 @@ func newWebRTCConn( ctxCancel: ctxCancel, uuid: uuid.New(), created: time.Now(), + iceTcpMux: iceTcpMux, } c.log(logger.Info, "opened") @@ -176,6 +182,29 @@ func (c *webRTCConn) run() { c.log(logger.Info, "closed (%v)", err) } +// NewPeerConnection creates a PeerConnection with the default codecs and +// interceptors. See RegisterDefaultCodecs and RegisterDefaultInterceptors. +// +// This function is a copy of webrtc/peerconnection.go +// unlike the original one, allows you to add additional custom options +func NewPeerConnection(configuration webrtc.Configuration, options ...func(*webrtc.API)) (*webrtc.PeerConnection, error) { + m := &webrtc.MediaEngine{} + if err := m.RegisterDefaultCodecs(); err != nil { + return nil, err + } + + i := &interceptor.Registry{} + if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil { + return nil, err + } + + options = append(options, webrtc.WithMediaEngine(m)) + options = append(options, webrtc.WithInterceptorRegistry(i)) + + api := webrtc.NewAPI(options...) + return api.NewPeerConnection(configuration) +} + func (c *webRTCConn) runInner(ctx context.Context) error { go func() { <-ctx.Done() @@ -222,9 +251,18 @@ func (c *webRTCConn) runInner(ctx context.Context) error { return err } - pc, err := webrtc.NewPeerConnection(webrtc.Configuration{ - ICEServers: c.genICEServers(), - }) + var configuration = webrtc.Configuration{ICEServers: c.genICEServers()} + var pc *webrtc.PeerConnection + + if c.iceTcpMux == nil { + pc, err = webrtc.NewPeerConnection(configuration) + } else { + settingsEngine := webrtc.SettingEngine{} + settingsEngine.SetICETCPMux(c.iceTcpMux) + settingsEngine.SetNetworkTypes([]webrtc.NetworkType{webrtc.NetworkTypeTCP4}) + pc, err = NewPeerConnection(configuration, webrtc.WithSettingEngine(settingsEngine)) + } + if err != nil { return err } diff --git a/internal/core/webrtc_server.go b/internal/core/webrtc_server.go index df9aac76ade..ef3f7f4e07c 100644 --- a/internal/core/webrtc_server.go +++ b/internal/core/webrtc_server.go @@ -15,6 +15,8 @@ import ( "github.com/gin-gonic/gin" "github.com/gorilla/websocket" + "github.com/pion/ice/v2" + "github.com/pion/webrtc/v3" "github.com/aler9/rtsp-simple-server/internal/conf" "github.com/aler9/rtsp-simple-server/internal/logger" @@ -84,6 +86,8 @@ type webRTCServer struct { tlsConfig *tls.Config conns map[*webRTCConn]struct{} + webrtcTCPMux ice.TCPMux + // in connNew chan webRTCConnNewReq chConnClose chan *webRTCConn @@ -105,6 +109,8 @@ func newWebRTCServer( pathManager *pathManager, metrics *metrics, parent webRTCServerParent, + iceTcpMuxEnable bool, + iceTcpMuxAddress string, ) (*webRTCServer, error) { ln, err := net.Listen("tcp", address) if err != nil { @@ -124,6 +130,17 @@ func newWebRTCServer( } } + var iceTcpMux ice.TCPMux + if iceTcpMuxEnable { + tcpMuxLn, err := net.Listen("tcp", iceTcpMuxAddress) + if err != nil { + tcpMuxLn.Close() + return nil, err + } + + iceTcpMux = webrtc.NewICETCPMux(nil, tcpMuxLn, 8) + } + ctx, ctxCancel := context.WithCancel(parentCtx) s := &webRTCServer{ @@ -139,6 +156,7 @@ func newWebRTCServer( ctxCancel: ctxCancel, ln: ln, tlsConfig: tlsConfig, + webrtcTCPMux: iceTcpMux, conns: make(map[*webRTCConn]struct{}), connNew: make(chan webRTCConnNewReq), chConnClose: make(chan *webRTCConn), @@ -206,6 +224,7 @@ outer: &s.wg, s.pathManager, s, + s.webrtcTCPMux, ) s.conns[c] = struct{}{} From 5879bcef6177b91c49eb3b77ce670f3722db8e0f Mon Sep 17 00:00:00 2001 From: andrew-ld <43882924+andrew-ld@users.noreply.github.com> Date: Thu, 22 Dec 2022 11:07:57 +0100 Subject: [PATCH 02/13] add ice nat1 host configuration and cleanup --- internal/conf/conf.go | 21 ++++++------ internal/core/core.go | 1 + internal/core/webrtc_conn.go | 58 ++++++++++++++++++---------------- internal/core/webrtc_server.go | 10 ++++-- 4 files changed, 50 insertions(+), 40 deletions(-) diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 871ff258cae..1b268f2de7b 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -224,16 +224,17 @@ type Conf struct { HLSTrustedProxies IPsOrCIDRs `json:"hlsTrustedProxies"` // WebRTC - WebRTCDisable bool `json:"webrtcDisable"` - WebRTCAddress string `json:"webrtcAddress"` - WebRTCEncryption bool `json:"webrtcEncryption"` - WebRTCServerKey string `json:"webrtcServerKey"` - WebRTCServerCert string `json:"webrtcServerCert"` - WebRTCAllowOrigin string `json:"webrtcAllowOrigin"` - WebRTCTrustedProxies IPsOrCIDRs `json:"webrtcTrustedProxies"` - WebRTCICEServers []string `json:"webrtcICEServers"` - WebRTCICETCPMuxEnable bool `json:"webRTCICETCPMuxEnable"` - WebRTCICETCPMuxAddress string `json:"webRTCICETCPMuxAddress"` + WebRTCDisable bool `json:"webrtcDisable"` + WebRTCAddress string `json:"webrtcAddress"` + WebRTCEncryption bool `json:"webrtcEncryption"` + WebRTCServerKey string `json:"webrtcServerKey"` + WebRTCServerCert string `json:"webrtcServerCert"` + WebRTCAllowOrigin string `json:"webrtcAllowOrigin"` + WebRTCTrustedProxies IPsOrCIDRs `json:"webrtcTrustedProxies"` + WebRTCICEServers []string `json:"webrtcICEServers"` + WebRTCICETCPMuxEnable bool `json:"webRTCICETCPMuxEnable"` + WebRTCICETCPMuxAddress string `json:"webRTCICETCPMuxAddress"` + WebRTCICEHostNAT1To1IPs []string `json:"webRTCICEHostNAT1To1IPs"` // paths Paths map[string]*PathConf `json:"paths"` diff --git a/internal/core/core.go b/internal/core/core.go index 1904af57f78..268f432004e 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -415,6 +415,7 @@ func (p *Core) createResources(initial bool) error { p, p.conf.WebRTCICETCPMuxEnable, p.conf.WebRTCICETCPMuxAddress, + p.conf.WebRTCICEHostNAT1To1IPs, ) if err != nil { return err diff --git a/internal/core/webrtc_conn.go b/internal/core/webrtc_conn.go index f80c598e519..290df7eb89a 100644 --- a/internal/core/webrtc_conn.go +++ b/internal/core/webrtc_conn.go @@ -63,13 +63,15 @@ type webRTCConnParent interface { } type webRTCConn struct { - readBufferCount int - pathName string - wsconn *websocket.Conn - iceServers []string - wg *sync.WaitGroup - pathManager webRTCConnPathManager - parent webRTCConnParent + readBufferCount int + pathName string + wsconn *websocket.Conn + iceServers []string + wg *sync.WaitGroup + pathManager webRTCConnPathManager + parent webRTCConnParent + iceTcpMux ice.TCPMux + iceHostNAT1To1IPs []string ctx context.Context ctxCancel func() @@ -77,8 +79,6 @@ type webRTCConn struct { created time.Time curPC *webrtc.PeerConnection mutex sync.RWMutex - - iceTcpMux ice.TCPMux } func newWebRTCConn( @@ -91,22 +91,24 @@ func newWebRTCConn( pathManager webRTCConnPathManager, parent webRTCConnParent, iceTcpMux ice.TCPMux, + iceHostNAT1To1IPs []string, ) *webRTCConn { ctx, ctxCancel := context.WithCancel(parentCtx) c := &webRTCConn{ - readBufferCount: readBufferCount, - pathName: pathName, - wsconn: wsconn, - iceServers: iceServers, - wg: wg, - pathManager: pathManager, - parent: parent, - ctx: ctx, - ctxCancel: ctxCancel, - uuid: uuid.New(), - created: time.Now(), - iceTcpMux: iceTcpMux, + readBufferCount: readBufferCount, + pathName: pathName, + wsconn: wsconn, + iceServers: iceServers, + wg: wg, + pathManager: pathManager, + parent: parent, + ctx: ctx, + ctxCancel: ctxCancel, + uuid: uuid.New(), + created: time.Now(), + iceTcpMux: iceTcpMux, + iceHostNAT1To1IPs: iceHostNAT1To1IPs, } c.log(logger.Info, "opened") @@ -251,18 +253,20 @@ func (c *webRTCConn) runInner(ctx context.Context) error { return err } + var settingsEngine = webrtc.SettingEngine{} var configuration = webrtc.Configuration{ICEServers: c.genICEServers()} - var pc *webrtc.PeerConnection - if c.iceTcpMux == nil { - pc, err = webrtc.NewPeerConnection(configuration) - } else { - settingsEngine := webrtc.SettingEngine{} + if c.iceTcpMux != nil { settingsEngine.SetICETCPMux(c.iceTcpMux) settingsEngine.SetNetworkTypes([]webrtc.NetworkType{webrtc.NetworkTypeTCP4}) - pc, err = NewPeerConnection(configuration, webrtc.WithSettingEngine(settingsEngine)) } + if c.iceHostNAT1To1IPs != nil { + settingsEngine.SetNAT1To1IPs(c.iceHostNAT1To1IPs, webrtc.ICECandidateTypeHost) + } + + pc, err := NewPeerConnection(configuration, webrtc.WithSettingEngine(settingsEngine)) + if err != nil { return err } diff --git a/internal/core/webrtc_server.go b/internal/core/webrtc_server.go index ef3f7f4e07c..dacd1c96431 100644 --- a/internal/core/webrtc_server.go +++ b/internal/core/webrtc_server.go @@ -86,7 +86,8 @@ type webRTCServer struct { tlsConfig *tls.Config conns map[*webRTCConn]struct{} - webrtcTCPMux ice.TCPMux + tcpMux ice.TCPMux + iceHostNAT1To1IPs []string // in connNew chan webRTCConnNewReq @@ -111,6 +112,7 @@ func newWebRTCServer( parent webRTCServerParent, iceTcpMuxEnable bool, iceTcpMuxAddress string, + iceHostNAT1To1IPs []string, ) (*webRTCServer, error) { ln, err := net.Listen("tcp", address) if err != nil { @@ -156,7 +158,8 @@ func newWebRTCServer( ctxCancel: ctxCancel, ln: ln, tlsConfig: tlsConfig, - webrtcTCPMux: iceTcpMux, + tcpMux: iceTcpMux, + iceHostNAT1To1IPs: iceHostNAT1To1IPs, conns: make(map[*webRTCConn]struct{}), connNew: make(chan webRTCConnNewReq), chConnClose: make(chan *webRTCConn), @@ -224,7 +227,8 @@ outer: &s.wg, s.pathManager, s, - s.webrtcTCPMux, + s.tcpMux, + s.iceHostNAT1To1IPs, ) s.conns[c] = struct{}{} From eefc1441e5d05976abc260a96ff60a2197b26ee2 Mon Sep 17 00:00:00 2001 From: andrew-ld <43882924+andrew-ld@users.noreply.github.com> Date: Thu, 22 Dec 2022 11:17:40 +0100 Subject: [PATCH 03/13] typo --- internal/core/webrtc_server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/core/webrtc_server.go b/internal/core/webrtc_server.go index dacd1c96431..318dd67c732 100644 --- a/internal/core/webrtc_server.go +++ b/internal/core/webrtc_server.go @@ -86,7 +86,7 @@ type webRTCServer struct { tlsConfig *tls.Config conns map[*webRTCConn]struct{} - tcpMux ice.TCPMux + iceTcpMux ice.TCPMux iceHostNAT1To1IPs []string // in @@ -158,7 +158,7 @@ func newWebRTCServer( ctxCancel: ctxCancel, ln: ln, tlsConfig: tlsConfig, - tcpMux: iceTcpMux, + iceTcpMux: iceTcpMux, iceHostNAT1To1IPs: iceHostNAT1To1IPs, conns: make(map[*webRTCConn]struct{}), connNew: make(chan webRTCConnNewReq), @@ -227,7 +227,7 @@ outer: &s.wg, s.pathManager, s, - s.tcpMux, + s.iceTcpMux, s.iceHostNAT1To1IPs, ) s.conns[c] = struct{}{} From 2ea14c34d9d5b269651f12f5684ebb2f1459208d Mon Sep 17 00:00:00 2001 From: andrew-ld <43882924+andrew-ld@users.noreply.github.com> Date: Thu, 22 Dec 2022 12:47:11 +0100 Subject: [PATCH 04/13] rename config keys --- internal/conf/conf.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 1b268f2de7b..331ee03a245 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -232,9 +232,9 @@ type Conf struct { WebRTCAllowOrigin string `json:"webrtcAllowOrigin"` WebRTCTrustedProxies IPsOrCIDRs `json:"webrtcTrustedProxies"` WebRTCICEServers []string `json:"webrtcICEServers"` - WebRTCICETCPMuxEnable bool `json:"webRTCICETCPMuxEnable"` - WebRTCICETCPMuxAddress string `json:"webRTCICETCPMuxAddress"` - WebRTCICEHostNAT1To1IPs []string `json:"webRTCICEHostNAT1To1IPs"` + WebRTCICETCPMuxEnable bool `json:"webrtcICETCPMuxEnable"` + WebRTCICETCPMuxAddress string `json:"webrtcICETCPMuxAddress"` + WebRTCICEHostNAT1To1IPs []string `json:"webrtcICEHostNAT1To1IPs"` // paths Paths map[string]*PathConf `json:"paths"` From f236531f033d403f2077878f902f95e557d7d517 Mon Sep 17 00:00:00 2001 From: "andrew (from workstation)" <43882924+andrew-ld@users.noreply.github.com> Date: Mon, 26 Dec 2022 14:30:11 +0100 Subject: [PATCH 05/13] apply codecov suggestions --- internal/core/webrtc_conn.go | 15 +++++++-------- internal/core/webrtc_server.go | 18 +++++++++--------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/internal/core/webrtc_conn.go b/internal/core/webrtc_conn.go index 290df7eb89a..405acd853fb 100644 --- a/internal/core/webrtc_conn.go +++ b/internal/core/webrtc_conn.go @@ -70,7 +70,7 @@ type webRTCConn struct { wg *sync.WaitGroup pathManager webRTCConnPathManager parent webRTCConnParent - iceTcpMux ice.TCPMux + iceTCPMux ice.TCPMux iceHostNAT1To1IPs []string ctx context.Context @@ -90,7 +90,7 @@ func newWebRTCConn( wg *sync.WaitGroup, pathManager webRTCConnPathManager, parent webRTCConnParent, - iceTcpMux ice.TCPMux, + iceTCPMux ice.TCPMux, iceHostNAT1To1IPs []string, ) *webRTCConn { ctx, ctxCancel := context.WithCancel(parentCtx) @@ -107,7 +107,7 @@ func newWebRTCConn( ctxCancel: ctxCancel, uuid: uuid.New(), created: time.Now(), - iceTcpMux: iceTcpMux, + iceTCPMux: iceTCPMux, iceHostNAT1To1IPs: iceHostNAT1To1IPs, } @@ -253,11 +253,11 @@ func (c *webRTCConn) runInner(ctx context.Context) error { return err } - var settingsEngine = webrtc.SettingEngine{} - var configuration = webrtc.Configuration{ICEServers: c.genICEServers()} + settingsEngine := webrtc.SettingEngine{} + configuration := webrtc.Configuration{ICEServers: c.genICEServers()} - if c.iceTcpMux != nil { - settingsEngine.SetICETCPMux(c.iceTcpMux) + if c.iceTCPMux != nil { + settingsEngine.SetICETCPMux(c.iceTCPMux) settingsEngine.SetNetworkTypes([]webrtc.NetworkType{webrtc.NetworkTypeTCP4}) } @@ -266,7 +266,6 @@ func (c *webRTCConn) runInner(ctx context.Context) error { } pc, err := NewPeerConnection(configuration, webrtc.WithSettingEngine(settingsEngine)) - if err != nil { return err } diff --git a/internal/core/webrtc_server.go b/internal/core/webrtc_server.go index 318dd67c732..96886009512 100644 --- a/internal/core/webrtc_server.go +++ b/internal/core/webrtc_server.go @@ -86,7 +86,7 @@ type webRTCServer struct { tlsConfig *tls.Config conns map[*webRTCConn]struct{} - iceTcpMux ice.TCPMux + iceTCPMux ice.TCPMux iceHostNAT1To1IPs []string // in @@ -110,8 +110,8 @@ func newWebRTCServer( pathManager *pathManager, metrics *metrics, parent webRTCServerParent, - iceTcpMuxEnable bool, - iceTcpMuxAddress string, + iceTCPMuxEnable bool, + iceTCPMuxAddress string, iceHostNAT1To1IPs []string, ) (*webRTCServer, error) { ln, err := net.Listen("tcp", address) @@ -132,15 +132,15 @@ func newWebRTCServer( } } - var iceTcpMux ice.TCPMux - if iceTcpMuxEnable { - tcpMuxLn, err := net.Listen("tcp", iceTcpMuxAddress) + var iceTCPMux ice.TCPMux + if iceTCPMuxEnable { + tcpMuxLn, err := net.Listen("tcp", iceTCPMuxAddress) if err != nil { tcpMuxLn.Close() return nil, err } - iceTcpMux = webrtc.NewICETCPMux(nil, tcpMuxLn, 8) + iceTCPMux = webrtc.NewICETCPMux(nil, tcpMuxLn, 8) } ctx, ctxCancel := context.WithCancel(parentCtx) @@ -158,7 +158,7 @@ func newWebRTCServer( ctxCancel: ctxCancel, ln: ln, tlsConfig: tlsConfig, - iceTcpMux: iceTcpMux, + iceTCPMux: iceTCPMux, iceHostNAT1To1IPs: iceHostNAT1To1IPs, conns: make(map[*webRTCConn]struct{}), connNew: make(chan webRTCConnNewReq), @@ -227,7 +227,7 @@ outer: &s.wg, s.pathManager, s, - s.iceTcpMux, + s.iceTCPMux, s.iceHostNAT1To1IPs, ) s.conns[c] = struct{}{} From 6fc4b359a35e0e5770450df24926834047b2a7f9 Mon Sep 17 00:00:00 2001 From: andrew-ld <43882924+andrew-ld@users.noreply.github.com> Date: Thu, 29 Dec 2022 09:54:28 +0100 Subject: [PATCH 06/13] apply review suggestions --- apidocs/openapi.yaml | 8 ++++++++ internal/core/core.go | 5 ++++- internal/core/webrtc_server.go | 14 +++++++++++++- rtsp-simple-server.yml | 7 +++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/apidocs/openapi.yaml b/apidocs/openapi.yaml index 3081e64ab0a..0e8e5e0ffd7 100644 --- a/apidocs/openapi.yaml +++ b/apidocs/openapi.yaml @@ -147,6 +147,14 @@ components: type: array items: type: string + webrtcICETCPMuxEnable: + type: boolean + webrtcICETCPMuxAddress: + type: string + webrtcICEHostNAT1To1IPs: + type: array + items: + type: string # paths paths: diff --git a/internal/core/core.go b/internal/core/core.go index 268f432004e..2f3985c9f93 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -577,7 +577,10 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { !reflect.DeepEqual(newConf.WebRTCICEServers, p.conf.WebRTCICEServers) || newConf.ReadBufferCount != p.conf.ReadBufferCount || closeMetrics || - closePathManager + closePathManager || + newConf.WebRTCICETCPMuxEnable != p.conf.WebRTCICETCPMuxEnable || + !reflect.DeepEqual(newConf.WebRTCICETCPMuxAddress, p.conf.WebRTCICETCPMuxAddress) || + !reflect.DeepEqual(newConf.WebRTCICEHostNAT1To1IPs, p.conf.WebRTCICEHostNAT1To1IPs) closeAPI := newConf == nil || newConf.API != p.conf.API || diff --git a/internal/core/webrtc_server.go b/internal/core/webrtc_server.go index 96886009512..aed37170ee0 100644 --- a/internal/core/webrtc_server.go +++ b/internal/core/webrtc_server.go @@ -83,6 +83,7 @@ type webRTCServer struct { ctxCancel func() wg sync.WaitGroup ln net.Listener + tcpMuxLn net.Listener tlsConfig *tls.Config conns map[*webRTCConn]struct{} @@ -133,8 +134,9 @@ func newWebRTCServer( } var iceTCPMux ice.TCPMux + var tcpMuxLn net.Listener if iceTCPMuxEnable { - tcpMuxLn, err := net.Listen("tcp", iceTCPMuxAddress) + tcpMuxLn, err = net.Listen("tcp", iceTCPMuxAddress) if err != nil { tcpMuxLn.Close() return nil, err @@ -157,6 +159,7 @@ func newWebRTCServer( ctx: ctx, ctxCancel: ctxCancel, ln: ln, + tcpMuxLn: tcpMuxLn, tlsConfig: tlsConfig, iceTCPMux: iceTCPMux, iceHostNAT1To1IPs: iceHostNAT1To1IPs, @@ -169,6 +172,10 @@ func newWebRTCServer( s.log(logger.Info, "listener opened on "+address) + if tcpMuxLn != nil { + s.log(logger.Info, "ice mux tcp listener opened on "+iceTCPMuxAddress) + } + if s.metrics != nil { s.metrics.webRTCServerSet(s) } @@ -276,6 +283,11 @@ outer: s.ctxCancel() hs.Shutdown(context.Background()) + + if s.tcpMuxLn != nil { + s.tcpMuxLn.Close() + } + s.ln.Close() // in case Shutdown() is called before Serve() } diff --git a/rtsp-simple-server.yml b/rtsp-simple-server.yml index aeb9ebbbc54..79c57ba4bc4 100644 --- a/rtsp-simple-server.yml +++ b/rtsp-simple-server.yml @@ -173,6 +173,13 @@ hlsTrustedProxies: [] webrtcDisable: no # Address of the WebRTC listener. webrtcAddress: :8889 +# Enable support for the WebRTC ICE TCP protocol. +webrtcICETCPMuxEnable: no +# Address of the WebRTC ICE TCP address. +webrtcICETCPMuxAddress: :8886 +# contains a list of public IP addresses that are to be used as a host. +# This is used typically for servers that are behind 1:1 D-NAT +webrtcICEHostNAT1To1IPs: null # Enable TLS/HTTPS on the WebRTC server. webrtcEncryption: no # Path to the server key. From c9d5175576147efd36bc7dfc5668ce8240402a6f Mon Sep 17 00:00:00 2001 From: andrew-ld <43882924+andrew-ld@users.noreply.github.com> Date: Thu, 29 Dec 2022 09:55:58 +0100 Subject: [PATCH 07/13] typo --- rtsp-simple-server.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtsp-simple-server.yml b/rtsp-simple-server.yml index 79c57ba4bc4..e1d24ce01ca 100644 --- a/rtsp-simple-server.yml +++ b/rtsp-simple-server.yml @@ -175,7 +175,7 @@ webrtcDisable: no webrtcAddress: :8889 # Enable support for the WebRTC ICE TCP protocol. webrtcICETCPMuxEnable: no -# Address of the WebRTC ICE TCP address. +# Address of the WebRTC ICE TCP listener. webrtcICETCPMuxAddress: :8886 # contains a list of public IP addresses that are to be used as a host. # This is used typically for servers that are behind 1:1 D-NAT From dd0bdc5a1316463254462fb0af39d0a874d5d4b4 Mon Sep 17 00:00:00 2001 From: andrew-ld <43882924+andrew-ld@users.noreply.github.com> Date: Fri, 30 Dec 2022 11:07:45 +0100 Subject: [PATCH 08/13] dont use deepequal for WebRTCICETCPMuxAddress --- internal/core/core.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/core/core.go b/internal/core/core.go index 2f3985c9f93..c269a4759f6 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -579,7 +579,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { closeMetrics || closePathManager || newConf.WebRTCICETCPMuxEnable != p.conf.WebRTCICETCPMuxEnable || - !reflect.DeepEqual(newConf.WebRTCICETCPMuxAddress, p.conf.WebRTCICETCPMuxAddress) || + newConf.WebRTCICETCPMuxAddress != p.conf.WebRTCICETCPMuxAddress || !reflect.DeepEqual(newConf.WebRTCICEHostNAT1To1IPs, p.conf.WebRTCICEHostNAT1To1IPs) closeAPI := newConf == nil || From e24eaba1ffc80e1e8ee297fab2f55e4747ef0882 Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Fri, 30 Dec 2022 15:19:01 +0100 Subject: [PATCH 09/13] unexport NewPeerConnection() --- internal/core/webrtc_conn.go | 52 +++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/internal/core/webrtc_conn.go b/internal/core/webrtc_conn.go index 634550f597c..8179b33262d 100644 --- a/internal/core/webrtc_conn.go +++ b/internal/core/webrtc_conn.go @@ -36,6 +36,31 @@ const ( handshakeDeadline = 10 * time.Second ) +// newPeerConnection creates a PeerConnection with the default codecs and +// interceptors. See RegisterDefaultCodecs and RegisterDefaultInterceptors. +// +// This function is a copy of webrtc/peerconnection.go +// unlike the original one, allows you to add additional custom options +func newPeerConnection(configuration webrtc.Configuration, + options ...func(*webrtc.API), +) (*webrtc.PeerConnection, error) { + m := &webrtc.MediaEngine{} + if err := m.RegisterDefaultCodecs(); err != nil { + return nil, err + } + + i := &interceptor.Registry{} + if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil { + return nil, err + } + + options = append(options, webrtc.WithMediaEngine(m)) + options = append(options, webrtc.WithInterceptorRegistry(i)) + + api := webrtc.NewAPI(options...) + return api.NewPeerConnection(configuration) +} + type webRTCTrack struct { media *media.Media format format.Format @@ -184,29 +209,6 @@ func (c *webRTCConn) run() { c.log(logger.Info, "closed (%v)", err) } -// NewPeerConnection creates a PeerConnection with the default codecs and -// interceptors. See RegisterDefaultCodecs and RegisterDefaultInterceptors. -// -// This function is a copy of webrtc/peerconnection.go -// unlike the original one, allows you to add additional custom options -func NewPeerConnection(configuration webrtc.Configuration, options ...func(*webrtc.API)) (*webrtc.PeerConnection, error) { - m := &webrtc.MediaEngine{} - if err := m.RegisterDefaultCodecs(); err != nil { - return nil, err - } - - i := &interceptor.Registry{} - if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil { - return nil, err - } - - options = append(options, webrtc.WithMediaEngine(m)) - options = append(options, webrtc.WithInterceptorRegistry(i)) - - api := webrtc.NewAPI(options...) - return api.NewPeerConnection(configuration) -} - func (c *webRTCConn) runInner(ctx context.Context) error { go func() { <-ctx.Done() @@ -253,8 +255,8 @@ func (c *webRTCConn) runInner(ctx context.Context) error { return err } - settingsEngine := webrtc.SettingEngine{} configuration := webrtc.Configuration{ICEServers: c.genICEServers()} + settingsEngine := webrtc.SettingEngine{} if c.iceTCPMux != nil { settingsEngine.SetICETCPMux(c.iceTCPMux) @@ -265,7 +267,7 @@ func (c *webRTCConn) runInner(ctx context.Context) error { settingsEngine.SetNAT1To1IPs(c.iceHostNAT1To1IPs, webrtc.ICECandidateTypeHost) } - pc, err := NewPeerConnection(configuration, webrtc.WithSettingEngine(settingsEngine)) + pc, err := newPeerConnection(configuration, webrtc.WithSettingEngine(settingsEngine)) if err != nil { return err } From 34960d9d0af59694e88c01fbd1b5b4110b1d791a Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Fri, 30 Dec 2022 15:19:22 +0100 Subject: [PATCH 10/13] remove Dockerfile --- Dockerfile | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index e46b969c0a7..00000000000 --- a/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM golang:alpine as builder -WORKDIR /build -COPY . . -RUN go build - -FROM alpine:latest -COPY --from=builder /build/rtsp-simple-server / -CMD ["/rtsp-simple-server"] From 4c2a0835720a4735b5058ecf938791fd94615eb6 Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Fri, 30 Dec 2022 15:22:05 +0100 Subject: [PATCH 11/13] use an empty list instead of nil value in webrtcICEHostNAT1To1IPs --- internal/core/webrtc_conn.go | 2 +- rtsp-simple-server.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/core/webrtc_conn.go b/internal/core/webrtc_conn.go index 8179b33262d..20093339391 100644 --- a/internal/core/webrtc_conn.go +++ b/internal/core/webrtc_conn.go @@ -263,7 +263,7 @@ func (c *webRTCConn) runInner(ctx context.Context) error { settingsEngine.SetNetworkTypes([]webrtc.NetworkType{webrtc.NetworkTypeTCP4}) } - if c.iceHostNAT1To1IPs != nil { + if len(c.iceHostNAT1To1IPs) != 0 { settingsEngine.SetNAT1To1IPs(c.iceHostNAT1To1IPs, webrtc.ICECandidateTypeHost) } diff --git a/rtsp-simple-server.yml b/rtsp-simple-server.yml index e1d24ce01ca..ad39ea17830 100644 --- a/rtsp-simple-server.yml +++ b/rtsp-simple-server.yml @@ -177,9 +177,9 @@ webrtcAddress: :8889 webrtcICETCPMuxEnable: no # Address of the WebRTC ICE TCP listener. webrtcICETCPMuxAddress: :8886 -# contains a list of public IP addresses that are to be used as a host. +# List of public IP addresses that are to be used as a host. # This is used typically for servers that are behind 1:1 D-NAT -webrtcICEHostNAT1To1IPs: null +webrtcICEHostNAT1To1IPs: [] # Enable TLS/HTTPS on the WebRTC server. webrtcEncryption: no # Path to the server key. From f72c2454cf6b83f22e0183aca8a849131cc887a5 Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Fri, 30 Dec 2022 15:31:12 +0100 Subject: [PATCH 12/13] drop webrtcICETCPMuxEnable and enable TCP mux when webrtcICETCPMuxAddress is filled --- apidocs/openapi.yaml | 6 ++---- internal/conf/conf.go | 6 +----- internal/core/core.go | 8 +++----- internal/core/webrtc_server.go | 5 ++--- rtsp-simple-server.yml | 14 +++++++------- 5 files changed, 15 insertions(+), 24 deletions(-) diff --git a/apidocs/openapi.yaml b/apidocs/openapi.yaml index 0e8e5e0ffd7..dbfe4047509 100644 --- a/apidocs/openapi.yaml +++ b/apidocs/openapi.yaml @@ -147,14 +147,12 @@ components: type: array items: type: string - webrtcICETCPMuxEnable: - type: boolean - webrtcICETCPMuxAddress: - type: string webrtcICEHostNAT1To1IPs: type: array items: type: string + webrtcICETCPMuxAddress: + type: string # paths paths: diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 331ee03a245..1674dcdeaf6 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -232,9 +232,8 @@ type Conf struct { WebRTCAllowOrigin string `json:"webrtcAllowOrigin"` WebRTCTrustedProxies IPsOrCIDRs `json:"webrtcTrustedProxies"` WebRTCICEServers []string `json:"webrtcICEServers"` - WebRTCICETCPMuxEnable bool `json:"webrtcICETCPMuxEnable"` - WebRTCICETCPMuxAddress string `json:"webrtcICETCPMuxAddress"` WebRTCICEHostNAT1To1IPs []string `json:"webrtcICEHostNAT1To1IPs"` + WebRTCICETCPMuxAddress string `json:"webrtcICETCPMuxAddress"` // paths Paths map[string]*PathConf `json:"paths"` @@ -415,9 +414,6 @@ func (conf *Conf) CheckAndFillMissing() error { if conf.WebRTCICEServers == nil { conf.WebRTCICEServers = []string{"stun:stun.l.google.com:19302"} } - if conf.WebRTCICETCPMuxAddress == "" { - conf.WebRTCICETCPMuxAddress = "127.0.0.1:9996" - } // do not add automatically "all", since user may want to // initialize all paths through API or hot reloading. diff --git a/internal/core/core.go b/internal/core/core.go index c269a4759f6..21dfdd25fdd 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -413,9 +413,8 @@ func (p *Core) createResources(initial bool) error { p.pathManager, p.metrics, p, - p.conf.WebRTCICETCPMuxEnable, - p.conf.WebRTCICETCPMuxAddress, p.conf.WebRTCICEHostNAT1To1IPs, + p.conf.WebRTCICETCPMuxAddress, ) if err != nil { return err @@ -578,9 +577,8 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { newConf.ReadBufferCount != p.conf.ReadBufferCount || closeMetrics || closePathManager || - newConf.WebRTCICETCPMuxEnable != p.conf.WebRTCICETCPMuxEnable || - newConf.WebRTCICETCPMuxAddress != p.conf.WebRTCICETCPMuxAddress || - !reflect.DeepEqual(newConf.WebRTCICEHostNAT1To1IPs, p.conf.WebRTCICEHostNAT1To1IPs) + !reflect.DeepEqual(newConf.WebRTCICEHostNAT1To1IPs, p.conf.WebRTCICEHostNAT1To1IPs) || + newConf.WebRTCICETCPMuxAddress != p.conf.WebRTCICETCPMuxAddress closeAPI := newConf == nil || newConf.API != p.conf.API || diff --git a/internal/core/webrtc_server.go b/internal/core/webrtc_server.go index aed37170ee0..410c3659194 100644 --- a/internal/core/webrtc_server.go +++ b/internal/core/webrtc_server.go @@ -111,9 +111,8 @@ func newWebRTCServer( pathManager *pathManager, metrics *metrics, parent webRTCServerParent, - iceTCPMuxEnable bool, - iceTCPMuxAddress string, iceHostNAT1To1IPs []string, + iceTCPMuxAddress string, ) (*webRTCServer, error) { ln, err := net.Listen("tcp", address) if err != nil { @@ -135,7 +134,7 @@ func newWebRTCServer( var iceTCPMux ice.TCPMux var tcpMuxLn net.Listener - if iceTCPMuxEnable { + if iceTCPMuxAddress != "" { tcpMuxLn, err = net.Listen("tcp", iceTCPMuxAddress) if err != nil { tcpMuxLn.Close() diff --git a/rtsp-simple-server.yml b/rtsp-simple-server.yml index ad39ea17830..c6c9b703192 100644 --- a/rtsp-simple-server.yml +++ b/rtsp-simple-server.yml @@ -173,13 +173,6 @@ hlsTrustedProxies: [] webrtcDisable: no # Address of the WebRTC listener. webrtcAddress: :8889 -# Enable support for the WebRTC ICE TCP protocol. -webrtcICETCPMuxEnable: no -# Address of the WebRTC ICE TCP listener. -webrtcICETCPMuxAddress: :8886 -# List of public IP addresses that are to be used as a host. -# This is used typically for servers that are behind 1:1 D-NAT -webrtcICEHostNAT1To1IPs: [] # Enable TLS/HTTPS on the WebRTC server. webrtcEncryption: no # Path to the server key. @@ -203,6 +196,13 @@ webrtcTrustedProxies: [] # if user is "AUTH_SECRET", then authentication is secret based. # the secret must be inserted into the pass field. webrtcICEServers: [stun:stun.l.google.com:19302] +# List of public IP addresses that are to be used as a host. +# This is used typically for servers that are behind 1:1 D-NAT. +webrtcICEHostNAT1To1IPs: [] +# Address of a ICE TCP listener in format host:port. +# If filled, ICE traffic will come through a single TCP port, +# allowing the deployment of the server inside a container or behind a NAT. +webrtcICETCPMuxAddress: ############################################### # Path parameters From 83304babde7ed5551edf10f79750ba649d073ad8 Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Fri, 30 Dec 2022 15:39:08 +0100 Subject: [PATCH 13/13] run go mod tidy --- go.mod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 0c8b26e5999..4ac0e81f905 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,8 @@ require ( github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/notedit/rtmp v0.0.2 github.com/orcaman/writerseeker v0.0.0 + github.com/pion/ice/v2 v2.2.11 + github.com/pion/interceptor v0.1.11 github.com/pion/rtp v1.7.13 github.com/pion/webrtc/v3 v3.1.47 github.com/stretchr/testify v1.7.1 @@ -42,8 +44,6 @@ require ( github.com/pelletier/go-toml/v2 v2.0.1 // indirect github.com/pion/datachannel v1.5.2 // indirect github.com/pion/dtls/v2 v2.1.5 // indirect - github.com/pion/ice/v2 v2.2.11 // indirect - github.com/pion/interceptor v0.1.11 // indirect github.com/pion/logging v0.2.2 // indirect github.com/pion/mdns v0.0.5 // indirect github.com/pion/randutil v0.1.0 // indirect