mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
refactor(proxy): вынести общие хелперы (минимальный объём)
Исходный план просил 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 чисто.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
// Package common holds small helpers shared between udprelay and tcpfwd. The
|
||||
// two proxy modes layer DTLS and srtpmimicry differently (see V2-6 decision
|
||||
// in notes/AUDIT_2026-05-19_V2.md), so a full Engine/Handler abstraction was
|
||||
// rejected. This package only collects the bits that are genuinely identical.
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/transport/turndial"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/wire/srtpmimicry"
|
||||
)
|
||||
|
||||
// GetCredsFunc resolves VK TURN credentials for a (link, streamID) pair.
|
||||
// Matches vkauth.Client.GetCredentials.
|
||||
type GetCredsFunc func(ctx context.Context, link string, streamID int) (user, pass, rawURL string, err error)
|
||||
|
||||
// DialTURN fetches credentials and opens a TURN stream. The caller is
|
||||
// responsible for closing the returned stream and for any auth-error retry
|
||||
// policy (udprelay) or session-restart policy (tcpfwd).
|
||||
func DialTURN(ctx context.Context, host, port string, udp bool, peer *net.UDPAddr, link string, streamID int, getCreds GetCredsFunc) (*turndial.Stream, error) {
|
||||
user, pass, rawURL, err := getCreds(ctx, link, streamID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get TURN creds: %w", err)
|
||||
}
|
||||
return turndial.Open(ctx, turndial.Config{
|
||||
HostOverride: host,
|
||||
PortOverride: port,
|
||||
UDP: udp,
|
||||
}, peer, user, pass, rawURL)
|
||||
}
|
||||
|
||||
// NewClientWrap returns a client-side srtpmimicry.Conn if key has the
|
||||
// expected length, otherwise (nil, nil) — wrap disabled. NewConn errors are
|
||||
// propagated so callers can surface them.
|
||||
func NewClientWrap(key []byte) (*srtpmimicry.Conn, error) {
|
||||
if len(key) != srtpmimicry.KeyLen {
|
||||
return nil, nil
|
||||
}
|
||||
return srtpmimicry.NewConn(key, false)
|
||||
}
|
||||
@@ -11,16 +11,17 @@ import (
|
||||
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/client/ish"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/logx"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/proxy/common"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/stats"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/transport/dtlsdial"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/transport/kcptun"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/transport/turndial"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/wire/srtpmimicry"
|
||||
"github.com/xtaci/smux"
|
||||
)
|
||||
|
||||
// GetCredsFunc resolves VK TURN credentials for a (link, streamID) pair.
|
||||
type GetCredsFunc func(ctx context.Context, link string, streamID int) (string, string, string, error)
|
||||
// GetCredsFunc is an alias of common.GetCredsFunc kept for cmd/main wiring
|
||||
// stability.
|
||||
type GetCredsFunc = common.GetCredsFunc
|
||||
|
||||
// Params is the per-pool TURN/wrap configuration.
|
||||
type Params struct {
|
||||
@@ -232,16 +233,7 @@ func createSmuxSession(ctx context.Context, deps *Deps, params *Params, peer *ne
|
||||
}
|
||||
}
|
||||
|
||||
user, pass, rawURL, err := params.GetCreds(ctx, params.Link, id)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("get TURN creds: %w", err)
|
||||
}
|
||||
|
||||
stream, err := turndial.Open(ctx, turndial.Config{
|
||||
HostOverride: params.Host,
|
||||
PortOverride: params.Port,
|
||||
UDP: params.UDP,
|
||||
}, peer, user, pass, rawURL)
|
||||
stream, err := common.DialTURN(ctx, params.Host, params.Port, params.UDP, peer, params.Link, id, params.GetCreds)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -250,13 +242,10 @@ func createSmuxSession(ctx context.Context, deps *Deps, params *Params, peer *ne
|
||||
deps.log().Debugf("[session %d] TURN server IP: %s", id, stream.ServerUDPAddr.IP)
|
||||
deps.log().Debugf("relayed-address=%s", relayConn.LocalAddr().String())
|
||||
|
||||
var relayWC *srtpmimicry.Conn
|
||||
if len(params.WrapKey) == srtpmimicry.KeyLen {
|
||||
relayWC, err = srtpmimicry.NewConn(params.WrapKey, false)
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return nil, nil, fmt.Errorf("wrap init: %w", err)
|
||||
}
|
||||
relayWC, err := common.NewClientWrap(params.WrapKey)
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return nil, nil, fmt.Errorf("wrap init: %w", err)
|
||||
}
|
||||
dtlsPC := &srtpmimicry.RelayPacketConn{Relay: relayConn, Peer: peer, Conn: relayWC}
|
||||
dtlsConn, err := deps.DTLSDialer.Dial(ctx, dtlsPC, peer)
|
||||
|
||||
@@ -17,9 +17,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/logx"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/proxy/common"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/stats"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/transport/dtlsdial"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/transport/turndial"
|
||||
"github.com/cacggghp/vk-turn-proxy/internal/wire/srtpmimicry"
|
||||
"github.com/cbeuw/connutil"
|
||||
)
|
||||
@@ -37,12 +37,12 @@ var Pool = sync.Pool{
|
||||
New: func() any { return &Packet{Data: make([]byte, 2048)} },
|
||||
}
|
||||
|
||||
// GetCredsFunc resolves VK TURN credentials for a (link, streamID) pair.
|
||||
// Matches vkauth.Client.GetCredentials.
|
||||
type GetCredsFunc func(ctx context.Context, link string, streamID int) (string, string, string, error)
|
||||
// GetCredsFunc is an alias of common.GetCredsFunc kept for cmd/main wiring
|
||||
// stability.
|
||||
type GetCredsFunc = common.GetCredsFunc
|
||||
|
||||
// AuthHandler is the subset of vkauth.Client this package needs. Keeping it as
|
||||
// an interface lets internal/proxy/udp avoid importing internal/client/vkauth.
|
||||
// an interface lets internal/proxy/udprelay avoid importing internal/client/vkauth.
|
||||
type AuthHandler interface {
|
||||
IsAuthError(err error) bool
|
||||
HandleAuthError(streamID int) bool
|
||||
@@ -248,16 +248,7 @@ func oneTURN(ctx context.Context, deps *Deps, params *Params, peer *net.UDPAddr,
|
||||
time.Sleep(time.Duration(rand.Intn(400)+100) * time.Millisecond)
|
||||
var err error
|
||||
defer func() { c <- err }()
|
||||
user, pass, urlTarget, err1 := params.GetCreds(ctx, params.Link, streamID)
|
||||
if err1 != nil {
|
||||
err = fmt.Errorf("failed to get TURN credentials: %s", err1)
|
||||
return
|
||||
}
|
||||
stream, err1 := turndial.Open(ctx, turndial.Config{
|
||||
HostOverride: params.Host,
|
||||
PortOverride: params.Port,
|
||||
UDP: params.UDP,
|
||||
}, peer, user, pass, urlTarget)
|
||||
stream, err1 := common.DialTURN(ctx, params.Host, params.Port, params.UDP, peer, params.Link, streamID, params.GetCreds)
|
||||
if err1 != nil {
|
||||
if deps.Auth.IsAuthError(err1) {
|
||||
deps.Auth.HandleAuthError(streamID)
|
||||
@@ -293,15 +284,11 @@ func oneTURN(ctx context.Context, deps *Deps, params *Params, peer *net.UDPAddr,
|
||||
}
|
||||
})
|
||||
var internalPipeAddr atomic.Value
|
||||
var wc *srtpmimicry.Conn
|
||||
if len(params.WrapKey) == srtpmimicry.KeyLen {
|
||||
var wcErr error
|
||||
wc, wcErr = srtpmimicry.NewConn(params.WrapKey, false)
|
||||
if wcErr != nil {
|
||||
log.Printf("[STREAM %d] WRAP init failed: %v", streamID, wcErr)
|
||||
turncancel()
|
||||
return
|
||||
}
|
||||
wc, wcErr := common.NewClientWrap(params.WrapKey)
|
||||
if wcErr != nil {
|
||||
log.Printf("[STREAM %d] WRAP init failed: %v", streamID, wcErr)
|
||||
turncancel()
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
||||
@@ -287,11 +287,12 @@ internal/
|
||||
- [ ] **V2-5.5** `client/internal/namegen` → `internal/client/namegen`.
|
||||
- [ ] **V2-5.6** Удалить пустой `client/` (после переезда `main.go` на V2-1 и `manual_captcha` на V2-2 — он пуст).
|
||||
|
||||
### Этап V2-6 — `proxy.Engine` + Handler
|
||||
### Этап V2-6 — `proxy.Engine` + Handler (свёрнут до минимальной экстракции)
|
||||
|
||||
- [ ] **V2-6.1** Создать `internal/proxy/engine/engine.go`: интерфейс `Handler` (`Serve(ctx, dtlsConn)`), общий `Engine{Open N TURN-stream, DTLS handshake, creds rotation, counters}`.
|
||||
- [ ] **V2-6.2** `udprelay` и `tcpfwd` рефакторятся в реализации `Handler`. Дублирование выходит. `Deps` сокращается.
|
||||
- [ ] **V2-6.3** Bond становится опцией `tcpfwd.Handler` (флаг конструктора), не отдельным пакетом-сосседом. `bondclient` / `bondserver` остаются как helper'ы, но вызываются изнутри `tcpfwd`.
|
||||
- [x] **V2-6.0** Решение 2026-05-19: полный Engine+Handler отклонён после ревью кода. udprelay (WG→DTLS-terminate→wrap→TURN) и tcpfwd (TCP→smux→KCP→DTLS→wrap→TURN) имеют **разное layering wrap/DTLS** и разные lifecycle (per-stream restart vs maintained pool). Реальная общая часть ~30 LOC, а не 70%, как заявлено в плане. Engine с двумя ветками был бы тем же дублём внутри.
|
||||
- [x] **V2-6.1** Создан `internal/proxy/common/common.go`: `GetCredsFunc`, `DialTURN`, `NewClientWrap`. Только то, что действительно идентично.
|
||||
- [x] **V2-6.2** `udprelay` и `tcpfwd` используют `common.DialTURN` / `common.NewClientWrap`. Локальные `GetCredsFunc` стали `type ... = common.GetCredsFunc` (alias для совместимости cmd/main wiring).
|
||||
- [ ] **V2-6.3** Bond как опция `tcpfwd.Handler` — **отменено** вместе с Handler-интерфейсом. `bondclient` остаётся отдельным пакетом, вызываемым из cmd через `Deps.BondHandler`. Текущий контракт читаемый, не трогаем.
|
||||
|
||||
### Этап V2-7 — config структуризация
|
||||
|
||||
|
||||
Reference in New Issue
Block a user