rtpopus2 несёт RTP header extension (RFC 8285 one-byte: X=1,
ssrc-audio-level + transport-cc) - ближе к современному WebRTC, чем
rtpopus (X=0). Wire несовместим с rtpopus, overhead 52 против 40.
wire.Codec - общий контракт профиля; NewClientCodec/Listen диспатчат
по -obf-profile, RelayPacketConn обобщён по Codec. Профиль тянется
в pipeline (раньше шёл только ключ obf).
Попутно: tcpfwd на 1-based streamID (единый базис с udprelay для
CacheID); cmd/client задаёт probe-host login.vk.ru для vk.
VK отдаёт несколько relay-адресов, но стрим использовал ровно один
(streamID%n). Если этот IP душит DPI/RST — allocate падает без альтернативы.
Credentials несёт список адресов (primary-first по streamID), DialTURN
пробует кандидатов по очереди и берёт первый успешный allocate. Балансировка
relay-IP по стримам сохранена, остальные адреса — фоллбэк. HostOverride (-turn)
схлопывает список до одного адреса.
- internal/clientsdb: БД клиентов с hot-reload + length-prefixed ID wire
- internal/uri: parse/encode share-ссылок freeturn://
- internal/sub: загрузка и парсинг подписок (sub.md)
- client: флаги -auth, -client-id, -sub; позиционный URI; ID через crypto/rand
- server: подкоманда clients (add/remove/list), чтение ID под -clients-file
- запись/чтение ID учитывают DTLS record-orientation (буфер на запись целиком)
- docs: uri.md, sub.md; правки flags/deploy/quickstart
- снят UTF-8 BOM по всем исходникам
Вытаскивает источник TURN-creds из захардкоженной привязки к VK в интерфейс
internal/provider.Provider. Pipeline (proxy/udprelay, proxy/tcpfwd) работает
только через интерфейс — без VK-specific импортов и sentinel'ов.
Реализации:
- internal/provider/vk: фасад над client/vkauth (требует -link)
- internal/provider/static: фиксированные creds для self-hosted coturn /
metered / любого RFC 5766/8656 TURN (флаги -static-user/-static-pass/
-static-addr)
Изменения интерфейса:
- common.GetCredsFunc дропнула link (provider держит сам)
- udprelay AuthHandler: LockoutUntilUnix → BackoffUntilUnix
- vkauth sentinels обёрнуты в provider.ErrBackoffActive / ErrFatalNoStreams
через errors.Join (backward-compat сохранён)
Документация: docs/providers.md (новый), docs/glossary.md и docs/flags.md
обновлены.
Исходный план просил proxy.Engine + интерфейс Handler, объединяющий udprelay и
tcpfwd. После разбора кода заявленные ~70% пересечения оказались ближе к ~30
строкам: udprelay (WG → DTLS-terminate → wrap → TURN) и tcpfwd (TCP → smux →
KCP → DTLS → wrap → TURN) наслаивают wrap/DTLS по-разному и имеют разные
жизненные циклы. Engine с двумя if-ветками просто загнал бы дублирование внутрь,
а не убрал.
Объём минимальный: новый пакет internal/proxy/common с тем, что реально
идентично:
- тип GetCredsFunc (дублировался в обоих пакетах).
- DialTURN(ctx, host, port, udp, peer, link, streamID, getCreds) — берёт creds
и открывает turndial-стрим. Политика retry на auth-ошибке остаётся в udprelay.
- NewClientWrap(key) — возвращает (nil, nil) при пустом/коротком ключе, иначе
srtpmimicry.NewConn(key, false).
udprelay и tcpfwd теперь импортируют common.DialTURN / common.NewClientWrap.
Их локальные объявления GetCredsFunc становятся type alias на
common.GetCredsFunc, чтобы связка cmd/vk-turn-client компилировалась без churn.
bond-as-tcpfwd-option отменён вместе с интерфейсом Handler; bondclient остаётся
отдельным пакетом, подключённым через Deps.BondHandler.
Без изменений wire-формата, флагов CLI и поведения. go build / go vet /
go test / gofmt чисто.