From e503aaee332322bb3526e7489829a457790e8481 Mon Sep 17 00:00:00 2001 From: samosvalishe Date: Wed, 17 Jun 2026 09:26:39 +0300 Subject: [PATCH] =?UTF-8?q?style:=20ASCII-=D0=BF=D1=83=D0=BD=D0=BA=D1=82?= =?UTF-8?q?=D1=83=D0=B0=D1=86=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/server/main.go | 4 +-- internal/client/dnsdial/cli.go | 2 +- internal/client/dnsdial/doh.go | 16 ++++++------ internal/client/dnsdial/doh_test.go | 8 +++--- internal/client/ish/listener_linux_386.go | 6 ++--- internal/client/ish/listener_other.go | 4 +-- internal/clientsdb/db.go | 2 +- internal/logx/logx.go | 6 ++--- internal/netconn/netconn.go | 2 +- internal/netconn/pipe.go | 2 +- internal/provider/provider.go | 26 +++++++++---------- .../provider/vk/internal/captcha/captcha.go | 6 ++--- .../vk/internal/captcha/manual/manual.go | 24 ++++++++--------- .../provider/vk/internal/namegen/namegen.go | 4 +-- .../vk/internal/vkauth/auto_solver.go | 2 +- internal/provider/vk/internal/vkauth/cache.go | 2 +- .../vk/internal/vkauth/client_test.go | 10 +++---- .../provider/vk/internal/vkauth/order_test.go | 2 +- .../provider/vk/internal/vkauth/solver.go | 4 +-- .../provider/vk/internal/vkauth/token_anon.go | 2 +- .../provider/vk/internal/vkauth/token_call.go | 4 +-- .../vk/internal/vkauth/token_creds.go | 2 +- .../vk/internal/vkauth/token_oksession.go | 2 +- internal/provider/vk/internal/vkauth/types.go | 10 +++---- internal/proxy/bondclient/bondclient.go | 10 +++---- internal/proxy/bondserver/bondserver.go | 10 +++---- internal/proxy/common/common.go | 2 +- internal/proxy/tcpfwd/pool.go | 4 +-- internal/proxy/udprelay/listener.go | 6 ++--- internal/proxy/udprelay/loop.go | 8 +++--- internal/proxy/udprelay/run.go | 20 +++++++------- internal/proxy/udpserver/udpserver.go | 2 +- internal/randx/randx.go | 4 +-- internal/stats/stats.go | 4 +-- internal/transport/dtlsdial/doc.go | 8 +++--- internal/transport/dtlsdial/dtlsdial.go | 4 +-- internal/transport/dtlsdial/dtlsdial_test.go | 2 +- internal/transport/kcptun/kcptun.go | 6 ++--- internal/transport/turndial/permwatch.go | 2 +- internal/wire/bondframe/bondframe.go | 4 +-- internal/wire/codec.go | 2 +- internal/wire/codec_test.go | 6 ++--- internal/wire/rtpopus/listen.go | 2 +- internal/wire/rtpopus/rtpopus.go | 14 +++++----- internal/wire/rtpopus/rtpopus_test.go | 8 +++--- 45 files changed, 140 insertions(+), 140 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 8a8463d..28918ef 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -40,7 +40,7 @@ func main() { if errors.Is(err, flag.ErrHelp) { os.Exit(0) } - // логгер ещё не создан — единственный fatal до его инициализации. + // логгер ещё не создан - единственный fatal до его инициализации. log.Fatalf("%v", err) } logger := logx.New(cfg.Log.Debug) @@ -180,7 +180,7 @@ func handleAccepted(ctx context.Context, logger logx.Logger, registry *bondserve } logger.Debugf("Handshake done") - // Client ID читается всегда (клиент всегда шлёт его первой app-record) — + // Client ID читается всегда (клиент всегда шлёт его первой app-record) - // wire-контракт симметричен. -clients-file включает только enforce по allowlist. clientID, err := clientsdb.ReadClientID(dtlsConn) if err != nil { diff --git a/internal/client/dnsdial/cli.go b/internal/client/dnsdial/cli.go index a71636b..3c6f7d0 100644 --- a/internal/client/dnsdial/cli.go +++ b/internal/client/dnsdial/cli.go @@ -24,7 +24,7 @@ func AppDialer(mode string) net.Dialer { } // InstallGlobalResolver выставляет net.DefaultResolver на тот же DNS-транспорт, -// что и AppDialer — чтобы сторонние библиотеки, собирающие свой http.Client +// что и AppDialer - чтобы сторонние библиотеки, собирающие свой http.Client // без нашего Dialer, тоже шли через DoH / auto-fallback, а не OS resolver. func InstallGlobalResolver(mode string) { d := AppDialer(mode) diff --git a/internal/client/dnsdial/doh.go b/internal/client/dnsdial/doh.go index f65c25a..0dcc064 100644 --- a/internal/client/dnsdial/doh.go +++ b/internal/client/dnsdial/doh.go @@ -1,6 +1,6 @@ // Package dnsdial владеет DNS-резолвингом и net.Dialer'ом, прокинутым во все // outbound HTTP/TLS клиенты. По Mode выбирает UDP/53, DNS-over-HTTPS или auto -// (UDP-probe → sticky DoH fallback). +// (UDP-probe -> sticky DoH fallback). package dnsdial import ( @@ -50,12 +50,12 @@ const ( autoDoHProbeBudget = 6 * time.Second autoReevalInterval = 30 * time.Second // мин. интервал авто-перепроб (recovery) - autoUDPFailThreshold = 2 // подряд неудачных UDP-резолвов → перепроба + autoUDPFailThreshold = 2 // подряд неудачных UDP-резолвов -> перепроба dnsMinResponseBytes = 12 // размер DNS-заголовка; меньше = не ответ // defaultProbeHost - нейтральный дефолт auto-пробы, если провайдер не задал // свой через SetProbeHost. Провайдеру стоит указывать реальную control-plane - // цель (VK → login.vk.ru), чтобы проба мерила резолв нужного домена. + // цель (VK -> login.vk.ru), чтобы проба мерила резолв нужного домена. defaultProbeHost = "dns.google" ) @@ -496,7 +496,7 @@ func SetProbeHost(host string) { // рантайме (не one-shot): на UDP серия неудачных резолвов уводит на DoH; на DoH // периодическая перепроба возвращает на UDP, когда цель снова резолвится. Решение // принимается по резолву реального control-plane хоста (probeHost), а не -// нейтрального домена: ТСПУ фильтрует выборочно, «UDP жив на постороннем домене» +// нейтрального домена: ТСПУ фильтрует выборочно, "UDP жив на постороннем домене" // ничего не гарантирует. type autoState struct { udpDial dialFunc @@ -524,10 +524,10 @@ func autoDial(r *DohResolver) dialFunc { } // decide пробует резолвить цель и обновляет useDoH: -// 1. UDP оператора резолвит цель в валидный адрес → UDP; -// 2. уже на DoH и цель по UDP всё ещё недоступна → остаёмся (без лишней DoH-пробы); -// 3. иначе DoH резолвит цель → DoH; -// 4. ни то ни другое → DoH (больше шансов на recovery). +// 1. UDP оператора резолвит цель в валидный адрес -> UDP; +// 2. уже на DoH и цель по UDP всё ещё недоступна -> остаёмся (без лишней DoH-пробы); +// 3. иначе DoH резолвит цель -> DoH; +// 4. ни то ни другое -> DoH (больше шансов на recovery). // // quiet подавляет лог перехода - для стартового решения, логируемого в dial(). func (a *autoState) decide(quiet bool) { diff --git a/internal/client/dnsdial/doh_test.go b/internal/client/dnsdial/doh_test.go index abd855e..3cac690 100644 --- a/internal/client/dnsdial/doh_test.go +++ b/internal/client/dnsdial/doh_test.go @@ -104,7 +104,7 @@ func TestAutoDial_StickyAfterUDPFailure(t *testing.T) { } // startFakeUDPDNS поднимает локальный UDP DNS, отвечающий на A-запрос фиксированным -// answer (nil → NOERROR без записей). Возвращает адрес ip:port. +// answer (nil -> NOERROR без записей). Возвращает адрес ip:port. func startFakeUDPDNS(t *testing.T, answer net.IP) string { t.Helper() pc, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0}) @@ -146,7 +146,7 @@ func startFakeUDPDNS(t *testing.T, answer net.IP) string { func TestProbeResolves(t *testing.T) { cases := []struct { name string - answer net.IP // nil → NOERROR без A-записей (домен дропнут/отфильтрован) + answer net.IP // nil -> NOERROR без A-записей (домен дропнут/отфильтрован) want bool }{ {"valid public A", net.ParseIP("93.184.216.34"), true}, @@ -172,7 +172,7 @@ func failDial(context.Context, string, string) (net.Conn, error) { return nil, errors.New("dial unavailable") } -// UDP не резолвит цель и DoH-проба тоже падает → auto залипает на DoH. +// UDP не резолвит цель и DoH-проба тоже падает -> auto залипает на DoH. func TestAutoState_FailsOverToDoH(t *testing.T) { a := &autoState{udpDial: udpDNSDial, dohDial: failDial, host: func() string { return "login.vk.ru" }} @@ -187,7 +187,7 @@ func TestAutoState_FailsOverToDoH(t *testing.T) { } } -// Залипли на DoH, UDP снова резолвит цель → перепроба возвращает на UDP (recovery). +// Залипли на DoH, UDP снова резолвит цель -> перепроба возвращает на UDP (recovery). func TestAutoState_RecoversToUDP(t *testing.T) { a := &autoState{udpDial: udpDNSDial, dohDial: failDial, host: func() string { return "login.vk.ru" }} a.useDoH.Store(true) // имитируем залипание на DoH diff --git a/internal/client/ish/listener_linux_386.go b/internal/client/ish/listener_linux_386.go index c3eb2dc..a422cd2 100644 --- a/internal/client/ish/listener_linux_386.go +++ b/internal/client/ish/listener_linux_386.go @@ -46,10 +46,10 @@ func (l *listener) Accept() (net.Conn, error) { addrlen := uintptr(128) // i386 сетевые syscall'ы мультиплексируются через socketcall (102). - // SYS_ACCEPT — subcall 5. + // SYS_ACCEPT - subcall 5. args := [3]uintptr{uintptr(l.fd), uintptr(unsafe.Pointer(&addr[0])), uintptr(unsafe.Pointer(&addrlen))} - // Syscall6 — чтобы хватило регистров аргументов на этой платформе. + // Syscall6 - чтобы хватило регистров аргументов на этой платформе. r1, _, errno := syscall.Syscall6(102, 5, uintptr(unsafe.Pointer(&args)), 0, 0, 0, 0) if errno != 0 { if errno == syscall.EINTR { @@ -63,7 +63,7 @@ func (l *listener) Accept() (net.Conn, error) { _ = syscall.SetsockoptInt(nfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, 256*1024) _ = syscall.SetsockoptInt(nfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, 256*1024) - // избегаем net.FileConn — она регистрирует fd в Go epoll poller'е, что в + // избегаем net.FileConn - она регистрирует fd в Go epoll poller'е, что в // iSH стабильно падает с EEXIST. Возвращаем кастомный blocking net.Conn. conn := &ishConn{fd: nfd} return conn, nil diff --git a/internal/client/ish/listener_other.go b/internal/client/ish/listener_other.go index 7f2f4c3..95e1664 100644 --- a/internal/client/ish/listener_other.go +++ b/internal/client/ish/listener_other.go @@ -1,9 +1,9 @@ //go:build !(linux && 386) -// Package ish — TCP listener shim для iSH (https://ish.app), Linux user-mode +// Package ish - TCP listener shim для iSH (https://ish.app), Linux user-mode // эмулятор на iOS. iSH таргетит linux/386 и не имеет современного accept4 / // epoll-poller Go, поэтому там нужен sandbox-aware accept loop. На любом -// другом GOOS/GOARCH WrapListener — no-op passthrough. +// другом GOOS/GOARCH WrapListener - no-op passthrough. package ish import "net" diff --git a/internal/clientsdb/db.go b/internal/clientsdb/db.go index ba07fa4..8680483 100644 --- a/internal/clientsdb/db.go +++ b/internal/clientsdb/db.go @@ -143,7 +143,7 @@ func (db *DB) save() error { } tmpFile := db.path + ".tmp" - err = os.WriteFile(tmpFile, b, 0o600) // содержит Client ID (auth-токены) — не world-readable + err = os.WriteFile(tmpFile, b, 0o600) // содержит Client ID (auth-токены) - не world-readable if err == nil { err = os.Rename(tmpFile, db.path) } diff --git a/internal/logx/logx.go b/internal/logx/logx.go index 16e7360..1737588 100644 --- a/internal/logx/logx.go +++ b/internal/logx/logx.go @@ -1,11 +1,11 @@ -// Package logx — минимальный уровневый логгер поверх stdlib log. +// Package logx - минимальный уровневый логгер поверх stdlib log. // Вызывающий получает Logger и зовёт Debugf/Infof/Warnf/Errorf; // Debugf управляется debug-флагом, остальные уровни всегда пишут. package logx import "log" -// Logger — интерфейс уровневого логирования. +// Logger - интерфейс уровневого логирования. // Debugf гейтится debug-флагом конструктора; остальные уровни печатают всегда. type Logger interface { Debugf(format string, v ...any) @@ -22,7 +22,7 @@ type stdLogger struct { debug bool } -// New возвращает Logger поверх stdlib log. При debug=false Debugf — no-op. +// New возвращает Logger поверх stdlib log. При debug=false Debugf - no-op. func New(debug bool) Logger { return &stdLogger{debug: debug} } diff --git a/internal/netconn/netconn.go b/internal/netconn/netconn.go index f15d835..bdf96fa 100644 --- a/internal/netconn/netconn.go +++ b/internal/netconn/netconn.go @@ -1,4 +1,4 @@ -// Package netconn — мелкие net.Conn / transport.Net адаптеры для клиента +// Package netconn - мелкие net.Conn / transport.Net адаптеры для клиента // и сервера: passthrough transport.Net (для pion turn), ConnectedUDPConn // (WriteTo поверх dialed UDPConn) и SplitFirstWriteConn (обход DPI через // разбиение первого сегмента). diff --git a/internal/netconn/pipe.go b/internal/netconn/pipe.go index 52c2494..70f2d48 100644 --- a/internal/netconn/pipe.go +++ b/internal/netconn/pipe.go @@ -10,7 +10,7 @@ import ( // BiCopy запускает io.Copy в обе стороны между c1 и c2; возвращает // (bytesC1FromC2, bytesC2FromC1). Как только одна копия завершилась -// (EOF/ошибка/cancel) — обоим концам выставляется deadline=time.Now(), +// (EOF/ошибка/cancel) - обоим концам выставляется deadline=time.Now(), // чтобы разблокировать парную горутину. Ошибки уходят в errf, если он не nil. func BiCopy(ctx context.Context, c1, c2 net.Conn, errf func(format string, v ...any)) (int64, int64) { ctx2, cancel := context.WithCancel(ctx) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 0a575fb..415b119 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -2,12 +2,12 @@ // // Реализации (internal/provider/vk, ...) поставляют // короткоживущие user/pass/addr для TURN-allocate. Pipeline (proxy/udprelay, -// proxy/tcpfwd) работает только через этот интерфейс — никаких VK-specific +// proxy/tcpfwd) работает только через этот интерфейс - никаких VK-specific // типов в общем коде. // // Sentinel-ошибки описывают provider-нейтральные состояния, которые pipeline -// обрабатывает однотипно: ErrBackoffActive — провайдер просит подождать, -// ErrFatalNoStreams — фатально, дальше пробовать бессмысленно. +// обрабатывает однотипно: ErrBackoffActive - провайдер просит подождать, +// ErrFatalNoStreams - фатально, дальше пробовать бессмысленно. package provider import ( @@ -16,8 +16,8 @@ import ( "time" ) -// Credentials — выданные провайдером TURN-реквизиты для одного стрима. -// ServerAddrs — кандидаты host:port в порядке предпочтения (первый — +// Credentials - выданные провайдером TURN-реквизиты для одного стрима. +// ServerAddrs - кандидаты host:port в порядке предпочтения (первый - // предпочтительный для этого streamID). Pipeline пробует их по очереди при // allocate: если первый не проходит (DPI-дроп/RST), берёт следующий. type Credentials struct { @@ -27,7 +27,7 @@ type Credentials struct { ExpiresAt time.Time // 0 если провайдер не сообщает дедлайн } -// Provider — источник TURN-реквизитов для клиентского pipeline. +// Provider - источник TURN-реквизитов для клиентского pipeline. // Реализации обязаны быть thread-safe: pipeline вызывает GetCredentials и // HandleAuthError из N разных горутин одновременно (по числу стримов). type Provider interface { @@ -35,7 +35,7 @@ type Provider interface { // Реализация отвечает за throttling, кеширование, ретраи к upstream-API. GetCredentials(ctx context.Context, streamID int) (Credentials, error) - // IsAuthError — провайдер сам решает, какие ошибки от TURN-allocate + // IsAuthError - провайдер сам решает, какие ошибки от TURN-allocate // (401/403/stale-nonce/etc.) считать auth-related и приводить к // инвалидации кеша через HandleAuthError. IsAuthError(err error) bool @@ -47,24 +47,24 @@ type Provider interface { // ResetErrors обнуляет счётчик ошибок (вызывать после успешного allocate). ResetErrors(streamID int) - // BackoffUntilUnix — unix-секунда, до которой провайдер просит pipeline - // не звать GetCredentials. 0 — нет активного бэк-оффа. + // BackoffUntilUnix - unix-секунда, до которой провайдер просит pipeline + // не звать GetCredentials. 0 - нет активного бэк-оффа. // Используется только при возврате ошибки, обёрнутой ErrBackoffActive. BackoffUntilUnix() int64 - // Name — короткое имя провайдера для логов ("vk", ...). + // Name - короткое имя провайдера для логов ("vk", ...). Name() string } // Sentinel-ошибки, которые провайдер оборачивает (через errors.Join или // fmt.Errorf("%w: ...", ErrXxx, inner)) для сигнализации pipeline. var ( - // ErrBackoffActive — провайдер просит подождать. Pipeline вызывает - // BackoffUntilUnix() для получения точного дедлайна; если 0 — sleep по + // ErrBackoffActive - провайдер просит подождать. Pipeline вызывает + // BackoffUntilUnix() для получения точного дедлайна; если 0 - sleep по // дефолтному backoff (60s). ErrBackoffActive = errors.New("provider backoff active") - // ErrFatalNoStreams — провайдер не может выдать креды и ни один стрим + // ErrFatalNoStreams - провайдер не может выдать креды и ни один стрим // ещё не поднят. Pipeline возвращает фатальную ошибку наружу // (хост-процесс делает os.Exit без вмешательства pipeline). ErrFatalNoStreams = errors.New("provider fatal: no streams alive") diff --git a/internal/provider/vk/internal/captcha/captcha.go b/internal/provider/vk/internal/captcha/captcha.go index 1209b24..85ec09a 100644 --- a/internal/provider/vk/internal/captcha/captcha.go +++ b/internal/provider/vk/internal/captcha/captcha.go @@ -25,7 +25,7 @@ import ( "github.com/samosvalishe/free-turn-proxy/internal/randx" ) -// Log — пакетный логгер. По умолчанию no-op; main устанавливает его через +// Log - пакетный логгер. По умолчанию no-op; main устанавливает его через // SetLogger, чтобы captcha-вывод подчинялся глобальному -debug. Solve также // принимает logger параметром для DI. var Log logx.Logger = logx.Nop() @@ -125,7 +125,7 @@ func (s *captchaSession) logger() logx.Logger { } // Solve запускает авторешение captcha против VK captchaNotRobot API -// и возвращает success-токен при успехе. log может быть nil — тогда +// и возвращает success-токен при успехе. log может быть nil - тогда // используется пакетный Log. func Solve( ctx context.Context, @@ -479,7 +479,7 @@ func solveCaptchaPoW(ctx context.Context, input string, difficulty int) string { return "" } target := strings.Repeat("0", difficulty) - // ctx-check каждые 1024 итерации — задержка отмены в пределах нескольких мс + // ctx-check каждые 1024 итерации - задержка отмены в пределах нескольких мс // даже на слабом ARM (было 4096). buf := make([]byte, 0, len(input)+20) buf = append(buf, input...) diff --git a/internal/provider/vk/internal/captcha/manual/manual.go b/internal/provider/vk/internal/captcha/manual/manual.go index 4785320..0fd9813 100644 --- a/internal/provider/vk/internal/captcha/manual/manual.go +++ b/internal/provider/vk/internal/captcha/manual/manual.go @@ -1,4 +1,4 @@ -// Package manual реализует ручное решение CAPTCHA — fallback, когда автосолвер +// Package manual реализует ручное решение CAPTCHA - fallback, когда автосолвер // (internal/provider/vk/internal/captcha) не справился или пользователь дал -manual-captcha. // Поднимает локальный HTTP-сервер 127.0.0.1:8765, проксирующий страницу VK // CAPTCHA (с переписыванием абсолютных URL и gzip), открывает её в браузере и @@ -33,7 +33,7 @@ import ( // браузерного трафика. Ставится из main после разбора cfg. var Debug bool -// Log — пакетный логгер; по умолчанию no-op. main устанавливает его через +// Log - пакетный логгер; по умолчанию no-op. main устанавливает его через // SetLogger, чтобы вывод подчинялся -debug. var Log logx.Logger = logx.Nop() @@ -217,7 +217,7 @@ var htmlStyleContentRe = regexp.MustCompile(`(?is)(]*>)(.*?)()` // rewriteHTMLAttrsServerSide переписывает абсолютные и protocol-relative URL // в src/href/action HTML на стороне сервера. URL, совпадающие с upstream origin, -// идут на localhost; остальные — через /generic_proxy, чтобы cross-domain +// идут на localhost; остальные - через /generic_proxy, чтобы cross-domain // ресурсы (st.vk.ru, userapi.com и т.д.) грузились через прокси. func rewriteHTMLAttrsServerSide(html string, targetURL *neturl.URL) string { localOrigin := localCaptchaOrigin() @@ -235,7 +235,7 @@ func rewriteHTMLAttrsServerSide(html string, targetURL *neturl.URL) string { if strings.HasPrefix(absURL, localOrigin) { return rawURL } - // прочие абсолютные URL → через generic_proxy + // прочие абсолютные URL -> через generic_proxy return "/generic_proxy?proxy_url=" + neturl.QueryEscape(absURL) } @@ -293,7 +293,7 @@ func rewriteCaptchaHTML(html string, targetURL *neturl.URL) string { // Шаг 2: серверный rewrite остальных абсолютных URL в HTML-атрибутах. // Критично: браузер начинает грузить `, localOrigin, upstreamOrigin) - // Шаг 3: инжектируем клиентский скрипт как можно раньше — после , + // Шаг 3: инжектируем клиентский скрипт как можно раньше - после , // чтобы XHR/fetch-перехваты были активны до любого inline