Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 16 commits into from
Dec 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apidocs/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ components:
type: array
items:
type: string
webrtcICEHostNAT1To1IPs:
type: array
items:
type: string
webrtcICETCPMuxAddress:
type: string

# paths
paths:
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
18 changes: 10 additions & 8 deletions internal/conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down
6 changes: 5 additions & 1 deletion internal/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 ||
Expand Down
85 changes: 64 additions & 21 deletions internal/core/webrtc_conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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")
Expand Down Expand Up @@ -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
}
Expand Down
34 changes: 34 additions & 0 deletions internal/core/webrtc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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{
Expand All @@ -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),
Expand All @@ -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)
}
Expand Down Expand Up @@ -206,6 +233,8 @@ outer:
&s.wg,
s.pathManager,
s,
s.iceTCPMux,
s.iceHostNAT1To1IPs,
)
s.conns[c] = struct{}{}

Expand Down Expand Up @@ -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()
}

Expand Down
7 changes: 7 additions & 0 deletions rtsp-simple-server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down