164 lines
4.7 KiB
Go
164 lines
4.7 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
// Config holds all login server configuration
|
|
type Config struct {
|
|
Port int `json:"port"`
|
|
MaxConnections int `json:"max_connections"`
|
|
TimeoutSeconds int `json:"timeout_seconds"`
|
|
EnableCompression bool `json:"enable_compression"`
|
|
EnableEncryption bool `json:"enable_encryption"`
|
|
AllowAccountCreation bool `json:"allow_account_creation"`
|
|
DefaultSubscriptionLevel uint32 `json:"default_subscription_level"`
|
|
ExpansionFlag uint16 `json:"expansion_flag"`
|
|
CitiesFlag uint8 `json:"cities_flag"`
|
|
EnabledRaces uint32 `json:"enabled_races"`
|
|
SupportedVersions []uint16 `json:"supported_versions"`
|
|
Database DatabaseConfig `json:"database"`
|
|
WebServer WebServerConfig `json:"web_server"`
|
|
WorldServers []WorldServerConfig `json:"world_servers"`
|
|
}
|
|
|
|
// WebServerConfig holds web server settings
|
|
type WebServerConfig struct {
|
|
Enabled bool `json:"enabled"`
|
|
Address string `json:"address"`
|
|
Port int `json:"port"`
|
|
CertFile string `json:"cert_file"`
|
|
KeyFile string `json:"key_file"`
|
|
KeyPassword string `json:"key_password"`
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
// WorldServerConfig holds world server connection info
|
|
type WorldServerConfig struct {
|
|
ID int32 `json:"id"`
|
|
Name string `json:"name"`
|
|
Address string `json:"address"`
|
|
Port int `json:"port"`
|
|
SharedKey string `json:"shared_key"`
|
|
AutoConnect bool `json:"auto_connect"`
|
|
}
|
|
|
|
// DefaultConfig returns sensible default configuration
|
|
func DefaultConfig() *Config {
|
|
return &Config{
|
|
Port: 5999,
|
|
MaxConnections: 1000,
|
|
TimeoutSeconds: 45,
|
|
EnableCompression: true,
|
|
EnableEncryption: true,
|
|
AllowAccountCreation: false,
|
|
DefaultSubscriptionLevel: 0xFFFFFFFF,
|
|
ExpansionFlag: 0x7CFF,
|
|
CitiesFlag: 0xFF,
|
|
EnabledRaces: 0xFFFF,
|
|
SupportedVersions: []uint16{283, 373, 546, 561, 1096, 1208},
|
|
Database: DatabaseConfig{
|
|
FilePath: "eq2login.db",
|
|
MaxConnections: 10,
|
|
BusyTimeout: 5000,
|
|
},
|
|
WebServer: WebServerConfig{
|
|
Enabled: true,
|
|
Address: "0.0.0.0",
|
|
Port: 8080,
|
|
},
|
|
}
|
|
}
|
|
|
|
// LoadConfig loads configuration from a JSON file
|
|
func LoadConfig(filename string) (*Config, error) {
|
|
// Start with defaults
|
|
config := DefaultConfig()
|
|
|
|
// Check if config file exists
|
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
|
// Create default config file
|
|
if err := SaveConfig(filename, config); err != nil {
|
|
return nil, fmt.Errorf("failed to create default config: %w", err)
|
|
}
|
|
fmt.Printf("Created default configuration file: %s\n", filename)
|
|
return config, nil
|
|
}
|
|
|
|
// Read existing config file
|
|
data, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read config file: %w", err)
|
|
}
|
|
|
|
// Parse JSON
|
|
if err := json.Unmarshal(data, config); err != nil {
|
|
return nil, fmt.Errorf("failed to parse config JSON: %w", err)
|
|
}
|
|
|
|
// Validate configuration
|
|
if err := config.Validate(); err != nil {
|
|
return nil, fmt.Errorf("invalid configuration: %w", err)
|
|
}
|
|
|
|
return config, nil
|
|
}
|
|
|
|
// SaveConfig saves configuration to a JSON file
|
|
func SaveConfig(filename string, config *Config) error {
|
|
data, err := json.MarshalIndent(config, "", " ")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal config: %w", err)
|
|
}
|
|
|
|
if err := os.WriteFile(filename, data, 0644); err != nil {
|
|
return fmt.Errorf("failed to write config file: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Validate checks if the configuration is valid
|
|
func (c *Config) Validate() error {
|
|
if c.Port < 1 || c.Port > 65535 {
|
|
return fmt.Errorf("invalid port: %d", c.Port)
|
|
}
|
|
|
|
if c.MaxConnections < 1 {
|
|
return fmt.Errorf("max_connections must be positive")
|
|
}
|
|
|
|
if c.TimeoutSeconds < 1 {
|
|
return fmt.Errorf("timeout_seconds must be positive")
|
|
}
|
|
|
|
if len(c.SupportedVersions) == 0 {
|
|
return fmt.Errorf("must specify at least one supported version")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// IsVersionSupported checks if a client version is supported
|
|
func (c *Config) IsVersionSupported(version uint16) bool {
|
|
for _, supported := range c.SupportedVersions {
|
|
if supported == version {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// GetWorldServerConfig returns configuration for a specific world server
|
|
func (c *Config) GetWorldServerConfig(id int32) *WorldServerConfig {
|
|
for i := range c.WorldServers {
|
|
if c.WorldServers[i].ID == id {
|
|
return &c.WorldServers[i]
|
|
}
|
|
}
|
|
return nil
|
|
}
|