diff --git a/README.md b/README.md index 6fb4ad29..9a3b07ee 100644 --- a/README.md +++ b/README.md @@ -170,14 +170,18 @@ The `--network=host` flag is mandatory since Docker can change the source port o ``` docker run --rm -it \ -e MTX_PROTOCOLS=tcp \ +-e MTX_WEBRTCADDITIONALHOSTS=192.168.x.x \ -p 8554:8554 \ -p 1935:1935 \ -p 8888:8888 \ -p 8889:8889 \ -p 8890:8890/udp \ +-p 8189:8189/udp \ bluenviron/mediamtx ``` +set `MTX_WEBRTCADDITIONALHOSTS` to your local IP address. + ### Arch Linux package If you are running the Arch Linux distribution, run: @@ -1596,18 +1600,15 @@ Be aware that RTMPS is currently unsupported by all major players. However, you #### Connectivity issues -If the server is hosted inside a container or is behind a NAT, additional configuration is required in order to allow the two WebRTC parts (the browser and the server) to establish a connection (WebRTC/ICE connection). +If the server is hosted inside a container or is behind a NAT, additional configuration is required in order to allow the two WebRTC parts (server and client) to establish a connection. -A first method consists into forcing all WebRTC/ICE connections to pass through a single UDP server port, by using the parameters: +Make sure that `webrtcAdditionalHosts` includes your public IP, that is the IP that can be used by clients to reach the server. If clients are on the same LAN as the server, then it's the LAN address of the server, otherwise it's the public internet IP of the server: ```yml -# public IP of the server -webrtcICEHostNAT1To1IPs: [192.168.x.x] -# any port of choice -webrtcICEUDPMuxAddress: :8189 +webrtcAdditionalHosts: [192.168.x.x] ``` -The NAT / container must then be configured in order to route all incoming UDP packets on port 8189 to the server. If you're using Docker, this can be achieved with the flag: +If there's a NAT / container between server and clients, it must be configured to route all incoming UDP packets on port 8189 to the server. If you're using Docker, this can be achieved with the flag: ```sh docker run --rm -it \ @@ -1616,27 +1617,27 @@ docker run --rm -it \ bluenviron/mediamtx ``` -If the UDP protocol is blocked by a firewall, all WebRTC/ICE connections can be forced to pass through a single TCP server port: +If you still have problems, maybe the UDP protocol is blocked by a firewall. Enable the local TCP listener: ```yml -# public IP of the server -webrtcICEHostNAT1To1IPs: [192.168.x.x] # any port of choice -webrtcICETCPMuxAddress: :8189 +webrtcLocalTCPAddress: :8189 ``` -The NAT / container must then be configured in order to redirect all incoming TCP packets on port 8189 to the server. If you're using Docker, this can be achieved with the flag: +If there's a NAT / container between server and clients, it must be configured to route all incoming TCP packets on port 8189 to the server. -```sh -docker run --rm -it \ --p 8189:8189 -.... -bluenviron/mediamtx -``` - -Finally, if none of these methods work, you can force all WebRTC/ICE connections to pass through a TURN server, like coturn, that must be configured externally. The server address and credentials must be set in the configuration file: +If you still have problems, enable a STUN server: ```yml +# STUN servers allows to obtain and share the public IP of the server. +webrtcICEServers2: + - url: stun:stun.l.google.com:19302 +``` + +If you really still have problems, you can force all WebRTC/ICE connections to pass through a TURN server, like coturn, that must be configured externally. The server address and credentials must be set in the configuration file: + +```yml +# TURN/TURNS servers forces all traffic through them. webrtcICEServers2: - url: turn:host:port username: user diff --git a/apidocs/openapi.yaml b/apidocs/openapi.yaml index cfb760db..1efec8e4 100644 --- a/apidocs/openapi.yaml +++ b/apidocs/openapi.yaml @@ -157,6 +157,20 @@ components: type: array items: type: string + webrtcLocalUDPAddress: + type: string + webrtcLocalTCPAddress: + type: string + webrtcIPsFromInterfaces: + type: boolean + webrtcIPsFromInterfacesList: + type: array + items: + type: string + webrtcAdditionalHosts: + type: array + items: + type: string webrtcICEServers2: type: array items: @@ -168,18 +182,6 @@ components: type: string password: type: string - webrtcICEInterfaces: - type: array - items: - type: string - webrtcICEHostNAT1To1IPs: - type: array - items: - type: string - webrtcICEUDPMuxAddress: - type: string - webrtcICETCPMuxAddress: - type: string # SRT srt: diff --git a/go.mod b/go.mod index 1ef6d3a1..2e7e4aeb 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,7 @@ require ( github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pion/datachannel v1.5.5 // indirect github.com/pion/dtls/v2 v2.2.7 // indirect - github.com/pion/mdns v0.0.8 // indirect + github.com/pion/mdns v0.0.9 // indirect github.com/pion/randutil v0.1.0 // indirect github.com/pion/sctp v1.8.8 // indirect github.com/pion/srtp/v2 v2.0.18 // indirect @@ -76,4 +76,8 @@ replace code.cloudfoundry.org/bytefmt => github.com/cloudfoundry/bytefmt v0.0.0- replace github.com/pion/sdp/v3 => github.com/aler9/sdp/v3 v3.0.0-20231022165400-33437e07f326 +replace github.com/pion/ice/v2 => github.com/aler9/ice/v2 v2.0.0-20231112223552-32d34dfcf3a1 + +replace github.com/pion/webrtc/v3 => github.com/aler9/webrtc/v3 v3.0.0-20231112223655-e402ed2689c6 + replace github.com/datarhei/gosrt => github.com/aler9/gosrt v0.0.0-20231104205907-3f110868f71d diff --git a/go.sum b/go.sum index ec8e7421..e45777f3 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,12 @@ github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= github.com/aler9/gosrt v0.0.0-20231104205907-3f110868f71d h1:e+oBFUPyjr6dYd4lmT3+NI0lQVpr6R7nTO6z+1XGceQ= github.com/aler9/gosrt v0.0.0-20231104205907-3f110868f71d/go.mod h1:z+FuFVKH0eG03LwuMwVrOLlWhPlpbRlL2OytRK+hs5c= +github.com/aler9/ice/v2 v2.0.0-20231112223552-32d34dfcf3a1 h1:fD6eZt+3/t8bzFn6ZZA2eP63xBP06v3EPfPJu8DO8ys= +github.com/aler9/ice/v2 v2.0.0-20231112223552-32d34dfcf3a1/go.mod h1:lT3kv5uUIlHfXHU/ZRD7uKD/ufM202+eTa3C/umgGf4= github.com/aler9/sdp/v3 v3.0.0-20231022165400-33437e07f326 h1:HA7u47vkcxFiHtiOjm8srh1JRgC0ZPYefPtpDCaTtS0= github.com/aler9/sdp/v3 v3.0.0-20231022165400-33437e07f326/go.mod h1:I40uD/ZSmK2peI6AdJga5fd55d4bFK0oWOgLS9Q8sVc= +github.com/aler9/webrtc/v3 v3.0.0-20231112223655-e402ed2689c6 h1:wMd3D1mLghoYYh31STig8Kwm2qi8QyQKUy09qUUZrVw= +github.com/aler9/webrtc/v3 v3.0.0-20231112223655-e402ed2689c6/go.mod h1:1CaT2fcZzZ6VZA+O1i9yK2DU4EOcXVvSbWG9pr5jefs= github.com/aler9/writerseeker v1.1.0 h1:t+Sm3tjp8scNlqyoa8obpeqwciMNOvdvsxjxEb3Sx3g= github.com/aler9/writerseeker v1.1.0/go.mod h1:QNCcjSKnLsYoTfMmXkEEfgbz6nNXWxKSaBY+hGJGWDA= github.com/asticode/go-astikit v0.30.0 h1:DkBkRQRIxYcknlaU7W7ksNfn4gMFsB0tqMJflxkRsZA= @@ -73,7 +77,7 @@ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= @@ -128,14 +132,13 @@ github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0= github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= -github.com/pion/ice/v2 v2.3.11 h1:rZjVmUwyT55cmN8ySMpL7rsS8KYsJERsrxJLLxpKhdw= -github.com/pion/ice/v2 v2.3.11/go.mod h1:hPcLC3kxMa+JGRzMHqQzjoSj3xtE9F+eoncmXLlCL4E= github.com/pion/interceptor v0.1.25 h1:pwY9r7P6ToQ3+IF0bajN0xmk/fNw/suTgaTdlwTDmhc= github.com/pion/interceptor v0.1.25/go.mod h1:wkbPYAak5zKsfpVDYMtEfWEy8D4zL+rpxCxPImLOg3Y= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/mdns v0.0.8 h1:HhicWIg7OX5PVilyBO6plhMetInbzkVJAhbdJiAeVaI= -github.com/pion/mdns v0.0.8/go.mod h1:hYE72WX8WDveIhg7fmXgMKivD3Puklk0Ymzog0lSyaI= +github.com/pion/mdns v0.0.7/go.mod h1:4iP2UbeFhLI/vWju/bw6ZfwjJzk0z8DNValjGxR/dD8= +github.com/pion/mdns v0.0.9 h1:7Ue5KZsqq8EuqStnpPWV33vYYEH0+skdDN5L7EiEsI4= +github.com/pion/mdns v0.0.9/go.mod h1:2JA5exfxwzXiCihmxpTKgFUpiQws2MnipoPK09vecIc= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I= @@ -153,16 +156,15 @@ github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40= github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI= +github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= -github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc= github.com/pion/transport/v2 v2.2.3 h1:XcOE3/x41HOSKbl1BfyY1TF1dERx7lVvlMCbXU7kfvA= github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pion/turn/v2 v2.1.2/go.mod h1:1kjnPkBcex3dhCU2Am+AAmxDcGhLX3WnMfmkNpvSTQU= github.com/pion/turn/v2 v2.1.3 h1:pYxTVWG2gpC97opdRc5IGsQ1lJ9O/IlNhkzj7MMrGAA= github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= -github.com/pion/webrtc/v3 v3.2.22 h1:Hno262T7+V56MgUO30O0ZirZmVSvbXtnau31SB0WSpc= -github.com/pion/webrtc/v3 v3.2.22/go.mod h1:1CaT2fcZzZ6VZA+O1i9yK2DU4EOcXVvSbWG9pr5jefs= github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -199,8 +201,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -215,12 +217,13 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= -golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -246,24 +249,26 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -271,11 +276,12 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 8e36efa0..e3098942 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -143,20 +143,24 @@ type Conf struct { HLSDirectory string `json:"hlsDirectory"` // WebRTC - WebRTC bool `json:"webrtc"` - WebRTCDisable *bool `json:"webrtcDisable,omitempty"` // deprecated - 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,omitempty"` // deprecated - WebRTCICEServers2 []WebRTCICEServer `json:"webrtcICEServers2"` - WebRTCICEInterfaces []string `json:"webrtcICEInterfaces"` - WebRTCICEHostNAT1To1IPs []string `json:"webrtcICEHostNAT1To1IPs"` - WebRTCICEUDPMuxAddress string `json:"webrtcICEUDPMuxAddress"` - WebRTCICETCPMuxAddress string `json:"webrtcICETCPMuxAddress"` + WebRTC bool `json:"webrtc"` + WebRTCDisable *bool `json:"webrtcDisable,omitempty"` // deprecated + WebRTCAddress string `json:"webrtcAddress"` + WebRTCEncryption bool `json:"webrtcEncryption"` + WebRTCServerKey string `json:"webrtcServerKey"` + WebRTCServerCert string `json:"webrtcServerCert"` + WebRTCAllowOrigin string `json:"webrtcAllowOrigin"` + WebRTCTrustedProxies IPsOrCIDRs `json:"webrtcTrustedProxies"` + WebRTCLocalUDPAddress string `json:"webrtcLocalUDPAddress"` + WebRTCLocalTCPAddress string `json:"webrtcLocalTCPAddress"` + WebRTCIPsFromInterfaces bool `json:"webrtcIPsFromInterfaces"` + WebRTCIPsFromInterfacesList []string `json:"webrtcIPsFromInterfacesList"` + WebRTCAdditionalHosts []string `json:"webrtcAdditionalHosts"` + WebRTCICEServers2 []WebRTCICEServer `json:"webrtcICEServers2"` + WebRTCICEUDPMuxAddress *string `json:"webrtcICEUDPMuxAddress,omitempty"` // deprecated + WebRTCICETCPMuxAddress *string `json:"webrtcICETCPMuxAddress,omitempty"` // deprecated + WebRTCICEHostNAT1To1IPs *[]string `json:"webrtcICEHostNAT1To1IPs,omitempty"` // deprecated + WebRTCICEServers *[]string `json:"webrtcICEServers,omitempty"` // deprecated // SRT SRT bool `json:"srt"` @@ -234,9 +238,11 @@ func (conf *Conf) setDefaults() { conf.WebRTCServerKey = "server.key" conf.WebRTCServerCert = "server.crt" conf.WebRTCAllowOrigin = "*" - conf.WebRTCICEServers2 = []WebRTCICEServer{{URL: "stun:stun.l.google.com:19302"}} - conf.WebRTCICEInterfaces = []string{} - conf.WebRTCICEHostNAT1To1IPs = []string{} + conf.WebRTCLocalUDPAddress = ":8189" + conf.WebRTCIPsFromInterfaces = true + conf.WebRTCIPsFromInterfacesList = []string{} + conf.WebRTCAdditionalHosts = []string{} + conf.WebRTCICEServers2 = []WebRTCICEServer{} // SRT conf.SRT = true @@ -382,6 +388,15 @@ func (conf *Conf) Check() error { if conf.WebRTCDisable != nil { conf.WebRTC = !*conf.WebRTCDisable } + if conf.WebRTCICEUDPMuxAddress != nil { + conf.WebRTCLocalUDPAddress = *conf.WebRTCICEUDPMuxAddress + } + if conf.WebRTCICETCPMuxAddress != nil { + conf.WebRTCLocalTCPAddress = *conf.WebRTCICETCPMuxAddress + } + if conf.WebRTCICEHostNAT1To1IPs != nil { + conf.WebRTCAdditionalHosts = *conf.WebRTCICEHostNAT1To1IPs + } if conf.WebRTCICEServers != nil { for _, server := range *conf.WebRTCICEServers { parts := strings.Split(server, ":") @@ -405,6 +420,17 @@ func (conf *Conf) Check() error { return fmt.Errorf("invalid ICE server: '%s'", server.URL) } } + if conf.WebRTCLocalUDPAddress == "" && + conf.WebRTCLocalTCPAddress == "" && + len(conf.WebRTCICEServers2) == 0 { + return fmt.Errorf("at least one between 'webrtcLocalUDPAddress'," + + " 'webrtcLocalTCPAddress' or 'webrtcICEServers2' must be filled") + } + if conf.WebRTCLocalUDPAddress != "" || conf.WebRTCLocalTCPAddress != "" { + if !conf.WebRTCIPsFromInterfaces && len(conf.WebRTCAdditionalHosts) == 0 { + return fmt.Errorf("at least one between 'webrtcIPsFromInterfaces' or 'webrtcAdditionalHosts' must be filled") + } + } // Record if conf.Record != nil { diff --git a/internal/conf/encryption.go b/internal/conf/encryption.go index 3f0e4028..d7ff4177 100644 --- a/internal/conf/encryption.go +++ b/internal/conf/encryption.go @@ -8,7 +8,7 @@ import ( // Encryption is the encryption parameter. type Encryption int -// supported encryption policies. +// values. const ( EncryptionNo Encryption = iota EncryptionOptional diff --git a/internal/core/core.go b/internal/core/core.go index d41886d5..d649dee1 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -472,26 +472,29 @@ func (p *Core) createResources(initial bool) error { if p.conf.WebRTC && p.webRTCManager == nil { - p.webRTCManager, err = newWebRTCManager( - p.conf.WebRTCAddress, - p.conf.WebRTCEncryption, - p.conf.WebRTCServerKey, - p.conf.WebRTCServerCert, - p.conf.WebRTCAllowOrigin, - p.conf.WebRTCTrustedProxies, - p.conf.WebRTCICEServers2, - p.conf.ReadTimeout, - p.conf.WriteQueueSize, - p.conf.WebRTCICEInterfaces, - p.conf.WebRTCICEHostNAT1To1IPs, - p.conf.WebRTCICEUDPMuxAddress, - p.conf.WebRTCICETCPMuxAddress, - p.externalCmdPool, - p.pathManager, - p.metrics, - p, - ) + p.webRTCManager = &webRTCManager{ + Address: p.conf.WebRTCAddress, + Encryption: p.conf.WebRTCEncryption, + ServerKey: p.conf.WebRTCServerKey, + ServerCert: p.conf.WebRTCServerCert, + AllowOrigin: p.conf.WebRTCAllowOrigin, + TrustedProxies: p.conf.WebRTCTrustedProxies, + ReadTimeout: p.conf.ReadTimeout, + WriteQueueSize: p.conf.WriteQueueSize, + LocalUDPAddress: p.conf.WebRTCLocalUDPAddress, + LocalTCPAddress: p.conf.WebRTCLocalTCPAddress, + IPsFromInterfaces: p.conf.WebRTCIPsFromInterfaces, + IPsFromInterfacesList: p.conf.WebRTCIPsFromInterfacesList, + AdditionalHosts: p.conf.WebRTCAdditionalHosts, + ICEServers: p.conf.WebRTCICEServers2, + ExternalCmdPool: p.externalCmdPool, + PathManager: p.pathManager, + Metrics: p.metrics, + Parent: p, + } + err = p.webRTCManager.initialize() if err != nil { + p.webRTCManager = nil return err } } @@ -689,13 +692,14 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { newConf.WebRTCServerCert != p.conf.WebRTCServerCert || newConf.WebRTCAllowOrigin != p.conf.WebRTCAllowOrigin || !reflect.DeepEqual(newConf.WebRTCTrustedProxies, p.conf.WebRTCTrustedProxies) || - !reflect.DeepEqual(newConf.WebRTCICEServers2, p.conf.WebRTCICEServers2) || newConf.ReadTimeout != p.conf.ReadTimeout || newConf.WriteQueueSize != p.conf.WriteQueueSize || - !reflect.DeepEqual(newConf.WebRTCICEInterfaces, p.conf.WebRTCICEInterfaces) || - !reflect.DeepEqual(newConf.WebRTCICEHostNAT1To1IPs, p.conf.WebRTCICEHostNAT1To1IPs) || - newConf.WebRTCICEUDPMuxAddress != p.conf.WebRTCICEUDPMuxAddress || - newConf.WebRTCICETCPMuxAddress != p.conf.WebRTCICETCPMuxAddress || + newConf.WebRTCLocalUDPAddress != p.conf.WebRTCLocalUDPAddress || + newConf.WebRTCLocalTCPAddress != p.conf.WebRTCLocalTCPAddress || + newConf.WebRTCIPsFromInterfaces != p.conf.WebRTCIPsFromInterfaces || + !reflect.DeepEqual(newConf.WebRTCIPsFromInterfacesList, p.conf.WebRTCIPsFromInterfacesList) || + !reflect.DeepEqual(newConf.WebRTCAdditionalHosts, p.conf.WebRTCAdditionalHosts) || + !reflect.DeepEqual(newConf.WebRTCICEServers2, p.conf.WebRTCICEServers2) || closeMetrics || closePathManager || closeLogger diff --git a/internal/core/path.go b/internal/core/path.go index 16796906..62ac397f 100644 --- a/internal/core/path.go +++ b/internal/core/path.go @@ -376,10 +376,6 @@ func (pa *path) runInner() error { case <-pa.onDemandPublisherCloseTimer.C: pa.doOnDemandPublisherCloseTimer() - if pa.shouldClose() { - return fmt.Errorf("not in use") - } - case newConf := <-pa.chReloadConf: pa.doReloadConf(newConf) diff --git a/internal/core/webrtc_manager.go b/internal/core/webrtc_manager.go index fdf2c8f7..0e5dbaf3 100644 --- a/internal/core/webrtc_manager.go +++ b/internal/core/webrtc_manager.go @@ -15,7 +15,6 @@ import ( "time" "github.com/google/uuid" - "github.com/pion/ice/v2" "github.com/pion/logging" pwebrtc "github.com/pion/webrtc/v3" @@ -165,14 +164,24 @@ type webRTCManagerParent interface { } type webRTCManager struct { - allowOrigin string - trustedProxies conf.IPsOrCIDRs - iceServers []conf.WebRTCICEServer - writeQueueSize int - externalCmdPool *externalcmd.Pool - pathManager *pathManager - metrics *metrics - parent webRTCManagerParent + Address string + Encryption bool + ServerKey string + ServerCert string + AllowOrigin string + TrustedProxies conf.IPsOrCIDRs + ReadTimeout conf.StringDuration + WriteQueueSize int + LocalUDPAddress string + LocalTCPAddress string + IPsFromInterfaces bool + IPsFromInterfacesList []string + AdditionalHosts []string + ICEServers []conf.WebRTCICEServer + ExternalCmdPool *externalcmd.Pool + PathManager *pathManager + Metrics *metrics + Parent webRTCManagerParent ctx context.Context ctxCancel func() @@ -196,127 +205,97 @@ type webRTCManager struct { done chan struct{} } -func newWebRTCManager( - address string, - encryption bool, - serverKey string, - serverCert string, - allowOrigin string, - trustedProxies conf.IPsOrCIDRs, - iceServers []conf.WebRTCICEServer, - readTimeout conf.StringDuration, - writeQueueSize int, - iceInterfaces []string, - iceHostNAT1To1IPs []string, - iceUDPMuxAddress string, - iceTCPMuxAddress string, - externalCmdPool *externalcmd.Pool, - pathManager *pathManager, - metrics *metrics, - parent webRTCManagerParent, -) (*webRTCManager, error) { +func (m *webRTCManager) initialize() error { ctx, ctxCancel := context.WithCancel(context.Background()) - m := &webRTCManager{ - allowOrigin: allowOrigin, - trustedProxies: trustedProxies, - iceServers: iceServers, - writeQueueSize: writeQueueSize, - externalCmdPool: externalCmdPool, - pathManager: pathManager, - metrics: metrics, - parent: parent, - ctx: ctx, - ctxCancel: ctxCancel, - sessions: make(map[*webRTCSession]struct{}), - sessionsBySecret: make(map[uuid.UUID]*webRTCSession), - chNewSession: make(chan webRTCNewSessionReq), - chCloseSession: make(chan *webRTCSession), - chAddSessionCandidates: make(chan webRTCAddSessionCandidatesReq), - chDeleteSession: make(chan webRTCDeleteSessionReq), - chAPISessionsList: make(chan webRTCManagerAPISessionsListReq), - chAPISessionsGet: make(chan webRTCManagerAPISessionsGetReq), - chAPIConnsKick: make(chan webRTCManagerAPISessionsKickReq), - done: make(chan struct{}), - } + m.ctx = ctx + m.ctxCancel = ctxCancel + m.sessions = make(map[*webRTCSession]struct{}) + m.sessionsBySecret = make(map[uuid.UUID]*webRTCSession) + m.chNewSession = make(chan webRTCNewSessionReq) + m.chCloseSession = make(chan *webRTCSession) + m.chAddSessionCandidates = make(chan webRTCAddSessionCandidatesReq) + m.chDeleteSession = make(chan webRTCDeleteSessionReq) + m.chAPISessionsList = make(chan webRTCManagerAPISessionsListReq) + m.chAPISessionsGet = make(chan webRTCManagerAPISessionsGetReq) + m.chAPIConnsKick = make(chan webRTCManagerAPISessionsKickReq) + m.done = make(chan struct{}) var err error m.httpServer, err = newWebRTCHTTPServer( - address, - encryption, - serverKey, - serverCert, - allowOrigin, - trustedProxies, - readTimeout, - pathManager, + m.Address, + m.Encryption, + m.ServerKey, + m.ServerCert, + m.AllowOrigin, + m.TrustedProxies, + m.ReadTimeout, + m.PathManager, m, ) if err != nil { ctxCancel() - return nil, err + return err } - var iceUDPMux ice.UDPMux + apiConf := webrtc.APIConf{ + LocalRandomUDP: false, + IPsFromInterfaces: m.IPsFromInterfaces, + IPsFromInterfacesList: m.IPsFromInterfacesList, + AdditionalHosts: m.AdditionalHosts, + } - if iceUDPMuxAddress != "" { - m.udpMuxLn, err = net.ListenPacket(restrictnetwork.Restrict("udp", iceUDPMuxAddress)) + if m.LocalUDPAddress != "" { + m.udpMuxLn, err = net.ListenPacket(restrictnetwork.Restrict("udp", m.LocalUDPAddress)) if err != nil { m.httpServer.close() ctxCancel() - return nil, err + return err } - iceUDPMux = pwebrtc.NewICEUDPMux(webrtcNilLogger, m.udpMuxLn) + apiConf.ICEUDPMux = pwebrtc.NewICEUDPMux(webrtcNilLogger, m.udpMuxLn) } - var iceTCPMux ice.TCPMux - - if iceTCPMuxAddress != "" { - m.tcpMuxLn, err = net.Listen(restrictnetwork.Restrict("tcp", iceTCPMuxAddress)) + if m.LocalTCPAddress != "" { + m.tcpMuxLn, err = net.Listen(restrictnetwork.Restrict("tcp", m.LocalTCPAddress)) if err != nil { m.udpMuxLn.Close() m.httpServer.close() ctxCancel() - return nil, err + return err } - iceTCPMux = pwebrtc.NewICETCPMux(webrtcNilLogger, m.tcpMuxLn, 8) + apiConf.ICETCPMux = pwebrtc.NewICETCPMux(webrtcNilLogger, m.tcpMuxLn, 8) } - m.api, err = webrtc.NewAPI(webrtc.APIConf{ - ICEInterfaces: iceInterfaces, - ICEHostNAT1To1IPs: iceHostNAT1To1IPs, - ICEUDPMux: iceUDPMux, - ICETCPMux: iceTCPMux, - }) + m.api, err = webrtc.NewAPI(apiConf) if err != nil { m.udpMuxLn.Close() m.tcpMuxLn.Close() m.httpServer.close() ctxCancel() - return nil, err + return err } - str := "listener opened on " + address + " (HTTP)" + str := "listener opened on " + m.Address + " (HTTP)" if m.udpMuxLn != nil { - str += ", " + iceUDPMuxAddress + " (ICE/UDP)" + str += ", " + m.LocalUDPAddress + " (ICE/UDP)" } if m.tcpMuxLn != nil { - str += ", " + iceTCPMuxAddress + " (ICE/TCP)" + str += ", " + m.LocalTCPAddress + " (ICE/TCP)" } m.Log(logger.Info, str) - if m.metrics != nil { - m.metrics.webRTCManagerSet(m) + if m.Metrics != nil { + m.Metrics.webRTCManagerSet(m) } go m.run() - return m, nil + return nil } // Log is the main logging function. func (m *webRTCManager) Log(level logger.Level, format string, args ...interface{}) { - m.parent.Log(level, "[WebRTC] "+format, args...) + m.Parent.Log(level, "[WebRTC] "+format, args...) } func (m *webRTCManager) close() { @@ -336,12 +315,12 @@ outer: case req := <-m.chNewSession: sx := newWebRTCSession( m.ctx, - m.writeQueueSize, + m.WriteQueueSize, m.api, req, &wg, - m.externalCmdPool, - m.pathManager, + m.ExternalCmdPool, + m.PathManager, m, ) m.sessions[sx] = struct{}{} @@ -441,9 +420,9 @@ func (m *webRTCManager) findSessionByUUID(uuid uuid.UUID) *webRTCSession { } func (m *webRTCManager) generateICEServers() ([]pwebrtc.ICEServer, error) { - ret := make([]pwebrtc.ICEServer, len(m.iceServers)) + ret := make([]pwebrtc.ICEServer, len(m.ICEServers)) - for i, server := range m.iceServers { + for i, server := range m.ICEServers { if server.Username == "AUTH_SECRET" { expireDate := time.Now().Add(webrtcTurnSecretExpiration).Unix() diff --git a/internal/protocols/webrtc/api.go b/internal/protocols/webrtc/api.go index 989ab03e..d1b9b167 100644 --- a/internal/protocols/webrtc/api.go +++ b/internal/protocols/webrtc/api.go @@ -99,34 +99,44 @@ var audioCodecs = []webrtc.RTPCodecParameters{ // APIConf is the configuration passed to NewAPI(). type APIConf struct { - ICEInterfaces []string - ICEHostNAT1To1IPs []string - ICEUDPMux ice.UDPMux - ICETCPMux ice.TCPMux + ICEUDPMux ice.UDPMux + ICETCPMux ice.TCPMux + LocalRandomUDP bool + IPsFromInterfaces bool + IPsFromInterfacesList []string + AdditionalHosts []string } // NewAPI allocates a webrtc API. -func NewAPI(conf APIConf) (*webrtc.API, error) { +func NewAPI(cnf APIConf) (*webrtc.API, error) { settingsEngine := webrtc.SettingEngine{} - if len(conf.ICEInterfaces) != 0 { - settingsEngine.SetInterfaceFilter(func(iface string) bool { - return stringInSlice(iface, conf.ICEInterfaces) - }) + settingsEngine.SetInterfaceFilter(func(iface string) bool { + return cnf.IPsFromInterfaces && (len(cnf.IPsFromInterfacesList) == 0 || + stringInSlice(iface, cnf.IPsFromInterfacesList)) + }) + + settingsEngine.SetAdditionalHosts(cnf.AdditionalHosts) + + var networkTypes []webrtc.NetworkType + + // always enable UDP in order to support STUN/TURN + networkTypes = append(networkTypes, webrtc.NetworkTypeUDP4) + + if cnf.ICEUDPMux != nil { + settingsEngine.SetICEUDPMux(cnf.ICEUDPMux) } - if len(conf.ICEHostNAT1To1IPs) != 0 { - settingsEngine.SetNAT1To1IPs(conf.ICEHostNAT1To1IPs, webrtc.ICECandidateTypeHost) + if cnf.ICETCPMux != nil { + settingsEngine.SetICETCPMux(cnf.ICETCPMux) + networkTypes = append(networkTypes, webrtc.NetworkTypeTCP4) } - if conf.ICEUDPMux != nil { - settingsEngine.SetICEUDPMux(conf.ICEUDPMux) + if cnf.LocalRandomUDP { + settingsEngine.SetICEUDPRandom(true) } - if conf.ICETCPMux != nil { - settingsEngine.SetICETCPMux(conf.ICETCPMux) - settingsEngine.SetNetworkTypes([]webrtc.NetworkType{webrtc.NetworkTypeTCP4}) - } + settingsEngine.SetNetworkTypes(networkTypes) mediaEngine := &webrtc.MediaEngine{} diff --git a/internal/protocols/webrtc/whip_client.go b/internal/protocols/webrtc/whip_client.go index 9e49c933..eb129403 100644 --- a/internal/protocols/webrtc/whip_client.go +++ b/internal/protocols/webrtc/whip_client.go @@ -33,7 +33,10 @@ func (c *WHIPClient) Publish( return nil, err } - api, err := NewAPI(APIConf{}) + api, err := NewAPI(APIConf{ + LocalRandomUDP: true, + IPsFromInterfaces: true, + }) if err != nil { return nil, err } @@ -113,7 +116,10 @@ func (c *WHIPClient) Read(ctx context.Context) ([]*IncomingTrack, error) { return nil, err } - api, err := NewAPI(APIConf{}) + api, err := NewAPI(APIConf{ + LocalRandomUDP: true, + IPsFromInterfaces: true, + }) if err != nil { return nil, err } diff --git a/internal/staticsources/webrtc/source_test.go b/internal/staticsources/webrtc/source_test.go index 0dfddfdf..cff918fa 100644 --- a/internal/staticsources/webrtc/source_test.go +++ b/internal/staticsources/webrtc/source_test.go @@ -27,7 +27,10 @@ func whipOffer(body []byte) *pwebrtc.SessionDescription { } func TestSource(t *testing.T) { - api, err := webrtc.NewAPI(webrtc.APIConf{}) + api, err := webrtc.NewAPI(webrtc.APIConf{ + LocalRandomUDP: true, + IPsFromInterfaces: true, + }) require.NoError(t, err) pc := &webrtc.PeerConnection{ diff --git a/mediamtx.yml b/mediamtx.yml index af2a1751..bdd3cd1a 100644 --- a/mediamtx.yml +++ b/mediamtx.yml @@ -190,7 +190,7 @@ hlsDirectory: '' # Allow publishing and reading streams with the WebRTC protocol. webrtc: yes -# Address of the WebRTC listener. +# Address of the WebRTC HTTP listener. webrtcAddress: :8889 # Enable TLS/HTTPS on the WebRTC server. webrtcEncryption: no @@ -208,34 +208,30 @@ webrtcAllowOrigin: '*' # If the server receives a request from one of these entries, IP in logs # will be taken from the X-Forwarded-For header. webrtcTrustedProxies: [] -# List of ICE servers. -webrtcICEServers2: - # URL can point to a STUN, TURN or TURNS server. - # STUN servers are used to obtain the public IP of server and clients. They are - # needed when server and clients are on different LANs. - # TURN/TURNS servers are needed when a direct connection between server and - # clients is not possible. All traffic is routed through them. -- url: stun:stun.l.google.com:19302 +# Address of a local UDP listener that will receive connections. +# Use a blank string to disable. +webrtcLocalUDPAddress: :8189 +# Address of a local TCP listener that will receive connections. +# This is disabled by default since TCP is less efficient than UDP and +# introduces a progressive delay when network is congested. +webrtcLocalTCPAddress: '' +# WebRTC clients need to know the IP of the server. +# Gather IPs from interfaces and send them to clients. +webrtcIPsFromInterfaces: yes +# List of interfaces whose IPs will be sent to clients. +# An empty value means to use all available interfaces. +webrtcIPsFromInterfacesList: [] +# List of additional hosts or IPs to send to clients. +webrtcAdditionalHosts: [] +# ICE servers. Needed only when local listeners can't be reached by clients. +# STUN servers allows to obtain and share the public IP of the server. +# TURN/TURNS servers forces all traffic through them. +webrtcICEServers2: [] + # - url: stun:stun.l.google.com:19302 # if user is "AUTH_SECRET", then authentication is secret based. # the secret must be inserted into the password field. - username: '' - password: '' -# List of interfaces whose IPs will be sent to clients -# to establish a connection. An empty list means all interfaces. -webrtcICEInterfaces: [] -# 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 UDP listener in format host:port. -# If filled, ICE traffic will pass through a single UDP port, -# allowing the deployment of the server inside a container or behind a NAT. -webrtcICEUDPMuxAddress: -# Address of a ICE TCP listener in format host:port. -# If filled, ICE traffic will pass through a single TCP port, -# allowing the deployment of the server inside a container or behind a NAT. -# Using this setting forces usage of the TCP protocol, which is not -# optimal for WebRTC. -webrtcICETCPMuxAddress: + # username: '' + # password: '' ############################################### # Global settings -> SRT