186 lines
4.8 KiB
Go
186 lines
4.8 KiB
Go
// Package config provides shared configuration types.
|
|
package config
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Version info (set via -ldflags)
|
|
var (
|
|
Version = "0.1.0"
|
|
GitCommit = "unknown"
|
|
BuildTime = "unknown"
|
|
GoVersion = "unknown"
|
|
)
|
|
|
|
const (
|
|
DefaultWSPort = 27183 // WSS signaling
|
|
DefaultSTUNUDP1 = 27182 // UDP STUN port 1
|
|
DefaultSTUNUDP2 = 27183 // UDP STUN port 2
|
|
DefaultSTUNTCP1 = 27180 // TCP STUN port 1
|
|
DefaultSTUNTCP2 = 27181 // TCP STUN port 2
|
|
DefaultWebPort = 10088 // Web console
|
|
DefaultAPIPort = 10008 // REST API
|
|
|
|
DefaultMaxRelayLoad = 20
|
|
DefaultRelayPort = 27185
|
|
|
|
HeartbeatInterval = 30 // seconds
|
|
HeartbeatTimeout = 90 // seconds — 3x missed heartbeats → offline
|
|
)
|
|
|
|
// ServerConfig holds inp2ps configuration.
|
|
type ServerConfig struct {
|
|
WSPort int `json:"wsPort"`
|
|
STUNUDP1 int `json:"stunUDP1"`
|
|
STUNUDP2 int `json:"stunUDP2"`
|
|
STUNTCP1 int `json:"stunTCP1"`
|
|
STUNTCP2 int `json:"stunTCP2"`
|
|
WebPort int `json:"webPort"`
|
|
APIPort int `json:"apiPort"`
|
|
DBPath string `json:"dbPath"`
|
|
CertFile string `json:"certFile"`
|
|
KeyFile string `json:"keyFile"`
|
|
LogLevel int `json:"logLevel"` // 0=debug, 1=info, 2=warn, 3=error
|
|
Token uint64 `json:"token"` // master token for auth
|
|
Tokens []uint64 `json:"tokens"` // additional tenant tokens
|
|
JWTKey string `json:"jwtKey"` // auto-generated if empty
|
|
|
|
AdminUser string `json:"adminUser"`
|
|
AdminPass string `json:"adminPass"`
|
|
}
|
|
|
|
func DefaultServerConfig() ServerConfig {
|
|
return ServerConfig{
|
|
WSPort: DefaultWSPort,
|
|
STUNUDP1: DefaultSTUNUDP1,
|
|
STUNUDP2: DefaultSTUNUDP2,
|
|
STUNTCP1: DefaultSTUNTCP1,
|
|
STUNTCP2: DefaultSTUNTCP2,
|
|
WebPort: DefaultWebPort,
|
|
APIPort: DefaultAPIPort,
|
|
DBPath: "inp2ps.db",
|
|
LogLevel: 1,
|
|
AdminUser: "admin",
|
|
AdminPass: "admin123",
|
|
}
|
|
}
|
|
|
|
func (c *ServerConfig) FillFromEnv() {
|
|
if v := os.Getenv("INP2PS_WS_PORT"); v != "" {
|
|
c.WSPort, _ = strconv.Atoi(v)
|
|
}
|
|
if v := os.Getenv("INP2PS_WEB_PORT"); v != "" {
|
|
c.WebPort, _ = strconv.Atoi(v)
|
|
}
|
|
if v := os.Getenv("INP2PS_DB_PATH"); v != "" {
|
|
c.DBPath = v
|
|
}
|
|
if v := os.Getenv("INP2PS_TOKEN"); v != "" {
|
|
c.Token, _ = strconv.ParseUint(v, 10, 64)
|
|
}
|
|
if v := os.Getenv("INP2PS_TOKENS"); v != "" {
|
|
parts := strings.Split(v, ",")
|
|
for _, p := range parts {
|
|
p = strings.TrimSpace(p)
|
|
if p == "" {
|
|
continue
|
|
}
|
|
if tv, err := strconv.ParseUint(p, 10, 64); err == nil {
|
|
c.Tokens = append(c.Tokens, tv)
|
|
}
|
|
}
|
|
}
|
|
if v := os.Getenv("INP2PS_CERT"); v != "" {
|
|
c.CertFile = v
|
|
}
|
|
if v := os.Getenv("INP2PS_KEY"); v != "" {
|
|
c.KeyFile = v
|
|
}
|
|
if c.JWTKey == "" {
|
|
b := make([]byte, 32)
|
|
rand.Read(b)
|
|
c.JWTKey = hex.EncodeToString(b)
|
|
}
|
|
}
|
|
|
|
func (c *ServerConfig) Validate() error {
|
|
if c.Token == 0 && len(c.Tokens) == 0 {
|
|
return fmt.Errorf("token is required (INP2PS_TOKEN or INP2PS_TOKENS)")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ClientConfig holds inp2pc configuration.
|
|
type ClientConfig struct {
|
|
ServerHost string `json:"serverHost"`
|
|
ServerPort int `json:"serverPort"`
|
|
Node string `json:"node"`
|
|
Token uint64 `json:"token"`
|
|
NodeSecret string `json:"nodeSecret,omitempty"`
|
|
User string `json:"user,omitempty"`
|
|
Insecure bool `json:"insecure"` // skip TLS verify
|
|
|
|
// STUN ports (defaults match server defaults)
|
|
STUNUDP1 int `json:"stunUDP1,omitempty"`
|
|
STUNUDP2 int `json:"stunUDP2,omitempty"`
|
|
STUNTCP1 int `json:"stunTCP1,omitempty"`
|
|
STUNTCP2 int `json:"stunTCP2,omitempty"`
|
|
|
|
RelayEnabled bool `json:"relayEnabled"` // --relay
|
|
SuperRelay bool `json:"superRelay"` // --super
|
|
RelayOfficial bool `json:"relayOfficial"` // official relay tag
|
|
RelayPort int `json:"relayPort"`
|
|
MaxRelayLoad int `json:"maxRelayLoad"`
|
|
|
|
ShareBandwidth int `json:"shareBandwidth"` // Mbps
|
|
LogLevel int `json:"logLevel"`
|
|
|
|
Apps []AppConfig `json:"apps"`
|
|
}
|
|
|
|
type AppConfig struct {
|
|
AppName string `json:"appName"`
|
|
Protocol string `json:"protocol"` // tcp, udp
|
|
SrcPort int `json:"srcPort"`
|
|
PeerNode string `json:"peerNode"`
|
|
DstHost string `json:"dstHost"`
|
|
DstPort int `json:"dstPort"`
|
|
Enabled bool `json:"enabled"`
|
|
}
|
|
|
|
func DefaultClientConfig() ClientConfig {
|
|
return ClientConfig{
|
|
ServerPort: DefaultWSPort,
|
|
STUNUDP1: DefaultSTUNUDP1,
|
|
STUNUDP2: DefaultSTUNUDP2,
|
|
STUNTCP1: DefaultSTUNTCP1,
|
|
STUNTCP2: DefaultSTUNTCP2,
|
|
ShareBandwidth: 10,
|
|
RelayPort: DefaultRelayPort,
|
|
MaxRelayLoad: DefaultMaxRelayLoad,
|
|
RelayEnabled: true,
|
|
RelayOfficial: false,
|
|
LogLevel: 1,
|
|
}
|
|
}
|
|
|
|
func (c *ClientConfig) Validate() error {
|
|
if c.ServerHost == "" {
|
|
return fmt.Errorf("serverHost is required")
|
|
}
|
|
if c.Token == 0 && c.NodeSecret == "" {
|
|
return fmt.Errorf("token or nodeSecret is required")
|
|
}
|
|
if c.Node == "" {
|
|
hostname, _ := os.Hostname()
|
|
c.Node = hostname
|
|
}
|
|
return nil
|
|
}
|