Files
inp2p/pkg/config/config.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
}