From e3854eaff4e9a8f645d125c0dc57103666393d25 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Sat, 15 May 2021 17:31:48 -0700 Subject: [PATCH] handle ICE restart and candidate gathering race --- deploy/aws-ecs/config.tf | 1 + pkg/rtc/transport.go | 32 ++++++++++++++++++++++++++------ version/version.go | 2 +- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/deploy/aws-ecs/config.tf b/deploy/aws-ecs/config.tf index 2bc1ea479..13e92c8a2 100644 --- a/deploy/aws-ecs/config.tf +++ b/deploy/aws-ecs/config.tf @@ -6,6 +6,7 @@ locals { port_range_end = var.udp_port_end tcp_port = var.rtc_tcp_port udp_port = var.rtc_udp_port + use_external_ip = true } turn = { enabled = var.turn_enabled diff --git a/pkg/rtc/transport.go b/pkg/rtc/transport.go index 787a6b4ac..5a10a419a 100644 --- a/pkg/rtc/transport.go +++ b/pkg/rtc/transport.go @@ -30,10 +30,11 @@ type PCTransport struct { pc *webrtc.PeerConnection me *webrtc.MediaEngine - lock sync.Mutex - pendingCandidates []webrtc.ICECandidateInit - debouncedNegotiate func(func()) - onOffer func(offer webrtc.SessionDescription) + lock sync.Mutex + pendingCandidates []webrtc.ICECandidateInit + debouncedNegotiate func(func()) + onOffer func(offer webrtc.SessionDescription) + restartAfterGathering atomic.Value negotiationState atomic.Value } @@ -90,7 +91,15 @@ func NewPCTransport(params TransportParams) (*PCTransport, error) { debouncedNegotiate: debounce.New(negotiationFrequency), } t.negotiationState.Store(negotiationStateNone) - //t.pc.OnNegotiationNeeded(t.Negotiate) + t.pc.OnICEGatheringStateChange(func(state webrtc.ICEGathererState) { + if state == webrtc.ICEGathererStateComplete { + if restart, ok := t.restartAfterGathering.Load().(bool); ok && restart { + if err := t.CreateAndSendOffer(&webrtc.OfferOptions{ICERestart: true}); err != nil { + logger.Warnw("could not restart ICE", "error", err) + } + } + } + }) return t, nil } @@ -160,12 +169,22 @@ func (t *PCTransport) CreateAndSendOffer(options *webrtc.OfferOptions) error { return nil } + iceRestart := options != nil && options.ICERestart + + // if restart is requested, and we are not ready, then continue afterwards + if iceRestart && t.pc.ICEGatheringState() == webrtc.ICEGatheringStateGathering { + logger.Debugw("restart ICE after gathering") + t.restartAfterGathering.Store(true) + return nil + } + state := t.negotiationState.Load().(int) + logger.Debugw("restarting ICE") // when there's an ongoing negotiation, let it finish and not disrupt its state if state == negotiationStateClient { currentSD := t.pc.CurrentRemoteDescription() - if options != nil && options.ICERestart && currentSD != nil { + if iceRestart && currentSD != nil { logger.Debugw("recovering from client negotiation state") if err := t.pc.SetRemoteDescription(*currentSD); err != nil { return err @@ -191,6 +210,7 @@ func (t *PCTransport) CreateAndSendOffer(options *webrtc.OfferOptions) error { // indicate waiting for client t.negotiationState.Store(negotiationStateClient) + t.restartAfterGathering.Store(false) t.onOffer(offer) return nil diff --git a/version/version.go b/version/version.go index 648efe7c1..14b605756 100644 --- a/version/version.go +++ b/version/version.go @@ -1,3 +1,3 @@ package version -const Version = "0.9.2" +const Version = "0.9.3"