diff --git a/internal/engine/jitsi/jitsi.go b/internal/engine/jitsi/jitsi.go index dccc058..fce6d37 100644 --- a/internal/engine/jitsi/jitsi.go +++ b/internal/engine/jitsi/jitsi.go @@ -1003,6 +1003,7 @@ func (s *Session) reconnect(ctx context.Context) error { _ = oldPC.Close() } s.localEpoch.Store(randomEpoch()) + s.peerEpoch.Store(0) s.drainSendQueue() logger.Infof("jitsi: reconnecting %s/%s as %s ...", s.host, s.room, s.name) @@ -1014,13 +1015,14 @@ func (s *Session) reconnect(ctx context.Context) error { s.peerEndpoint.Store(nil) s.peerVideoSSRC.Store(0) s.bridgeReady.Store(true) - if err := s.Send(nil); err != nil { - logger.Debugf("jitsi: epoch announce failed: %v", err) - } s.wg.Add(1) go s.recvLoop() + if err := s.Send(nil); err != nil { + logger.Debugf("jitsi: epoch announce failed: %v", err) + } + if s.onReconnect != nil { s.onReconnect(nil) } diff --git a/internal/engine/jitsi/jitsi_test.go b/internal/engine/jitsi/jitsi_test.go index fa8aa61..b473df6 100644 --- a/internal/engine/jitsi/jitsi_test.go +++ b/internal/engine/jitsi/jitsi_test.go @@ -213,6 +213,29 @@ func TestDeliverBridgeMessageDropsStalePeerEpoch(t *testing.T) { } } +func TestReconnectEpochAnnounceWithZeroPeerEpochIsAccepted(t *testing.T) { + sess, err := New(context.Background(), engine.Config{ + URL: testHost, + Extra: map[string]string{credentialKeyRoom: testRoom}, + }) + if err != nil { + t.Fatalf("New: %v", err) + } + defer func() { _ = sess.Close() }() + + js, ok := sess.(*Session) + if !ok { + t.Fatal("sess is not *Session") + } + js.localEpoch.Store(0x2222) + + announce := makeBridgeFrameForEpoch(t, 0x1111, 0, nil) + js.deliverBridgeMessage(makeBridgeMessageFrom("peerA", map[string]any{rawFieldKey: announce}), true) + if got := js.peerEpoch.Load(); got != 0x1111 { + t.Fatalf("peerEpoch = 0x%08x, want announce epoch", got) + } +} + func TestDeliverBridgeMessagePeerEpochChangeRequestsReconnect(t *testing.T) { sess, err := New(context.Background(), engine.Config{ URL: testHost,