diff --git a/internal/config/webrtc.go b/internal/config/webrtc.go index faa23768..f8419d5f 100644 --- a/internal/config/webrtc.go +++ b/internal/config/webrtc.go @@ -12,6 +12,7 @@ import ( type WebRTC struct { ICELite bool + ICETrickle bool ICEServers []string EphemeralMin uint16 EphemeralMax uint16 @@ -39,11 +40,17 @@ func (WebRTC) Init(cmd *cobra.Command) error { return err } + cmd.PersistentFlags().Bool("icetrickle", true, "configures whether cadidates should be sent asynchronously using Trickle ICE") + if err := viper.BindPFlag("icetrickle", cmd.PersistentFlags().Lookup("icetrickle")); err != nil { + return err + } + return nil } func (s *WebRTC) Set() { s.ICELite = viper.GetBool("icelite") + s.ICETrickle = viper.GetBool("icetrickle") s.ICEServers = viper.GetStringSlice("iceserver") s.NAT1To1IPs = viper.GetStringSlice("nat1to1") diff --git a/internal/webrtc/manager.go b/internal/webrtc/manager.go index bb9b822c..a7e836d8 100644 --- a/internal/webrtc/manager.go +++ b/internal/webrtc/manager.go @@ -68,6 +68,7 @@ func (manager *WebRTCManagerCtx) Start() { manager.logger.Info(). Str("ice_lite", fmt.Sprintf("%t", manager.config.ICELite)). + Str("ice_trickle", fmt.Sprintf("%t", manager.config.ICETrickle)). Str("ice_servers", strings.Join(manager.config.ICEServers, ",")). Str("ephemeral_port_range", fmt.Sprintf("%d-%d", manager.config.EphemeralMin, manager.config.EphemeralMax)). Str("nat_ips", strings.Join(manager.config.NAT1To1IPs, ",")). @@ -108,23 +109,25 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session) (*webrtc.Sess } // Asynchronously send local ICE Candidates - connection.OnICECandidate(func(candidate *webrtc.ICECandidate) { - if candidate == nil { - logger.Debug().Msg("all local ice candidates sent") - return - } + if manager.config.ICETrickle { + connection.OnICECandidate(func(candidate *webrtc.ICECandidate) { + if candidate == nil { + logger.Debug().Msg("all local ice candidates sent") + return + } - ICECandidateInit := candidate.ToJSON() - err := session.Send( - message.SignalCandidate{ - Event: event.SIGNAL_CANDIDATE, - ICECandidateInit: &ICECandidateInit, - }) + ICECandidateInit := candidate.ToJSON() + err := session.Send( + message.SignalCandidate{ + Event: event.SIGNAL_CANDIDATE, + ICECandidateInit: &ICECandidateInit, + }) - if err != nil { - logger.Warn().Err(err).Msg("sending ice candidate failed") - } - }) + if err != nil { + logger.Warn().Err(err).Msg("sending ice candidate failed") + } + }) + } if err := manager.registerTracks(connection); err != nil { return nil, err @@ -135,8 +138,19 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session) (*webrtc.Sess return nil, err } - if err := connection.SetLocalDescription(offer); err != nil { - return nil, err + if !manager.config.ICETrickle { + // Create channel that is blocked until ICE Gathering is complete + gatherComplete := webrtc.GatheringCompletePromise(connection) + + if err := connection.SetLocalDescription(offer); err != nil { + return nil, err + } + + <-gatherComplete + } else { + if err := connection.SetLocalDescription(offer); err != nil { + return nil, err + } } connection.OnConnectionStateChange(func(state webrtc.PeerConnectionState) { @@ -201,7 +215,7 @@ func (manager *WebRTCManagerCtx) apiSettings(logger zerolog.Logger) *webrtc.Sett settings.SetEphemeralUDPPortRange(manager.config.EphemeralMin, manager.config.EphemeralMax) settings.SetNAT1To1IPs(manager.config.NAT1To1IPs, webrtc.ICECandidateTypeHost) settings.SetLite(manager.config.ICELite) - + return settings }