Browse Source

(webrtc) added support for ice mux tcp and nat1to1ips (#1323)

* add webrtcp static tcp mux port

* add ice nat1 host configuration and cleanup

* typo

* rename config keys

* apply codecov suggestions

* apply review suggestions

* typo

* dont use deepequal for WebRTCICETCPMuxAddress

* unexport NewPeerConnection()

* remove Dockerfile

* use an empty list instead of nil value in webrtcICEHostNAT1To1IPs

* drop webrtcICETCPMuxEnable and enable TCP mux when webrtcICETCPMuxAddress is filled

* run go mod tidy

Co-authored-by: aler9 <46489434+aler9@users.noreply.github.com>
pull/1364/head
andrew-ld 3 years ago committed by GitHub
parent
commit
b27c363ecf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      apidocs/openapi.yaml
  2. 4
      go.mod
  3. 18
      internal/conf/conf.go
  4. 6
      internal/core/core.go
  5. 85
      internal/core/webrtc_conn.go
  6. 34
      internal/core/webrtc_server.go
  7. 7
      rtsp-simple-server.yml

6
apidocs/openapi.yaml

@ -147,6 +147,12 @@ components: @@ -147,6 +147,12 @@ components:
type: array
items:
type: string
webrtcICEHostNAT1To1IPs:
type: array
items:
type: string
webrtcICETCPMuxAddress:
type: string
# paths
paths:

4
go.mod

@ -16,6 +16,8 @@ require ( @@ -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 ( @@ -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

18
internal/conf/conf.go

@ -224,14 +224,16 @@ type Conf struct { @@ -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"`
WebRTCICEHostNAT1To1IPs []string `json:"webrtcICEHostNAT1To1IPs"`
WebRTCICETCPMuxAddress string `json:"webrtcICETCPMuxAddress"`
// paths
Paths map[string]*PathConf `json:"paths"`

6
internal/core/core.go

@ -413,6 +413,8 @@ func (p *Core) createResources(initial bool) error { @@ -413,6 +413,8 @@ func (p *Core) createResources(initial bool) error {
p.pathManager,
p.metrics,
p,
p.conf.WebRTCICEHostNAT1To1IPs,
p.conf.WebRTCICETCPMuxAddress,
)
if err != nil {
return err
@ -574,7 +576,9 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { @@ -574,7 +576,9 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
!reflect.DeepEqual(newConf.WebRTCICEServers, p.conf.WebRTCICEServers) ||
newConf.ReadBufferCount != p.conf.ReadBufferCount ||
closeMetrics ||
closePathManager
closePathManager ||
!reflect.DeepEqual(newConf.WebRTCICEHostNAT1To1IPs, p.conf.WebRTCICEHostNAT1To1IPs) ||
newConf.WebRTCICETCPMuxAddress != p.conf.WebRTCICETCPMuxAddress
closeAPI := newConf == nil ||
newConf.API != p.conf.API ||

85
internal/core/webrtc_conn.go

@ -24,6 +24,8 @@ import ( @@ -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"
@ -34,6 +36,31 @@ const ( @@ -34,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
@ -61,13 +88,15 @@ type webRTCConnParent interface { @@ -61,13 +88,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()
@ -86,21 +115,25 @@ func newWebRTCConn( @@ -86,21 +115,25 @@ func newWebRTCConn(
wg *sync.WaitGroup,
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(),
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")
@ -222,9 +255,19 @@ func (c *webRTCConn) runInner(ctx context.Context) error { @@ -222,9 +255,19 @@ func (c *webRTCConn) runInner(ctx context.Context) error {
return err
}
pc, err := webrtc.NewPeerConnection(webrtc.Configuration{
ICEServers: c.genICEServers(),
})
configuration := webrtc.Configuration{ICEServers: c.genICEServers()}
settingsEngine := webrtc.SettingEngine{}
if c.iceTCPMux != nil {
settingsEngine.SetICETCPMux(c.iceTCPMux)
settingsEngine.SetNetworkTypes([]webrtc.NetworkType{webrtc.NetworkTypeTCP4})
}
if len(c.iceHostNAT1To1IPs) != 0 {
settingsEngine.SetNAT1To1IPs(c.iceHostNAT1To1IPs, webrtc.ICECandidateTypeHost)
}
pc, err := newPeerConnection(configuration, webrtc.WithSettingEngine(settingsEngine))
if err != nil {
return err
}

34
internal/core/webrtc_server.go

@ -15,6 +15,8 @@ import ( @@ -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"
@ -81,9 +83,13 @@ type webRTCServer struct { @@ -81,9 +83,13 @@ type webRTCServer struct {
ctxCancel func()
wg sync.WaitGroup
ln net.Listener
tcpMuxLn net.Listener
tlsConfig *tls.Config
conns map[*webRTCConn]struct{}
iceTCPMux ice.TCPMux
iceHostNAT1To1IPs []string
// in
connNew chan webRTCConnNewReq
chConnClose chan *webRTCConn
@ -105,6 +111,8 @@ func newWebRTCServer( @@ -105,6 +111,8 @@ func newWebRTCServer(
pathManager *pathManager,
metrics *metrics,
parent webRTCServerParent,
iceHostNAT1To1IPs []string,
iceTCPMuxAddress string,
) (*webRTCServer, error) {
ln, err := net.Listen("tcp", address)
if err != nil {
@ -124,6 +132,18 @@ func newWebRTCServer( @@ -124,6 +132,18 @@ func newWebRTCServer(
}
}
var iceTCPMux ice.TCPMux
var tcpMuxLn net.Listener
if iceTCPMuxAddress != "" {
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{
@ -138,7 +158,10 @@ func newWebRTCServer( @@ -138,7 +158,10 @@ func newWebRTCServer(
ctx: ctx,
ctxCancel: ctxCancel,
ln: ln,
tcpMuxLn: tcpMuxLn,
tlsConfig: tlsConfig,
iceTCPMux: iceTCPMux,
iceHostNAT1To1IPs: iceHostNAT1To1IPs,
conns: make(map[*webRTCConn]struct{}),
connNew: make(chan webRTCConnNewReq),
chConnClose: make(chan *webRTCConn),
@ -148,6 +171,10 @@ func newWebRTCServer( @@ -148,6 +171,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)
}
@ -206,6 +233,8 @@ outer: @@ -206,6 +233,8 @@ outer:
&s.wg,
s.pathManager,
s,
s.iceTCPMux,
s.iceHostNAT1To1IPs,
)
s.conns[c] = struct{}{}
@ -253,6 +282,11 @@ outer: @@ -253,6 +282,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()
}

7
rtsp-simple-server.yml

@ -196,6 +196,13 @@ webrtcTrustedProxies: [] @@ -196,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

Loading…
Cancel
Save