Files
90CNServer/server/internal/platform/config/config.go
T
hanfuit 645b64fe21 DNF90 服务端与启动器完整源码(含 GM 工具功能增强)
服务端(Go):
- GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面
- GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新
- 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新)
- 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍
- 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0)
- 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算

启动器(Python/JS):
- 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭
- GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐)
- 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
2026-11-04 14:31:55 +08:00

952 lines
32 KiB
Go

package config
import (
"fmt"
"slices"
"strings"
"github.com/BurntSushi/toml"
)
const defaultWSPayloadMax = 1024 * 1024
const defaultWSHBSeconds = 10
const defaultRPCPayloadMax = 1024 * 1024
const defaultKCPWindowSize = 128
const defaultQUICStreams int64 = 128
const defRateWindow = 10
const defaultConnRateMax = 60
const defConnMaxEntries = 4096
const defConnIPv4Prefix = 32
const defConnIPv6Prefix = 64
const defaultEventLogTable = "outbox_events"
const defaultAccountTable = "account_center_state"
const defaultObjectTable = "storage_objects"
const defaultOutboxStream = "battle.settlement"
const defaultOutboxType = "battle.settlement.created"
func Load(path, defaultName string) (ServiceConfig, error) {
var cfg ServiceConfig
meta, err := toml.DecodeFile(path, &cfg)
if err != nil {
return ServiceConfig{}, err
}
if keys := undecodedTOMLKeys(meta); len(keys) > 0 {
return ServiceConfig{}, fmt.Errorf("unknown config keys: %s", strings.Join(keys, ", "))
}
expandEnvValues(&cfg)
cfg.Normalize(defaultName)
if err := cfg.Validate(); err != nil {
return ServiceConfig{}, err
}
return cfg, nil
}
func undecodedTOMLKeys(meta toml.MetaData) []string {
undecoded := meta.Undecoded()
if len(undecoded) == 0 {
return nil
}
keys := make([]string, 0, len(undecoded))
for _, key := range undecoded {
keys = append(keys, key.String())
}
slices.Sort(keys)
return keys
}
func (c *ServiceConfig) Normalize(defaultName string) {
c.trim()
if c.Service.Name == "" {
c.Service.Name = defaultName
}
if c.Service.NodeID == "" {
c.Service.NodeID = c.Service.Name + "-local-1"
}
if c.Service.Environment == "" {
c.Service.Environment = "local"
}
if c.Service.StopTimeoutSeconds == 0 {
c.Service.StopTimeoutSeconds = 10
}
if c.Service.StopInitialGraceSeconds == 0 {
c.Service.StopInitialGraceSeconds = 2
}
if c.Service.StopProbeSeconds == 0 {
c.Service.StopProbeSeconds = 1
}
if c.Service.StopStableSeconds == 0 {
c.Service.StopStableSeconds = 5
}
if c.Cluster.ID == "" {
c.Cluster.ID = "local"
}
if c.Cluster.VirtualGID == 0 {
c.Cluster.VirtualGID = c.Cluster.GID
}
if c.Cluster.Zone == "" {
c.Cluster.Zone = c.Service.Environment
}
if c.Cluster.Version == "" {
c.Cluster.Version = "local"
}
if c.Cluster.DataVersion == "" {
c.Cluster.DataVersion = "local"
}
if c.Cluster.HeartbeatIntervalSeconds == 0 {
c.Cluster.HeartbeatIntervalSeconds = 10
}
if c.Admin.Listen == "" {
c.Admin.Listen = ":18080"
}
for idx := range c.Admin.Tokens {
if c.Admin.Tokens[idx].Role == "" {
c.Admin.Tokens[idx].Role = "operator"
}
}
if c.Admin.ReadTimeoutSeconds == 0 {
c.Admin.ReadTimeoutSeconds = 10
}
if c.Admin.ReadHeaderTimeoutSeconds == 0 {
c.Admin.ReadHeaderTimeoutSeconds = 5
}
if c.Admin.WriteTimeoutSeconds == 0 {
c.Admin.WriteTimeoutSeconds = 15
}
if c.Admin.IdleTimeoutSeconds == 0 {
c.Admin.IdleTimeoutSeconds = 60
}
if c.RateLimit.Algorithm == "" {
c.RateLimit.Algorithm = "window"
}
if c.RateLimit.WindowSeconds == 0 {
c.RateLimit.WindowSeconds = 1
}
if c.RateLimit.MaxRequests == 0 {
c.RateLimit.MaxRequests = 60
}
if c.RateLimit.CleanupIntervalSeconds == 0 {
c.RateLimit.CleanupIntervalSeconds = 60
}
if c.Tracing.MaxSpans == 0 {
c.Tracing.MaxSpans = 256
}
if c.OTel.Endpoint == "" {
c.OTel.Endpoint = "127.0.0.1:4318"
}
if c.OTel.ServiceName == "" {
c.OTel.ServiceName = c.Service.Name
}
if c.OTel.SampleRatio == 0 {
c.OTel.SampleRatio = 1
}
if c.OTel.BatchTimeoutSeconds == 0 {
c.OTel.BatchTimeoutSeconds = 5
}
if c.DataTables.Directory == "" {
c.DataTables.Directory = "configs/tables"
}
if c.DataTables.Version == "" {
c.DataTables.Version = c.Cluster.DataVersion
}
if c.I18N.Directory == "" {
c.I18N.Directory = "configs/i18n"
}
if c.I18N.DefaultLanguage == "" {
c.I18N.DefaultLanguage = "zh-CN"
}
if c.I18N.Version == "" {
c.I18N.Version = c.Cluster.DataVersion
}
c.normalizePVF()
if c.Audit.Kind == "" {
c.Audit.Kind = "memory"
}
if c.Audit.FilePath == "" {
c.Audit.FilePath = "data/audit/events.jsonl"
}
if c.Audit.MemoryLimit == 0 {
c.Audit.MemoryLimit = 256
}
if c.LogicLog.Kind == "" {
c.LogicLog.Kind = "memory"
}
if c.LogicLog.FilePath == "" {
c.LogicLog.FilePath = "data/logiclog/events.jsonl"
}
if c.LogicLog.ReasonsPath == "" {
c.LogicLog.ReasonsPath = "configs/logiclog/reasons.csv"
}
if c.LogicLog.MemoryLimit == 0 {
c.LogicLog.MemoryLimit = 256
}
if c.BILog.Kind == "" {
c.BILog.Kind = "memory"
}
if c.BILog.FilePath == "" {
c.BILog.FilePath = "data/bilog/events.jsonl"
}
if c.BILog.SchemaPath == "" {
c.BILog.SchemaPath = "configs/bilog/schema.json"
}
if c.BILog.MemoryLimit == 0 {
c.BILog.MemoryLimit = 256
}
if c.Bus.NATSName == "" {
c.Bus.NATSName = "longheng-bus"
}
if c.Bus.NATSTimeoutSeconds == 0 {
c.Bus.NATSTimeoutSeconds = 5
}
if c.Bus.NATSPingIntervalSeconds == 0 {
c.Bus.NATSPingIntervalSeconds = 1
}
if c.Bus.NATSMaxPingsOutstanding == 0 {
c.Bus.NATSMaxPingsOutstanding = 10
}
if c.Bus.NATSMaxReconnects == 0 {
c.Bus.NATSMaxReconnects = -1
}
if c.Bus.NATSReconnectWaitSeconds == 0 {
c.Bus.NATSReconnectWaitSeconds = 1
}
if c.Bus.NATSWireEncoding == "" {
c.Bus.NATSWireEncoding = "binary_v1"
}
if c.EventLog.StoreKind == "" {
c.EventLog.StoreKind = "memory"
}
if c.EventLog.MySQLTable == "" {
c.EventLog.MySQLTable = defaultEventLogTable
}
if c.EventLog.MySQLMaxOpenConns == 0 {
c.EventLog.MySQLMaxOpenConns = 32
}
if c.EventLog.MySQLMaxIdleConns == 0 {
c.EventLog.MySQLMaxIdleConns = 8
}
if c.EventLog.MySQLConnMaxLifetime == 0 {
c.EventLog.MySQLConnMaxLifetime = 300
}
if c.EventLog.AdminPrefix == "" {
c.EventLog.AdminPrefix = "/eventlog"
}
if c.EventLog.PublishIntervalSeconds == 0 {
c.EventLog.PublishIntervalSeconds = 1
}
if c.EventLog.PublishBatchSize == 0 {
c.EventLog.PublishBatchSize = 100
}
if c.EventLog.PublishRetrySeconds == 0 {
c.EventLog.PublishRetrySeconds = 1
}
if c.EventLog.PublishMaxAttempts == 0 {
c.EventLog.PublishMaxAttempts = 3
}
if c.EventLog.PublishKind == "" {
c.EventLog.PublishKind = "bus"
}
if c.EventLog.PublishHTTPMethod == "" {
c.EventLog.PublishHTTPMethod = "POST"
}
if c.EventLog.PublishHTTPTimeout == 0 {
c.EventLog.PublishHTTPTimeout = 10
}
if c.EventLog.PublishHTTPPayload == "" {
c.EventLog.PublishHTTPPayload = "event"
}
if c.AccountCenter.StoreKind == "" {
c.AccountCenter.StoreKind = "memory"
}
if c.AccountCenter.MySQLTable == "" {
c.AccountCenter.MySQLTable = defaultAccountTable
}
if c.AccountCenter.AdminPrefix == "" {
c.AccountCenter.AdminPrefix = "/accountcenter"
}
if c.StorageObject.StoreKind == "" {
c.StorageObject.StoreKind = "memory"
}
if c.StorageObject.MySQLTable == "" {
c.StorageObject.MySQLTable = defaultObjectTable
}
if c.StorageObject.AdminPrefix == "" {
c.StorageObject.AdminPrefix = "/storage"
}
if c.BattleAgent.SettlementOutboxKind == "" {
c.BattleAgent.SettlementOutboxKind = "memory"
}
if c.BattleAgent.SettlementOutboxStream == "" {
c.BattleAgent.SettlementOutboxStream = defaultOutboxStream
}
if c.BattleAgent.SettlementOutboxType == "" {
c.BattleAgent.SettlementOutboxType = defaultOutboxType
}
if c.Reload.PollIntervalSeconds == 0 {
c.Reload.PollIntervalSeconds = 5
}
if c.Reload.ApplyTimeoutSeconds == 0 {
c.Reload.ApplyTimeoutSeconds = 5
}
if c.HotUpdate.Target == "" {
c.HotUpdate.Target = c.Service.Name
}
if c.HotUpdate.ControlKind == "" {
c.HotUpdate.ControlKind = "memory"
}
if c.HotUpdate.SourceKind == "" {
c.HotUpdate.SourceKind = "local"
}
if c.HotUpdate.ApplierKind == "" {
c.HotUpdate.ApplierKind = "datatable"
}
if c.HotUpdate.Workspace == "" {
c.HotUpdate.Workspace = "data/hotupdate"
}
if c.HotUpdate.ApplyTimeoutSeconds == 0 {
c.HotUpdate.ApplyTimeoutSeconds = 30
}
if c.HotUpdate.ApplierKind == "native_patch" && c.HotUpdate.NativePatchMaxLiveSeconds == 0 {
c.HotUpdate.NativePatchMaxLiveSeconds = 300
}
if c.StateSync.Kind == "" {
c.StateSync.Kind = "memory"
}
if c.StateSync.Namespace == "" {
c.StateSync.Namespace = c.Cluster.ID
}
if c.StateSync.TTLSeconds == 0 {
c.StateSync.TTLSeconds = 60
}
if c.StateSync.CleanupIntervalSeconds == 0 {
c.StateSync.CleanupIntervalSeconds = 30
}
if c.StateSync.MaxPayloadBytes == 0 {
c.StateSync.MaxPayloadBytes = 64 * 1024
}
if c.ServerGroup.StoreKind == "" {
c.ServerGroup.StoreKind = "file"
}
if c.ServerGroup.PlanFile == "" {
c.ServerGroup.PlanFile = "configs/servergroup/plan.json"
}
if c.ServerGroup.MergeArchiveDir == "" {
c.ServerGroup.MergeArchiveDir = "data/servergroup/merge_archives"
}
if c.ServerGroup.AdminPrefix == "" {
c.ServerGroup.AdminPrefix = "/debug/servergroup"
}
if c.ServerGroup.InZoneDelaySeconds == 0 {
c.ServerGroup.InZoneDelaySeconds = 24 * 60 * 60
}
if c.ServerGroup.NoticeLeadSeconds == 0 {
c.ServerGroup.NoticeLeadSeconds = 24 * 60 * 60
}
if len(c.Topology.Services) == 0 && c.Service.Name != "" {
c.Topology.Services = []string{c.Service.Name}
}
if c.Topology.GatewayService == "" {
c.Topology.GatewayService = "gateway"
}
if c.Topology.GatewayBackendService == "" {
if c.Gateway.BackendService != "" {
c.Topology.GatewayBackendService = c.Gateway.BackendService
} else {
c.Topology.GatewayBackendService = "logic"
}
}
if c.Topology.RefreshIntervalSeconds == 0 {
c.Topology.RefreshIntervalSeconds = 5
}
if c.Discovery.CacheTTLSeconds == 0 {
c.Discovery.CacheTTLSeconds = 1
}
if c.Discovery.FailureTTLSeconds == 0 {
c.Discovery.FailureTTLSeconds = 5
}
if c.Discovery.FailureThreshold == 0 {
c.Discovery.FailureThreshold = 1
}
if c.Discovery.Strategy == "" {
c.Discovery.Strategy = "hash"
}
if c.RPC.CallTimeoutSeconds == 0 {
c.RPC.CallTimeoutSeconds = 3
}
if c.RPC.MaxPending == 0 {
c.RPC.MaxPending = 1024
}
if c.RPC.MaxPayloadBytes == 0 {
c.RPC.MaxPayloadBytes = defaultRPCPayloadMax
}
if c.Idempotency.Kind == "" {
c.Idempotency.Kind = "memory"
}
if c.Idempotency.TTLSeconds == 0 {
c.Idempotency.TTLSeconds = 600
}
if c.Idempotency.KeyPrefix == "" {
c.Idempotency.KeyPrefix = "idempotency"
}
if c.Idempotency.RedisAddress == "" {
c.Idempotency.RedisAddress = "127.0.0.1:6379"
}
if c.Idempotency.RedisPoolSize == 0 {
c.Idempotency.RedisPoolSize = 8
}
if c.Idempotency.RedisTimeoutSeconds == 0 {
c.Idempotency.RedisTimeoutSeconds = 2
}
if c.Idempotency.RedisConnectTimeoutSecs == 0 {
c.Idempotency.RedisConnectTimeoutSecs = c.Idempotency.RedisTimeoutSeconds
}
if c.Idempotency.RedisReadTimeoutSecs == 0 {
c.Idempotency.RedisReadTimeoutSecs = c.Idempotency.RedisTimeoutSeconds
}
if c.Idempotency.RedisWriteTimeoutSecs == 0 {
c.Idempotency.RedisWriteTimeoutSecs = c.Idempotency.RedisTimeoutSeconds
}
if c.Idempotency.MySQLDSN == "" {
c.Idempotency.MySQLDSN = "longheng:longheng@tcp(127.0.0.1:3306)/longheng?parseTime=true&charset=utf8mb4,utf8"
}
if c.Idempotency.MySQLMaxOpenConns == 0 {
c.Idempotency.MySQLMaxOpenConns = 32
}
if c.Idempotency.MySQLMaxIdleConns == 0 {
c.Idempotency.MySQLMaxIdleConns = 8
}
if c.Idempotency.MySQLConnMaxLifetimeSec == 0 {
c.Idempotency.MySQLConnMaxLifetimeSec = 300
}
if c.Registry.Kind == "" {
c.Registry.Kind = "memory"
}
if c.Registry.Namespace == "" {
c.Registry.Namespace = "longheng"
}
if c.Registry.LeaseTTL == 0 {
c.Registry.LeaseTTL = 15
}
if c.Bus.Kind == "" {
c.Bus.Kind = "memory"
}
if c.Bus.Namespace == "" {
c.Bus.Namespace = "longheng"
}
if c.Cache.Kind == "" {
c.Cache.Kind = "memory"
}
if c.Cache.KeyPrefix == "" {
c.Cache.KeyPrefix = "cache"
}
if c.Cache.DefaultTTLSeconds == 0 {
c.Cache.DefaultTTLSeconds = 60
}
if c.Cache.MaxEntries == 0 {
c.Cache.MaxEntries = 10000
}
if c.Cache.RedisAddress == "" {
c.Cache.RedisAddress = "127.0.0.1:6379"
}
if c.Cache.RedisPoolSize == 0 {
c.Cache.RedisPoolSize = 8
}
if c.Cache.RedisTimeoutSeconds == 0 {
c.Cache.RedisTimeoutSeconds = 2
}
if c.Cache.RedisConnectTimeout == 0 {
c.Cache.RedisConnectTimeout = c.Cache.RedisTimeoutSeconds
}
if c.Cache.RedisReadTimeout == 0 {
c.Cache.RedisReadTimeout = c.Cache.RedisTimeoutSeconds
}
if c.Cache.RedisWriteTimeout == 0 {
c.Cache.RedisWriteTimeout = c.Cache.RedisTimeoutSeconds
}
if c.Lock.Kind == "" {
c.Lock.Kind = "memory"
}
if c.Lock.KeyPrefix == "" {
c.Lock.KeyPrefix = "lock"
}
if c.Lock.TTLSeconds == 0 {
c.Lock.TTLSeconds = 10
}
if c.Lock.RedisAddress == "" {
c.Lock.RedisAddress = "127.0.0.1:6379"
}
if c.Lock.RedisPoolSize == 0 {
c.Lock.RedisPoolSize = 8
}
if c.Lock.RedisTimeoutSeconds == 0 {
c.Lock.RedisTimeoutSeconds = 2
}
if c.Lock.RedisConnectTimeout == 0 {
c.Lock.RedisConnectTimeout = c.Lock.RedisTimeoutSeconds
}
if c.Lock.RedisReadTimeout == 0 {
c.Lock.RedisReadTimeout = c.Lock.RedisTimeoutSeconds
}
if c.Lock.RedisWriteTimeout == 0 {
c.Lock.RedisWriteTimeout = c.Lock.RedisTimeoutSeconds
}
if c.Presence.Kind == "" {
c.Presence.Kind = "memory"
}
if c.Presence.KeyPrefix == "" {
c.Presence.KeyPrefix = "presence"
}
if c.Presence.TTLSeconds == 0 {
c.Presence.TTLSeconds = c.Gateway.SessionIdleTimeoutSeconds
if c.Presence.TTLSeconds == 0 {
c.Presence.TTLSeconds = 300
}
}
if c.Presence.RedisAddress == "" {
c.Presence.RedisAddress = "127.0.0.1:6379"
}
if c.Presence.RedisPoolSize == 0 {
c.Presence.RedisPoolSize = 8
}
if c.Presence.RedisTimeoutSeconds == 0 {
c.Presence.RedisTimeoutSeconds = 2
}
if c.Presence.RedisConnectTimeout == 0 {
c.Presence.RedisConnectTimeout = c.Presence.RedisTimeoutSeconds
}
if c.Presence.RedisReadTimeout == 0 {
c.Presence.RedisReadTimeout = c.Presence.RedisTimeoutSeconds
}
if c.Presence.RedisWriteTimeout == 0 {
c.Presence.RedisWriteTimeout = c.Presence.RedisTimeoutSeconds
}
if c.Worker.Size == 0 {
c.Worker.Size = 4
}
if c.Worker.Queue == 0 {
c.Worker.Queue = 128
}
if c.ProfileStore.StoreKind == "" {
c.ProfileStore.StoreKind = "memory"
}
if c.ProfileStore.StoreDirectory == "" {
c.ProfileStore.StoreDirectory = "data/profiles"
}
if c.ProfileStore.StoreAddress == "" {
c.ProfileStore.StoreAddress = "127.0.0.1:6379"
}
if c.ProfileStore.StoreKeyPrefix == "" {
c.ProfileStore.StoreKeyPrefix = "profile"
}
if c.ProfileStore.StorePoolSize == 0 {
c.ProfileStore.StorePoolSize = 8
}
if c.ProfileStore.StoreTimeoutSeconds == 0 {
c.ProfileStore.StoreTimeoutSeconds = 2
}
if c.ProfileStore.StoreConnectTimeout == 0 {
c.ProfileStore.StoreConnectTimeout = c.ProfileStore.StoreTimeoutSeconds
}
if c.ProfileStore.StoreReadTimeout == 0 {
c.ProfileStore.StoreReadTimeout = c.ProfileStore.StoreTimeoutSeconds
}
if c.ProfileStore.StoreWriteTimeout == 0 {
c.ProfileStore.StoreWriteTimeout = c.ProfileStore.StoreTimeoutSeconds
}
if c.ProfileStore.MySQLDSN == "" {
c.ProfileStore.MySQLDSN = "longheng:longheng@tcp(127.0.0.1:3306)/longheng?parseTime=true&charset=utf8mb4,utf8"
}
if c.ProfileStore.MySQLMaxOpenConns == 0 {
c.ProfileStore.MySQLMaxOpenConns = 32
}
if c.ProfileStore.MySQLMaxIdleConns == 0 {
c.ProfileStore.MySQLMaxIdleConns = 8
}
if c.ProfileStore.MySQLConnMaxLifetime == 0 {
c.ProfileStore.MySQLConnMaxLifetime = 300
}
if c.ProfileStore.SummaryStoreKind == "" {
if c.ProfileStore.StoreKind == "mysql_redis" {
c.ProfileStore.SummaryStoreKind = "redis"
} else {
c.ProfileStore.SummaryStoreKind = "memory"
}
}
if c.ProfileStore.SummaryStoreAddress == "" {
c.ProfileStore.SummaryStoreAddress = c.ProfileStore.StoreAddress
}
if c.ProfileStore.SummaryStoreKeyPrefix == "" {
c.ProfileStore.SummaryStoreKeyPrefix = "profile_summary"
}
if c.ProfileStore.SummaryStorePoolSize == 0 {
c.ProfileStore.SummaryStorePoolSize = c.ProfileStore.StorePoolSize
}
if c.ProfileStore.SummaryStoreTimeout == 0 {
c.ProfileStore.SummaryStoreTimeout = c.ProfileStore.StoreTimeoutSeconds
}
if c.ProfileStore.SummaryStoreConnectTimeout == 0 {
c.ProfileStore.SummaryStoreConnectTimeout = c.ProfileStore.SummaryStoreTimeout
}
if c.ProfileStore.SummaryStoreReadTimeout == 0 {
c.ProfileStore.SummaryStoreReadTimeout = c.ProfileStore.SummaryStoreTimeout
}
if c.ProfileStore.SummaryStoreWriteTimeout == 0 {
c.ProfileStore.SummaryStoreWriteTimeout = c.ProfileStore.SummaryStoreTimeout
}
if c.ProfileStore.SaveMode == "" {
c.ProfileStore.SaveMode = "sync"
}
if c.ProfileStore.AsyncFlushIntervalSeconds == 0 {
c.ProfileStore.AsyncFlushIntervalSeconds = 5
}
if c.ProfileStore.AsyncMaxPending == 0 {
c.ProfileStore.AsyncMaxPending = 128
}
if c.ProfileStore.AsyncRetryBackoffSeconds == 0 {
c.ProfileStore.AsyncRetryBackoffSeconds = 1
}
if c.ProfileStore.AsyncDeadLetterLimit == 0 {
c.ProfileStore.AsyncDeadLetterLimit = 128
}
if c.ProfileStore.AsyncDeadLetterDirectory == "" {
c.ProfileStore.AsyncDeadLetterDirectory = "data/profile_dead_letters"
}
if c.Gateway.AuthListen == "" {
c.Gateway.AuthListen = ":8081"
}
if c.Gateway.AuthMode == "" {
c.Gateway.AuthMode = "mock"
}
if c.Gateway.GateRouteFeature == "" {
c.Gateway.GateRouteFeature = "gateway"
}
if c.Gateway.GateService == "" {
if c.Topology.GatewayService != "" {
c.Gateway.GateService = c.Topology.GatewayService
} else {
c.Gateway.GateService = c.Service.Name
}
}
if c.Gateway.TCPListen == "" {
c.Gateway.TCPListen = ":3341"
}
if c.Gateway.TCPProxyProtocolEnabled && c.Gateway.TCPProxyHeaderSec == 0 {
c.Gateway.TCPProxyHeaderSec = 3
}
if c.Gateway.KCPEnabled {
if c.Gateway.KCPListen == "" {
c.Gateway.KCPListen = ":3342"
}
if c.Gateway.KCPNoDelay == 0 {
c.Gateway.KCPNoDelay = 1
}
if c.Gateway.KCPInterval == 0 {
c.Gateway.KCPInterval = 10
}
if c.Gateway.KCPResend == 0 {
c.Gateway.KCPResend = 2
}
if c.Gateway.KCPNoCongestion == 0 {
c.Gateway.KCPNoCongestion = 1
}
if c.Gateway.KCPWindowSize == 0 {
c.Gateway.KCPWindowSize = defaultKCPWindowSize
}
}
if c.Gateway.QUICEnabled {
if c.Gateway.QUICListen == "" {
c.Gateway.QUICListen = ":3343"
}
if c.Gateway.QUICHandshakeSec == 0 {
c.Gateway.QUICHandshakeSec = 5
}
if c.Gateway.QUICMaxIdleTimeoutSeconds == 0 {
c.Gateway.QUICMaxIdleTimeoutSeconds = c.Gateway.SessionIdleTimeoutSeconds
if c.Gateway.QUICMaxIdleTimeoutSeconds == 0 {
c.Gateway.QUICMaxIdleTimeoutSeconds = 300
}
}
if c.Gateway.QUICKeepAliveSeconds == 0 {
c.Gateway.QUICKeepAliveSeconds = 10
}
if c.Gateway.QUICMaxIncomingStreams == 0 {
c.Gateway.QUICMaxIncomingStreams = defaultQUICStreams
}
}
if c.Gateway.WebSocketPath == "" {
c.Gateway.WebSocketPath = "/ws"
}
if c.Gateway.WebSocketEnabled && c.Gateway.WebSocketListen == "" {
c.Gateway.WebSocketListen = ":8082"
}
if c.Gateway.WebSocketMaxPayloadBytes == 0 {
c.Gateway.WebSocketMaxPayloadBytes = defaultWSPayloadMax
}
if c.Gateway.WebSocketHeartbeatSeconds == 0 {
c.Gateway.WebSocketHeartbeatSeconds = defaultWSHBSeconds
}
if c.Gateway.ChatListen == "" {
c.Gateway.ChatListen = "127.0.0.1:10001"
}
if c.Gateway.BackendService == "" {
c.Gateway.BackendService = "logic"
}
if c.Gateway.BackendPollIntervalSeconds == 0 {
c.Gateway.BackendPollIntervalSeconds = 5
}
if c.Gateway.MaxConnections == 0 {
c.Gateway.MaxConnections = 1024
}
if c.Gateway.ConnRateWindowSec == 0 {
c.Gateway.ConnRateWindowSec = defRateWindow
}
if c.Gateway.ConnectionRateLimitMax == 0 {
c.Gateway.ConnectionRateLimitMax = defaultConnRateMax
}
if c.Gateway.ConnRateMaxEntries == 0 {
c.Gateway.ConnRateMaxEntries = defConnMaxEntries
}
if c.Gateway.ConnRateIPv4Prefix == 0 {
c.Gateway.ConnRateIPv4Prefix = defConnIPv4Prefix
}
if c.Gateway.ConnRateIPv6Prefix == 0 {
c.Gateway.ConnRateIPv6Prefix = defConnIPv6Prefix
}
if c.Gateway.SessionIdleTimeoutSeconds == 0 {
c.Gateway.SessionIdleTimeoutSeconds = 300
}
if c.Gateway.SessionSweepSec == 0 {
c.Gateway.SessionSweepSec = 30
}
if c.Gateway.SessionHookTimeoutSeconds == 0 {
c.Gateway.SessionHookTimeoutSeconds = 3
}
if c.Gateway.AccountID == "" {
c.Gateway.AccountID = "local_account_10001"
}
if c.Gateway.AccountNumID == 0 {
c.Gateway.AccountNumID = 10001
}
if c.Gateway.AuthMode == "mock" && c.Gateway.AuthToken == "" {
c.Gateway.AuthToken = "local-auth-token"
}
if c.Gateway.AuthMode == "mock" && c.Gateway.LoginToken == "" {
c.Gateway.LoginToken = "local-login-token"
}
if c.Gateway.ServerVersion == "" {
c.Gateway.ServerVersion = "local-gateway 1.0"
}
if c.Gateway.ShardID == 0 {
c.Gateway.ShardID = 9999
}
if c.Gateway.ShardName == "" {
c.Gateway.ShardName = "9999"
}
if c.Gateway.ShardDisplay == "" {
c.Gateway.ShardDisplay = "9999.Local"
}
if c.Gateway.ShardState == 0 {
c.Gateway.ShardState = 1
}
if c.Gateway.Recommend == 0 {
c.Gateway.Recommend = 1
}
if c.Gateway.RecommendLang == "" {
c.Gateway.RecommendLang = "ZH"
}
if c.Gateway.VirtualGID == 0 {
c.Gateway.VirtualGID = 2
}
if len(c.Gateway.ProductIDs) == 0 {
c.Gateway.ProductIDs = []string{"1", "2", "3", "4", "25", "1001"}
}
if !c.Gateway.HasRole {
c.Gateway.SendCreatePush = true
}
}
func (c *ServiceConfig) trim() {
c.Service.Name = strings.TrimSpace(c.Service.Name)
c.Service.NodeID = strings.TrimSpace(c.Service.NodeID)
c.Service.Environment = strings.TrimSpace(c.Service.Environment)
c.Service.PublicAddr = strings.TrimSpace(c.Service.PublicAddr)
c.Service.PrivateAddr = strings.TrimSpace(c.Service.PrivateAddr)
c.Cluster.ID = strings.TrimSpace(c.Cluster.ID)
c.Cluster.Zone = strings.TrimSpace(c.Cluster.Zone)
c.Cluster.Version = strings.TrimSpace(c.Cluster.Version)
c.Cluster.DataVersion = strings.TrimSpace(c.Cluster.DataVersion)
c.Admin.Listen = strings.TrimSpace(c.Admin.Listen)
c.Admin.Token = strings.TrimSpace(c.Admin.Token)
for idx := range c.Admin.Tokens {
c.Admin.Tokens[idx].Name = strings.TrimSpace(c.Admin.Tokens[idx].Name)
c.Admin.Tokens[idx].Token = strings.TrimSpace(c.Admin.Tokens[idx].Token)
c.Admin.Tokens[idx].Role = strings.ToLower(strings.TrimSpace(c.Admin.Tokens[idx].Role))
c.Admin.Tokens[idx].Scopes = trimLowerStringSlice(c.Admin.Tokens[idx].Scopes)
}
c.OTel.Endpoint = strings.TrimSpace(c.OTel.Endpoint)
c.OTel.ServiceName = strings.TrimSpace(c.OTel.ServiceName)
c.DataTables.Directory = strings.TrimSpace(c.DataTables.Directory)
c.DataTables.Version = strings.TrimSpace(c.DataTables.Version)
c.I18N.Directory = strings.TrimSpace(c.I18N.Directory)
c.I18N.DefaultLanguage = strings.TrimSpace(c.I18N.DefaultLanguage)
c.I18N.Version = strings.TrimSpace(c.I18N.Version)
c.trimPVF()
c.Audit.Kind = strings.ToLower(strings.TrimSpace(c.Audit.Kind))
c.Audit.FilePath = strings.TrimSpace(c.Audit.FilePath)
c.LogicLog.Kind = strings.ToLower(strings.TrimSpace(c.LogicLog.Kind))
c.LogicLog.FilePath = strings.TrimSpace(c.LogicLog.FilePath)
c.LogicLog.ReasonsPath = strings.TrimSpace(c.LogicLog.ReasonsPath)
c.BILog.Kind = strings.ToLower(strings.TrimSpace(c.BILog.Kind))
c.BILog.FilePath = strings.TrimSpace(c.BILog.FilePath)
c.BILog.SchemaPath = strings.TrimSpace(c.BILog.SchemaPath)
c.EventLog.StoreKind = strings.ToLower(strings.TrimSpace(c.EventLog.StoreKind))
c.EventLog.MySQLDSN = strings.TrimSpace(c.EventLog.MySQLDSN)
c.EventLog.MySQLTable = strings.TrimSpace(c.EventLog.MySQLTable)
c.EventLog.AdminPrefix = strings.TrimSpace(c.EventLog.AdminPrefix)
c.EventLog.PublishKind = strings.ToLower(strings.TrimSpace(c.EventLog.PublishKind))
c.EventLog.PublishHTTPURL = strings.TrimSpace(c.EventLog.PublishHTTPURL)
c.EventLog.PublishHTTPMethod = strings.ToUpper(strings.TrimSpace(c.EventLog.PublishHTTPMethod))
c.EventLog.PublishHTTPPayload = strings.ToLower(strings.TrimSpace(c.EventLog.PublishHTTPPayload))
c.EventLog.PublishHTTPHeaders = trimStringMap(c.EventLog.PublishHTTPHeaders)
c.AccountCenter.StoreKind = strings.ToLower(strings.TrimSpace(c.AccountCenter.StoreKind))
c.AccountCenter.MySQLDSN = strings.TrimSpace(c.AccountCenter.MySQLDSN)
c.AccountCenter.MySQLTable = strings.TrimSpace(c.AccountCenter.MySQLTable)
c.AccountCenter.AdminPrefix = strings.TrimSpace(c.AccountCenter.AdminPrefix)
c.StorageObject.StoreKind = strings.ToLower(strings.TrimSpace(c.StorageObject.StoreKind))
c.StorageObject.MySQLDSN = strings.TrimSpace(c.StorageObject.MySQLDSN)
c.StorageObject.MySQLTable = strings.TrimSpace(c.StorageObject.MySQLTable)
c.StorageObject.AdminPrefix = strings.TrimSpace(c.StorageObject.AdminPrefix)
c.BattleAgent.SettlementOutboxKind = strings.ToLower(strings.TrimSpace(c.BattleAgent.SettlementOutboxKind))
c.BattleAgent.SettlementOutboxStream = strings.TrimSpace(c.BattleAgent.SettlementOutboxStream)
c.BattleAgent.SettlementOutboxType = strings.TrimSpace(c.BattleAgent.SettlementOutboxType)
c.HotUpdate.Target = strings.TrimSpace(c.HotUpdate.Target)
c.HotUpdate.ControlKind = strings.ToLower(strings.TrimSpace(c.HotUpdate.ControlKind))
c.HotUpdate.SourceKind = strings.ToLower(strings.TrimSpace(c.HotUpdate.SourceKind))
c.HotUpdate.ApplierKind = strings.ToLower(strings.TrimSpace(c.HotUpdate.ApplierKind))
c.HotUpdate.Workspace = strings.TrimSpace(c.HotUpdate.Workspace)
c.HotUpdate.SigningKeyEnv = strings.TrimSpace(c.HotUpdate.SigningKeyEnv)
c.HotUpdate.NativePatchAllowedTargets = trimStringSlice(c.HotUpdate.NativePatchAllowedTargets)
c.HotUpdate.PatchOldSymbols = trimStringSlice(c.HotUpdate.PatchOldSymbols)
c.StateSync.Kind = strings.ToLower(strings.TrimSpace(c.StateSync.Kind))
c.StateSync.Namespace = strings.TrimSpace(c.StateSync.Namespace)
c.ServerGroup.StoreKind = strings.ToLower(strings.TrimSpace(c.ServerGroup.StoreKind))
c.ServerGroup.PlanFile = strings.TrimSpace(c.ServerGroup.PlanFile)
c.ServerGroup.MergeArchiveDir = strings.TrimSpace(c.ServerGroup.MergeArchiveDir)
c.ServerGroup.AdminPrefix = strings.TrimSpace(c.ServerGroup.AdminPrefix)
c.Topology.Services = trimStringSlice(c.Topology.Services)
c.Topology.GatewayService = strings.TrimSpace(c.Topology.GatewayService)
c.Topology.GatewayBackendService = strings.TrimSpace(c.Topology.GatewayBackendService)
c.Discovery.Strategy = strings.ToLower(strings.TrimSpace(c.Discovery.Strategy))
c.RateLimit.Algorithm = strings.ToLower(strings.TrimSpace(c.RateLimit.Algorithm))
if c.RateLimit.Algorithm == "tokenbucket" || c.RateLimit.Algorithm == "token-bucket" {
c.RateLimit.Algorithm = "token_bucket"
}
c.RateLimit.Rules = strings.TrimSpace(c.RateLimit.Rules)
c.RateLimit.TrustedHeader = strings.TrimSpace(c.RateLimit.TrustedHeader)
c.Idempotency.Kind = strings.ToLower(strings.TrimSpace(c.Idempotency.Kind))
c.Idempotency.KeyPrefix = strings.TrimSpace(c.Idempotency.KeyPrefix)
c.Idempotency.RedisAddress = strings.TrimSpace(c.Idempotency.RedisAddress)
c.Idempotency.RedisPassword = strings.TrimSpace(c.Idempotency.RedisPassword)
c.Idempotency.MySQLDSN = strings.TrimSpace(c.Idempotency.MySQLDSN)
c.Registry.Kind = strings.ToLower(strings.TrimSpace(c.Registry.Kind))
c.Registry.Namespace = strings.TrimSpace(c.Registry.Namespace)
c.Registry.Endpoints = trimStringSlice(c.Registry.Endpoints)
c.Registry.RedisPassword = strings.TrimSpace(c.Registry.RedisPassword)
c.Bus.Kind = strings.ToLower(strings.TrimSpace(c.Bus.Kind))
c.Bus.Namespace = strings.TrimSpace(c.Bus.Namespace)
c.Bus.Endpoints = trimStringSlice(c.Bus.Endpoints)
c.Bus.RedisUsername = strings.TrimSpace(c.Bus.RedisUsername)
c.Bus.RedisPassword = strings.TrimSpace(c.Bus.RedisPassword)
c.Bus.RedisTLSServerName = strings.TrimSpace(c.Bus.RedisTLSServerName)
c.Bus.NATSToken = strings.TrimSpace(c.Bus.NATSToken)
c.Bus.NATSUsername = strings.TrimSpace(c.Bus.NATSUsername)
c.Bus.NATSPassword = strings.TrimSpace(c.Bus.NATSPassword)
c.Bus.NATSCredentials = strings.TrimSpace(c.Bus.NATSCredentials)
c.Bus.NATSTLSServerName = strings.TrimSpace(c.Bus.NATSTLSServerName)
c.Bus.NATSCAFile = strings.TrimSpace(c.Bus.NATSCAFile)
c.Bus.NATSCertFile = strings.TrimSpace(c.Bus.NATSCertFile)
c.Bus.NATSKeyFile = strings.TrimSpace(c.Bus.NATSKeyFile)
c.Cache.Kind = strings.ToLower(strings.TrimSpace(c.Cache.Kind))
c.Cache.KeyPrefix = strings.TrimSpace(c.Cache.KeyPrefix)
c.Cache.RedisAddress = strings.TrimSpace(c.Cache.RedisAddress)
c.Cache.RedisPassword = strings.TrimSpace(c.Cache.RedisPassword)
c.Lock.Kind = strings.ToLower(strings.TrimSpace(c.Lock.Kind))
c.Lock.KeyPrefix = strings.TrimSpace(c.Lock.KeyPrefix)
c.Lock.RedisAddress = strings.TrimSpace(c.Lock.RedisAddress)
c.Lock.RedisPassword = strings.TrimSpace(c.Lock.RedisPassword)
c.Presence.Kind = strings.ToLower(strings.TrimSpace(c.Presence.Kind))
c.Presence.KeyPrefix = strings.TrimSpace(c.Presence.KeyPrefix)
c.Presence.RedisAddress = strings.TrimSpace(c.Presence.RedisAddress)
c.Presence.RedisPassword = strings.TrimSpace(c.Presence.RedisPassword)
c.ProfileStore.StoreKind = strings.ToLower(strings.TrimSpace(c.ProfileStore.StoreKind))
c.ProfileStore.StoreDirectory = strings.TrimSpace(c.ProfileStore.StoreDirectory)
c.ProfileStore.StoreAddress = strings.TrimSpace(c.ProfileStore.StoreAddress)
c.ProfileStore.StorePassword = strings.TrimSpace(c.ProfileStore.StorePassword)
c.ProfileStore.StoreKeyPrefix = strings.TrimSpace(c.ProfileStore.StoreKeyPrefix)
c.ProfileStore.MySQLDSN = strings.TrimSpace(c.ProfileStore.MySQLDSN)
for idx := range c.ProfileStore.MySQLShards {
c.ProfileStore.MySQLShards[idx].ID = strings.TrimSpace(c.ProfileStore.MySQLShards[idx].ID)
c.ProfileStore.MySQLShards[idx].DSN = strings.TrimSpace(c.ProfileStore.MySQLShards[idx].DSN)
c.ProfileStore.MySQLShards[idx].TableName = strings.TrimSpace(c.ProfileStore.MySQLShards[idx].TableName)
c.ProfileStore.MySQLShards[idx].TablePrefix = strings.TrimSpace(c.ProfileStore.MySQLShards[idx].TablePrefix)
c.ProfileStore.MySQLShards[idx].HashSlots = strings.TrimSpace(c.ProfileStore.MySQLShards[idx].HashSlots)
}
c.ProfileStore.SummaryStoreKind = strings.ToLower(strings.TrimSpace(c.ProfileStore.SummaryStoreKind))
c.ProfileStore.SummaryStoreAddress = strings.TrimSpace(c.ProfileStore.SummaryStoreAddress)
c.ProfileStore.SummaryStorePassword = strings.TrimSpace(c.ProfileStore.SummaryStorePassword)
c.ProfileStore.SummaryStoreKeyPrefix = strings.TrimSpace(c.ProfileStore.SummaryStoreKeyPrefix)
c.ProfileStore.SaveMode = strings.ToLower(strings.TrimSpace(c.ProfileStore.SaveMode))
c.ProfileStore.AsyncDeadLetterDirectory = strings.TrimSpace(c.ProfileStore.AsyncDeadLetterDirectory)
c.Gateway.AuthListen = strings.TrimSpace(c.Gateway.AuthListen)
c.Gateway.AuthMode = strings.ToLower(strings.TrimSpace(c.Gateway.AuthMode))
c.Gateway.GateRouteFeature = strings.TrimSpace(c.Gateway.GateRouteFeature)
c.Gateway.GateService = strings.TrimSpace(c.Gateway.GateService)
c.Gateway.TCPListen = strings.TrimSpace(c.Gateway.TCPListen)
c.Gateway.TCPProxyTrustedCIDRs = trimStringSlice(c.Gateway.TCPProxyTrustedCIDRs)
c.Gateway.KCPListen = strings.TrimSpace(c.Gateway.KCPListen)
c.Gateway.QUICListen = strings.TrimSpace(c.Gateway.QUICListen)
c.Gateway.QUICCertFile = strings.TrimSpace(c.Gateway.QUICCertFile)
c.Gateway.QUICKeyFile = strings.TrimSpace(c.Gateway.QUICKeyFile)
c.Gateway.WebSocketListen = strings.TrimSpace(c.Gateway.WebSocketListen)
c.Gateway.WebSocketPath = strings.TrimSpace(c.Gateway.WebSocketPath)
c.Gateway.ChatListen = strings.TrimSpace(c.Gateway.ChatListen)
c.Gateway.BackendService = strings.TrimSpace(c.Gateway.BackendService)
c.Gateway.AccountID = strings.TrimSpace(c.Gateway.AccountID)
c.Gateway.SessionKeyMasterSecret = strings.TrimSpace(c.Gateway.SessionKeyMasterSecret)
c.Gateway.AuthToken = strings.TrimSpace(c.Gateway.AuthToken)
c.Gateway.LoginToken = strings.TrimSpace(c.Gateway.LoginToken)
c.Gateway.ServerVersion = strings.TrimSpace(c.Gateway.ServerVersion)
c.Gateway.ShardName = strings.TrimSpace(c.Gateway.ShardName)
c.Gateway.ShardDisplay = strings.TrimSpace(c.Gateway.ShardDisplay)
c.Gateway.RecommendLang = strings.TrimSpace(c.Gateway.RecommendLang)
c.Gateway.ProductIDs = trimStringSlice(c.Gateway.ProductIDs)
}
func trimStringSlice(values []string) []string {
for idx := range values {
values[idx] = strings.TrimSpace(values[idx])
}
return values
}
func trimLowerStringSlice(values []string) []string {
for idx := range values {
values[idx] = strings.ToLower(strings.TrimSpace(values[idx]))
}
return values
}
func trimStringMap(values map[string]string) map[string]string {
if len(values) == 0 {
return nil
}
out := make(map[string]string, len(values))
for key, value := range values {
key = strings.TrimSpace(key)
if key == "" {
continue
}
out[key] = strings.TrimSpace(value)
}
return out
}