diff --git a/internal/engine/jitsi/jitsi.go b/internal/engine/jitsi/jitsi.go index 8195120..19b5728 100644 --- a/internal/engine/jitsi/jitsi.go +++ b/internal/engine/jitsi/jitsi.go @@ -550,10 +550,7 @@ func (s *Session) negotiatePC(ctx context.Context, jSess *j.Session, sctpBridge } }) pc.OnConnectionStateChange(func(state webrtc.PeerConnectionState) { - logger.Debugf("jitsi pc state: %s", state.String()) - if state == webrtc.PeerConnectionStateFailed && !s.closed.Load() && s.onEnded != nil { - s.onEnded("jitsi peer connection failed") - } + s.handlePeerConnectionState(state) }) neg := jSess.Negotiator() @@ -1818,6 +1815,13 @@ func (s *Session) signalEnded(reason string) { } } +func (s *Session) handlePeerConnectionState(state webrtc.PeerConnectionState) { + logger.Debugf("jitsi pc state: %s", state.String()) + if state == webrtc.PeerConnectionStateFailed && !s.closed.Load() { + s.requestReconnect("jitsi peer connection failed") + } +} + // normaliseHost strips an optional scheme and trailing slashes off a Jitsi // host string. The j library expects a bare host; auth providers might pass // a full URL through verbatim. diff --git a/internal/engine/jitsi/keepalive_test.go b/internal/engine/jitsi/keepalive_test.go index c3155b2..bdbb020 100644 --- a/internal/engine/jitsi/keepalive_test.go +++ b/internal/engine/jitsi/keepalive_test.go @@ -15,6 +15,7 @@ import ( "time" "github.com/openlibrecommunity/olcrtc/internal/engine" + "github.com/pion/webrtc/v4" ) func newSilentSession(t *testing.T) *Session { @@ -304,6 +305,23 @@ func TestRequestReconnectIdempotent(t *testing.T) { } } +func TestPeerConnectionFailureRequestsReconnect(t *testing.T) { + js := newSilentSession(t) + js.SetShouldReconnect(func() bool { return true }) + + var endedReason string + js.SetEndedCallback(func(reason string) { endedReason = reason }) + + js.handlePeerConnectionState(webrtc.PeerConnectionStateFailed) + + if endedReason != "" { + t.Fatalf("peer failure ended session: %q", endedReason) + } + if !reconnectQueued(js) { + t.Fatal("peer failure did not enqueue reconnect") + } +} + func drainReconnectChNonBlocking(s *Session) { for { select {