Store servers in a map

Closes #100
master
HimbeerserverDE 2022-05-02 21:57:38 +02:00
parent c32739ab92
commit ce203b8f18
No known key found for this signature in database
GPG Key ID: A3D3E205DA0B0401
5 changed files with 87 additions and 65 deletions

120
config.go
View File

@ -24,7 +24,6 @@ var configMu sync.RWMutex
var loadConfigOnce sync.Once var loadConfigOnce sync.Once
type Server struct { type Server struct {
Name string
Addr string Addr string
MediaPool string MediaPool string
Fallbacks []string Fallbacks []string
@ -44,7 +43,7 @@ type Config struct {
NoTelnet bool NoTelnet bool
TelnetAddr string TelnetAddr string
BindAddr string BindAddr string
Servers []Server Servers map[string]Server
ForceDefaultSrv bool ForceDefaultSrv bool
FallbackServers []string FallbackServers []string
CSMRF struct { CSMRF struct {
@ -92,16 +91,17 @@ func Conf() Config {
} }
// PoolServers returns all media pools and their member servers. // PoolServers returns all media pools and their member servers.
func PoolServers() map[string][]Server { func PoolServers() map[string]map[string]Server {
var srvs = make(map[string][]Server) pools := make(map[string]map[string]Server)
conf := Conf() for name, srv := range Conf().Servers {
if pools[srv.MediaPool] == nil {
pools[srv.MediaPool] = make(map[string]Server)
}
// map all to.. map of slices pools[srv.MediaPool][name] = srv
for _, srv := range conf.Servers {
srvs[srv.MediaPool] = append(srvs[srv.MediaPool], srv)
} }
return srvs return pools
} }
// AddServer dynamically configures a new Server at runtime. // AddServer dynamically configures a new Server at runtime.
@ -110,16 +110,14 @@ func PoolServers() map[string][]Server {
// The server must be part of a media pool with at least one // The server must be part of a media pool with at least one
// other member. At least one of the other members always // other member. At least one of the other members always
// needs to be reachable. // needs to be reachable.
func AddServer(s Server) bool { func AddServer(name string, s Server) bool {
configMu.Lock() configMu.Lock()
defer configMu.Unlock() defer configMu.Unlock()
s.dynamic = true s.dynamic = true
for _, srv := range config.Servers { if _, ok := config.Servers[name]; ok {
if srv.Name == s.Name { return false
return false
}
} }
var poolMembers bool var poolMembers bool
@ -133,7 +131,7 @@ func AddServer(s Server) bool {
return false return false
} }
config.Servers = append(config.Servers, s) config.Servers[name] = s
return true return true
} }
@ -144,52 +142,70 @@ func RmServer(name string) bool {
configMu.Lock() configMu.Lock()
defer configMu.Unlock() defer configMu.Unlock()
for i, srv := range config.Servers { s, ok := config.Servers[name]
if srv.Name == name { if !ok {
if srv.dynamic { return true
return false }
}
// Can't remove server if players are connected to it if !s.dynamic {
for cc := range Clts() { return false
if cc.ServerName() == name { }
return false
}
}
config.Servers = append(config.Servers[:i], config.Servers[1+i:]...) // Can't remove server if players are connected to it
return true for cc := range Clts() {
if cc.ServerName() == name {
return false
} }
} }
delete(config.Servers, name)
return true return true
} }
func (cnf Config) defaultSrvInfo() (string, Server) {
for name, srv := range Conf().Servers {
return name, srv
}
// No servers are configured.
return "", Server{}
}
// DefaultSrvName returns the name of the default server.
// If no servers exist it returns an empty string.
func (cnf Config) DefaultSrvName() string {
name, _ := cnf.defaultSrvInfo()
return name
}
// DefaultSrv returns information about the default server.
// If no servers exist the returned struct will be uninitialized.
// This is a faster shortcut for Config.Servers[Config.DefaultSrvName].
// You should thus only use this method.
func (cnf Config) DefaultSrv() Server {
_, srv := cnf.defaultSrvInfo()
return srv
}
// FallbackServers returns a slice of server names that // FallbackServers returns a slice of server names that
// a server can fall back to. // a server can fall back to.
func FallbackServers(server string) []string { func FallbackServers(server string) []string {
configMu.RLock()
defer configMu.RUnlock()
fallbacks := make([]string, 0)
conf := Conf() conf := Conf()
// find server srv, ok := conf.Servers[server]
for _, srv := range conf.Servers { if !ok {
if srv.Name == server { return nil
fallbacks = append(fallbacks, srv.Fallbacks...)
break
}
} }
fallbacks := srv.Fallbacks
// global fallbacks // global fallbacks
if len(conf.FallbackServers) == 0 { if len(conf.FallbackServers) == 0 {
if len(conf.Servers) == 0 { if len(conf.Servers) == 0 {
return fallbacks return fallbacks
} }
return append(fallbacks, conf.Servers[0].Name) return append(fallbacks, conf.DefaultSrvName())
} else { } else {
return append(fallbacks, conf.FallbackServers...) return append(fallbacks, conf.FallbackServers...)
} }
@ -235,35 +251,37 @@ func LoadConfig() error {
// Dynamic servers shouldn't be deleted silently. // Dynamic servers shouldn't be deleted silently.
DynLoop: DynLoop:
for _, srv := range oldConf.Servers { for name, srv := range oldConf.Servers {
if srv.dynamic { if srv.dynamic {
config.Servers = append(config.Servers, srv) config.Servers[name] = srv
} else { } else {
for _, s := range config.Servers { for name2 := range config.Servers {
if srv.Name == s.Name { if name == name2 {
continue DynLoop continue DynLoop
} }
} }
for cc := range Clts() { for cc := range Clts() {
if cc.ServerName() == srv.Name { if cc.ServerName() == name {
config = oldConf config = oldConf
return fmt.Errorf("can't delete server %s with players", srv.Name) return fmt.Errorf("can't delete server %s with players", name)
} }
} }
} }
} }
for i, srv := range config.Servers { for name, srv := range config.Servers {
for _, s := range config.Servers { for name2 := range config.Servers {
if srv.Name == s.Name { if name == name2 {
config = oldConf config = oldConf
return fmt.Errorf("duplicate server %s", s.Name) return fmt.Errorf("duplicate server %s", name2)
} }
} }
if srv.MediaPool == "" { if srv.MediaPool == "" {
config.Servers[i].MediaPool = srv.Name s := config.Servers[name]
s.MediaPool = name
config.Servers[name] = s
} }
} }

View File

@ -18,8 +18,8 @@ func connect(conn net.Conn, name string, cc *ClientConn) *ServerConn {
cc.mu.RUnlock() cc.mu.RUnlock()
var mediaPool string var mediaPool string
for _, srv := range Conf().Servers { for srvName, srv := range Conf().Servers {
if srv.Name == name { if srvName == name {
mediaPool = srv.MediaPool mediaPool = srv.MediaPool
} }
} }

View File

@ -501,7 +501,7 @@ PoolLoop:
for _, pool := range PoolServers() { for _, pool := range PoolServers() {
var addr *net.UDPAddr var addr *net.UDPAddr
for _, srv := range pool { for name, srv := range pool {
addr, err = net.ResolveUDPAddr("udp", srv.Addr) addr, err = net.ResolveUDPAddr("udp", srv.Addr)
if err != nil { if err != nil {
continue continue
@ -514,7 +514,7 @@ PoolLoop:
} }
var cc *contentConn var cc *contentConn
cc, err = connectContent(conn, srv.Name, userName, srv.MediaPool) cc, err = connectContent(conn, name, userName, srv.MediaPool)
if err != nil { if err != nil {
continue continue
} }

4
hop.go
View File

@ -24,8 +24,8 @@ func (cc *ClientConn) Hop(serverName string) error {
} }
var strAddr string var strAddr string
for _, srv := range Conf().Servers { for name, srv := range Conf().Servers {
if srv.Name == serverName { if name == serverName {
strAddr = srv.Addr strAddr = srv.Addr
break break
} }

20
run.go
View File

@ -100,19 +100,23 @@ func runFunc() {
<-cc.Init() <-cc.Init()
cc.Log("<->", "handshake completed") cc.Log("<->", "handshake completed")
srvs := Conf().Servers conf := Conf()
if len(srvs) == 0 { if len(conf.Servers) == 0 {
cc.Log("<-", "no servers") cc.Log("<-", "no servers")
cc.Kick("No servers are configured.") cc.Kick("No servers are configured.")
return return
} }
srv := srvs[0] srv := conf.DefaultSrv()
srvName := conf.DefaultSrvName()
lastSrv, err := authIface.LastSrv(cc.Name()) lastSrv, err := authIface.LastSrv(cc.Name())
if err == nil && !Conf().ForceDefaultSrv && lastSrv != srv.Name { if err == nil && !Conf().ForceDefaultSrv && lastSrv != srvName {
for _, v := range srvs { for name, s := range conf.Servers {
if v.Name == lastSrv { if name == lastSrv {
srv = v srv = s
srvName = name
break break
} }
} }
@ -132,7 +136,7 @@ func runFunc() {
return return
} }
connect(conn, srv.Name, cc) connect(conn, srvName, cc)
}() }()
} }