diff --git a/internal/webrtc/candidates.go b/internal/webrtc/candidates.go index 1138db76..d378022f 100644 --- a/internal/webrtc/candidates.go +++ b/internal/webrtc/candidates.go @@ -18,9 +18,11 @@ type Address struct { Priority uint32 } +var stuns []string + func (a *Address) Host() string { if a.host == "stun" { - ip, err := webrtc.GetCachedPublicIP() + ip, err := webrtc.GetCachedPublicIP(stuns...) if err != nil { return "" } diff --git a/internal/webrtc/webrtc.go b/internal/webrtc/webrtc.go index eca1e12b..03545cff 100644 --- a/internal/webrtc/webrtc.go +++ b/internal/webrtc/webrtc.go @@ -26,7 +26,7 @@ func Init() { cfg.Mod.Listen = ":8555" cfg.Mod.IceServers = []pion.ICEServer{ - {URLs: []string{"stun:stun.l.google.com:19302"}}, + {URLs: []string{"stun:stun.cloudflare.com:3478", "stun:stun.l.google.com:19302"}}, } app.LoadConfig(&cfg) @@ -38,6 +38,16 @@ func Init() { address, network, _ := strings.Cut(cfg.Mod.Listen, "/") for _, candidate := range cfg.Mod.Candidates { AddCandidate(network, candidate) + + if strings.HasPrefix(candidate, "stun:") && stuns == nil { + for _, ice := range cfg.Mod.IceServers { + for _, url := range ice.URLs { + if strings.HasPrefix(url, "stun:") { + stuns = append(stuns, url[5:]) + } + } + } + } } var err error diff --git a/pkg/webrtc/helpers.go b/pkg/webrtc/helpers.go index 766254a0..bac5087c 100644 --- a/pkg/webrtc/helpers.go +++ b/pkg/webrtc/helpers.go @@ -185,8 +185,8 @@ func LookupIP(address string) (string, error) { } // GetPublicIP example from https://github.com/pion/stun -func GetPublicIP() (net.IP, error) { - conn, err := net.Dial("udp", "stun.l.google.com:19302") +func GetPublicIP(address string) (net.IP, error) { + conn, err := net.Dial("udp", address) if err != nil { return nil, err } @@ -225,18 +225,19 @@ func GetPublicIP() (net.IP, error) { var cachedIP net.IP var cachedTS time.Time -func GetCachedPublicIP() (net.IP, error) { - now := time.Now() - if now.After(cachedTS) { - newIP, err := GetPublicIP() - if err == nil { - cachedIP = newIP - cachedTS = now.Add(time.Minute * 5) - } else if cachedIP == nil { - return nil, err +func GetCachedPublicIP(stuns ...string) (net.IP, error) { + if now := time.Now(); now.After(cachedTS) { + for _, addr := range stuns { + if ip, _ := GetPublicIP(addr); ip != nil { + cachedIP = ip + cachedTS = now.Add(time.Minute * 5) + return ip, nil + } } } - + if cachedIP == nil { + return nil, errors.New("webrtc: can't get public IP") + } return cachedIP, nil } diff --git a/www/video-rtc.js b/www/video-rtc.js index 8ecbce72..cab5bf04 100644 --- a/www/video-rtc.js +++ b/www/video-rtc.js @@ -71,7 +71,7 @@ export class VideoRTC extends HTMLElement { */ this.pcConfig = { bundlePolicy: 'max-bundle', - iceServers: [{urls: 'stun:stun.l.google.com:19302'}], + iceServers: [{urls: ['stun:stun.cloudflare.com:3478', 'stun:stun.l.google.com:19302']}], sdpSemantics: 'unified-plan', // important for Chromecast 1 }; diff --git a/www/webrtc-sync.html b/www/webrtc-sync.html index 68fcf458..89d742bc 100644 --- a/www/webrtc-sync.html +++ b/www/webrtc-sync.html @@ -21,7 +21,7 @@