usb-server/internal/config/config.go

94 lines
2.5 KiB
Go

package config
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
)
// AutoConnectRule defines a rule for automatic device connection
type AutoConnectRule struct {
BusID string `json:"bus_id,omitempty"`
VendorID string `json:"vendor_id,omitempty"`
ProductID string `json:"product_id,omitempty"`
ClientName string `json:"client_name,omitempty"`
}
// Config holds the client configuration
type Config struct {
RelayAddr string `json:"relay_addr"` // e.g. "ws://localhost:8443" or "wss://relay.example.com:8443"
Hash string `json:"hash"` // SHA256 hash of 3 tokens
Mode string `json:"mode"` // "share" or "use"
Name string `json:"name"` // friendly name for this client
WebPort int `json:"web_port"` // web UI port (default 8080)
// Tokens (optional, stored for convenience - hash is what matters)
Token1 string `json:"token1,omitempty"`
Token2 string `json:"token2,omitempty"`
Token3 string `json:"token3,omitempty"`
// Auto-connect rules (use mode only)
AutoConnect []AutoConnectRule `json:"auto_connect,omitempty"`
// Share mode: allow other clients to force-detach devices in use
AllowForceDetach bool `json:"allow_force_detach,omitempty"`
}
// DefaultConfig returns a config with sensible defaults
func DefaultConfig() *Config {
hostname, _ := os.Hostname()
if hostname == "" {
hostname = "unknown"
}
return &Config{
RelayAddr: "ws://localhost:8443",
Mode: "use",
Name: hostname,
WebPort: 8080,
}
}
// DefaultConfigPath returns the default config file path
func DefaultConfigPath() string {
home, err := os.UserHomeDir()
if err != nil {
return "usb-client.json"
}
return filepath.Join(home, ".usb-server", "config.json")
}
// Load reads config from a JSON file
func Load(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("reading config: %w", err)
}
cfg := DefaultConfig()
if err := json.Unmarshal(data, cfg); err != nil {
return nil, fmt.Errorf("parsing config: %w", err)
}
return cfg, nil
}
// Save writes config to a JSON file
func (c *Config) Save(path string) error {
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0700); err != nil {
return fmt.Errorf("creating config directory: %w", err)
}
data, err := json.MarshalIndent(c, "", " ")
if err != nil {
return fmt.Errorf("encoding config: %w", err)
}
if err := os.WriteFile(path, data, 0600); err != nil {
return fmt.Errorf("writing config: %w", err)
}
return nil
}