diff --git a/galene.go b/galene.go index 8a25d85..da68a27 100644 --- a/galene.go +++ b/galene.go @@ -44,6 +44,8 @@ func main() { "store mutex profile in `file`") flag.StringVar(&udpRange, "udp-range", "", "UDP port `range`") + flag.StringVar(&group.UDPAddr, "udp", "", + "UDP `address:port` (default dynamic)") flag.BoolVar(&group.UseMDNS, "mdns", false, "gather mDNS addresses") flag.BoolVar(&ice.ICERelayOnly, "relay-only", false, "require use of TURN relays for all media traffic") diff --git a/group/group.go b/group/group.go index e6cbb74..7c3c655 100644 --- a/group/group.go +++ b/group/group.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "log" + "net" "os" "path" "path/filepath" @@ -20,6 +21,10 @@ var Directory string var UseMDNS bool var UDPMin, UDPMax uint16 +var UDPAddr string +var udpListenerMu sync.Mutex +var udpListener *net.UDPConn + var ErrNotAuthorised = errors.New("not authorised") type UserError string @@ -199,6 +204,27 @@ func payloadType(codec webrtc.RTPCodecCapability) (webrtc.PayloadType, error) { } } +func getUDPListener() (*net.UDPConn, error) { + if UDPAddr == "" { + return nil, nil + } + udpListenerMu.Lock() + defer udpListenerMu.Unlock() + if udpListener == nil { + addr, err := net.ResolveUDPAddr("udp", UDPAddr) + if err != nil { + return nil, err + } + udpListener, err = net.ListenUDP("udp", addr) + if err != nil { + udpListener = nil + return nil, err + } + } + return udpListener, nil + +} + func APIFromCodecs(codecs []webrtc.RTPCodecCapability) (*webrtc.API, error) { s := webrtc.SettingEngine{} s.SetSRTPReplayProtectionWindow(512) @@ -253,6 +279,14 @@ func APIFromCodecs(codecs []webrtc.RTPCodecCapability) (*webrtc.API, error) { s.SetEphemeralUDPPortRange(UDPMin, UDPMax) } + listener, err := getUDPListener() + if err != nil { + return nil, err + } + if listener != nil { + s.SetICEUDPMux(webrtc.NewICEUDPMux(nil, listener)) + } + return webrtc.NewAPI( webrtc.WithSettingEngine(s), webrtc.WithMediaEngine(&m),