docs: translate docs to Russian and remove project-map

This commit is contained in:
zarazaex69
2026-05-19 22:46:39 +03:00
parent 2fc9caac6c
commit 9e7d0836a3
10 changed files with 401 additions and 1522 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,22 @@
# olcrtc client config example
# Run with: olcrtc client.yaml
# Пример клиентского конфига olcrtc
# Запуск: olcrtc client.yaml
mode: cnc
link: direct
auth:
provider: jitsi # must match the server
provider: jitsi # должен совпадать с сервером
# For jitsi: full conference URL (https://host/room or host/room).
# Must match the server.
# Для jitsi: полный URL комнаты (https://host/room или host/room).
# Должен совпадать с сервером.
room:
id: "https://meet.small-dm.ru/REPLACE_WITH_ROOM_NAME"
crypto:
# Or use key_file: "./olcrtc.key" to keep the secret out of this file.
key: "REPLACE_ME_WITH_64_HEX_CHARS" # must match the server
# Можно использовать key_file: "./olcrtc.key", чтобы не хранить секрет прямо здесь.
key: "REPLACE_ME_WITH_64_HEX_CHARS" # должен совпадать с сервером
net:
transport: datachannel # must match the server
transport: datachannel # должен совпадать с сервером
dns: "8.8.8.8:53"
liveness:
@@ -26,24 +24,24 @@ liveness:
timeout: 5s
failures: 3
# Optional planned rebuild for long-running calls.
# Необязательный плановый rebuild долгих звонков.
# lifecycle:
# max_session_duration: 6h
# Optional reliability shaping for encrypted wire messages.
# Необязательный лимит/pacing для зашифрованных wire-сообщений.
# traffic:
# max_payload_size: 4096
# min_delay: 5ms
# max_delay: 30ms
# Local SOCKS5 listener exposed to applications
# Локальный SOCKS5 listener для приложений.
socks:
host: "127.0.0.1"
port: 8808
user: "" # optional inbound auth
user: "" # необязательная входящая auth
pass: ""
# Direct engine mode — only when auth.provider is "none"
# Прямой engine-режим: используется только при auth.provider: none.
engine:
name: ""
url: ""
@@ -54,10 +52,10 @@ vp8:
batch_size: 64
sei:
fps: 20
batch_size: 1
fps: 60
batch_size: 64
fragment_size: 900
ack_timeout_ms: 3000
ack_timeout_ms: 2000
video:
width: 1920

View File

