package main import ( "flag" "log" "os" "path/filepath" "sync" ) var Mutex sync.Mutex func ParseFlags() (string, error) { // String that contains the configured configuration path var configPath string exe, _ := os.Executable() defaultCfgPath := filepath.Dir(exe) defaultCfgPath = filepath.Join(defaultCfgPath, "/config.yml") // Set up a CLI flag called "-config" to allow users // to supply the configuration file flag.StringVar(&configPath, "config", defaultCfgPath, "path to config file") // Actually parse the flags flag.Parse() // Validate the path first if err := ValidateConfigPath(configPath); err != nil { return "", err } // Return the configuration path return configPath, nil } func GracefulShutdown(tcpClient *TCPClient, tcpServer *TCPServer, flexClient *FlexClient, flexRepo *FlexDXClusterRepository, contactRepo *Log4OMContactsRepository) { Log.Info("Starting graceful shutdown...") // Fermer les clients if tcpClient != nil { tcpClient.Close() } if flexClient != nil { flexClient.Close() } // Fermer les serveurs if tcpServer != nil { // tcpServer.Close() si tu as une méthode close } // Fermer les bases de données if flexRepo != nil && flexRepo.db != nil { flexRepo.db.Close() } if contactRepo != nil && contactRepo.db != nil { contactRepo.db.Close() } // ✅ Fermer le log en dernier Log.Info("Shutdown complete") CloseLog() } func main() { // Generate our config based on the config supplied // by the user in the flags cfgPath, err := ParseFlags() if err != nil { log.Fatal(err) } NewConfig(cfgPath) configWatcher, err := NewConfigWatcher(cfgPath) if err != nil { log.Fatalf("Could not create config watcher: %v", err) } defer configWatcher.Stop() if err := configWatcher.Start(); err != nil { log.Fatalf("Could not start config watcher: %v", err) } log := NewLog() defer CloseLog() log.Info("Running FlexDXCluster version 2.1") log.Infof("Callsign: %s", Cfg.General.Callsign) log.Info("Config hot reload enabled") DeleteDatabase("./flex.sqlite", log) log.Debugf("Gotify Push Enabled: %v", Cfg.Gotify.Enable) if Cfg.Gotify.Enable { log.Debugf("Gotify Push NewDXCC: %v - NewBand: %v - NewMode: %v - NewBandAndMode: %v", Cfg.Gotify.NewDXCC, Cfg.Gotify.NewBand, Cfg.Gotify.NewMode, Cfg.Gotify.NewBandAndMode) } // Load country.xml to get all the DXCC number Countries := LoadCountryFile() log.Debug("XML Country File has been loaded properly.") // Database to keep track of all spots fRepo := NewFlexDXDatabase("flex.sqlite") defer fRepo.db.Close() // Database connection to Log4OM cRepo := NewLog4OMContactsRepository(Cfg.SQLite.SQLitePath) defer cRepo.db.Close() contacts := cRepo.CountEntries() log.Infof("Log4OM Database Contains %v Contacts", contacts) // ✅ Créer le canal pour le traitement centralisé des spots SpotChanToHTTPServer := make(chan TelnetSpot, 100) // Initialize servers and clients TCPServer := NewTCPServer(Cfg.TelnetServer.Host, Cfg.TelnetServer.Port) TCPClient := NewTCPClient(TCPServer, Countries, cRepo, SpotChanToHTTPServer) FlexClient := NewFlexClient(*fRepo, TCPServer, nil, nil) // Initialize HTTP Server for Dashboard HTTPServer := NewHTTPServer(fRepo, cRepo, TCPServer, TCPClient, FlexClient, "8080") InitLogHook() FlexClient.HTTPServer = HTTPServer spotProcessor := NewSpotProcessor(fRepo, FlexClient, HTTPServer, SpotChanToHTTPServer) go spotProcessor.Start() // Start all services go FlexClient.StartFlexClient() go TCPClient.StartClient() go TCPServer.StartServer() go HTTPServer.Start() log.Infof("Telnet Server: %s:%s", Cfg.TelnetServer.Host, Cfg.TelnetServer.Port) log.Infof("Cluster: %s:%s", Cfg.Cluster.Server, Cfg.Cluster.Port) CheckSignal(TCPClient, TCPServer, FlexClient, fRepo, cRepo) }