From 98c6dec4a030832fdbca7a1e6505c27c8517119b Mon Sep 17 00:00:00 2001 From: zarazaex69 Date: Sun, 24 May 2026 05:31:55 +0300 Subject: [PATCH] docs: normalize em dash to hyphen in Russian documentation and code comments --- docs/fast.md | 2 +- docs/manual.md | 6 ++--- docs/settings.md | 6 ++--- docs/uri.md | 2 +- internal/auth/auth.go | 6 ++--- internal/auth/jitsi/jitsi.go | 6 ++--- internal/auth/telemost/api.go | 4 +-- internal/client/client.go | 12 ++++----- internal/e2e/local_soak_test.go | 2 +- internal/e2e/stress_test.go | 14 +++++----- internal/e2e/tunnel_test.go | 12 ++++----- internal/engine/engine.go | 2 +- internal/engine/goolom/session.go | 14 +++++----- internal/engine/jitsi/churn_test.go | 6 ++--- internal/engine/jitsi/jitsi.go | 28 ++++++++++---------- internal/muxconn/conn.go | 2 +- internal/server/server.go | 4 +-- internal/server/server_test.go | 2 +- internal/transport/common/common.go | 4 +-- internal/transport/common/stress_test.go | 6 ++--- internal/transport/seichannel/transport.go | 3 +-- internal/transport/transport.go | 4 +-- internal/transport/videochannel/transport.go | 4 +-- internal/transport/vp8channel/chaos_test.go | 6 ++--- internal/transport/vp8channel/transport.go | 2 +- pkg/olcrtc/conn.go | 2 +- pkg/olcrtc/olcrtc.go | 4 +-- 27 files changed, 82 insertions(+), 83 deletions(-) diff --git a/docs/fast.md b/docs/fast.md index 50ecf22..7e123fc 100644 --- a/docs/fast.md +++ b/docs/fast.md @@ -127,7 +127,7 @@ cd olcrtc Введите Room ID: ``` -Для **jitsi** — полный URL комнаты в формате `https://host/room` (например `https://meet.cryptopro.ru/myroom`). Имя комнаты придумывается на лету, без регистрации. Подойдёт любой публичный или self-hosted Jitsi Meet. +Для **jitsi** - полный URL комнаты в формате `https://host/room` (например `https://meet.cryptopro.ru/myroom`). Имя комнаты придумывается на лету, без регистрации. Подойдёт любой публичный или self-hosted Jitsi Meet. Для **telemost** и **wbstream** - создай руму через сайт ([telemost](https://telemost.yandex.ru/), [wbstream](https://stream.wb.ru)) и вставь её ID. diff --git a/docs/manual.md b/docs/manual.md index fd2107e..737755e 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -155,7 +155,7 @@ openssl rand -hex 32 ### jitsi + datachannel (рекомендуется) -Самый простой способ: используй любой self-hosted или публичный Jitsi Meet инстанс. Регистрация не нужна, имя комнаты выдумывается на лету. По умолчанию в примерах ниже — `meet.cryptopro.ru`, но подойдёт любой другой (`meet.jit.si`, свой self-hosted и т.п.). +Самый простой способ: используй любой self-hosted или публичный Jitsi Meet инстанс. Регистрация не нужна, имя комнаты выдумывается на лету. По умолчанию в примерах ниже - `meet.cryptopro.ru`, но подойдёт любой другой (`meet.jit.si`, свой self-hosted и т.п.). Создай YAML конфиг: @@ -180,13 +180,13 @@ data: data ./build/olcrtc-linux-amd64 server.yaml ``` -Сервер сам присоединится к комнате (в качестве участника без камеры/микрофона) и будет ждать, пока клиент тоже зайдёт. Без второго участника Jicofo не выдаёт session-initiate — это особенность Jitsi. +Сервер сам присоединится к комнате (в качестве участника без камеры/микрофона) и будет ждать, пока клиент тоже зайдёт. Без второго участника Jicofo не выдаёт session-initiate - это особенность Jitsi. ### wbstream + vp8channel (альтернатива) Создай руму через сайт [wbstream](https://stream.wb.ru) и вставь её ID в `room.id`. -`wbstream + datachannel` **не работает** в обычном guest flow — WB Stream выдаёт токены с `canPublishData=false`, и DC не маршрутизирует данные. Для обычного использования выбирай `vp8channel`. +`wbstream + datachannel` **не работает** в обычном guest flow - WB Stream выдаёт токены с `canPublishData=false`, и DC не маршрутизирует данные. Для обычного использования выбирай `vp8channel`. Создай YAML конфиг: diff --git a/docs/settings.md b/docs/settings.md index 77fd0c4..213c535 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -30,9 +30,9 @@ **Jitsi:** datachannel стабильно проходит - реализован поверх colibri-ws bridge channel и шлёт байты через `EndpointMessage{raw}` broadcast. Подходит для self-hosted и публичных Jitsi Meet инстансов без аутентификации (`https://meet.cryptopro.ru/...`, `https://meet.jit.si/...` и т.п.). Видео-транспорты (vp8channel, seichannel, videochannel) экспонируют sendable VideoTrack через pion PeerConnection после Jingle session-accept, но Jicofo требует дополнительных протокольных шагов (LastN, ReceiverVideoConstraints, source-add) для маршрутизации видео - поэтому они помечены `~` . -**Jitsi + seichannel — отдельная оговорка.** SEI NAL-юниты идут пассажиром в H.264 видеопотоке, а Jicofo на self-hosted инстансах (например `meet.cryptopro.ru`) периодически режет/откладывает upstream видео когда ресивера в комнате формально нет - для нас это выглядит как `seichannel ack timeout` при формально живом PeerConnection. В steady-state транспорт работает, но e2e матрица помечает его `Unstable` (флаппит): зелёного и красного результата в CI достаточно, тест suite на этом не валится. Для надёжной передачи данных через jitsi предпочтительнее `datachannel` или `vp8channel`. +**Jitsi + seichannel - отдельная оговорка.** SEI NAL-юниты идут пассажиром в H.264 видеопотоке, а Jicofo на self-hosted инстансах (например `meet.cryptopro.ru`) периодически режет/откладывает upstream видео когда ресивера в комнате формально нет - для нас это выглядит как `seichannel ack timeout` при формально живом PeerConnection. В steady-state транспорт работает, но e2e матрица помечает его `Unstable` (флаппит): зелёного и красного результата в CI достаточно, тест suite на этом не валится. Для надёжной передачи данных через jitsi предпочтительнее `datachannel` или `vp8channel`. -**Рекомендуемая комбинация: `jitsi + datachannel`** — стабильно работает на любом self-hosted или публичном Jitsi Meet (например `meet.cryptopro.ru`), не требует регистрации, простая руму создания. Альтернатива: `wbstream + vp8channel` — стабильно для коммерческих сценариев, не требует специальных прав. +**Рекомендуемая комбинация: `jitsi + datachannel`** - стабильно работает на любом self-hosted или публичном Jitsi Meet (например `meet.cryptopro.ru`), не требует регистрации, простая руму создания. Альтернатива: `wbstream + vp8channel` - стабильно для коммерческих сценариев, не требует специальных прав. Скорость по убыванию: `datachannel` > `vp8channel` > `seichannel` > `videochannel` @@ -191,7 +191,7 @@ transport. Используй одинаковые traffic-настройки н ### wbstream + datachannel (не работает в обычном guest flow) -WB Stream DataChannel **не работает** в обычном guest flow — WB Stream выдаёт токены с `canPublishData=false`, и DC не маршрутизирует данные. Этот режим помечен как expected fail в E2E тестах. Для обычного использования выбирай `vp8channel`, `seichannel` или `videochannel`. +WB Stream DataChannel **не работает** в обычном guest flow - WB Stream выдаёт токены с `canPublishData=false`, и DC не маршрутизирует данные. Этот режим помечен как expected fail в E2E тестах. Для обычного использования выбирай `vp8channel`, `seichannel` или `videochannel`. ```yaml # room ID нужно создать вручную через https://stream.wb.ru diff --git a/docs/uri.md b/docs/uri.md index 37e6639..c306f3a 100644 --- a/docs/uri.md +++ b/docs/uri.md @@ -222,7 +222,7 @@ data: data olcrtc://jitsi?datachannel@https://meet.cryptopro.ru/myroom#d823fa01cb3e0609b67322f7cf984c4ee2e4ce2e294936fc24ef38c9e59f4799$RU / olc free sub ``` -`` для jitsi — полный URL комнаты в формате `https://host/room` (или `host/room`). Поддерживается любой self-hosted Jitsi Meet инстанс без аутентификации; для публичных серверов вроде `meet.jit.si` тот же формат. +`` для jitsi - полный URL комнаты в формате `https://host/room` (или `host/room`). Поддерживается любой self-hosted Jitsi Meet инстанс без аутентификации; для публичных серверов вроде `meet.jit.si` тот же формат. ### Эквивалент YAML diff --git a/internal/auth/auth.go b/internal/auth/auth.go index e345f8c..257a247 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -7,7 +7,7 @@ // expressed via the RoomCreator interface. // // The "none" auth provider passes a caller-supplied URL+Token through -// unchanged — this is the path that sing-box and other downstream consumers +// unchanged - this is the path that sing-box and other downstream consumers // take when they want to use olcrtc as a generic LiveKit/Goolom/Jitsi // transport without any service-specific behaviour baked in. package auth @@ -30,7 +30,7 @@ var ( // // URL is the signaling endpoint (e.g. wss://livekit.example/). Token is the // access token (LiveKit JWT, Goolom session credential, etc). Extra is for -// engine-specific bits that don't fit the common shape — engines should not +// engine-specific bits that don't fit the common shape - engines should not // rely on it being populated unless their paired auth provider documents it. type Credentials struct { URL string @@ -56,7 +56,7 @@ type Provider interface { // Engine reports which engine this auth provider feeds. Engine() string // DefaultServiceURL returns the well-known service URL for this provider - // (e.g. "https://stream.wb.ru"). Returns "" if no default exists — in that + // (e.g. "https://stream.wb.ru"). Returns "" if no default exists - in that // case the caller must supply -url explicitly. DefaultServiceURL() string // Issue obtains credentials for the given room. diff --git a/internal/auth/jitsi/jitsi.go b/internal/auth/jitsi/jitsi.go index 9af38e1..8cb6ccc 100644 --- a/internal/auth/jitsi/jitsi.go +++ b/internal/auth/jitsi/jitsi.go @@ -3,7 +3,7 @@ // // Public Jitsi Meet servers do not require authentication for guest access; // the only "credentials" the engine needs are the host+room pair extracted -// from a user-supplied room URL. This provider does no HTTP at all — it just +// from a user-supplied room URL. This provider does no HTTP at all - it just // parses the URL and forwards host+room to the engine via auth.Credentials. // // Supported RoomURL forms: @@ -14,7 +14,7 @@ // // Optional URL path prefixes (e.g. "/jitsi") are preserved as part of the // host when present, so deployments behind a path-mounted reverse proxy work -// transparently — the j library accepts any host string the WebSocket dial +// transparently - the j library accepts any host string the WebSocket dial // can resolve. package jitsi @@ -51,7 +51,7 @@ func (Provider) DefaultServiceURL() string { return defaultServiceURL } // // The URL field of the returned Credentials carries the Jitsi host (e.g. // "meet.example.com"); the room name lives in Extra under CredentialKeyRoom. -// Token is unused — Jitsi guest access requires no token. +// Token is unused - Jitsi guest access requires no token. func (Provider) Issue(_ context.Context, cfg auth.Config) (auth.Credentials, error) { host, room, err := parseRoomURL(cfg.RoomURL) if err != nil { diff --git a/internal/auth/telemost/api.go b/internal/auth/telemost/api.go index 7babca1..d0fb3dc 100644 --- a/internal/auth/telemost/api.go +++ b/internal/auth/telemost/api.go @@ -2,8 +2,8 @@ // It fetches the connection metadata (media server URL, peer ID, room ID, // signing credentials) the Goolom engine needs to join a conference. // -// Telemost does not expose an API to create rooms — they originate in the -// Yandex UI — so this provider does not implement auth.RoomCreator. +// Telemost does not expose an API to create rooms - they originate in the +// Yandex UI - so this provider does not implement auth.RoomCreator. package telemost import ( diff --git a/internal/client/client.go b/internal/client/client.go index 41f1d1f..ec6dea6 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -142,7 +142,7 @@ func RunWithReady(ctx context.Context, cfg Config, onReady func()) error { // (e.g. handshake timeout against a wedged seichannel transport) // without ever calling Close on the carrier link, leaving our MUC // presence behind as a ghost participant in the next test that - // joined the same room. shutdown is nil-safe — it skips fields + // joined the same room. shutdown is nil-safe - it skips fields // that bringUpLink hadn't populated yet. defer c.shutdown() @@ -204,7 +204,7 @@ func (c *Client) bringUpLink( } // Carrier callback fires after the link is back up. If handshake // still fails it usually means the server hasn't completed its - // own reinstall yet — keep the listener up and wait for either + // own reinstall yet - keep the listener up and wait for either // another callback or a future liveness loss to re-trigger. c.handleReconnect(ctx, cfg, cancel, "carrier") }) @@ -287,8 +287,8 @@ func openControlStreamTimeout( // resolveDeviceID returns the device ID to send in CLIENT_HELLO. // // Precedence: -// 1. Explicit deviceID arg (Config.DeviceID) — used verbatim. -// 2. Persistent file at path (Config.DeviceIDPath) — read if it exists, +// 1. Explicit deviceID arg (Config.DeviceID) - used verbatim. +// 2. Persistent file at path (Config.DeviceIDPath) - read if it exists, // otherwise generated and written for future runs. // 3. Random UUID per run when both inputs are empty. func resolveDeviceID(deviceID, path string) (string, error) { @@ -392,12 +392,12 @@ func (c *Client) retryHandshake(ctx context.Context, cfg Config, cancel context. } // Don't fail the whole process on liveness reconnect: the carrier // rebuild may take dozens of seconds (e.g. ICE restart on a flaky - // network). Keep the SOCKS5 listener open and wait — handleSocks5 + // network). Keep the SOCKS5 listener open and wait - handleSocks5 // will return host-unreachable to clients until we recover. For // carrier-driven reconnects the callback fires after the link is // already up, so a missed handshake is more suspicious; cap it. if reason == "carrier" && attempt >= 5 { - logger.Warnf("client reconnect: exhausted %d handshake attempts (reason=%s) — keeping listener up", attempt, reason) + logger.Warnf("client reconnect: exhausted %d handshake attempts (reason=%s) - keeping listener up", attempt, reason) return } select { diff --git a/internal/e2e/local_soak_test.go b/internal/e2e/local_soak_test.go index a33dc5a..1a8e18d 100644 --- a/internal/e2e/local_soak_test.go +++ b/internal/e2e/local_soak_test.go @@ -407,7 +407,7 @@ func pumpReader( } // isExpectedShutdownErr filters errors that just mean "we asked the conn -// to stop" — deadline expirations from our SetDeadline kick, EOF from the +// to stop" - deadline expirations from our SetDeadline kick, EOF from the // peer half-closing, etc. func isExpectedShutdownErr(err error) bool { if err == nil { diff --git a/internal/e2e/stress_test.go b/internal/e2e/stress_test.go index 3d59f7e..fb1b9fd 100644 --- a/internal/e2e/stress_test.go +++ b/internal/e2e/stress_test.go @@ -27,7 +27,7 @@ var ( realStress = flag.Bool( //nolint:gochecknoglobals // package-level state intentional "olcrtc.stress", false, - "run real provider stress matrix (bulk transfer + sustained echo) — requires -olcrtc.real-e2e", + "run real provider stress matrix (bulk transfer + sustained echo) - requires -olcrtc.real-e2e", ) realStressBulkDuration = flag.Duration( //nolint:gochecknoglobals // package-level state intentional "olcrtc.stress-bulk-duration", @@ -183,7 +183,7 @@ func runRealE2EStressCase(t *testing.T, carrierName, transportName, roomURL, ech } goroutinesAfter := runtime.NumGoroutine() - // Allow some slack — pion/quic spawn helpers that take time to wind down + // Allow some slack - pion/quic spawn helpers that take time to wind down // after Close, but a real leak shows up as tens of extra goroutines. const goroutineLeakSlack = 30 if goroutinesAfter > goroutinesBefore+goroutineLeakSlack { @@ -204,7 +204,7 @@ func runRealE2EStressCase(t *testing.T, carrierName, transportName, roomURL, ech // MiB/s; videochannel/seichannel ~25 KB/s through 256-byte qr-encoded // frames at 25 FPS). An asynchronous writer outruns a slow transport, // fills muxconn / SOCKS / RTP-track buffers, and the deadlocked pipe -// eventually trips a TCP-write deadline — which is not a real bug, just +// eventually trips a TCP-write deadline - which is not a real bug, just // the natural consequence of pumping into a slow pipe with no flow // control. Request-response naturally rate-limits to the transport's // actual round-trip throughput, which is what we want to measure. @@ -251,10 +251,10 @@ func streamPatternForDuration(conn net.Conn, duration time.Duration, chunkSize i } type echoStats struct { - count int - lost int - p50, p95, p99 time.Duration - maxLatency time.Duration + count int + lost int + p50, p95, p99 time.Duration + maxLatency time.Duration } // sustainedEcho writes payloads of size `payloadSize` and waits for them to diff --git a/internal/e2e/tunnel_test.go b/internal/e2e/tunnel_test.go index 7f364f7..1445547 100644 --- a/internal/e2e/tunnel_test.go +++ b/internal/e2e/tunnel_test.go @@ -110,7 +110,7 @@ const ( // known to flap: it sometimes succeeds and sometimes fails for // reasons outside our control (third-party server load, lossy SFU // paths, etc.). The matrix runner records the outcome but does - // not fail the test either way. Use this sparingly — prefer + // not fail the test either way. Use this sparingly - prefer // ExpectPass / ExpectFail when the behaviour is deterministic. realE2EExpectUnstable ) @@ -234,7 +234,7 @@ type memoryStream struct { // video tracks through a real (in-process) WebRTC stack. // // streamCtx is owned by the stream itself (cancelled in Close), not - // by the short-lived ctx that Connect receives — the video + // by the short-lived ctx that Connect receives - the video // transport's connectCtx fires its deferred cancel as soon as // streamTransport.Connect returns, which would otherwise tear down // the async SDP negotiation goroutine before it can find its peer. @@ -385,7 +385,7 @@ func (s *memoryStream) SetVideoTrackHandler(cb func(*webrtc.TrackRemote, *webrtc // transceiver that AddTrack on the peer side will create even if // SetVideoTrackHandler arrives before AddVideoTrack. if _, err := s.ensurePC(); err != nil { - // e2e helper: swallow — the failure surfaces on the next + // e2e helper: swallow - the failure surfaces on the next // AddVideoTrack/Connect path that actually needs the PC. _ = err } @@ -813,13 +813,13 @@ func realRoomURL(ctx context.Context, t *testing.T, carrierName string) string { t.Skip("skip wbstream real e2e: set -olcrtc.real-wbstream-room to an existing room ID") return "" case "jitsi": - // Jitsi has no notion of "creating" a room — names are conjured + // Jitsi has no notion of "creating" a room - names are conjured // on first join. The default flag points at meet.cryptopro.ru // by default. When the flag is left at its default value, a // per-process random suffix is appended // to the slug: two participants share a single room by design (one - // pair, one shared key), so any third participant — including another - // concurrent test process with the same shared key — would corrupt + // pair, one shared key), so any third participant - including another + // concurrent test process with the same shared key - would corrupt // the wire protocol on both sides. Users overriding the flag are // trusted to manage room uniqueness themselves. _ = ctx diff --git a/internal/engine/engine.go b/internal/engine/engine.go index 7217f5d..fd44581 100644 --- a/internal/engine/engine.go +++ b/internal/engine/engine.go @@ -30,7 +30,7 @@ type Capabilities struct { VideoTrack bool } -// Credentials are produced by an auth provider — duplicated here to avoid an +// Credentials are produced by an auth provider - duplicated here to avoid an // import cycle between engine and auth. type Credentials struct { URL string diff --git a/internal/engine/goolom/session.go b/internal/engine/goolom/session.go index 64aa183..2782b96 100644 --- a/internal/engine/goolom/session.go +++ b/internal/engine/goolom/session.go @@ -1,8 +1,8 @@ // Package goolom implements an engine.Session backed by the Goolom SFU // signaling protocol. Goolom is the proprietary SFU developed for Yandex -// Telemost; the on-wire protocol — capabilities offer, separated subscriber +// Telemost; the on-wire protocol - capabilities offer, separated subscriber // and publisher PeerConnections, ack/pong keepalive, slots-based subscribe -// model — is what this engine speaks. +// model - is what this engine speaks. // // HTTP auth (room-info lookup, telemetry referer, etc.) lives in the auth // package; this engine consumes a media-server WebSocket URL plus the @@ -35,10 +35,10 @@ const ( wsReadTimeout = 60 * time.Second wsHandshakeTimeout = 15 * time.Second - keyUID = "uid" - keyDescription = "description" - keyPcSeq = "pcSeq" - keyName = "name" + keyUID = "uid" + keyDescription = "description" + keyPcSeq = "pcSeq" + keyName = "name" stateTerminated = "terminated" credentialKeyRoomID = "roomID" @@ -88,7 +88,7 @@ type Session struct { peerID string roomID string credentials string - roomURL string // referer for telemetry — opaque to the engine + roomURL string // referer for telemetry - opaque to the engine telemetryReferer string refresh func(ctx context.Context) (engine.Credentials, error) diff --git a/internal/engine/jitsi/churn_test.go b/internal/engine/jitsi/churn_test.go index b0e59f5..4657580 100644 --- a/internal/engine/jitsi/churn_test.go +++ b/internal/engine/jitsi/churn_test.go @@ -81,7 +81,7 @@ func TestReconnectWindowEnforcesCapWithinWindow(t *testing.T) { // TestResetPeerClearsBindingForNewPeer covers fix 032151b: after an // upper-layer handshake failure the supervisor calls ResetPeer, and the -// next peer in the room must be allowed to latch — not blocked by the +// next peer in the room must be allowed to latch - not blocked by the // previously-latched (now stale) endpoint. // // jitsi_test.go has no coverage for this path. @@ -102,7 +102,7 @@ func TestResetPeerClearsBindingForNewPeer(t *testing.T) { frameA := makeBridgeFrameForEpoch(t, 0x1111, 0, []byte("from-A")) js.deliverBridgeMessage(makeBridgeMessageFrom("peerA", map[string]any{rawFieldKey: frameA}), true) - // Peer B tries while A still owns the latch — must be dropped. + // Peer B tries while A still owns the latch - must be dropped. frameB1 := makeBridgeFrameForEpoch(t, 0x2222, 0, []byte("from-B-blocked")) js.deliverBridgeMessage(makeBridgeMessageFrom("peerB", map[string]any{rawFieldKey: frameB1}), true) @@ -196,7 +196,7 @@ func TestChurnPeerEpochChanges(t *testing.T) { t.Fatalf("stale frames delivered: %d (filter regression)", staleDelivered.Load()) } if delivered.Load() == 0 { - t.Fatal("no frames delivered at all — filter is too aggressive") + t.Fatal("no frames delivered at all - filter is too aggressive") } } diff --git a/internal/engine/jitsi/jitsi.go b/internal/engine/jitsi/jitsi.go index 278ab0c..3e7a5b8 100644 --- a/internal/engine/jitsi/jitsi.go +++ b/internal/engine/jitsi/jitsi.go @@ -138,7 +138,7 @@ type bridgeOutbound struct { // New creates a new Jitsi engine session. // -// cfg.URL carries the Jitsi host (e.g. "meet.cryptopro.ru") — populated by the +// cfg.URL carries the Jitsi host (e.g. "meet.cryptopro.ru") - populated by the // jitsi auth provider after parsing the user-supplied room URL. cfg.Extra // must contain the room name under the "room" key. func New(_ context.Context, cfg engine.Config) (engine.Session, error) { @@ -364,7 +364,7 @@ func (s *Session) videoTrackHandler() func(*webrtc.TrackRemote, *webrtc.RTPRecei // negotiatePC builds the pion PeerConnection, applies Jicofo's offer, // answers it and registers all the per-side wiring (DTLS state, ICE -// callbacks, transceiver direction). It's branchy on purpose — Jingle +// callbacks, transceiver direction). It's branchy on purpose - Jingle // negotiation has many discrete steps that can fail and each step // belongs to the same logical operation, so splitting it into helpers // would obscure the wire order rather than clarify it. @@ -376,7 +376,7 @@ func (s *Session) negotiatePC(ctx context.Context, jSess *j.Session) error { // pion auto-registers a default interceptor chain (sender reports, // receiver reports, NACK, etc.) when none is supplied. Several of - // those probe the DTLS transport on a tick — until DTLS comes up + // those probe the DTLS transport on a tick - until DTLS comes up // (which can take seconds against Jitsi's STUN-only path, or never // in pathological cases) they spam logs with // "the DTLS transport has not started yet". JVB performs its own @@ -423,7 +423,7 @@ func (s *Session) negotiatePC(ctx context.Context, jSess *j.Session) error { // When sending video, AddTrack already creates the video m-line (sendonly). // When only receiving, an explicit recvonly transceiver is required so the - // SDP answer includes a video m-line — without it JVB does not set up a + // SDP answer includes a video m-line - without it JVB does not set up a // video forwarding path and ICE stalls. Mirrors the j library reference CLI: // AddTrack and AddTransceiverFromKind(video,recvonly) are mutually exclusive // in Plan B; using both produces a malformed SDP. @@ -469,13 +469,13 @@ func (s *Session) negotiatePC(ctx context.Context, jSess *j.Session) error { // (trickle ICE) and source-add (other participants' SSRCs) the moment // it sees us reply to session-initiate. If we started the drain loop // only after Accept and SendSourceAdd, those stanzas would queue in - // the 64-slot channel while RTP — which travels straight over UDP/TURN - // and reaches us in tens of ms — arrives first. Pion then drops the + // the 64-slot channel while RTP - which travels straight over UDP/TURN + // and reaches us in tens of ms - arrives first. Pion then drops the // peer's RTP as "unhandled SSRC, media section has an explicit SSRC" // because HandleSourceAdd hasn't grafted the SSRC onto the remote SDP // yet. The peer never produces an OnTrack callback, our handshake // never gets an ACK, and the tunnel dies. Starting the consumer first - // closes that race window — any source-add Jicofo emits is picked up + // closes that race window - any source-add Jicofo emits is picked up // the instant it lands on the wire. s.wg.Add(1) go s.trickleDrainLoop(pc, neg, jSess.LowLevel().Stanzas()) @@ -939,7 +939,7 @@ func (s *Session) peerLatchAccepts(from string) bool { } // decodeRaw extracts the bytes from an EndpointMessage produced by the j -// library's BridgeSendRaw helper. Mirrors the unexported colibri.DecodeRaw — +// library's BridgeSendRaw helper. Mirrors the unexported colibri.DecodeRaw - // the j library's BridgeMessage type alias keeps the necessary fields public, // but the helper itself lives in an internal package. func decodeRaw(m j.BridgeMessage) []byte { @@ -963,14 +963,14 @@ func decodeRaw(m j.BridgeMessage) []byte { // // 1. Mark the session closed so send/recv loops drop new work. // 2. Close the pion PeerConnection (stops media, sends DTLS bye). This -// mirrors jvbJingleSession.close() in lib-jitsi-meet — note that +// mirrors jvbJingleSession.close() in lib-jitsi-meet - note that // graceful leave there does NOT send Jingle session-terminate; Jicofo // learns of the departure from the MUC presence-unavailable stanza // and only then frees the JVB bridge slot. // 3. Close the underlying j.Session, which closes the colibri-ws bridge, // performs the MUC presence-unavailable handshake (LeaveMUCWait -// waits for Prosody to echo our own unavailable presence — the -// XMPP-level equivalent of XMPPEvents.MUC_LEFT — with a 5s cap), +// waits for Prosody to echo our own unavailable presence - the +// XMPP-level equivalent of XMPPEvents.MUC_LEFT - with a 5s cap), // and only then tears down the websocket. // 4. Cancel the supervisor context and wait for goroutines. // @@ -979,7 +979,7 @@ func decodeRaw(m j.BridgeMessage) []byte { // stops replying to our session-terminate IQ. TerminateWait then ate its // 3s budget and we still left ghost participants behind. lib-jitsi-meet // avoids this entirely by relying on MUC presence as the single source of -// truth for departure — Prosody's MUC layer is far more reliable than +// truth for departure - Prosody's MUC layer is far more reliable than // Jicofo's IQ handler under load. func (s *Session) Close() error { if !s.closed.CompareAndSwap(false, true) { @@ -1200,7 +1200,7 @@ func (s *Session) CanSend() bool { return false } if s.onData == nil && s.onPeerData == nil { - // pure video mode — readiness driven by PC connection state + // pure video mode - readiness driven by PC connection state s.pcMu.Lock() ready := s.pc != nil && s.pc.ConnectionState() == webrtc.PeerConnectionStateConnected s.pcMu.Unlock() @@ -1234,7 +1234,7 @@ func (s *Session) GetBufferedAmount() uint64 { // // Tracks added before Connect are sent as part of the session-accept SDP // (so Jicofo announces them to other participants automatically). Tracks -// added afterwards are attached to the live PeerConnection — Jitsi's +// added afterwards are attached to the live PeerConnection - Jitsi's // source-add flow is not yet implemented in this engine, so late tracks // will only be visible on the next reconnect. func (s *Session) AddVideoTrack(track webrtc.TrackLocal) error { diff --git a/internal/muxconn/conn.go b/internal/muxconn/conn.go index 9fdb4cc..aeef5f1 100644 --- a/internal/muxconn/conn.go +++ b/internal/muxconn/conn.go @@ -52,7 +52,7 @@ const ( // frameBufPool recycles plaintext buffers between Push (decrypts a wire // frame into a buffer) and Read (consumes the buffer fully then returns -// it). It is global so all Conn instances share the same hot cache — +// it). It is global so all Conn instances share the same hot cache - // most clients in the same process talk to a handful of peers, and // per-Conn pools fragment the warm set unnecessarily. var frameBufPool = sync.Pool{ //nolint:gochecknoglobals // intentional process-wide buffer pool diff --git a/internal/server/server.go b/internal/server/server.go index 73e4bfb..a3dffdc 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -328,7 +328,7 @@ func (s *Server) reinstallSession(dead *smux.Session) { s.sessMu.Lock() if s.session != dead { - // Someone else already reinstalled — discard our build. + // Someone else already reinstalled - discard our build. s.sessMu.Unlock() _ = newSess.Close() _ = newConn.Close() @@ -487,7 +487,7 @@ func (s *Server) getPeerSession(peerID string) *peerSession { } // serve drives the smux Accept loop. The first accepted stream on a given -// smux session is the control stream — the handshake runs there. Subsequent +// smux session is the control stream - the handshake runs there. Subsequent // streams are tunnel streams and proxy traffic. func (s *Server) serve(ctx context.Context) { if s.peerLn != nil { diff --git a/internal/server/server_test.go b/internal/server/server_test.go index 2468348..274a70b 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -362,7 +362,7 @@ func TestHandleStreamDispatchAfterConnect(t *testing.T) { req, err := json.Marshal(ConnectRequest{ Cmd: testConnectCmd, Addr: testConnectAddr, - Port: 1, // unreachable port — dispatch will fail dial and exit + Port: 1, // unreachable port - dispatch will fail dial and exit }) if err != nil { t.Fatalf("Marshal() error = %v", err) diff --git a/internal/transport/common/common.go b/internal/transport/common/common.go index 5c98fb9..94178fa 100644 --- a/internal/transport/common/common.go +++ b/internal/transport/common/common.go @@ -1,5 +1,5 @@ // Package common provides building blocks shared by the video-track based -// transports (videochannel, seichannel) — fragment/reassembly, ack waiters, +// transports (videochannel, seichannel) - fragment/reassembly, ack waiters, // and per-peer random IDs. vp8channel does its own KCP-based framing and // only consumes RandomID. package common @@ -208,7 +208,7 @@ func (a *AckRegistry) Unregister(seq uint32) { } // Resolve delivers crc to the waiter for seq, if present. A missing waiter -// is silently ignored — the sender has already moved on. +// is silently ignored - the sender has already moved on. func (a *AckRegistry) Resolve(seq, crc uint32) { a.mu.Lock() waiter := a.waiters[seq] diff --git a/internal/transport/common/stress_test.go b/internal/transport/common/stress_test.go index d93a113..6252995 100644 --- a/internal/transport/common/stress_test.go +++ b/internal/transport/common/stress_test.go @@ -101,7 +101,7 @@ func TestReassemblerStressShuffledFragments(t *testing.T) { } } if dupCount == 0 { - t.Fatal("test injected duplicates but reassembler reported none — duplicate path not exercised") + t.Fatal("test injected duplicates but reassembler reported none - duplicate path not exercised") } t.Logf("delivered %d/%d messages, observed %d duplicates", len(delivered), messages, dupCount) } @@ -137,8 +137,8 @@ func TestReassemblerConcurrentPushIsSafe(t *testing.T) { r.Push(common.Fragment{ Seq: seq, CRC: crc, - TotalLen: uint32(len(p)), //nolint:gosec // bounded - FragIdx: uint16(idx), //nolint:gosec // bounded + TotalLen: uint32(len(p)), //nolint:gosec // bounded + FragIdx: uint16(idx), //nolint:gosec // bounded FragTotal: uint16(len(raw)), //nolint:gosec // bounded Payload: raw[idx], }) diff --git a/internal/transport/seichannel/transport.go b/internal/transport/seichannel/transport.go index 6399ae7..e6667b2 100644 --- a/internal/transport/seichannel/transport.go +++ b/internal/transport/seichannel/transport.go @@ -135,7 +135,7 @@ func New(ctx context.Context, cfg transport.Config) (transport.Transport, error) } stream := &engineVideoSession{session: session, vt: vt} - // Stream/track IDs must be unique per peer — Jitsi rejects session-accept + // Stream/track IDs must be unique per peer - Jitsi rejects session-accept // when msid collides with another participant in the conference. track, err := webrtc.NewTrackLocalStaticSample( webrtc.RTPCodecCapability{ @@ -542,4 +542,3 @@ func decodeTransportFrame(data []byte) (transportFrame, error) { return transportFrame{}, ErrUnexpectedFrameType } } - diff --git a/internal/transport/transport.go b/internal/transport/transport.go index 63aa22e..be2af30 100644 --- a/internal/transport/transport.go +++ b/internal/transport/transport.go @@ -1,6 +1,6 @@ // Package transport defines transport abstractions and registry. // -// A transport encodes byte payloads onto a carrier (engine) primitive — either +// A transport encodes byte payloads onto a carrier (engine) primitive - either // a reliable byte stream (datachannel) or a video track (videochannel, // seichannel, vp8channel). Transport-specific tuning lives in per-transport // Options types; the common configuration shared by every transport lives in @@ -41,7 +41,7 @@ type Transport interface { Features() Features // Reconnect asks the underlying carrier (engine) to tear down and // re-establish the SFU connection. Upper layers call this when a - // liveness probe declares the link dead — useful when the engine has + // liveness probe declares the link dead - useful when the engine has // not yet noticed silent packet loss. Reconnect(reason string) } diff --git a/internal/transport/videochannel/transport.go b/internal/transport/videochannel/transport.go index 831c493..3ad7854 100644 --- a/internal/transport/videochannel/transport.go +++ b/internal/transport/videochannel/transport.go @@ -73,7 +73,7 @@ type streamTransport struct { sendMu sync.Mutex startWriter sync.Once fragAcks *fragAckTracker - reassembler *common.Reassembler + reassembler *common.Reassembler videoW int videoH int videoFPS int @@ -650,7 +650,7 @@ func (p *streamTransport) handleInboundFrame(frame transportFrame) { p.sendAck(frame.seq, frame.crc, frame.fragIdx) case common.ResultPartial, common.ResultDuplicate: // Every fragment we successfully decoded gets acked, including - // duplicates — under retransmits the sender may have lost the + // duplicates - under retransmits the sender may have lost the // earlier ack and is waiting on this one. p.sendAck(frame.seq, frame.crc, frame.fragIdx) case common.ResultIgnore: diff --git a/internal/transport/vp8channel/chaos_test.go b/internal/transport/vp8channel/chaos_test.go index 94fd515..a99f8da 100644 --- a/internal/transport/vp8channel/chaos_test.go +++ b/internal/transport/vp8channel/chaos_test.go @@ -122,7 +122,7 @@ func runChaosLoopback(t *testing.T, msgs [][]byte, cfg chaosCfg, timeout time.Du var droppedAB, droppedBA atomic.Uint64 go chaosPump(t, stop, a2b, rtB, cfg, &droppedAB) - // Return path stays clean by default — KCP ACKs must come back reliably + // Return path stays clean by default - KCP ACKs must come back reliably // for fair loss measurement; loss on one direction is enough to stress. go chaosPump(t, stop, b2a, rtA, chaosCfg{}, &droppedBA) @@ -161,7 +161,7 @@ func TestKCPSurvivesModeratePacketLoss(t *testing.T) { dur, dropped := runChaosLoopback(t, msgs, chaosCfg{lossRatio: 0.10, seed: 0xC0FFEE}, 20*time.Second) t.Logf("delivered %d msgs in %s with %d packets dropped (10%% loss)", len(msgs), dur, dropped) if dropped == 0 { - t.Fatal("chaos pump did not drop any packets — loss injection broken") + t.Fatal("chaos pump did not drop any packets - loss injection broken") } } @@ -259,7 +259,7 @@ func TestKCPRecoversFromBurstLoss(t *testing.T) { } // TestKCPThroughputBaseline establishes a perfect-channel throughput floor. -// Not an assertion — if this number regresses meaningfully on the same +// Not an assertion - if this number regresses meaningfully on the same // hardware, something changed in KCP options (window size, MTU, tick). func TestKCPThroughputBaseline(t *testing.T) { if testing.Short() { diff --git a/internal/transport/vp8channel/transport.go b/internal/transport/vp8channel/transport.go index 084c26c..8176b00 100644 --- a/internal/transport/vp8channel/transport.go +++ b/internal/transport/vp8channel/transport.go @@ -143,7 +143,7 @@ func New(ctx context.Context, cfg transport.Config) (transport.Transport, error) } stream := &engineVideoSession{session: session, vt: vt} - // Stream/track IDs must be unique per peer — Jitsi rejects session-accept + // Stream/track IDs must be unique per peer - Jitsi rejects session-accept // when msid collides with another participant in the conference. track, err := webrtc.NewTrackLocalStaticSample( webrtc.RTPCodecCapability{ diff --git a/pkg/olcrtc/conn.go b/pkg/olcrtc/conn.go index c614845..28ab2cd 100644 --- a/pkg/olcrtc/conn.go +++ b/pkg/olcrtc/conn.go @@ -10,7 +10,7 @@ import ( // conn wraps a Session as a net.Conn. // Read is backed by an io.Pipe fed by the engine's OnData callback. // Write calls Session.Send. -// Deadlines are not supported — callers should use context cancellation. +// Deadlines are not supported - callers should use context cancellation. type conn struct { s *Session } diff --git a/pkg/olcrtc/olcrtc.go b/pkg/olcrtc/olcrtc.go index 601ffd9..87b96ff 100644 --- a/pkg/olcrtc/olcrtc.go +++ b/pkg/olcrtc/olcrtc.go @@ -1,6 +1,6 @@ // Package olcrtc exposes olcrtc as an embeddable Go library. // -// Typical usage — obtain a [net.Conn]-compatible handle and dial: +// Typical usage - obtain a [net.Conn]-compatible handle and dial: // // sess, err := olcrtc.New(ctx, olcrtc.Config{ // Engine: "livekit", @@ -9,7 +9,7 @@ // }) // if err != nil { ... } // conn, err := sess.Dial(ctx) // blocks until WebRTC data channel is ready -// // conn implements net.Conn — pass it to sing-box / any io.ReadWriter consumer +// // conn implements net.Conn - pass it to sing-box / any io.ReadWriter consumer // // Built-in auth providers (jitsi, telemost, wbstream): //