Files
Archive/echo/internal/config/config.go
2025-03-22 19:35:00 +01:00

149 lines
3.6 KiB
Go

package config
import (
"encoding/json"
"fmt"
"os"
"strings"
"time"
"github.com/Ehco1996/ehco/internal/constant"
"github.com/Ehco1996/ehco/internal/relay/conf"
"github.com/Ehco1996/ehco/internal/tls"
myhttp "github.com/Ehco1996/ehco/pkg/http"
xConf "github.com/xtls/xray-core/infra/conf"
"go.uber.org/zap"
)
type Config struct {
PATH string `json:"-"`
NodeLabel string `json:"node_label,omitempty"`
WebHost string `json:"web_host,omitempty"`
WebPort int `json:"web_port,omitempty"`
WebToken string `json:"web_token,omitempty"`
WebAuthUser string `json:"web_auth_user,omitempty"`
WebAuthPass string `json:"web_auth_pass,omitempty"`
LogLeveL string `json:"log_level,omitempty"`
EnablePing bool `json:"enable_ping,omitempty"`
ReloadInterval int `json:"reload_interval,omitempty"`
RelayConfigs []*conf.Config `json:"relay_configs"`
RelaySyncURL string `json:"relay_sync_url,omitempty"`
RelaySyncInterval int `json:"relay_sync_interval,omitempty"`
XRayConfig *xConf.Config `json:"xray_config,omitempty"`
SyncTrafficEndPoint string `json:"sync_traffic_endpoint,omitempty"`
lastLoadTime time.Time
l *zap.SugaredLogger
}
func NewConfig(path string) *Config {
return &Config{PATH: path, l: zap.S().Named("cfg")}
}
func (c *Config) NeedSyncFromServer() bool {
return strings.Contains(c.PATH, "http")
}
func (c *Config) LoadConfig(force bool) error {
if c.ReloadInterval > 0 && time.Since(c.lastLoadTime).Seconds() < float64(c.ReloadInterval) && !force {
c.l.Warnf("Skip Load Config, last load time: %s", c.lastLoadTime)
return nil
}
// reset
c.RelayConfigs = nil
c.lastLoadTime = time.Now()
if c.NeedSyncFromServer() {
if err := c.readFromHttp(); err != nil {
return err
}
} else {
if err := c.readFromFile(); err != nil {
return err
}
}
return c.Adjust()
}
func (c *Config) readFromFile() error {
file, err := os.ReadFile(c.PATH)
if err != nil {
return err
}
c.l.Infof("Load Config From File: %s", c.PATH)
return json.Unmarshal([]byte(file), &c)
}
func (c *Config) readFromHttp() error {
c.l.Infof("Load Config From HTTP: %s", c.PATH)
return myhttp.GetJSONWithRetry(c.PATH, &c)
}
func (c *Config) Adjust() error {
if c.LogLeveL == "" {
c.LogLeveL = "info"
}
if c.WebHost == "" {
c.WebHost = "0.0.0.0"
}
for _, r := range c.RelayConfigs {
if err := r.Validate(); err != nil {
return err
}
}
// check relay config label is unique
labelMap := make(map[string]struct{})
for _, r := range c.RelayConfigs {
if _, ok := labelMap[r.Label]; ok {
return fmt.Errorf("relay label %s is not unique", r.Label)
}
labelMap[r.Label] = struct{}{}
}
// init tls when need
for _, r := range c.RelayConfigs {
if r.ListenType == constant.RelayTypeWSS || r.TransportType == constant.RelayTypeWSS {
if err := tls.InitTlsCfg(); err != nil {
return err
}
break
}
}
return nil
}
func (c *Config) NeedStartWebServer() bool {
return c.WebPort != 0
}
func (c *Config) NeedStartXrayServer() bool {
return c.XRayConfig != nil
}
func (c *Config) NeedStartRelayServer() bool {
return len(c.RelayConfigs) > 0
}
func (c *Config) NeedStartCmgr() bool {
return c.RelaySyncURL != "" && c.RelaySyncInterval > 0
}
func (c *Config) GetMetricURL() string {
if !c.NeedStartWebServer() {
return ""
}
url := fmt.Sprintf("http://%s:%d/metrics/", c.WebHost, c.WebPort)
if c.WebToken != "" {
url += fmt.Sprintf("?token=%s", c.WebToken)
}
// for basic auth
if c.WebAuthUser != "" && c.WebAuthPass != "" {
url = fmt.Sprintf("http://%s:%s@%s:%d/metrics/", c.WebAuthUser, c.WebAuthPass, c.WebHost, c.WebPort)
}
return url
}