166 lines
5.0 KiB
Go
166 lines
5.0 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"super-frpc/config"
|
|
"super-frpc/database"
|
|
"super-frpc/frpLogger"
|
|
"super-frpc/global"
|
|
"super-frpc/postLog"
|
|
"super-frpc/session"
|
|
"super-frpc/sys"
|
|
"super-frpc/utils"
|
|
"super-frpc/watchdog"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
func main() {
|
|
global.CurrentPath = utils.GetCurrentPath()
|
|
postLog.Info(fmt.Sprintf("%s %s (Build %d.%s) by %s", global.Software.Name, global.Software.Version, global.Software.BuildVer, global.Software.BuildType, global.Software.Developer))
|
|
global.ConfigPath = flag.String("config", global.CurrentPath+string(os.PathSeparator)+"config.json", "path to config file")
|
|
global.DBPath_data = flag.String("db", global.CurrentPath+string(os.PathSeparator)+"database.db", "path to database file")
|
|
global.DBPath_log = flag.String("log", global.CurrentPath+string(os.PathSeparator)+"logs.db", "path to logs database file")
|
|
flag.Parse()
|
|
|
|
if _, err := os.Stat(*global.ConfigPath); os.IsNotExist(err) {
|
|
// Load the default config
|
|
configData, err := json.MarshalIndent(global.CurrentConfig, "", " ")
|
|
if err != nil {
|
|
postLog.Warning(fmt.Sprintf("Failed to marshal default config: %v", err))
|
|
} else if err := os.WriteFile(*global.ConfigPath, configData, 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", *global.ConfigPath))
|
|
}
|
|
|
|
err := config.LoadConfig(*global.ConfigPath, sys.GetInitSystem)
|
|
if err != nil {
|
|
postLog.Fatal(fmt.Sprintf("Failed to load config: %v", err))
|
|
}
|
|
|
|
if global.Software.BuildType == "debug" { // If debug build, set debug mode to true
|
|
global.CurrentConfig.Debug = true
|
|
}
|
|
postLog.SetDebugMode(global.CurrentConfig.Debug)
|
|
global.Is.Debug = global.CurrentConfig.Debug
|
|
|
|
if err := postLog.InitLogsDatabase(*global.DBPath_log); err != nil {
|
|
postLog.Fatal(fmt.Sprintf("Failed to initialize logs database: %v", err))
|
|
}
|
|
postLog.Info("Logs database initialized successfully")
|
|
|
|
if err := database.InitDatabase(*global.DBPath_data, *global.DBPath_log); err != nil {
|
|
postLog.Fatal(fmt.Sprintf("Failed to initialize database: %v", err))
|
|
}
|
|
postLog.Info("Database initialized successfully")
|
|
|
|
if err := database.InitFrpcDatabase(*global.DBPath_data); err != nil {
|
|
postLog.Fatal(fmt.Sprintf("Failed to initialize frpc database: %v", err))
|
|
}
|
|
|
|
if global.CurrentConfig.LogsPath != "" && !global.CurrentConfig.Status.IsLogrotateConfigured { // Set up logrotate policy if LogsPath is configured
|
|
if err := sys.CreateLogrotatePolicy(); err != nil {
|
|
postLog.Fatal(fmt.Sprintf("Failed to create logrotate policy: %v", err))
|
|
} else {
|
|
global.CurrentConfig.Status.IsLogrotateConfigured = true
|
|
config.SaveConfig()
|
|
postLog.Info("Logrotate policy has been configured successfully.")
|
|
}
|
|
}
|
|
|
|
frpLogger.SetDatabase(global.ConfigDB, global.FrpcDB)
|
|
frpLogger.SetDebugMode(global.CurrentConfig.Debug)
|
|
|
|
postLog.InitLogBroadcaster()
|
|
|
|
setupRoutes()
|
|
|
|
// Initialize watchdog connection
|
|
if global.CurrentConfig.Watchdog.Enabled {
|
|
err = watchdog.Init()
|
|
if err != nil {
|
|
postLog.Error(fmt.Sprintf("Unable to initialize Watchdog: %s", err))
|
|
} else {
|
|
if !watchdog.Connect() {
|
|
postLog.Error("Failed to connect to Watchdog")
|
|
} else {
|
|
postLog.Info("Connected to Watchdog successfully")
|
|
|
|
go func() {
|
|
if err := watchdog.StartKeepAlive(); err != nil {
|
|
postLog.Error(fmt.Sprintf("Watchdog keepalive stopped: %v", err))
|
|
global.Is.WatchdogConnected = false
|
|
}
|
|
}()
|
|
}
|
|
}
|
|
}
|
|
|
|
addr := fmt.Sprintf("%s:%s", global.CurrentConfig.ListenAddr, global.CurrentConfig.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))
|
|
global.Is.Online = true
|
|
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
postLog.Fatal(fmt.Sprintf("Failed to start server: %v", err))
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
ticker := time.NewTicker(1 * time.Hour)
|
|
defer ticker.Stop()
|
|
for range ticker.C {
|
|
session.CleanupExpiredTokens()
|
|
session.CleanupExpiredSessions()
|
|
}
|
|
}()
|
|
|
|
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 := database.CloseDatabase(); err != nil {
|
|
postLog.Error(fmt.Sprintf("Error closing database: %v", err))
|
|
}
|
|
|
|
watchdog.Close()
|
|
|
|
postLog.Info("Server stopped")
|
|
}
|
|
|
|
func GetStatusHandler(w http.ResponseWriter, r *http.Request) {
|
|
statusInfo := map[string]string{
|
|
"ServerStatus": "Offline",
|
|
"WatchdogStatus": "Offline",
|
|
}
|
|
if global.Is.Online {
|
|
statusInfo["ServerStatus"] = "Online"
|
|
}
|
|
if global.Is.WatchdogConnected {
|
|
statusInfo["WatchdogStatus"] = "Online"
|
|
}
|
|
utils.SendSuccessResponse(w, "getStatus", statusInfo)
|
|
}
|
|
|
|
func GetSoftwareInfoHandler(w http.ResponseWriter, r *http.Request) {
|
|
utils.SendSuccessResponse(w, "getSoftwareInfo", global.Software)
|
|
}
|