func Load(path string) *Config { cfg := new(Config) if _, err := toml.DecodeFile(path, &cfg); err != nil { logger.Fatalf("Cannot read config file; %s", err) } return cfg }
func (a *NPServer) Start() error { // You can't use property, err := sth, because golang will qq // This thing binds a classic TCP listener to the server var err error a.listener, err = net.Listen("tcp", environment.Env.Config.NP.BindingAddress) if err != nil { logger.Fatalf("Error listening; %s", err) } defer a.listener.Close() logger.Infof("Serving NP server on %s", environment.Env.Config.NP.BindingAddress) var tempDelay time.Duration for { conn, e := a.listener.Accept() if e != nil { if ne, ok := e.(net.Error); ok && ne.Temporary() { if tempDelay == 0 { tempDelay = 5 * time.Millisecond } else { tempDelay *= 2 } if max := 1 * time.Second; tempDelay > max { tempDelay = max } logger.Errorf("http: Accept error: %v; retrying in %v", e, tempDelay) time.Sleep(tempDelay) continue } return e } // Seperated it from the listener code to make it clean go a.HandleConnection(conn) } return nil }
func main() { // Add the Stdout logger logger.AddOutput(logger.Stdout{ MinLevel: logger.ERROR, //logger.DEBUG, Colored: true, }) // Load settings from config.toml in working directory settings := config.Load("./config.toml") /*logger.AddOutput(&logger.File{ MinLevel: logger.WARNING, Path: "./server.log", })*/ // Load the aCI3 key err := aci.LoadKey(settings.NP.AnticheatKeyPath) if err != nil { logger.Fatalf("Cannot load aCI3 key; %s", err) } else { logger.Infof("Loaded aCI3 key") } // Start the NewRelic client if it's enabled in the config file if settings.NewRelic.Enabled { agent := gorelic.NewAgent() agent.Verbose = settings.NewRelic.Verbose agent.NewrelicName = settings.NewRelic.Name agent.NewrelicLicense = settings.NewRelic.License agent.Run() } // Generate a Jet database connector. // Here, err shows if the connection string syntax is valid. // The actual creds are checked during the first query. database, err := jet.Open( settings.Database.Driver, settings.Database.ConnectionString, ) defer database.Close() if err != nil { logger.Fatalf("Cannot connect to database; %s", err) } // But Redis connects here! As far as I know, autoreconnect is implemented cache := redis.NewTCPClient(&redis.Options{ Addr: settings.Redis.Address, Password: settings.Redis.Password, DB: int64(settings.Redis.Database), }) defer cache.Close() // Set up a new environment object environment.SetEnvironment(&environment.Environment{ Config: settings, Database: database, Redis: cache, }) // This thing is massive // The main network platform server that game connects to if settings.NP.Enabled { np_server := np.New() go np_server.Start() } // HTTP-based remote authentication form and a simple API // Is supposed to replace half of 3k if settings.HTTP.Enabled { http_server := http.New() go http_server.Start() } /*if settings.PlayerLog.Enabled { playerlog_server := playerlog.Init(settings.PlayerLog) go playerlog_server.Start() } if settings.Misc.Enabled { misc_server := misc.Init(settings.Misc) go misc_server.Start() }*/ // select{} stops execution of the program until all goroutines close // TODO: add panic recovery! if settings.NP.Enabled || settings.PlayerLog.Enabled || settings.Misc.Enabled || settings.HTTP.Enabled { select {} } }