@@ -57,6 +57,15 @@ func Init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
webrtc.OnNewListener = func(ln any) {
|
||||||
|
switch ln := ln.(type) {
|
||||||
|
case *net.TCPListener:
|
||||||
|
log.Info().Stringer("addr", ln.Addr()).Msg("[webrtc] listen tcp")
|
||||||
|
case *net.UDPConn:
|
||||||
|
log.Info().Stringer("addr", ln.LocalAddr()).Msg("[webrtc] listen udp")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// create pionAPI with custom codecs list and custom network settings
|
// create pionAPI with custom codecs list and custom network settings
|
||||||
@@ -70,7 +79,6 @@ func Init() {
|
|||||||
clientAPI = serverAPI
|
clientAPI = serverAPI
|
||||||
|
|
||||||
if address != "" {
|
if address != "" {
|
||||||
log.Info().Str("addr", cfg.Mod.Listen).Msg("[webrtc] listen")
|
|
||||||
clientAPI, _ = webrtc.NewAPI()
|
clientAPI, _ = webrtc.NewAPI()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+123
-38
@@ -1,7 +1,9 @@
|
|||||||
package webrtc
|
package webrtc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/AlexxIT/go2rtc/pkg/core"
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
||||||
"github.com/AlexxIT/go2rtc/pkg/xnet"
|
"github.com/AlexxIT/go2rtc/pkg/xnet"
|
||||||
@@ -27,6 +29,69 @@ type Filters struct {
|
|||||||
UDPPorts []uint16 `yaml:"udp_ports"`
|
UDPPorts []uint16 `yaml:"udp_ports"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Filters) Network(protocol string) string {
|
||||||
|
if f == nil || f.Networks == nil {
|
||||||
|
return protocol
|
||||||
|
}
|
||||||
|
v4 := slices.Contains(f.Networks, protocol+"4")
|
||||||
|
v6 := slices.Contains(f.Networks, protocol+"6")
|
||||||
|
if v4 && v6 {
|
||||||
|
return protocol
|
||||||
|
} else if v4 {
|
||||||
|
return protocol + "4"
|
||||||
|
} else if v6 {
|
||||||
|
return protocol + "6"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Filters) NetIPs() (ips []net.IP) {
|
||||||
|
itfs, _ := net.Interfaces()
|
||||||
|
for _, itf := range itfs {
|
||||||
|
if itf.Flags&net.FlagUp == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !f.IncludeLoopback() && itf.Flags&net.FlagLoopback != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !f.InterfaceFilter(itf.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs, _ := itf.Addrs()
|
||||||
|
for _, addr := range addrs {
|
||||||
|
ip := parseNetAddr(addr)
|
||||||
|
if ip == nil || !f.IPFilter(ip) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ips = append(ips, ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseNetAddr(addr net.Addr) net.IP {
|
||||||
|
switch addr := addr.(type) {
|
||||||
|
case *net.IPNet:
|
||||||
|
return addr.IP
|
||||||
|
case *net.IPAddr:
|
||||||
|
return addr.IP
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Filters) IncludeLoopback() bool {
|
||||||
|
return f != nil && f.Loopback
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Filters) InterfaceFilter(name string) bool {
|
||||||
|
return f == nil || f.Interfaces == nil || slices.Contains(f.Interfaces, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Filters) IPFilter(ip net.IP) bool {
|
||||||
|
return f == nil || f.IPs == nil || core.Contains(f.IPs, ip.String())
|
||||||
|
}
|
||||||
|
|
||||||
func NewServerAPI(network, address string, filters *Filters) (*webrtc.API, error) {
|
func NewServerAPI(network, address string, filters *Filters) (*webrtc.API, error) {
|
||||||
// for debug logs add to env: `PION_LOG_DEBUG=all`
|
// for debug logs add to env: `PION_LOG_DEBUG=all`
|
||||||
m := &webrtc.MediaEngine{}
|
m := &webrtc.MediaEngine{}
|
||||||
@@ -99,48 +164,17 @@ func NewServerAPI(network, address string, filters *Filters) (*webrtc.API, error
|
|||||||
_ = s.SetEphemeralUDPPortRange(filters.UDPPorts[0], filters.UDPPorts[1])
|
_ = s.SetEphemeralUDPPortRange(filters.UDPPorts[0], filters.UDPPorts[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
//if len(hosts) != 0 {
|
// If you don't specify an address, this won't cause an error.
|
||||||
// // support only: host, srflx
|
// Connections can still be established using random UDP addresses.
|
||||||
// if candidateType, err := webrtc.NewICECandidateType(hosts[0]); err == nil {
|
|
||||||
// s.SetNAT1To1IPs(hosts[1:], candidateType)
|
|
||||||
// } else {
|
|
||||||
// s.SetNAT1To1IPs(hosts, 0) // 0 = host
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
if address != "" {
|
if address != "" {
|
||||||
|
// Both newMux functions respect filters and do not raise an error
|
||||||
|
// if the port cannot be listened on.
|
||||||
if network == "" || network == "tcp" {
|
if network == "" || network == "tcp" {
|
||||||
if ln, err := net.Listen("tcp", address); err == nil {
|
tcpMux := newTCPMux(address, filters)
|
||||||
tcpMux := webrtc.NewICETCPMux(nil, ln, 8)
|
s.SetICETCPMux(tcpMux)
|
||||||
s.SetICETCPMux(tcpMux)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if network == "" || network == "udp" {
|
if network == "" || network == "udp" {
|
||||||
// UDPMuxDefault should not listening on unspecified address, use NewMultiUDPMuxFromPort instead
|
udpMux := newUDPMux(address, filters)
|
||||||
var udpMux ice.UDPMux
|
|
||||||
if port := xnet.ParseUnspecifiedPort(address); port != 0 {
|
|
||||||
var networks []ice.NetworkType
|
|
||||||
for _, ntype := range networkTypes {
|
|
||||||
networks = append(networks, ice.NetworkType(ntype))
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
if udpMux, err = ice.NewMultiUDPMuxFromPort(
|
|
||||||
port,
|
|
||||||
ice.UDPMuxFromPortWithInterfaceFilter(interfaceFilter),
|
|
||||||
ice.UDPMuxFromPortWithIPFilter(ipFilter),
|
|
||||||
ice.UDPMuxFromPortWithNetworks(networks...),
|
|
||||||
); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ln, err := net.ListenPacket("udp", address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
udpMux = ice.NewUDPMuxDefault(ice.UDPMuxParams{UDPConn: ln})
|
|
||||||
}
|
|
||||||
s.SetICEUDPMux(udpMux)
|
s.SetICEUDPMux(udpMux)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,6 +186,57 @@ func NewServerAPI(network, address string, filters *Filters) (*webrtc.API, error
|
|||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnNewListener temporary ugly solution for log
|
||||||
|
var OnNewListener = func(ln any) {}
|
||||||
|
|
||||||
|
func newTCPMux(address string, filters *Filters) ice.TCPMux {
|
||||||
|
networkTCP := filters.Network("tcp") // tcp or tcp4 or tcp6
|
||||||
|
if ln, _ := net.Listen(networkTCP, address); ln != nil {
|
||||||
|
OnNewListener(ln)
|
||||||
|
return webrtc.NewICETCPMux(nil, ln, 8)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUDPMux(address string, filters *Filters) ice.UDPMux {
|
||||||
|
host, port, err := net.SplitHostPort(address)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDPMux should not listening on unspecified address.
|
||||||
|
// So we will create a listener on all available interfaces.
|
||||||
|
// We can't use ice.NewMultiUDPMuxFromPort, because it sometimes crashes with an error:
|
||||||
|
// listen udp [***]:8555: bind: cannot assign requested address
|
||||||
|
var addrs []string
|
||||||
|
if host == "" {
|
||||||
|
for _, ip := range filters.NetIPs() {
|
||||||
|
addrs = append(addrs, fmt.Sprintf("%s:%s", ip, port))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addrs = []string{address}
|
||||||
|
}
|
||||||
|
|
||||||
|
networkUDP := filters.Network("udp") // udp or udp4 or udp6
|
||||||
|
|
||||||
|
var muxes []ice.UDPMux
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if ln, _ := net.ListenPacket(networkUDP, addr); ln != nil {
|
||||||
|
OnNewListener(ln)
|
||||||
|
mux := ice.NewUDPMuxDefault(ice.UDPMuxParams{UDPConn: ln})
|
||||||
|
muxes = append(muxes, mux)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch len(muxes) {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case 1:
|
||||||
|
return muxes[0]
|
||||||
|
}
|
||||||
|
return ice.NewMultiUDPMuxDefault(muxes...)
|
||||||
|
}
|
||||||
|
|
||||||
func RegisterDefaultCodecs(m *webrtc.MediaEngine) error {
|
func RegisterDefaultCodecs(m *webrtc.MediaEngine) error {
|
||||||
for _, codec := range []webrtc.RTPCodecParameters{
|
for _, codec := range []webrtc.RTPCodecParameters{
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user