package main import ( "flag" "fmt" "net/http" "os" "os/signal" "super-frpc/postLog" "syscall" "time" ) type SoftwareInfo struct { Name string Version string Developer string BuildVer int16 Description string BuildType string } func main() { softwareInfo := SoftwareInfo{ Name: "Super-frpc", Version: "0.0.1", Developer: "Madobi Nanami", BuildVer: 1, Description: "A backend application for managing local frpc instances, allowing users to easily start, stop, restart, and perform daily maintenance operations on frpc instances. It also provides automated error handling, such as automatic restart when an instance crashes.", BuildType: "debug", } postLog.Info(fmt.Sprintf("%s %s (Build %d.%s) by %s", softwareInfo.Name, softwareInfo.Version, softwareInfo.BuildVer, softwareInfo.BuildType, softwareInfo.Developer)) configPath := flag.String("config", "./config.json", "path to config file") dbPath := flag.String("db", "./database.db", "path to database file") flag.Parse() if _, err := os.Stat(*configPath); os.IsNotExist(err) { defaultConfig := `{ listenAddr": " "0.0.0.0", "listenPort": "8080", "configDir": "./configs" }` if err := os.WriteFile(*configPath, []byte(defaultConfig), 0644); err != nil { postLog.Warning(fmt.Sprintf("Failed to create default config file: %v", err)) } postLog.Info(fmt.Sprintf("Created default config file at %s", *configPath)) } config, err := LoadConfig(*configPath) if err != nil { postLog.Fatal(fmt.Sprintf("Failed to load config: %v", err)) } // Initialize logger with debug mode postLog.SetDebugMode(config.Debug) if err := InitDatabase(*dbPath); err != nil { postLog.Fatal(fmt.Sprintf("Failed to initialize database: %v", err)) } postLog.Info("Database initialized successfully") if err := InitFrpcDatabase(*dbPath); err != nil { postLog.Warning(fmt.Sprintf("Failed to initialize frpc database: %v", err)) } _, err = GetConfig() if err != nil { postLog.Fatal(fmt.Sprintf("Failed to get config: %v", err)) } setupRoutes() addr := fmt.Sprintf("%s:%s", config.ListenAddr, config.ListenPort) server := &http.Server{ Addr: addr, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 60 * time.Second, } go func() { postLog.Info(fmt.Sprintf("Server starting on %s", addr)) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { postLog.Fatal(fmt.Sprintf("Failed to start server: %v", err)) } }() quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit postLog.Info("Shutting down server...") if err := server.Close(); err != nil { postLog.Error(fmt.Sprintf("Server closed with error: %v", err)) } if err := CloseDatabase(); err != nil { postLog.Error(fmt.Sprintf("Error closing database: %v", err)) } if err := CloseFrpcDatabase(); err != nil { postLog.Error(fmt.Sprintf("Error closing frpc database: %v", err)) } postLog.Info("Server stopped") }