@@ -1,63 +1,94 @@
# Настройка
# Настройка YAML
olcrtc считывает всю свою конфигурацию среды выполнения из одного YAML-файла.
теперь флагов CLI нет.
`olcrtc` читает runtime-настройки из одного YAML-файла. CLI принимает ровно один аргумент - путь к конфигу; отдельных CLI-флагов для режима, транспорта и провайдера больше нет.
```bash
olcrtc /etc/olcrtc/server.yaml
olcrtc /etc/olcrtc/client.yaml
```
Примеры:
Готовые примеры:
- [`server.example.yaml`](./server.example.yaml)
- [`client.example.yaml`](./client.example.yaml)
- [`failover.example.yaml`](./failover.example.yaml)
## Схема
## Схема
| YAML path | Значение |
|------------------------------------------------------------------|-----------------------------------------------------------|
| `mode` | `srv`, `cnc`, or `gen` |
| `link` | `direct` |
| `auth.provider` | `jitsi`, `telemost`, `wbstream`, `none` |
| `room.id` | conference room id |
| `crypto.key` / `crypto.key_file` | 64-char hex (32 bytes), inline or read from file |
| `net.transport` | `datachannel`, `videochannel`, `seichannel`, `vp8channel` |
| `net.dns` | resolver `host:port` |
| `socks.host` / `.port` | client-side listener |
| `socks.user` / `.pass` | optional client-side auth |
| `socks.proxy_addr` / `.proxy_port` | server-side egress proxy |
| `engine.name` / `.url` / `.token` | only when `auth.provider: none` |
| `video.*` | videochannel tuning |
| `vp8.*` | vp8channel tuning |
| `sei.fps` / `.batch_size` / `.fragment_size` / `.ack_timeout_ms` | seichannel tuning |
| `liveness.interval` | control-stream ping interval, default `10s` |
| `liveness.timeout` | pong timeout, default `5s` |
| `liveness.failures` | missed pongs before reconnect, default `3` |
| `lifecycle.max_session_duration` | planned session rebuild interval, e.g. `6h`; unset = off |
| `traffic.max_payload_size` | safe encrypted wire-message cap; `0` = transport default |
| `traffic.min_delay` / `.max_delay` | optional send pacing jitter, e.g. `5ms` / `30ms` |
| `gen.amount` | gen mode: number of rooms to create |
| `profiles[]` | ordered srv/cnc failover profiles |
| `failover.retry_delay` | delay before trying the next profile, e.g. `2s` |
| `failover.max_cycles` | stop after N full profile-list passes; `0` = forever |
| `data` | path to data directory |
| `debug` | verbose logging |
| `ffmpeg` | path to ffmpeg binary |
| YAML path | Значение |
|---|---|
| `mode` | `srv`, `cnc` или `gen` |
| `auth.provider` | `jitsi`, `telemost`, `wbstream`, `none` |
| `room.id` | ID/URL комнаты для выбранного auth-провайдера |
| `room.channel` | необязательный ID канала для peer-routing сценариев |
| `crypto.key` / `crypto.key_file` | общий ключ: 64 hex-символа, напрямую или из файла |
| `net.transport` | `datachannel`, `vp8channel`, `seichannel`, `videochannel` |
| `net.dns` | DNS resolver в формате `host:port` |
| `socks.host` / `socks.port` | локальный SOCKS5 listener в `mode: cnc` |
| `socks.user` / `socks.pass` | необязательная auth для входящих SOCKS5-подключений |
| `socks.proxy_addr` / `socks.proxy_port` | исходящий SOCKS5-прокси на серверной стороне |
| `engine.name` / `engine.url` / `engine.token` | прямой engine-режим, только при `auth.provider: none` |
| `video.*` | настройки `videochannel` |
| `vp8.*` | настройки `vp8channel` |
| `sei.*` | настройки `seichannel` |
| `liveness.interval` | интервал ping по control stream, по умолчанию `10s` |
| `liveness.timeout` | таймаут pong, по умолчанию `5s` |
| `liveness.failures` | сколько pong можно пропустить до rebuild, по умолчанию `3` |
| `lifecycle.max_session_duration` | плановый rebuild сессии, например `6h`; пусто = выключено |
| `traffic.max_payload_size` | лимит зашифрованного wire-message; `0` = лимит транспорта |
| `traffic.min_delay` / `traffic.max_delay` | необязательный pacing отправки, например `5ms` / `30ms` |
| `gen.amount` | режим `gen`: сколько комнат создать |
| `profiles[]` | список failover-профилей для `srv`/`cnc` |
| `failover.retry_delay` | пауза перед следующим профилем, например `2s` |
| `failover.max_cycles` | сколько полных проходов по профилям сделать; `0` = бесконечно |
| `data` | путь к директории с runtime-данными (`names`, `surnames`) |
| `debug` | подробное логирование |
| `ffmpeg` | путь к бинарнику ffmpeg для `videochannel` |
`mode: cnc` refuses non-loopback `socks.host` values unless both
`socks.user` and `socks.pass` are set.
`crypto.key_file` читается относительно YAML-файла. Нельзя одновременно задавать `crypto.key` и `crypto.key_file`.
`crypto.key_file` is resolved relative to the YAML file. Do not set it
together with `crypto.key`.
`mode: cnc` запрещает слушать не-loopback адрес (`0.0.0.0`, LAN IP и т.п.), если не заданы оба поля `socks.user` и `socks.pass`.
## Обязательный минимум
### Сервер
```yaml
mode: srv
auth:
provider: jitsi
room:
id: "https://meet.small-dm.ru/myroom"
crypto:
key: "REPLACE_ME_WITH_64_HEX_CHARS"
net:
transport: datachannel
dns: "1.1.1.1:53"
data: data
```
### Клиент
```yaml
mode: cnc
auth:
provider: jitsi
room:
id: "https://meet.small-dm.ru/myroom"
crypto:
key: "REPLACE_ME_WITH_64_HEX_CHARS"
net:
transport: datachannel
dns: "1.1.1.1:53"
socks:
host: "127.0.0.1"
port: 8808
data: data
```
## Liveness
After `CLIENT_HELLO` / `SERVER_WELCOME`, the first smux stream stays open as
an encrypted control stream. olcrtc now sends `CONTROL_PING` / `CONTROL_PONG`
messages over that stream to prove the real tunnel path still round-trips.
This detects states where a provider or WebRTC layer looks connected but the
encrypted smux path is no longer usable.
После `CLIENT_HELLO` / `SERVER_WELCOME` первый smux stream остаётся открытым как зашифрованный control stream. По нему `olcrtc` отправляет `CONTROL_PING` / `CONTROL_PONG`, чтобы проверять именно рабочий путь туннеля, а не только статус WebRTC-соединения.
```yaml
liveness:
@@ -66,34 +97,22 @@ liveness:
failures: 3
```
When the failure threshold is reached, the current smux session is rebuilt.
In failover mode, a profile that exits after liveness-triggered reconnect
failure lets the supervisor advance to the next profile.
Когда порог пропущенных pong достигнут, текущая smux-сессия пересоздаётся. В failover-режиме профиль, который завершился после неудачного reconnect, отдаёт управление supervisor, и тот пробует следующий профиль.
## Lifecycle Rotation
`lifecycle.max_session_duration` sets a planned upper bound for one provider
call/session. When the duration expires, olcrtc cancels the active server or
client session and starts a fresh one with the same config. While this option
is enabled, clean session endings are also restarted so the peer that did not
fire the timer can follow the rebuild. This is useful for long-running
deployments where provider calls get stale, accumulate media state, or should
be periodically re-created.
`lifecycle.max_session_duration` задаёт плановый верхний предел длительности одного звонка/сессии у провайдера. Когда время истекает, активная `srv` или `cnc` сессия закрывается и запускается заново с тем же конфигом.
```yaml
lifecycle:
max_session_duration: 6h
```
The field is optional and disabled when omitted. Values use Go duration syntax
such as `30m`, `2h`, or `6h`; zero and negative durations are rejected.
Поле необязательное. Формат - Go duration: `30m`, `2h`, `6h`. Ноль и отрицательные значения не принимаются.
## Traffic Shaping
`traffic` applies a shared reliability-oriented wrapper around the selected
transport. It can cap encrypted wire-message size and add small send pacing
delays without truncating data. When a payload would exceed the effective cap,
the send fails clearly instead of cutting bytes and corrupting smux.
`traffic` добавляет общий wrapper вокруг выбранного транспорта. Он может ограничить размер зашифрованного сообщения и добавить небольшую задержку перед отправкой. Данные не обрезаются: если payload не помещается в эффективный лимит, отправка завершается явной ошибкой.
```yaml
traffic:
@@ -102,23 +121,14 @@ traffic:
max_delay: 30ms
```
The wrapper clamps the configured payload cap to the selected transport's
advertised `MaxPayloadSize`. Client and server also reduce smux frame size to
fit the effective encrypted payload cap, accounting for crypto overhead. `0`
adds no extra cap beyond the selected transport's advertised limit. Delays use
Go duration syntax; if only `min_delay` is set, it is a fixed delay. Use the
same traffic settings on both peers.
Лимит сжимается до `MaxPayloadSize`, который заявляет выбранный транспорт. Клиент и сервер также уменьшают smux frame size с учётом crypto overhead. Значение `0` не добавляет лимит сверх лимита транспорта. Если задан только `min_delay`, задержка фиксированная. Используй одинаковые `traffic`-настройки на обеих сторонах.
## Failover Profiles
`mode: srv` and `mode: cnc` can define `profiles`. Top-level fields are used
as common defaults; each profile overrides only the fields it sets. The CLI
runs profiles in order. If a profile fails or ends while the process is still
alive, olcrtc waits `failover.retry_delay` and starts the next profile.
`mode: srv` и `mode: cnc` могут задавать `profiles`. Верхнеуровневые поля становятся общими defaults, а каждый профиль переопределяет только то, что указано внутри него.
```yaml
mode: srv
link: direct
crypto:
key_file: ./olcrtc.key
net:
@@ -147,10 +157,26 @@ failover:
max_cycles: 0
```
Both peers must use compatible profile order and room settings. This first
failover layer rebuilds the session on the next profile; active smux streams
do not migrate, but new connections can recover on the next profile.
Порядок профилей и параметры комнаты должны быть совместимы на сервере и клиенте. Активные smux streams между профилями не мигрируют; новые подключения смогут восстановиться на следующем профиле.
When `debug: true` is enabled, the CLI also emits a compact supervisor status
snapshot with the active profile, per-profile start/failure counters, and
bounded failover history size.
## mode: gen
`gen` создаёт Room ID заранее и печатает их в stdout. Сейчас это полезно прежде всего для `wbstream`, потому что его auth-провайдер реализует создание комнат.
```yaml
mode: gen
auth:
provider: wbstream
crypto:
key: "REPLACE_ME_WITH_64_HEX_CHARS"
net:
transport: vp8channel
dns: "1.1.1.1:53"
gen:
amount: 3
data: data
```
```bash
olcrtc gen.yaml
```

