930 Commits

Author SHA1 Message Date
zarazaex69 38b837790b docs: simplify quick start to podman-based setup 2026-07-01 23:29:18 +03:00
zarazaex 0a304352d6 Merge pull request #117 from neuronori/feat/mobile-wbstream-auth-token
feat(mobile): pass wbstream auth.token via SetWBToken
2026-07-01 02:43:54 +03:00
nori 048e35354c feat(mobile): pass wbstream auth.token via SetWBToken 2026-06-30 23:33:50 +00:00
Nori 8362b861c0 feat(scripts): prompt for wbstream auth.token in srv/cnc (#116) 2026-07-01 02:21:43 +03:00
zarazaex 9168d8b786 Merge pull request #115 from neuronori/fix/issue-114-wbstream-access-token
feat(wbstream): support pre-issued account token via auth.token
2026-06-30 23:18:22 +03:00
neuronori 698fef580e docs(wbstream): explain datachannel needs moderator token in auth.token
- expand auth.token entry with canPublishData effect on datachannel
- note in compatibility matrix and transport table
- add moderator-grant screenshots and ru sync
- record future auto-grant idea as a docs note
2026-06-30 20:15:04 +00:00
neuronori bdaf82b1a7 feat(wbstream): surface guest access token for reuse via auth.token 2026-06-30 19:34:25 +00:00
neuronori 1408cf81ab feat(wbstream): support pre-issued account token via auth.token
allow supplying a wb account access token in config so the session
joins as that account instead of an anonymous guest. when auth.token
is empty the provider falls back to the guest-register flow.

threads auth.token through config -> session -> server/client ->
transport -> engine builtin -> auth provider.
2026-06-30 19:15:03 +00:00
zarazaex 58df8899c1 Merge pull request #112 from openlibrecommunity/docs/fast-via-scripts
docs: rewrite fast guide around srv.sh/cnc.sh scripts
2026-06-30 14:59:07 +03:00
nori 66abe2ad53 docs: rewrite fast guide around srv.sh/cnc.sh scripts 2026-06-30 11:57:50 +00:00
zarazaex 8846d49f10 Merge pull request #111 from hawkff/feat/pion-socket-protection
feat: apply socket protection to Pion
2026-06-30 14:36:20 +03:00
neuronori 605de6e5b3 fix: resolve lint issues in pion socket protection
- add package and exported-method doc comments
- use errors.New for sentinel, drop unused nolint directives
- wrap AcceptTCP error
- fix errcheck/noctx in tests
- extract newSettingEngine to keep negotiatePC under complexity limit
2026-06-30 11:32:38 +00:00
hawkff a68f2b668f feat: apply socket protection to Pion 2026-06-29 19:54:44 -04:00
zarazaex 94db67dc7b Merge pull request #110 from neuronori/fix/issue-109-vp8-payload-integrity !breaking changes!
fix(vp8channel): add per-packet crc to drop carrier-corrupted kcp data
2026-06-30 00:18:31 +03:00
neuronori 23db4c13fe fix(vp8channel): add per-packet crc to drop carrier-corrupted kcp data
vp8channel runs kcp with block=nil (no fec, no checksum), so the
fake-vp8 carrier has no integrity protection. an sfu that perturbs a
payload byte lets a corrupt-but-parseable kcp segment ride through as
valid in-order data and break the muxconn aead above it, surfacing as
chacha20poly1305: message authentication failed under sustained
transfers (issue #109).

append a crc32 trailer to every kcp packet at the kcpconn seam and
verify+strip it on deliver; a mismatch drops the packet so kcp
retransmits via sack, restoring udp-equivalent semantics below kcp.
2026-06-29 20:59:08 +00:00
zarazaex 3b68e0fcac Merge pull request #108 from neuronori/fix/issue-107-vp8-tunable-rate
fix(vp8channel): remove byte-rate pacer that throttled throughput
2026-06-29 19:45:33 +03:00
neuronori 4ddb981366 fix(vp8channel): remove byte-rate pacer that throttled throughput
the pacer (52aea2d) and its per-tick byte budget capped the wire well
below the sfu's real ceiling: telemost ran ~10mbit before it landed and
2-3mbit after. it was added to fix the #95 collapse, but that collapse
was keyframe starvation (sfu dropped the track with no decodable
keyframe after ~40s), fixed separately by forceKeepalive in b20554b. the
pacer was treating a symptom that no longer exists.

drop perTickBytes and the vp8.max_bytes_per_sec knob, and restore the
kcp send window (512->4096) and tick (20ms->5ms) that were shrunk
alongside the pacer. control liveness no longer depends on a small data
window: ping/pong runs on its own isolated kcp session drained with
priority by writerLoop, so the original starvation rationale is gone.

batchSample still bounds one sample to defaultMaxPayloadSize.

refs #107 #95
2026-06-29 06:27:32 +00:00
neuronori 1e270de44a fix(vp8channel): drop delay-based pacer, run static rate at 1mb/s
the aimd pacer read kcp's GetSRTT as its congestion signal, but the data
kcp runs with nc=1 and a fixed 512-segment (~716kb) window it keeps full
on purpose (kcp.go: data queues ~2-3s). that self-inflicted bufferbloat
dominates srtt no matter where the rate sits relative to the sfu policer
knee, so every tick tripped the high-delay mark and the rate decayed to
the 120kb/s floor. the result was slower, not faster.

the srtt signal is unusable as a knee detector on this carrier, so drop
adaptive control and keep the simple static pacer. raise the default to
the 1mb/s target from #107 (the old ~42s collapse at 1.2mib/s was the
keyframe-starvation drop fixed in #95, not a raw rate ceiling), still
tunable via vp8.max_bytes_per_sec.

refs #107
2026-06-29 05:50:36 +00:00
neuronori 2dffb5acbe feat(vp8channel): auto-discover wire rate via delay-based pacer
the hardcoded 400kb/s was a stability compromise and the previous knob
just moved the guesswork to operators: they had to hand-measure each
sfu's policer knee by ramping until stalls. replace both with a
delay-based aimd controller that finds the knee at runtime.

the sfu policer queues before it drops, so kcp's smoothed rtt inflates
ahead of the throughput collapse from #95/#107. the pacer folds one
srtt sample per writer tick: probe the rate up additively while delay
sits near the path baseline, back off multiplicatively once it
inflates. it settles just under the per-sfu knee on its own, both on
the client->server writerLoop and each server->client peer pump.

vp8.max_bytes_per_sec is now just the probe ceiling (default 1mb/s);
a fresh session still starts from the old 400kb/s operating point so a
healthy path only ramps up. no per-service hand-tuning left.

refs #107
2026-06-29 02:25:28 +00:00
neuronori 443f97edb0 feat(vp8channel): expose tunable wire byte-rate via vp8.max_bytes_per_sec
the pacer was pinned at a hardcoded 400kb/s stability compromise, so
operators could not reach their sfu's real throughput ceiling without
recompiling. the options.maxbytespersec knob already existed but was
never wired from yaml. plumb it through config -> session -> transport,
keeping 400kb/s as the conservative default.

refs #107
2026-06-29 01:38:15 +00:00
zarazaex 64d3d29980 Merge pull request #106 from neuronori/fix/issue-105-peer-restart-reconnect
fix(vp8channel): detect server restart via fresh peer epoch
2026-06-29 03:58:49 +03:00
neuronori f79439e61a fix(vp8channel): rebuild carrier on peer restart via fresh epoch
detect a server restart when a frame from a new epoch arrives after the
latched peer has gone silent past a grace window, then drive the full
carrier rebuild (stream.Reconnect) instead of a bare re-handshake over
the stale carrier. the restarted server rejoins the sfu as a fresh
participant, so re-handshaking on the old media path only times out;
rebuilding the carrier re-establishes a path the new server answers on
and recovers in seconds instead of waiting out the ~70s liveness window
2026-06-28 23:58:01 +00:00
neuronori e511d3204b Revert "fix(vp8channel): detect server restart via fresh peer epoch"
This reverts commit 660263881d.
2026-06-28 23:41:56 +00:00
neuronori 660263881d fix(vp8channel): detect server restart via fresh peer epoch
A restarted server rejoins the SFU with a new vp8channel epoch. The
client stayed latched to the old epoch and dropped every frame from the
new one, so recovery only happened once the relaxed control-liveness
window expired (~70s).

Watch for a frame from a different epoch after the latched peer has been
silent past a short grace window and fire the carrier reconnect callback,
driving a re-handshake against the new epoch in seconds. A live peer keeps
the latch fresh via its ~2s keepalives, so the watchdog never trips under
load or during SFU renegotiation.
2026-06-28 22:24:27 +00:00
zarazaex 6c8b6e6be7 Merge pull request #104 from neuronori/docs/translate-en
docs: translate all docs to english with ru/en switcher
2026-06-28 20:37:07 +03:00
zarazaex e75ce60bb3 Merge pull request #103 from neuronori/fix/issue-99-readme
docs: rewrite readme as proper project entry point
2026-06-28 20:07:07 +03:00
neuronori a14e34d027 docs: translate all docs to english with ru/en switcher 2026-06-28 17:04:28 +00:00
neuronori a21793dec9 docs: make english readme default with ru/en switch
- swap readme.md to english as default entry point
- move russian readme to readme.ru.md
- use RU / EN language switch buttons
- drop ffmpeg remark for videochannel
2026-06-28 16:54:40 +00:00
neuronori 9c05dc6ec3 docs: add english readme with language switcher 2026-06-28 16:40:25 +00:00
neuronori 91ed03f3d3 docs: rewrite readme as proper project entry point 2026-06-28 16:33:33 +00:00
nori 1ad1a7d51e fix: target xmpp domain not web host in keepalive ping 2026-06-28 16:02:32 +00:00
nori ca76e1026b fix: skip stale sessionID in legacy peer datachannel path 2026-06-28 15:59:04 +00:00
zarazaex69 9fde48ac53 docs: clarify room id placeholders and service checks 2026-06-28 00:27:14 +03:00
nori 5ae06c7983 fix(vp8channel): per-peer control plane + dst-addressed frames for concurrent clients (issue #95) 2026-06-27 01:58:57 +00:00
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