mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
193 lines
4.4 KiB
Go
193 lines
4.4 KiB
Go
package config
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/samosvalishe/free-turn-proxy/internal/uri"
|
|
)
|
|
|
|
// ClientJSON - JSON-схема конфигурации клиента (gomobile).
|
|
type ClientJSON struct {
|
|
Peer string `json:"peer"`
|
|
ClientID string `json:"clientId"`
|
|
SubURL string `json:"subUrl"`
|
|
Provider string `json:"provider"`
|
|
Routes bool `json:"routes"`
|
|
|
|
TURN turnJSON `json:"turn"`
|
|
Proxy proxyJSON `json:"proxy"`
|
|
VK vkJSON `json:"vk"`
|
|
Obf obfJSON `json:"obf"`
|
|
DNS dnsJSON `json:"dns"`
|
|
Log logJSON `json:"log"`
|
|
KCP kcpJSON `json:"kcp"`
|
|
Tunnel tunnelJSON `json:"tunnel"`
|
|
}
|
|
|
|
// tunnelJSON - параметры встроенного wg-quick туннеля.
|
|
type tunnelJSON struct {
|
|
Mode string `json:"mode"`
|
|
Config string `json:"config"`
|
|
MTU int `json:"mtu"`
|
|
}
|
|
|
|
type turnJSON struct {
|
|
N int `json:"n"`
|
|
Transport string `json:"transport"`
|
|
Host string `json:"host"`
|
|
Port string `json:"port"`
|
|
}
|
|
|
|
type proxyJSON struct {
|
|
Mode string `json:"mode"`
|
|
Listen string `json:"listen"`
|
|
}
|
|
|
|
type vkJSON struct {
|
|
Links []string `json:"links"`
|
|
StreamsPerCred int `json:"streamsPerCred"`
|
|
ManualCaptcha bool `json:"manualCaptcha"`
|
|
Platform string `json:"platform"`
|
|
}
|
|
|
|
type obfJSON struct {
|
|
Profile string `json:"profile"`
|
|
Key string `json:"key"`
|
|
TimingMs int `json:"timingMs"`
|
|
}
|
|
|
|
type dnsJSON struct {
|
|
Mode string `json:"mode"`
|
|
Servers []string `json:"servers"`
|
|
}
|
|
|
|
type logJSON struct {
|
|
Debug bool `json:"debug"`
|
|
}
|
|
|
|
// DefaultClientJSON возвращает дефолтную конфигурацию клиента в формате JSON.
|
|
func DefaultClientJSON() string {
|
|
b, err := json.MarshalIndent(defaultClientJSON(), "", " ")
|
|
if err != nil {
|
|
panic("config: default JSON must marshal: " + err.Error())
|
|
}
|
|
return string(b)
|
|
}
|
|
|
|
// PeekSubURLJSON извлекает subUrl из сырого JSON без полной валидации.
|
|
func PeekSubURLJSON(data []byte) string {
|
|
var peek struct {
|
|
SubURL string `json:"subUrl"`
|
|
}
|
|
if json.Unmarshal(data, &peek) != nil {
|
|
return ""
|
|
}
|
|
return peek.SubURL
|
|
}
|
|
|
|
// ParseClientJSON парсит JSON-конфигурацию клиента с опциональным overlayURI подписки.
|
|
func ParseClientJSON(data []byte, overlayURI string) (*Client, error) {
|
|
dto := defaultClientJSON()
|
|
dec := json.NewDecoder(bytes.NewReader(data))
|
|
dec.DisallowUnknownFields()
|
|
if err := dec.Decode(&dto); err != nil {
|
|
return nil, fmt.Errorf("config json: %w", err)
|
|
}
|
|
|
|
r := dto.toRaw()
|
|
if overlayURI != "" {
|
|
u, err := uri.Parse(overlayURI)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse freeturn:// URI: %w", err)
|
|
}
|
|
r.applyURI(u)
|
|
}
|
|
|
|
c, err := assemble(r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := Validate(c); err != nil {
|
|
return nil, err
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
func defaultClientJSON() ClientJSON {
|
|
r := defaultRaw()
|
|
return ClientJSON{
|
|
Peer: r.Peer,
|
|
ClientID: r.ClientID,
|
|
SubURL: r.SubURL,
|
|
Provider: r.Provider,
|
|
Routes: r.Routes,
|
|
TURN: turnJSON{
|
|
N: r.N,
|
|
Transport: r.Transport,
|
|
Host: r.Turn,
|
|
Port: r.Port,
|
|
},
|
|
Proxy: proxyJSON{Mode: r.Mode, Listen: r.Listen},
|
|
KCP: kcpJSONFrom(r.KCP),
|
|
VK: vkJSON{
|
|
StreamsPerCred: r.StreamsPerCred,
|
|
ManualCaptcha: r.ManualCaptcha,
|
|
Platform: r.Platform,
|
|
},
|
|
Obf: obfJSON{
|
|
Profile: r.ObfProfile,
|
|
Key: r.ObfKey,
|
|
TimingMs: int(r.ObfTiming / time.Millisecond),
|
|
},
|
|
DNS: dnsJSON{Mode: r.DNSMode},
|
|
Log: logJSON{Debug: r.Debug},
|
|
Tunnel: tunnelJSON{
|
|
Mode: r.TunnelMode,
|
|
Config: r.TunnelConfig,
|
|
MTU: r.TunnelMTU,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (j ClientJSON) toRaw() raw {
|
|
return raw{
|
|
Turn: j.TURN.Host,
|
|
Port: j.TURN.Port,
|
|
Listen: j.Proxy.Listen,
|
|
Peer: j.Peer,
|
|
|
|
Provider: j.Provider,
|
|
Links: strings.Join(j.VK.Links, ","),
|
|
|
|
N: j.TURN.N,
|
|
StreamsPerCred: j.VK.StreamsPerCred,
|
|
Transport: j.TURN.Transport,
|
|
Mode: j.Proxy.Mode,
|
|
|
|
ObfProfile: j.Obf.Profile,
|
|
ObfKey: j.Obf.Key,
|
|
ObfTiming: time.Duration(j.Obf.TimingMs) * time.Millisecond,
|
|
|
|
ManualCaptcha: j.VK.ManualCaptcha,
|
|
Platform: j.VK.Platform,
|
|
|
|
DNSMode: j.DNS.Mode,
|
|
DNSServers: strings.Join(j.DNS.Servers, ","),
|
|
|
|
Debug: j.Log.Debug,
|
|
ClientID: j.ClientID,
|
|
SubURL: j.SubURL,
|
|
Routes: j.Routes,
|
|
|
|
TunnelMode: j.Tunnel.Mode,
|
|
TunnelConfig: j.Tunnel.Config,
|
|
TunnelMTU: j.Tunnel.MTU,
|
|
|
|
KCP: j.KCP.profile(),
|
|
}
|
|
}
|