fix(jitsi): add RTCP keepalive to prevent JVB session expiry

This commit is contained in:
zarazaex69
2026-05-25 12:57:18 +03:00
parent 794df240a5
commit fe85457754
2 changed files with 40 additions and 18 deletions

18
go.sum
View File

@@ -231,24 +231,6 @@ github.com/xtaci/smux v1.5.57/go.mod h1:IGQ9QYrBphmb/4aTnLEcJby0TNr3NV+OslIOMrX8
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zarazaex69/gr v0.1.4 h1:7u9JRGCFqAfMKk3cG2VR9uiZRSHdCdv25ySwzK4LTOY=
github.com/zarazaex69/gr v0.1.4/go.mod h1:hAk5j/s2QFlvr3bJkjPwakZENsMBx6VOUN1GwYzYoRw=
github.com/zarazaex69/j v0.0.0-20260525065402-ab14a8750587 h1:BBlIf0+5czVJKS/ti5D/UGq24qw9CLiDDev4PFB33SU=
github.com/zarazaex69/j v0.0.0-20260525065402-ab14a8750587/go.mod h1:7/ypJTenOIPx23fpo5uF7l4u+rxZqg9cFbTL/N77Ktc=
github.com/zarazaex69/j v0.0.0-20260525070842-7db7b32d7255 h1:SGRiNJpCvIHUrAQxPKLu55EC5iZdt1sK8t8TSmXIJ/Y=
github.com/zarazaex69/j v0.0.0-20260525070842-7db7b32d7255/go.mod h1:7/ypJTenOIPx23fpo5uF7l4u+rxZqg9cFbTL/N77Ktc=
github.com/zarazaex69/j v0.0.0-20260525072612-27cb999da9fc h1:LQ9YzrfcuXf4BHAgotAKBQtmW3eCegs60+YcKON9gr4=
github.com/zarazaex69/j v0.0.0-20260525072612-27cb999da9fc/go.mod h1:7/ypJTenOIPx23fpo5uF7l4u+rxZqg9cFbTL/N77Ktc=
github.com/zarazaex69/j v0.0.0-20260525073820-97bd0a207728 h1:KC1+P2RytHIjaEPbqdCRF3C142Edj2KJj/1O0t57pV8=
github.com/zarazaex69/j v0.0.0-20260525073820-97bd0a207728/go.mod h1:7/ypJTenOIPx23fpo5uF7l4u+rxZqg9cFbTL/N77Ktc=
github.com/zarazaex69/j v0.0.0-20260525074211-5b001c9a66a0 h1:KXxeiwgdxR0T0zUwdaQ+VPanFEU/abij4tc91S14xto=
github.com/zarazaex69/j v0.0.0-20260525074211-5b001c9a66a0/go.mod h1:7/ypJTenOIPx23fpo5uF7l4u+rxZqg9cFbTL/N77Ktc=
github.com/zarazaex69/j v0.0.0-20260525075808-d35d82587a5d h1:C5zn+QFxj5u7sdA0HOWprfjAqioPq7f61TpGeH0LCZU=
github.com/zarazaex69/j v0.0.0-20260525075808-d35d82587a5d/go.mod h1:7/ypJTenOIPx23fpo5uF7l4u+rxZqg9cFbTL/N77Ktc=
github.com/zarazaex69/j v0.0.0-20260525080536-4baed2627868 h1:sVQZjngeHUkhYUo4hy53BjFDGZzWhv814fN5BuaXyQc=
github.com/zarazaex69/j v0.0.0-20260525080536-4baed2627868/go.mod h1:7/ypJTenOIPx23fpo5uF7l4u+rxZqg9cFbTL/N77Ktc=
github.com/zarazaex69/j v0.0.0-20260525082259-730a4c448bcf h1:8Rin8fYYKH3BqLS1VUxktTCchZy3SXkZC/0B0F0qPhw=
github.com/zarazaex69/j v0.0.0-20260525082259-730a4c448bcf/go.mod h1:7/ypJTenOIPx23fpo5uF7l4u+rxZqg9cFbTL/N77Ktc=
github.com/zarazaex69/j v0.0.0-20260525084838-37e184b41e37 h1:H7nRrEvDYOgOnZC+mA7UC65NPhbSRqKbg/ieri31rPc=
github.com/zarazaex69/j v0.0.0-20260525084838-37e184b41e37/go.mod h1:7/ypJTenOIPx23fpo5uF7l4u+rxZqg9cFbTL/N77Ktc=
github.com/zarazaex69/j v0.0.0-20260525090009-ce2ca552a46b h1:Qod8qBMKesKg+gIqL3f1yqh/v00qG/dnTEMqTkz7pTU=
github.com/zarazaex69/j v0.0.0-20260525090009-ce2ca552a46b/go.mod h1:7/ypJTenOIPx23fpo5uF7l4u+rxZqg9cFbTL/N77Ktc=
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=

View File

@@ -32,6 +32,7 @@ import (
"github.com/openlibrecommunity/olcrtc/internal/engine"
"github.com/openlibrecommunity/olcrtc/internal/logger"
pioninterceptor "github.com/pion/interceptor"
"github.com/pion/rtcp"
"github.com/pion/webrtc/v4"
"github.com/zarazaex69/j"
)
@@ -541,6 +542,17 @@ func (s *Session) negotiatePC(ctx context.Context, jSess *j.Session, sctpBridge
s.pcMu.Lock()
s.pc = pc
s.pcMu.Unlock()
// Start an RTCP keepalive. JVB tracks endpoint liveness via
// lastIncomingActivityInstant = max(lastRtpReceived, lastIceConsent).
// In a TURN-relay-only path, ICE consent updates can fail to reach
// JVB's lastIceActivityInstant tracker. Periodic RTCP RR packets
// guarantee lastRtpReceived is fresh and the endpoint is not expired
// after the default 1-minute inactivity timeout, which causes JVB to
// shut down the DTLS session and emit close_notify.
s.wg.Add(1)
go s.rtcpKeepalive(pc)
return nil
}
@@ -550,6 +562,34 @@ type negotiator interface {
HandleSourceAdd(stanza string) error
}
// rtcpKeepalive sends an empty RTCP Receiver Report every 5 seconds so JVB
// updates its lastRtpPacketReceivedInstant tracker for our endpoint. JVB's
// shouldExpire() check fires every minute and tears down the DTLS session
// (causing the observed CloseNotify alert) when no activity has been seen in
// more than the configured inactivityTimeout (default 1 minute). Even an
// empty RR keeps the timestamp fresh - JVB does not require the report to
// reference any specific SSRC.
func (s *Session) rtcpKeepalive(pc *webrtc.PeerConnection) {
defer s.wg.Done()
const interval = 5 * time.Second
ticker := time.NewTicker(interval)
defer ticker.Stop()
pkts := []rtcp.Packet{&rtcp.ReceiverReport{}}
for {
select {
case <-s.done:
return
case <-ticker.C:
if err := pc.WriteRTCP(pkts); err != nil {
if s.closed.Load() {
return
}
logger.Debugf("jitsi: rtcp keepalive write: %v", err)
}
}
}
}
// trickleDrainLoop reads the XMPP stanza channel and feeds any
// transport-info ICE candidates into the PeerConnection. It also drains
// non-jingle stanzas so the channel never fills and blocks the read loop.