mirror of
https://github.com/wyx2685/V2bX.git
synced 2026-02-04 04:30:08 +00:00
update
add conditional compilation support add multi core support
This commit is contained in:
307
core/hy/config.go
Normal file
307
core/hy/config.go
Normal file
@@ -0,0 +1,307 @@
|
||||
package hy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/yosuke-furukawa/json5/encoding/json5"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
mbpsToBps = 125000
|
||||
minSpeedBPS = 16384
|
||||
|
||||
DefaultALPN = "hysteria"
|
||||
|
||||
DefaultStreamReceiveWindow = 16777216 // 16 MB
|
||||
DefaultConnectionReceiveWindow = DefaultStreamReceiveWindow * 5 / 2 // 40 MB
|
||||
|
||||
DefaultMaxIncomingStreams = 1024
|
||||
|
||||
DefaultMMDBFilename = "GeoLite2-Country.mmdb"
|
||||
|
||||
ServerMaxIdleTimeoutSec = 60
|
||||
DefaultClientIdleTimeoutSec = 20
|
||||
|
||||
DefaultClientHopIntervalSec = 10
|
||||
)
|
||||
|
||||
var rateStringRegexp = regexp.MustCompile(`^(\d+)\s*([KMGT]?)([Bb])ps$`)
|
||||
|
||||
type serverConfig struct {
|
||||
Listen string `json:"listen"`
|
||||
Protocol string `json:"protocol"`
|
||||
ACME struct {
|
||||
Domains []string `json:"domains"`
|
||||
Email string `json:"email"`
|
||||
DisableHTTPChallenge bool `json:"disable_http"`
|
||||
DisableTLSALPNChallenge bool `json:"disable_tlsalpn"`
|
||||
AltHTTPPort int `json:"alt_http_port"`
|
||||
AltTLSALPNPort int `json:"alt_tlsalpn_port"`
|
||||
} `json:"acme"`
|
||||
CertFile string `json:"cert"`
|
||||
KeyFile string `json:"key"`
|
||||
// Optional below
|
||||
Up string `json:"up"`
|
||||
UpMbps int `json:"up_mbps"`
|
||||
Down string `json:"down"`
|
||||
DownMbps int `json:"down_mbps"`
|
||||
DisableUDP bool `json:"disable_udp"`
|
||||
ACL string `json:"acl"`
|
||||
MMDB string `json:"mmdb"`
|
||||
Obfs string `json:"obfs"`
|
||||
Auth struct {
|
||||
Mode string `json:"mode"`
|
||||
Config json5.RawMessage `json:"config"`
|
||||
} `json:"auth"`
|
||||
ALPN string `json:"alpn"`
|
||||
PrometheusListen string `json:"prometheus_listen"`
|
||||
ReceiveWindowConn uint64 `json:"recv_window_conn"`
|
||||
ReceiveWindowClient uint64 `json:"recv_window_client"`
|
||||
MaxConnClient int `json:"max_conn_client"`
|
||||
DisableMTUDiscovery bool `json:"disable_mtu_discovery"`
|
||||
Resolver string `json:"resolver"`
|
||||
ResolvePreference string `json:"resolve_preference"`
|
||||
SOCKS5Outbound struct {
|
||||
Server string `json:"server"`
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
} `json:"socks5_outbound"`
|
||||
BindOutbound struct {
|
||||
Address string `json:"address"`
|
||||
Device string `json:"device"`
|
||||
} `json:"bind_outbound"`
|
||||
}
|
||||
|
||||
func (c *serverConfig) Speed() (uint64, uint64, error) {
|
||||
var up, down uint64
|
||||
if len(c.Up) > 0 {
|
||||
up = stringToBps(c.Up)
|
||||
if up == 0 {
|
||||
return 0, 0, errors.New("invalid speed format")
|
||||
}
|
||||
} else {
|
||||
up = uint64(c.UpMbps) * mbpsToBps
|
||||
}
|
||||
if len(c.Down) > 0 {
|
||||
down = stringToBps(c.Down)
|
||||
if down == 0 {
|
||||
return 0, 0, errors.New("invalid speed format")
|
||||
}
|
||||
} else {
|
||||
down = uint64(c.DownMbps) * mbpsToBps
|
||||
}
|
||||
return up, down, nil
|
||||
}
|
||||
|
||||
func (c *serverConfig) Check() error {
|
||||
if len(c.Listen) == 0 {
|
||||
return errors.New("missing listen address")
|
||||
}
|
||||
if len(c.ACME.Domains) == 0 && (len(c.CertFile) == 0 || len(c.KeyFile) == 0) {
|
||||
return errors.New("need either ACME info or cert/key files")
|
||||
}
|
||||
if len(c.ACME.Domains) > 0 && (len(c.CertFile) > 0 || len(c.KeyFile) > 0) {
|
||||
return errors.New("cannot use both ACME and cert/key files, they are mutually exclusive")
|
||||
}
|
||||
if up, down, err := c.Speed(); err != nil || (up != 0 && up < minSpeedBPS) || (down != 0 && down < minSpeedBPS) {
|
||||
return errors.New("invalid speed")
|
||||
}
|
||||
if (c.ReceiveWindowConn != 0 && c.ReceiveWindowConn < 65536) ||
|
||||
(c.ReceiveWindowClient != 0 && c.ReceiveWindowClient < 65536) {
|
||||
return errors.New("invalid receive window size")
|
||||
}
|
||||
if c.MaxConnClient < 0 {
|
||||
return errors.New("invalid max connections per client")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *serverConfig) Fill() {
|
||||
if len(c.ALPN) == 0 {
|
||||
c.ALPN = DefaultALPN
|
||||
}
|
||||
if c.ReceiveWindowConn == 0 {
|
||||
c.ReceiveWindowConn = DefaultStreamReceiveWindow
|
||||
}
|
||||
if c.ReceiveWindowClient == 0 {
|
||||
c.ReceiveWindowClient = DefaultConnectionReceiveWindow
|
||||
}
|
||||
if c.MaxConnClient == 0 {
|
||||
c.MaxConnClient = DefaultMaxIncomingStreams
|
||||
}
|
||||
if len(c.MMDB) == 0 {
|
||||
c.MMDB = DefaultMMDBFilename
|
||||
}
|
||||
}
|
||||
|
||||
func (c *serverConfig) String() string {
|
||||
return fmt.Sprintf("%+v", *c)
|
||||
}
|
||||
|
||||
type Relay struct {
|
||||
Listen string `json:"listen"`
|
||||
Remote string `json:"remote"`
|
||||
Timeout int `json:"timeout"`
|
||||
}
|
||||
|
||||
func (r *Relay) Check() error {
|
||||
if len(r.Listen) == 0 {
|
||||
return errors.New("missing relay listen address")
|
||||
}
|
||||
if len(r.Remote) == 0 {
|
||||
return errors.New("missing relay remote address")
|
||||
}
|
||||
if r.Timeout != 0 && r.Timeout < 4 {
|
||||
return errors.New("invalid relay timeout")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type clientConfig struct {
|
||||
Server string `json:"server"`
|
||||
Protocol string `json:"protocol"`
|
||||
Up string `json:"up"`
|
||||
UpMbps int `json:"up_mbps"`
|
||||
Down string `json:"down"`
|
||||
DownMbps int `json:"down_mbps"`
|
||||
// Optional below
|
||||
Retry int `json:"retry"`
|
||||
RetryInterval *int `json:"retry_interval"`
|
||||
QuitOnDisconnect bool `json:"quit_on_disconnect"`
|
||||
HandshakeTimeout int `json:"handshake_timeout"`
|
||||
IdleTimeout int `json:"idle_timeout"`
|
||||
HopInterval int `json:"hop_interval"`
|
||||
SOCKS5 struct {
|
||||
Listen string `json:"listen"`
|
||||
Timeout int `json:"timeout"`
|
||||
DisableUDP bool `json:"disable_udp"`
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
} `json:"socks5"`
|
||||
HTTP struct {
|
||||
Listen string `json:"listen"`
|
||||
Timeout int `json:"timeout"`
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
Cert string `json:"cert"`
|
||||
Key string `json:"key"`
|
||||
} `json:"http"`
|
||||
TUN struct {
|
||||
Name string `json:"name"`
|
||||
Timeout int `json:"timeout"`
|
||||
MTU uint32 `json:"mtu"`
|
||||
TCPSendBufferSize string `json:"tcp_sndbuf"`
|
||||
TCPReceiveBufferSize string `json:"tcp_rcvbuf"`
|
||||
TCPModerateReceiveBuffer bool `json:"tcp_autotuning"`
|
||||
} `json:"tun"`
|
||||
TCPRelays []Relay `json:"relay_tcps"`
|
||||
TCPRelay Relay `json:"relay_tcp"` // deprecated, but we still support it for backward compatibility
|
||||
UDPRelays []Relay `json:"relay_udps"`
|
||||
UDPRelay Relay `json:"relay_udp"` // deprecated, but we still support it for backward compatibility
|
||||
TCPTProxy struct {
|
||||
Listen string `json:"listen"`
|
||||
Timeout int `json:"timeout"`
|
||||
} `json:"tproxy_tcp"`
|
||||
UDPTProxy struct {
|
||||
Listen string `json:"listen"`
|
||||
Timeout int `json:"timeout"`
|
||||
} `json:"tproxy_udp"`
|
||||
TCPRedirect struct {
|
||||
Listen string `json:"listen"`
|
||||
Timeout int `json:"timeout"`
|
||||
} `json:"redirect_tcp"`
|
||||
ACL string `json:"acl"`
|
||||
MMDB string `json:"mmdb"`
|
||||
Obfs string `json:"obfs"`
|
||||
Auth []byte `json:"auth"`
|
||||
AuthString string `json:"auth_str"`
|
||||
ALPN string `json:"alpn"`
|
||||
ServerName string `json:"server_name"`
|
||||
Insecure bool `json:"insecure"`
|
||||
CustomCA string `json:"ca"`
|
||||
ReceiveWindowConn uint64 `json:"recv_window_conn"`
|
||||
ReceiveWindow uint64 `json:"recv_window"`
|
||||
DisableMTUDiscovery bool `json:"disable_mtu_discovery"`
|
||||
FastOpen bool `json:"fast_open"`
|
||||
LazyStart bool `json:"lazy_start"`
|
||||
Resolver string `json:"resolver"`
|
||||
ResolvePreference string `json:"resolve_preference"`
|
||||
}
|
||||
|
||||
func (c *clientConfig) Speed() (uint64, uint64, error) {
|
||||
var up, down uint64
|
||||
if len(c.Up) > 0 {
|
||||
up = stringToBps(c.Up)
|
||||
if up == 0 {
|
||||
return 0, 0, errors.New("invalid speed format")
|
||||
}
|
||||
} else {
|
||||
up = uint64(c.UpMbps) * mbpsToBps
|
||||
}
|
||||
if len(c.Down) > 0 {
|
||||
down = stringToBps(c.Down)
|
||||
if down == 0 {
|
||||
return 0, 0, errors.New("invalid speed format")
|
||||
}
|
||||
} else {
|
||||
down = uint64(c.DownMbps) * mbpsToBps
|
||||
}
|
||||
return up, down, nil
|
||||
}
|
||||
|
||||
func (c *clientConfig) Fill() {
|
||||
if len(c.ALPN) == 0 {
|
||||
c.ALPN = DefaultALPN
|
||||
}
|
||||
if c.ReceiveWindowConn == 0 {
|
||||
c.ReceiveWindowConn = DefaultStreamReceiveWindow
|
||||
}
|
||||
if c.ReceiveWindow == 0 {
|
||||
c.ReceiveWindow = DefaultConnectionReceiveWindow
|
||||
}
|
||||
if len(c.MMDB) == 0 {
|
||||
c.MMDB = DefaultMMDBFilename
|
||||
}
|
||||
if c.IdleTimeout == 0 {
|
||||
c.IdleTimeout = DefaultClientIdleTimeoutSec
|
||||
}
|
||||
if c.HopInterval == 0 {
|
||||
c.HopInterval = DefaultClientHopIntervalSec
|
||||
}
|
||||
}
|
||||
|
||||
func (c *clientConfig) String() string {
|
||||
return fmt.Sprintf("%+v", *c)
|
||||
}
|
||||
|
||||
func stringToBps(s string) uint64 {
|
||||
if s == "" {
|
||||
return 0
|
||||
}
|
||||
m := rateStringRegexp.FindStringSubmatch(s)
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var n uint64
|
||||
switch m[2] {
|
||||
case "K":
|
||||
n = 1 << 10
|
||||
case "M":
|
||||
n = 1 << 20
|
||||
case "G":
|
||||
n = 1 << 30
|
||||
case "T":
|
||||
n = 1 << 40
|
||||
default:
|
||||
n = 1
|
||||
}
|
||||
v, _ := strconv.ParseUint(m[1], 10, 64)
|
||||
n = v * n
|
||||
if m[3] == "b" {
|
||||
// Bits, need to convert to bytes
|
||||
n = n >> 3
|
||||
}
|
||||
return n
|
||||
}
|
||||
Reference in New Issue
Block a user