Skip to content

Commit cf06c23

Browse files
authored
fix: race that causes LocalParticipant to show up as RemoteParticipant (#619)
* fix: race that causes LocalParticipant to show up as RemoteParticipant RTCEngine.JoinContext starts SignalClient's dispatch loop. If there's an update to the local participant (in the form of ParticipantUpdate) before PeerConnection is established, then we would incorrectly categorize the LocalParticipant as a RemoteParticipant. * actually call it * fix staticcheck
1 parent 1477da5 commit cf06c23

File tree

3 files changed

+37
-23
lines changed

3 files changed

+37
-23
lines changed

engine.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ type RTCEngine struct {
8383
OnResuming func()
8484
OnResumed func()
8585
OnTranscription func(*livekit.Transcription)
86+
OnSignalClientConnected func(*livekit.JoinResponse)
8687

8788
// callbacks to get data
8889
CbGetLocalParticipantSID func() string
@@ -160,6 +161,10 @@ func (e *RTCEngine) JoinContext(ctx context.Context, url string, token string, p
160161
return nil, err
161162
}
162163

164+
if e.OnSignalClientConnected != nil {
165+
e.OnSignalClientConnected(res)
166+
}
167+
163168
e.client.Start()
164169

165170
// send offer

regionurlprovider.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,19 @@ func (r *regionURLProvider) RefreshRegionSettings(cloudHostname, token string) e
7878
return errors.New("refreshRegionSettings failed to decode region settings: " + err.Error())
7979
}
8080

81-
r.mutex.Lock()
82-
r.hostnameSettingsCache[cloudHostname] = &hostnameSettingsCacheItem{
81+
item := &hostnameSettingsCacheItem{
8382
regionSettings: regions,
8483
updatedAt: time.Now(),
8584
regionURLAttempts: map[string]int{},
8685
}
86+
r.mutex.Lock()
87+
r.hostnameSettingsCache[cloudHostname] = item
8788
r.mutex.Unlock()
8889

90+
if len(item.regionSettings.Regions) == 0 {
91+
logger.Warnw("no regions returned", nil, "cloudHostname", cloudHostname)
92+
}
93+
8994
return nil
9095
}
9196

room.go

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ func NewRoom(callback *RoomCallback) *Room {
189189
r.LocalParticipant = newLocalParticipant(engine, r.callback)
190190

191191
// callbacks from engine
192+
engine.OnSignalClientConnected = r.handleSignalClientConnected
192193
engine.OnMediaTrack = r.handleMediaTrack
193194
engine.OnDisconnected = r.handleDisconnect
194195
engine.OnParticipantUpdate = r.handleParticipantUpdate
@@ -328,6 +329,7 @@ func (r *Room) JoinWithToken(url, token string, opts ...ConnectOption) error {
328329
d := time.Duration(1<<min(tries, 6)) * time.Second // max 64 seconds
329330
logger.Errorw("failed to join room", err,
330331
"retrying in", d,
332+
"url", bestURL,
331333
)
332334
time.Sleep(d)
333335
continue
@@ -338,32 +340,12 @@ func (r *Room) JoinWithToken(url, token string, opts ...ConnectOption) error {
338340

339341
if joinRes == nil {
340342
var err error
341-
joinRes, err = r.engine.JoinContext(ctx, url, token, params)
343+
_, err = r.engine.JoinContext(ctx, url, token, params)
342344
if err != nil {
343345
return err
344346
}
345347
}
346348

347-
r.lock.Lock()
348-
r.name = joinRes.Room.Name
349-
r.metadata = joinRes.Room.Metadata
350-
r.serverInfo = joinRes.ServerInfo
351-
r.connectionState = ConnectionStateConnected
352-
r.sifTrailer = make([]byte, len(joinRes.SifTrailer))
353-
copy(r.sifTrailer, joinRes.SifTrailer)
354-
r.lock.Unlock()
355-
356-
r.setSid(joinRes.Room.Sid, false)
357-
358-
r.LocalParticipant.updateInfo(joinRes.Participant)
359-
r.LocalParticipant.updateSubscriptionPermission()
360-
361-
for _, pi := range joinRes.OtherParticipants {
362-
rp := r.addRemoteParticipant(pi, true)
363-
r.clearParticipantDefers(livekit.ParticipantID(pi.Sid), pi)
364-
r.runParticipantDefers(livekit.ParticipantID(pi.Sid), rp)
365-
}
366-
367349
return nil
368350
}
369351

@@ -552,6 +534,28 @@ func (r *Room) handleMediaTrack(track *webrtc.TrackRemote, receiver *webrtc.RTPR
552534
r.runParticipantDefers(livekit.ParticipantID(participantID), rp)
553535
}
554536

537+
func (r *Room) handleSignalClientConnected(joinRes *livekit.JoinResponse) {
538+
r.lock.Lock()
539+
r.name = joinRes.Room.Name
540+
r.metadata = joinRes.Room.Metadata
541+
r.serverInfo = joinRes.ServerInfo
542+
r.connectionState = ConnectionStateConnected
543+
r.sifTrailer = make([]byte, len(joinRes.SifTrailer))
544+
copy(r.sifTrailer, joinRes.SifTrailer)
545+
r.lock.Unlock()
546+
547+
r.setSid(joinRes.Room.Sid, false)
548+
549+
r.LocalParticipant.updateInfo(joinRes.Participant)
550+
r.LocalParticipant.updateSubscriptionPermission()
551+
552+
for _, pi := range joinRes.OtherParticipants {
553+
r.addRemoteParticipant(pi, true)
554+
r.clearParticipantDefers(livekit.ParticipantID(pi.Sid), pi)
555+
// no need to run participant defers here, since we are connected for the first time
556+
}
557+
}
558+
555559
func (r *Room) handleDisconnect(reason DisconnectionReason) {
556560
r.callback.OnDisconnected()
557561
r.callback.OnDisconnectedWithReason(reason)

0 commit comments

Comments
 (0)