Commit Graph

896 Commits

Author SHA1 Message Date
nori 0489e183c4 test(e2e): add real multi-client concurrent reproducer for issue #95 2026-06-27 00:49:52 +00:00
nori b950af70e9 fix(vp8channel): latch control epoch so loopback filter survives data epoch rotation (issue #95) 2026-06-27 00:18:05 +00:00
nori 14e36eede6 fix(server): split swapSession to satisfy cyclop (issue #95) 2026-06-27 02:16:34 +03:00
nori c926f3adec fix(server): re-arm handshake on control-session reinstall (issue #95) 2026-06-27 02:11:04 +03:00
nori 7d0d9093d8 fix(goolom): bound peer connection close so stuck TURN dealloc cannot stall teardown (issue #95) 2026-06-26 16:02:30 +03:00
nori ae78a4c870 fix(goolom): keep advertised TURN relays for NAT traversal (issue #95) 2026-06-26 15:37:43 +03:00
neuronori 751b30b730 fix(jitsi): accept pre-latch broadcast so WaitForPeer unblocks (issue #95)
WaitForPeer makes the client block before it sends its SYN, so the
server cannot yet know the client epoch and its first welcome arrives as
a broadcast (receiverEpoch=0). The same happens on every reconnect:
peerEpoch is reset to 0 and the peer re-announces via a broadcast
Send(nil). The strict requireTargetedPeer guard dropped those broadcasts
while unlatched, so peerEpoch never latched and WaitForPeer hung for its
whole timeout - the link connected and pinged but no data ever flowed
("ping works, no connection"), most visibly when a peer left and
reconnected. Accept a broadcast while unlatched (peerEpoch==0) and keep
rejecting third-party broadcasts once latched.
2026-06-25 17:52:29 +00:00
neuronori cd3d568fd5 fix(vp8channel): reorder RTP and inject server keyframes (issue #95) 2026-06-25 16:07:19 +00:00
neuronori 2a9b1ec867 fix(vp8channel): pace server->client peer writer like client path
peerWriterPump emitted every KCP frame the instant it was queued. With
KCP congestion control off (nc=1) and a BDP-sized window that overran the
SFU policer on the server->client direction. Pace it on the same frame
ticker and per-tick byte budget as writerLoop, sharing batchSample via
batchSampleFrom.
2026-06-25 14:17:26 +00:00
neuronori a420683707 fix(server): use relaxed smux keepalive for control-plane transports (issue #95)
Server data-plane peer sessions used the conservative 30s smux keepalive
while the client used the relaxed window (SmuxConfigFor) for ControlPlane
transports like vp8channel. When the carrier went legitimately silent for
tens of seconds (publisher-PC reconnect / SFU renegotiation), the server
tore down its peer data session first at 30s, surfacing as 'closed pipe'
on the client and triggering a reconnect storm. Mirror the client and
apply SmuxConfigFor on the server data plane too.
2026-06-25 13:39:49 +00:00
neuronori 3d94446c1e docs: add AGENTS.md with project dev guidelines 2026-06-25 13:19:05 +00:00
neuronori 344373543f fix(vp8channel): serialize concurrent track writes (issue #95)
pion TrackLocalStaticSample.WriteSample packetizes under its lock but
emits RTP after releasing it, so concurrent callers interleave sequence
numbers on the wire. The server runs a per-peer writer pump for bulk data
alongside writerLoop for control/keepalive, both hitting the shared track;
the remote VP8 reassembler enforces strict sequence contiguity and drops
the interleaved frames, stalling server->client traffic. Funnel every
WriteSample through one mutex so each frame's packetize+emit is atomic.
2026-06-25 13:18:27 +00:00
zarazaex 7e339632c1 Merge pull request #98 from VaisVaisov/fix-handshake
fix: resolve connection failures in jitsi and vp8channel transports
2026-06-25 15:17:48 +03:00
neuronori ca2488b7da Merge remote-tracking branch 'origin/master' into fix-handshake
# Conflicts:
#	internal/client/client.go
2026-06-25 12:11:50 +00:00
neuronori 152f091490 fix(client,jitsi): bound peer wait, guard reconnect SYN race, drop pre-latch broadcasts
- bound WaitForPeer in bringUpLink/tryReopenSession to handshake timeout
  so a missing peer fails fast instead of hanging before the SOCKS listener
- call waitForPeer on the reconnect path too: resetLinkPeer clears the peer
  epoch, so without it the post-reconnect SYN re-races the server bridge
- restore strict requireTargetedPeer guard: the server always replies
  targeted (it latches the client epoch from the SYN before smux replies),
  so untargeted broadcasts before latch must be dropped
- remove per-frame debug logging on the bridge send/recv hot path
- extract buildSmuxClient / establishPeerSession helpers and wrap interface
  errors to satisfy cyclop/nestif/wrapcheck
2026-06-25 12:02:40 +00:00
neuronori 13f77b1da7 test(e2e): prove dead-link detection window via blackhole carrier
add a silent dead-link mode to the memory carrier (link stays up,
frames vanish) and a flag-gated TestDeadLinkDetectionWindow that
measures how long the datachannel client takes to notice a dead link
and reconnect. on the conservative liveness window it reconnects in
~58s; with the buggy 120s smux keepalive it fails to detect within 75s.

also drop dead restartControlKCP (both callers moved to
restartControlKCPWithHeader)
2026-06-24 14:54:19 +00:00
nori 384268b83e fix(runtime): scope relaxed liveness/keepalive to control-plane transports
The #95 telemost fix widened three global windows (control pong 15s->45s,
smux keepalive 30s->120s, tunnel ack 15s->90s). These live in shared
packages, so they also slowed dead-link detection on jitsi/datachannel:
a genuinely dead session stayed alive up to 120s before reconnecting,
which presented as the link going down and not recovering.

Restore the conservative defaults globally and apply the relaxed windows
only when the transport implements transport.ControlPlane (vp8channel/
goolom), where KCP batching + SFU publisher-PC renegotiation legitimately
go silent for ~25-30s. Conventional carriers reconnect promptly again.
2026-06-24 14:36:41 +00:00
VaisVaisov 05133a953b transport/vp8channel: add WaitForPeer to fix smux SYN race
Without this, the client could send a smux SYN frame before the server
had opened its bridge side. JVB would drop the frame and smux would not
retransmit, causing a connection timeout.

Mirrors the same fix already applied to transport/datachannel.
2026-06-22 11:55:20 +05:00
VaisVaisov c035f403a2 fix: wait for remote peer before opening smux stream (race condition)
Client was racing ahead of the server by ~2s: it opened the smux SYN
right after bridge-ready, but JVB silently dropped those frames because
the server hadn't opened its datachannel yet. smux does not retransmit
SYN, so AcceptStream on the server side never returned and the handshake
timed out.

Add WaitForPeer (engine.PeerReadySession / transport.PeerReadyTransport)
that polls peerEpoch until the first epoch broadcast from the remote
side is received, then proceed to smux + handshake.
2026-06-21 23:58:39 +05:00
VaisVaisov ca50e7fe81 fix(server): run handshake inline when transport has no control plane
In peer-routing mode installControlSession() returns early when the
transport does not implement transport.ControlPlane (e.g. datachannel),
leaving acceptHandshake() never called and s.sessionID never set.
servePeer() then spin-waits forever for a sessionID that never arrives,
so the client never receives the SERVER_WELCOME frame.

Mirror the legacy path from waitHandshake/serveSingle: if controlConn
is nil, drive acceptHandshake directly on the per-peer smux session
before entering the AcceptStream loop.
2026-06-21 15:15:04 +05:00
VaisVaisov c19906e85e fix(jitsi): keep xmpp connection alive and accept server broadcasts
xmppKeepalive was using fire-and-forget Send(); on a half-open TCP
connection pings were sent but the missing reply went undetected,
leaving the session stuck. Switch to SendIQWait so a timeout triggers
a reconnect.

In peer-routing mode the server may send the initial welcome frame as a
broadcast (receiverEpoch=0) before it has learned the client's
localEpoch. The previous requireTargetedPeer guard dropped every
broadcast unconditionally. Tighten the guard: only drop frames whose
senderEpoch is unknown or belongs to a different peer; frames from the
already-latched peer are always accepted.
2026-06-21 15:14:33 +05:00
neuronori f0de6b441e fix(vp8channel): preserve control epoch across reconnect/reset
Control KCP epoch must stay stable across both carrier reconnects and
liveness resets to avoid breaking ping/pong routing. Previously:

- SetReconnectCallback rotated control epoch (fix: preserve)
- ResetPeer also rotated control epoch (fix: preserve)

Both now snapshot the control epoch header before data epoch rotation
and use restartControlKCPWithHeader() with the preserved epoch.

This prevents control frames from using a mismatched epoch after
liveness timeout or carrier reconnect, which broke routing and caused
reconnect loops.
2026-06-20 08:03:28 +00:00
neuronori 8505dc19b6 Revert ci: allow real e2e to fail without failing entire workflow 2026-06-20 03:46:16 +00:00
neuronori 5f5700baa0 ci: allow real e2e to fail without failing entire workflow 2026-06-20 03:44:32 +00:00
neuronori a20fa1f32a test(e2e): expect jitsi video and sei to pass 2026-06-20 00:51:13 +00:00
nori b20554b19c fix(vp8channel): keep SFU forwarding bulk via decodable keepalive keyframe
inject a clean VP8 keyframe every ~2s during bulk so the SFU keeps
forwarding the track instead of stalling after its decode timeout.
add RTCP interceptors and IPv4-only ICE, priority control/data mux,
publisher PC reconnect with stable control epoch, and longer smux
keepalive/liveness windows to survive the reconnect gap
2026-06-20 00:37:08 +00:00
neuronori a3ae913c55 fix(e2e): increase timeouts for video-paced transports in stress test (issue #95)
Video-paced transports (vp8channel, videochannel, seichannel) need
longer operation timeouts due to frame pacing and KCP batching:
- streamPatternForDuration: 15s -> 60s for video transports
- sustainedEcho: 5s -> 60s for video transports

Part of fix for issue #95.

Related to #95
2026-06-19 01:58:48 +00:00
neuronori d5fb7eec39 fix(olcrtc): resolve telemost vp8channel disconnects (issue #95) 2026-06-19 01:58:26 +00:00
nori 9af4afffc2 test(e2e): expect jitsi video and sei to pass 2026-06-16 05:40:42 +00:00
nori 03ef36dda2 fix(e2e): align jitsi vp8channel expectation with test table 2026-06-16 05:01:37 +00:00
nori 9822defe53 deps: bump j to e98457d for rtx ssrc signaling fix 2026-06-15 09:09:08 +00:00
nori e7588c07bb build(deps): bump github.com/zarazaex69/j 2026-06-14 20:14:05 +00:00
zarazaex69 83972e9820 fix(transport): cap pending reassembly messages 2026-06-14 12:49:30 +03:00
zarazaex b95024b5a4 Merge pull request #96 from tankionline2005/master_peer_count
feat(server): log live peer count and connect/disconnect events
2026-06-13 09:40:55 +03:00
tankionline2005 18849933b5 implement peer counter 2026-06-13 13:27:53 +07:00
zarazaex69 95dc660d3d test(e2e): expect jitsi/vp8channel to pass 2026-06-13 02:57:21 +03:00
zarazaex69 95fd5b7d3c fix(server): tolerate stale control frames during handshake
After a session reinstall, the old client's control loop may have
already written a CONTROL_PING frame to the link before its context
was cancelled. This frame arrives at the server's new smux session and
is routed to the handshake stream (matching stream ID), where the
framing layer interprets the JSON bytes as an impossibly large length
prefix ('{\x22ve' = 2065856101 > 65536).

Previously this triggered a full reinstall, which could cascade into
a reconnect storm. Now acceptHandshake and acceptPeerHandshake
recognize ErrFrameTooLarge as a stale-frame artifact: they close the
polluted stream and retry AcceptStream up to 3 times, giving the real
CLIENT_HELLO a chance to arrive on the next stream.
2026-06-13 02:53:22 +03:00
zarazaex69 1f72c87d1e fix(jitsi): remove RTCP keepalive reconnect loop 2026-06-13 00:54:55 +03:00
zarazaex69 26141697c2 fix(jitsi): keep byte-stream sessions alive with RTP 2026-06-13 00:51:20 +03:00
zarazaex69 39cc3fafa3 fix(server,client): close old muxconn before session swap 2026-06-07 16:34:12 +03:00
zarazaex69 029ed22cc1 feat(script): add client and server deployment scripts 2026-06-07 15:07:11 +03:00
zarazaex69 68a6e6d52c chore: update default Jitsi service URL to meet.handyweb.org 2026-06-07 01:33:09 +03:00
zarazaex69 2ed53c3d53 style: remove gocognit nolint directive from negotiatePC 2026-06-07 01:25:43 +03:00
zarazaex69 be6428b0b1 test(e2e): update jitsi expectations to pass/fail per transport 2026-06-07 01:23:44 +03:00
zarazaex 7757b0cfec Merge pull request #94 from cyber-debug/master
perf: снизить idle CPU и удалить Docker-поддержку
2026-06-07 01:16:40 +03:00
zarazaex69 5051ea7c8f fix(jitsi): reconnect on peer connection failure
- now jitsi not fail and work SO stable
2026-06-06 18:39:16 +03:00
sbramn e6336e202c test(e2e): mark public jitsi matrix unstable 2026-06-05 20:09:51 +03:00
sbramn 1f6571d1c1 fix(jitsi): keep negotiation while avoiding idle rtcp 2026-06-05 20:01:45 +03:00
sbramn 275b61480c fix(jitsi): skip idle peer connection keepalive 2026-06-05 19:49:06 +03:00
sbramn 760ff2b6c0 Merge branch 'openlibrecommunity:master' into master 2026-06-05 19:40:39 +03:00