View File

@@ -1,8 +1,7 @@
# olcrtc failover config example
# Use the same profile order on both peers.
# Пример failover-конфига olcrtc
# Используй одинаковый порядок профилей на обеих сторонах.
mode: srv
link: direct
crypto:
key_file: "./olcrtc.key"
@@ -15,11 +14,11 @@ liveness:
timeout: 5s
failures: 3
# Optional planned rebuild for each active profile.
# Необязательный плановый rebuild для каждого активного профиля.
# lifecycle:
# max_session_duration: 6h
# Optional reliability shaping for encrypted wire messages.
# Необязательный лимит/pacing для зашифрованных wire-сообщений.
# traffic:
# max_payload_size: 4096
# min_delay: 5ms

View File

@@ -93,11 +93,11 @@ cd olcrtc
### Auth (на каком сервисе передавать трафик)
```
Select auth provider:
Выберите auth-провайдера:
1) jitsi
2) telemost
3) wbstream
Enter choice [1-3, default: 1]:
Введите номер [1-3, по умолчанию: 1]:
```
Выбери сервис. Полную матрицу совместимости смотри в [settings.md](settings.md).
@@ -107,26 +107,26 @@ Enter choice [1-3, default: 1]:
### Transport (как именно передавать данные)
```
Select transport:
Выберите транспорт:
1) datachannel
2) videochannel
3) seichannel
4) vp8channel
Enter choice [1-4, default: 1]:
Введите номер [1-4, по умолчанию: 1]:
```
Рекомендации:
- **datachannel** - самый быстрый, минимальный пинг. Стабильно работает с `jitsi` через colibri-ws bridge channel. **WBStream DC не работает** в обычном guest flow (токены без `canPublishData`). **Telemost удалил DC**.
- **vp8channel** - работает с telemost и wbstream, быстрый, но большой пинг.
- **seichannel** - работает только с wbstream, медленный, но мелкий пинг.
- **videochannel** - работает с wbstream (стабильно) и telemost (best effort), самый медленный и большой пинг.
- **videochannel** - работает с wbstream стабильно, с telemost по возможности; самый медленный и с большим пингом.
**Рекомендуемая комбинация: `jitsi + datachannel`** — работает стабильно, не требует регистрации, легко поднимать на своём сервере. Альтернатива: `wbstream + vp8channel`.
### Room ID
```
Enter Room ID:
Введите Room ID:
```
Для **jitsi** — полный URL комнаты в формате `https://host/room` (например `https://meet.small-dm.ru/myroom`). Имя комнаты придумывается на лету, без регистрации. Подойдёт любой публичный или self-hosted Jitsi Meet.
@@ -136,7 +136,7 @@ Enter Room ID:
### DNS
```
DNS server [default: 8.8.8.8:53]:
DNS-сервер [по умолчанию: 8.8.8.8:53]:
```
Нажми Enter. Менять не нужно если нет причин, на всякий можно поставить 77.88.8.8 или DNS твоего провайдера.
@@ -144,7 +144,7 @@ DNS server [default: 8.8.8.8:53]:
### SOCKS5 прокси для исходящего трафика
```
Use SOCKS5 proxy for egress? (y/N):
Использовать SOCKS5-прокси для исходящего трафика? (y/N):
```
Если нет - просто Enter, если надо то введи `y`. Нужно чтобы сервер сам ходил через прокси.
@@ -152,10 +152,10 @@ Use SOCKS5 proxy for egress? (y/N):
### Параметры транспорта (только для videochannel)
```
Video codec:
Видео-кодек:
1) qrcode
2) tile (requires 1080x1080)
Enter choice [1-2, default: 1]:
2) tile (требует 1080x1080)
Введите номер [1-2, по умолчанию: 1]:
```
Выбери кодек:
@@ -165,57 +165,57 @@ Enter choice [1-2, default: 1]:
#### qrcode
```
Video width [default: 1920]:
Video height [default: 1080]:
QR error correction (low/medium/high/highest) [default: low]:
QR fragment size bytes [default: 0 (auto)]:
Ширина видео [по умолчанию: 1920]:
Высота видео [по умолчанию: 1080]:
Коррекция ошибок QR (low/medium/high/highest) [по умолчанию: low]:
Размер QR-фрагмента в байтах [по умолчанию: 0 (авто)]:
```
- **Video width / height** - разрешение видео. Больше = больше данных за кадр, но тяжелее поток.
- **QR error correction** - коррекция ошибок: `low` быстрее, `highest` надёжнее при плохом канале.
- **QR fragment size** - размер фрагмента в байтах. `0` = автоматически.
- **Ширина / высота видео** - разрешение видео. Больше = больше данных за кадр, но тяжелее поток.
- **Коррекция ошибок QR** - `low` быстрее, `highest` надёжнее при плохом канале.
- **Размер QR-фрагмента** - размер фрагмента в байтах. `0` = автоматически.
#### tile
```
[*] Tile codec selected - forcing 1080x1080
Tile module size in pixels 1..270 [default: 4]:
Tile Reed-Solomon parity percent 0..200 [default: 20]:
[*] Выбран tile-кодек, принудительно выставляю 1080x1080
Размер tile-модуля в пикселях 1..270 [по умолчанию: 4]:
Процент Reed-Solomon parity для tile 0..200 [по умолчанию: 20]:
```
- **Tile module size** - размер одного тайла в пикселях. Меньше = больше данных за кадр.
- **Размер tile-модуля** - размер одного тайла в пикселях. Меньше = больше данных за кадр.
- **Tile Reed-Solomon parity** - процент избыточности. `0` = без коррекции, `20` оптимально.
#### Общие параметры (для обоих кодеков)
```
Video FPS [default: 30]:
Video bitrate [default: 2M]:
Hardware acceleration (none/nvenc) [default: none]:
FPS видео [по умолчанию: 30]:
Битрейт видео [по умолчанию: 2M]:
Аппаратное ускорение (none/nvenc) [по умолчанию: none]:
```
- **Video FPS** - кадров в секунду. Больше FPS = выше пропускная способность, больше нагрузка на CPU.
- **Video bitrate** - битрейт ffmpeg. Примеры: `2M`, `5M`, `500K`.
- **Hardware acceleration** - `none` если нет GPU, `nvenc` для NVIDIA GPU.
- **FPS видео** - кадров в секунду. Больше FPS = выше пропускная способность, больше нагрузка на CPU.
- **Битрейт видео** - битрейт ffmpeg. Примеры: `2M`, `5M`, `500K`.
- **Аппаратное ускорение** - `none` если нет GPU, `nvenc` для NVIDIA GPU.
---
### Параметры транспорта (только для vp8channel)
```
VP8 FPS [default: 60]: 60
VP8 batch size (frames per tick) [default: 64]: 64
VP8 FPS [по умолчанию: 60]:
VP8 batch size (кадров за тик) [по умолчанию: 64]:
```
Введи `60` и `64` - это оптимальные значения.
Нажми Enter, если устраивают значения по умолчанию `60` и `64`.
### Параметры транспорта (только для seichannel)
```
SEI FPS [default: 20]: 60
SEI batch size (frames per tick) [default: 1]: 64
SEI fragment size in bytes [default: 900]: 900
SEI ACK timeout in milliseconds [default: 3000]: 2000
SEI FPS [по умолчанию: 60]:
SEI batch size (кадров за тик) [по умолчанию: 64]:
Размер SEI-фрагмента в байтах [по умолчанию: 900]:
SEI ACK timeout в миллисекундах [по умолчанию: 2000]:
```
Нажми Enter для всех - значения по умолчанию оптимальны.
@@ -227,16 +227,16 @@ SEI ACK timeout in milliseconds [default: 3000]: 2000
После запуска скрипт выведет:
```
[+] Server started successfully!
[+] Сервер успешно запущен!
Container name: olcrtc-server
Auth: wbstream
Transport: datachannel
Room ID: abc123xyz
Encryption key: d823fa01cb3e0609b67322f7cf984c4ee2e4ce2e294936fc24ef38c9e59f4799
Имя контейнера: olcrtc-server
Auth: wbstream
Transport: datachannel
Room ID: abc123xyz
Ключ шифрования: d823fa01cb3e0609b67322f7cf984c4ee2e294936fc24ef38c9e59f4799
```
**Сохрани Room ID и Encryption key** - они нужны для клиента.
**Сохрани Room ID и ключ шифрования** - они нужны для клиента.
---
@@ -255,7 +255,7 @@ cd olcrtc
Когда спросит ключ:
```
Enter Encryption Key (hex): Encryption key
Введите ключ шифрования (hex):
```
Вставь ключ с сервера.
@@ -263,8 +263,8 @@ Enter Encryption Key (hex): Encryption key
### SOCKS5 адрес и порт
```
SOCKS5 ip [default: 127.0.0.1]:
SOCKS5 port [default: 8808]:
SOCKS5 IP [по умолчанию: 127.0.0.1]:
SOCKS5 порт [по умолчанию: 8808]:
```
Нажми Enter оба раза. Прокси поднимется на `127.0.0.1:8808`.
@@ -272,7 +272,7 @@ SOCKS5 port [default: 8808]:
### SOCKS5 аутентификация (необязательно)
```
SOCKS5 username (leave empty to disable auth):
SOCKS5 логин (оставь пустым, чтобы отключить auth):
```
Если нужна защита логином и паролем - введи логин, затем пароль. Если нет - просто Enter, аутентификация будет отключена.
@@ -280,9 +280,9 @@ SOCKS5 username (leave empty to disable auth):
### Результат
```
[+] Client started successfully!
[+] Клиент успешно запущен!
Container name: olcrtc-client
Имя контейнера: olcrtc-client
SOCKS5 proxy: 127.0.0.1:8808
```

View File

@@ -143,7 +143,7 @@ openssl rand -hex 32
## Шаг 7: Запустить сервер
На серверной машине (VPS и т.д.). Подбери нужную комбинацию carrier + transport из матрицы в [settings.md](settings.md).
На серверной машине (VPS и т.д.). Подбери нужную комбинацию auth provider + transport из матрицы в [settings.md](settings.md).
### jitsi + datachannel (рекомендуется)
@@ -154,7 +154,6 @@ openssl rand -hex 32
```yaml
# server.yaml
mode: srv
link: direct
auth:
provider: jitsi
room:
@@ -186,7 +185,6 @@ data: data
```yaml
# server.yaml
mode: srv
link: direct
auth:
provider: wbstream
room:
@@ -223,14 +221,13 @@ Room ID нужно передать клиенту.
## Шаг 8: Запустить клиент
На своей машине. Auth provider, transport, room ID и key должны совпадать с сервером.
На своей машине. `auth.provider`, `net.transport`, `room.id` и `crypto.key` должны совпадать с сервером.
### jitsi + datachannel (рекомендуется)
```yaml
# client.yaml
mode: cnc
link: direct
auth:
provider: jitsi
room:
@@ -257,7 +254,6 @@ data: data
```yaml
# client.yaml
mode: cnc
link: direct
auth:
provider: wbstream
room:
@@ -288,7 +284,6 @@ SOCKS5 server listening on 127.0.0.1:8808
```yaml
# client.yaml
mode: cnc
link: direct
auth:
provider: wbstream
room:

View File

@@ -1,422 +0,0 @@
# olcRTC Project Map
This is a developer map for finding the useful parts of the project quickly.
It focuses on code ownership, runtime flow, extension points, and areas that
are worth deeper work.
## One-Sentence Model
olcRTC is an encrypted TCP-over-WebRTC tunnel: the client exposes a local
SOCKS5 listener, the server dials requested TCP targets, and both sides carry
the smux byte stream through a selected WebRTC carrier and transport.
## Runtime Stack
```text
YAML config
-> cmd/olcrtc
-> internal/config
-> internal/app/session
-> internal/server or internal/client
-> internal/link/direct
-> internal/transport/{datachannel,vp8channel,seichannel,videochannel}
-> internal/carrier/builtin
-> internal/auth/<provider> + internal/engine/<engine>
-> external service SFU / signaling
```
Tunnel data path:
```text
local app
-> client SOCKS5
-> smux stream
-> muxconn AEAD encrypt
-> link.Send
-> transport encoding
-> carrier/engine
-> SFU/service
-> peer engine/carrier
-> transport decoding
-> muxconn AEAD decrypt
-> smux stream
-> server TCP dial
-> target host
```
## Entrypoints
| Path | Purpose |
|---|---|
| `cmd/olcrtc/main.go` | Main CLI. Accepts one YAML file, applies auth and transport defaults, starts `srv`, `cnc`, or `gen`. |
| `cmd/olcrtc-cgo/main.go` | Small c-shared entrypoint for desktop/native consumers. |
| `pkg/olcrtc` | Embeddable lower-level API that returns a `net.Conn`-like handle over an engine data path. |
| `pkg/olcrtc/tunnel` | Embeddable server-side tunnel API with auth and traffic hooks. |
| `mobile/mobile.go` | gomobile API for Android clients, including VPN socket protection. |
| `script/srv.sh`, `script/cnc.sh` | Interactive shell launchers that generate YAML and run/build the app. |
| `Dockerfile`, `script/docker/*` | Container build and server entrypoint/healthcheck. |
## Config And Session Layer
`internal/config` owns YAML parsing and file-backed secret loading.
Important fields:
| YAML | Runtime field | Notes |
|---|---|---|
| `mode` | `session.Config.Mode` | `srv`, `cnc`, or `gen`. |
| `auth.provider` | `Auth` | `jitsi`, `telemost`, `wbstream`, or `none`. |
| `room.id` | `RoomID` | Carrier-specific room reference. |
| `crypto.key` / `crypto.key_file` | `KeyHex` | Shared 32-byte key encoded as 64 hex chars. |
| `net.transport` | `Transport` | `datachannel`, `vp8channel`, `seichannel`, or `videochannel`. |
| `net.dns` | `DNSServer` | Resolver used by server-side target dials and provider HTTP where wired. |
| `socks.*` | SOCKS fields | Client listener and optional server egress proxy. |
| `engine.*` | direct engine fields | Used only with `auth.provider: none`. |
| `liveness.*` | control liveness | Ping/pong interval, timeout, and missed-pong threshold. |
| `lifecycle.*` | session lifecycle | Planned call/session rotation. |
| `traffic.*` | send shaping | Encrypted wire-message size cap and optional pacing jitter. |
`internal/app/session` is the main router:
1. Registers built-ins via `RegisterDefaults`.
2. Applies auth defaults: auth provider decides engine and default service URL.
3. Applies transport defaults: documented defaults for `vp8`, `sei`, and `video`.
4. Validates mode, auth, link, transport, room, key, DNS, transport options, and SOCKS listener safety.
5. Runs `server.Run`, `client.Run`, or `Gen`.
## Server Side
`internal/server` accepts encrypted smux sessions from the peer and proxies
each smux stream to a TCP target.
Core pieces:
| Symbol | Role |
|---|---|
| `server.Run` | Creates cipher, link, smux server, and serve loop. |
| `bringUpLink` | Builds `link.Link`, wires reconnect callbacks, connects carrier. |
| `installSession` / `reinstallSession` | Creates or replaces `muxconn + smux.Session`. |
| `acceptHandshake` | First smux stream; runs `handshake.Server`. |
| `handleStream` | Reads connect JSON and dispatches a tunnel stream. |
| `dispatch` | Dials target, sends ready byte, copies both directions. |
| `AuthHook` | Embedders can authorize clients after `CLIENT_HELLO`. |
| `OnSessionOpen`, `OnSessionClose`, `OnTraffic` | Observability hooks. |
Server risk areas:
- Target dialing is powerful by design. Any real product wrapper should add
an `AuthHook` and probably destination policy.
- `defaultAuthHook` admits everyone who knows the room and key.
- Reconnect rebuilds smux sessions; active streams are sacrificed.
## Client Side
`internal/client` exposes a local SOCKS5 listener and opens one smux stream
per SOCKS CONNECT request.
Core pieces:
| Symbol | Role |
|---|---|
| `RunWithReady` | Starts link, opens smux client, listens on local SOCKS. |
| `openControlStream` | First smux stream; runs `handshake.Client`. |
| `handleSocks5` | SOCKS method negotiation and CONNECT parsing. |
| `sendConnectRequest` | Sends server-side target JSON and waits for ready byte. |
| `handleReconnect` | Rebuilds smux and control stream after carrier reconnect. |
| `resolveDeviceID` | Optional persistent client identity for hooks. |
Client risk areas:
- A non-loopback SOCKS listener must require `socks.user` and `socks.pass`.
- SOCKS credentials are simple static credentials, not a full account system.
- Existing streams do not survive reconnect; new SOCKS connections can recover.
## Wire Protocol Above WebRTC
`internal/muxconn` adapts `link.Link` to `io.ReadWriteCloser`.
- Every smux write is encrypted with `internal/crypto`.
- Every inbound link message is decrypted and appended to an internal byte buffer.
- Bad AEAD frames are dropped.
- `CanSend` provides backpressure before encrypting and sending.
`internal/crypto` uses XChaCha20-Poly1305 with a random nonce prepended to
each ciphertext.
`internal/handshake` runs on the first smux stream:
```text
CLIENT_HELLO { version, device_id, claims }
SERVER_WELCOME { version, session_id }
or
SERVER_REJECT { version, reason }
```
The handshake has a 64 KiB frame cap and a default 15 second timeout.
After handshake, `internal/control` keeps that same encrypted smux stream open
and exchanges length-prefixed JSON control messages:
```text
CONTROL_PING { version, seq, sent_unix_nano }
CONTROL_PONG { version, seq, sent_unix_nano }
```
Defaults are `liveness.interval: 10s`, `liveness.timeout: 5s`, and
`liveness.failures: 3`. Missed pongs mark the smux session unhealthy and
trigger a session rebuild/reconnect path.
Client and server runtimes also maintain a `control.Status` snapshot with
session ID, last pong time, RTT, missed pongs, reconnect count, and unhealthy
event count. Embedders can consume it through the client/server health
callbacks.
## Registries And Plugin Shape
The universal-carrier refactor centers on small registries:
| Registry | Package | Registers |
|---|---|---|
| Auth providers | `internal/auth` | Service-specific credential and room creation flows. |
| Engines | `internal/engine` | Wire-level SFU protocol implementations. |
| Carriers | `internal/carrier` | Auth + engine adapters exposed as byte/video capability providers. |
| Transports | `internal/transport` | Byte transport strategy over carrier primitives. |
| Links | `internal/link` | Higher-level link abstraction; currently only `direct`. |
`internal/carrier/builtin` connects the auth and engine worlds:
```text
carrier "wbstream" -> auth/wbstream -> engine/livekit
carrier "telemost"-> auth/telemost -> engine/goolom
carrier "jitsi" -> auth/jitsi -> engine/jitsi
carrier "none" -> direct user-supplied engine/url/token
```
## Auth Providers
| Provider | Engine | Room generation | Notes |
|---|---|---:|---|
| `jitsi` | `jitsi` | No | Parses host/room from a public or self-hosted Jitsi URL. No HTTP auth. |
| `telemost` | `goolom` | No | Calls Telemost room-info flow and returns Goolom credentials. |
| `wbstream` | `livekit` | Yes | Registers guest, optionally creates room, joins room, fetches LiveKit token. |
| `none` | chosen by config | No | Direct engine mode for downstream tools or self-hosted SFUs. |
## Engines
Engines expose the low-level service/SFU protocol.
| Engine | Package | Byte stream | Video track | Main job |
|---|---|---:|---:|---|
| `livekit` | `internal/engine/livekit` | Yes | Yes | LiveKit SDK room, data packets, local/remote tracks, reconnect with credential refresh. |
| `goolom` | `internal/engine/goolom` | Yes | Yes | Yandex Telemost/Goolom signaling, split publisher/subscriber peer connections, telemetry/keepalive. |
| `jitsi` | `internal/engine/jitsi` | Yes | Best effort | Jitsi MUC/Jingle/colibri-ws plus optional video track negotiation. |
Engine work is where most provider breakage and reconnect complexity lives.
## Transports
Transports decide how raw tunnel bytes are carried once the carrier provides
either a byte stream or a video track.
| Transport | Primitive | Reliability model | Best fit | Notes |
|---|---|---|---|---|
| `datachannel` | Carrier byte stream | Native reliable ordered messages | Jitsi and direct engines | Simple pass-through with 12 KiB message cap. |
| `vp8channel` | VP8 video track | KCP over VP8-looking frames | WB Stream and Telemost-style video paths | Highest-performance video-path transport. Uses epochs and binding tokens to survive restarts/loopback. |
| `seichannel` | H264 SEI video track | Custom fragments + ACK/retry | WB Stream fallback | Carries data in SEI NAL units with fragmentation, CRC, ACK. |
| `videochannel` | Visual frames via ffmpeg | QR/tile frames + ACK/retry | Experimental/inspection-friendly path | Encodes visual payload frames, requires ffmpeg, supports QR and tile codecs. |
Transport work is where throughput, loss recovery, and adaptive tuning should
happen.
## Public/Embedding Surfaces
| Package | User |
|---|---|
| `pkg/olcrtc` | Go programs that want a `net.Conn` over a selected auth/engine. |
| `pkg/olcrtc/tunnel` | Go programs that want to embed the server-side tunnel with auth/traffic hooks. |
| `mobile` | Android app bindings. Wraps client mode, VPN socket protection, logging, simple health checks. |
| `cmd/olcrtc-cgo` | Native desktop/client integrations using c-shared Go export. |
These surfaces are important if the CLI becomes only one frontend among many.
## Tests
The project has broad unit coverage:
- Config/session validation and defaults.
- Auth provider HTTP flows with test servers.
- Engine helper logic and reconnect paths.
- SOCKS parsing, smux handshake, server dispatch.
- Crypto, muxconn, names, protect, logging.
- Transport frame codecs, ACK paths, KCP loopback, ffmpeg helpers.
- Memory-backed E2E tunnel tests and optional real-provider E2E matrix.
Useful commands:
```sh
go test -count=1 ./...
go test -race -count=1 ./cmd/olcrtc ./internal/app/session ./internal/config ./internal/engine/livekit
go test -race -count=1 -v ./internal/e2e
E2E_CARRIERS=wbstream E2E_TRANSPORTS=vp8channel mage e2e
go build -trimpath -o build/olcrtc ./cmd/olcrtc
```
## High-Value Coding Areas
### 1. Supervisor And Multi-Profile Failover
The first supervisor layer exists in `internal/supervisor`: the CLI can run a
prioritized list of carrier/transport profiles and move to the next profile
when the active one fails or ends.
```yaml
mode: srv
link: direct
crypto:
key_file: ./olcrtc.key
net:
dns: "1.1.1.1:53"
profiles:
- name: wb-vp8
auth:
provider: wbstream
room:
id: WB_ROOM_ID
net:
transport: vp8channel
- name: jitsi-dc
auth:
provider: jitsi
room:
id: https://meet.example.org/olcrtc-room
net:
transport: datachannel
failover:
retry_delay: 2s
max_cycles: 0
```
Implemented:
- Config schema for `profiles[]`.
- Ordered supervisor loop.
- `failover.retry_delay`.
- `failover.max_cycles`.
- Profile start/end logs.
- Planned session rotation with `lifecycle.max_session_duration`.
- Shared supervisor status snapshots with bounded failover history.
- Shared traffic wrapper with payload cap, pacing jitter, and smux frame sizing.
Still valuable:
- Health scoring per profile.
- Control-stream coordination before switching.
- Stream draining and migration instead of dropping active smux streams.
- User-facing status endpoint/export for the active profile and failover history.
Likely files:
- `internal/config/config.go`
- `internal/app/session/session.go`
- `internal/supervisor`
- `internal/server`
- `internal/client`
- `docs/configuration.md`
- `internal/e2e/tunnel_test.go`
### 2. Transport Telemetry And Adaptive Tuning
Add metrics from transport to link/session:
- Send queue depth.
- ACK latency.
- Retries.
- Reconnect count.
- Dropped/decrypt-failed frames.
- KCP RTT/loss where available.
Then make `vp8.batch_size`, `sei.fragment_size`, ACK timeout, and pacing
adaptive instead of static YAML knobs.
### 3. Control Stream Protocol
The first smux stream now carries control ping/pong after handshake. It is
still the natural place for:
- Server policy updates.
- Graceful reconnect notifications.
- Drain/start markers for failover.
- More per-session stats.
Likely files:
- `internal/control`
- `internal/server`
- `internal/client`
### 4. Destination Policy And Real Auth
The tunnel can dial arbitrary server-side TCP targets. A production wrapper
should use `AuthHook` and enforce:
- Allowed destination CIDRs/domains/ports.
- Per-device or per-plan policy.
- Session expiration.
- Traffic accounting limits.
- Sanitized rejection reasons.
This mostly belongs in `pkg/olcrtc/tunnel` and `internal/server`.
### 5. Provider Hardening
Provider APIs can drift. Worth adding:
- Central protected HTTP/WebSocket client creation with TLS 1.2+,
environment proxy support, HTTP/2 for HTTP, and bounded timeouts.
- Better typed errors from auth providers.
- Provider health probes.
- Fixture-based contract tests for API response changes.
- Per-provider rate/backoff policy.
- Safer secret/log redaction.
Likely files:
- `internal/auth/*`
- `internal/engine/*`
- `internal/carrier/builtin`
### 6. Codebase Hygiene
Some public-facing text and comments are not suitable for a serious external
project. Cleaning that up would improve maintainability and downstream trust.
The most obvious targets are top-level docs and a large hostile block comment
in `internal/transport/vp8channel/transport.go`.
## Where To Look First
| Goal | Start here |
|---|---|
| Change YAML schema | `internal/config/config.go`, `cmd/olcrtc/main.go`, docs examples. |
| Change validation/defaults | `internal/app/session/session.go`. |
| Add a new auth provider | `internal/auth`, then register in `internal/carrier/builtin/register.go`. |
| Add a new SFU protocol | `internal/engine`, then connect through auth/carrier. |
| Add a new byte transport | `internal/transport`, then register in `session.RegisterDefaults`. |
| Add link behavior above transports | `internal/link`; currently only `direct`. |
| Improve SOCKS behavior | `internal/client`. |
| Improve server target dialing or policy | `internal/server`, `pkg/olcrtc/tunnel`. |
| Improve reconnect | Engines first, then `internal/client` and `internal/server` smux rebuild behavior. |
| Improve Android app integration | `mobile`, `internal/protect`, `client.RunWithReady`. |
## Mental Model For Big Changes
Prefer to keep the layer boundaries:
- Auth creates credentials; it should not know transport details.
- Engine speaks service/SFU protocol; it should not know SOCKS or smux.
- Carrier adapts auth+engine into byte/video capabilities.
- Transport turns byte/video capabilities into reliable-ish tunnel bytes.
- Link is policy above transport.
- Client/server own SOCKS, smux, handshake, target dialing, and session hooks.
If a change crosses more than two layers, it probably deserves a new
orchestrator package instead of pushing more state into an engine or transport.

View File

@@ -1,22 +1,19 @@
# olcrtc server config example
# Run with: olcrtc server.yaml
# Пример серверного конфига olcrtc
# Запуск: olcrtc server.yaml
mode: srv
# Connection topology
link: direct # p2p link type
auth:
provider: jitsi # jitsi | telemost | wbstream | none
# For jitsi: full conference URL (https://host/room or host/room).
# For telemost / wbstream: room ID returned by the service.
# Для jitsi: полный URL комнаты (https://host/room или host/room).
# Для telemost / wbstream: Room ID, который вернул сервис.
room:
id: "https://meet.small-dm.ru/REPLACE_WITH_ROOM_NAME"
crypto:
# 32-byte hex (64 chars). Generate with: openssl rand -hex 32
# Or use key_file: "./olcrtc.key" to keep the secret out of this file.
# 32 байта в hex (64 символа). Сгенерировать: openssl rand -hex 32
# Можно использовать key_file: "./olcrtc.key", чтобы не хранить секрет прямо здесь.
key: "REPLACE_ME_WITH_64_HEX_CHARS"
net:
@@ -28,52 +25,52 @@ liveness:
timeout: 5s
failures: 3
# Optional planned rebuild for long-running calls.
# Необязательный плановый rebuild долгих звонков.
# lifecycle:
# max_session_duration: 6h
# Optional reliability shaping for encrypted wire messages.
# Необязательный лимит/pacing для зашифрованных wire-сообщений.
# traffic:
# max_payload_size: 4096
# min_delay: 5ms
# max_delay: 30ms
# Outbound SOCKS5 proxy for server-side egress (optional)
# Исходящий SOCKS5-прокси на серверной стороне (необязательно).
socks:
proxy_addr: "" # e.g. "127.0.0.1"
proxy_port: 0 # e.g. 1080
proxy_addr: "" # например "127.0.0.1"
proxy_port: 0 # например 1080
# Direct engine mode — only used when auth.provider is "none"
# Прямой engine-режим: используется только при auth.provider: none.
engine:
name: "" # livekit | goolom | jitsi
url: ""
token: ""
# vp8channel tuning (only when net.transport == vp8channel)
# Настройки vp8channel (только когда net.transport == vp8channel).
vp8:
fps: 60
batch_size: 64
# seichannel tuning (only when net.transport == seichannel)
# Настройки seichannel (только когда net.transport == seichannel).
sei:
fps: 20
batch_size: 1
fps: 60
batch_size: 64
fragment_size: 900
ack_timeout_ms: 3000
ack_timeout_ms: 2000
# videochannel tuning (only when net.transport == videochannel)
# Настройки videochannel (только когда net.transport == videochannel).
video:
width: 1920
height: 1080
fps: 30
bitrate: "2M"
hw: none # none | nvenc
codec: qrcode # qrcode | tile (tile requires 1080x1080)
qr_size: 0 # 0 = auto
codec: qrcode # qrcode | tile (для tile нужно 1080x1080)
qr_size: 0 # 0 = авто
qr_recovery: low # low (7%) | medium (15%) | high (25%) | highest (30%)
tile_module: 4 # 1..270, only for codec: tile
tile_rs: 20 # 0..200, only for codec: tile
tile_module: 4 # 1..270, только для codec: tile
tile_rs: 20 # 0..200, только для codec: tile
data: data # data directory (names files etc.)
data: data # директория с runtime-данными (names, surnames)
debug: false
ffmpeg: ffmpeg # path to ffmpeg binary (only used by videochannel)
ffmpeg: ffmpeg # путь к ffmpeg, нужен только videochannel

View File

@@ -43,11 +43,10 @@
| YAML поле | Что вводить |
|-----------|-------------|
| `mode` | `srv` на сервере, `cnc` на клиенте, `gen` для генерации Room ID |
| `auth.provider` | `telemost`, `wbstream` или `jitsi` |
| `auth.provider` | `telemost`, `wbstream`, `jitsi` или `none` |
| `net.transport` | `datachannel`, `vp8channel`, `seichannel` или `videochannel` |
| `room.id` | Room ID |
| `crypto.key` или `crypto.key_file` | Ключ шифрования hex 64 символа. Генерация: `openssl rand -hex 32` |
| `link` | Всегда `direct` |
| `data` | Всегда `data` |
| `net.dns` | DNS-сервер, например `1.1.1.1:53` |
@@ -216,7 +215,6 @@ WB Stream DataChannel **не работает** в обычном guest flow —
# server.yaml
mode: srv
link: direct
auth:
provider: wbstream
room:
@@ -232,7 +230,6 @@ data: data
```yaml
# client.yaml
mode: cnc
link: direct
auth:
provider: wbstream
room:
@@ -253,7 +250,6 @@ data: data
```yaml
# client.yaml с логином и паролем на прокси
mode: cnc
link: direct
auth:
provider: wbstream
room:
@@ -285,7 +281,6 @@ export all_proxy=socks5h://myuser:mypass@127.0.0.1:8808
```yaml
# server.yaml
mode: srv
link: direct
auth:
provider: telemost
room:
@@ -304,7 +299,6 @@ data: data
```yaml
# client.yaml
mode: cnc
link: direct
auth:
provider: telemost
room:
@@ -330,7 +324,6 @@ data: data
```yaml
# server.yaml
mode: srv
link: direct
auth:
provider: telemost
room:
@@ -351,7 +344,6 @@ data: data
```yaml
# client.yaml
mode: cnc
link: direct
auth:
provider: telemost
room:
@@ -377,7 +369,6 @@ data: data
```yaml
# server.yaml
mode: srv
link: direct
auth:
provider: telemost
room:
@@ -400,7 +391,6 @@ data: data
```yaml
# client.yaml
mode: cnc
link: direct
auth:
provider: telemost
room:

View File

@@ -92,7 +92,7 @@ Payload не используется.
| `<EncryptionKey>` | `crypto.key` |
| `<MIMO>` | В `olcrtc` не передаётся. Это только клиентский комментарий |
`link: direct` и `data: data` в этом формате не кодируются, потому что для текущих сценариев они фиксированные.
`data: data` в этом формате не кодируется, потому что это локальная runtime-настройка конкретного запуска.
---
@@ -125,7 +125,6 @@ Payload не нужен - datachannel параметров не имеет. Дл
```yaml
mode: cnc
link: direct
auth:
provider: wbstream
room:
@@ -147,7 +146,6 @@ olcrtc://wbstream?vp8channel<vp8-fps=60&vp8-batch=64>@room-01#d823fa01cb3e0609b6
```yaml
mode: cnc
link: direct
auth:
provider: wbstream
room:
@@ -172,7 +170,6 @@ olcrtc://wbstream?seichannel<fps=60&batch=64&frag=900&ack-ms=2000>@room-01#d823f
```yaml
mode: cnc
link: direct
auth:
provider: wbstream
room:
@@ -199,7 +196,6 @@ olcrtc://telemost?videochannel<video-w=1080&video-h=1080&video-fps=60&video-bitr
```yaml
mode: cnc
link: direct
auth:
provider: telemost
room:
@@ -232,7 +228,6 @@ olcrtc://jitsi?datachannel@https://meet.small-dm.ru/myroom#d823fa01cb3e0609b6732
```yaml
mode: cnc
link: direct
auth:
provider: jitsi
room: