- Add Close() function to watchdog for graceful shutdown - Update instance message format for better consistency - Add watchdog status tracking in StatusInfo - Include watchdog field in FrpcInstance struct and database - Change port fields from string to int in FrpcProxyInfo - Add auth_token support in InstanceInfo
184 lines
4.5 KiB
Go
184 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"super-frpc/frpLogger"
|
|
"super-frpc/postLog"
|
|
"super-frpc/watchdog"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
type SoftwareInfo struct {
|
|
Name string
|
|
Version string
|
|
Developer string
|
|
BuildVer int16
|
|
Description string
|
|
BuildType string
|
|
}
|
|
|
|
var softwareInfo SoftwareInfo = SoftwareInfo{
|
|
Name: "Super-frpc",
|
|
Version: "0.0.1",
|
|
Developer: "Madobi Nanami",
|
|
BuildVer: 1,
|
|
BuildType: "debug",
|
|
}
|
|
|
|
type StatusInfo struct {
|
|
ServerStatus string
|
|
WatchdogStatus string
|
|
}
|
|
|
|
type Is struct {
|
|
debug bool
|
|
online bool
|
|
watchdogConnected bool
|
|
}
|
|
|
|
var is Is = Is {
|
|
debug: false,
|
|
online: false,
|
|
watchdogConnected: false,
|
|
}
|
|
|
|
func main() {
|
|
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_data := flag.String("db", "./database.db", "path to database file")
|
|
dbPath_log := flag.String("log", "./logs.db", "path to logs 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))
|
|
}
|
|
|
|
postLog.SetDebugMode(config.Debug)
|
|
is.debug = config.Debug
|
|
|
|
if err := postLog.InitLogsDatabase(*dbPath_log); err != nil {
|
|
postLog.Fatal(fmt.Sprintf("Failed to initialize logs database: %v", err))
|
|
}
|
|
postLog.Info("Logs database initialized successfully")
|
|
|
|
if err := InitDatabase(*dbPath_data, *dbPath_log); err != nil {
|
|
postLog.Fatal(fmt.Sprintf("Failed to initialize database: %v", err))
|
|
}
|
|
postLog.Info("Database initialized successfully")
|
|
|
|
if err := InitFrpcDatabase(*dbPath_data); err != nil {
|
|
postLog.Fatal(fmt.Sprintf("Failed to initialize frpc database: %v", err))
|
|
}
|
|
|
|
frpLogger.SetDatabase(db, frpcDB)
|
|
frpLogger.SetDebugMode(config.Debug)
|
|
|
|
_, err = GetConfig()
|
|
if err != nil {
|
|
postLog.Fatal(fmt.Sprintf("Failed to get config: %v", err))
|
|
}
|
|
|
|
postLog.InitLogBroadcaster()
|
|
|
|
setupRoutes()
|
|
|
|
err = watchdog.Init()
|
|
if err != nil {
|
|
postLog.Error(fmt.Sprintf("Unable to initialize Watchdog: %s", err))
|
|
} else {
|
|
if !watchdog.Connect("127.0.0.1", config.Watchdog.Port) {
|
|
postLog.Error(fmt.Sprintf("Failed to connect to Watchdog at %s:%d", "127.0.0.1", config.Watchdog.Port))
|
|
} else {
|
|
postLog.Info(fmt.Sprintf("Connected to Watchdog at %s:%d", "127.0.0.1", config.Watchdog.Port))
|
|
is.watchdogConnected = true
|
|
}
|
|
}
|
|
|
|
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))
|
|
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 {
|
|
CleanupExpiredTokens()
|
|
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 := 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))
|
|
}
|
|
|
|
watchdog.Close()
|
|
|
|
postLog.Info("Server stopped")
|
|
}
|
|
|
|
func GetStatusHandler(w http.ResponseWriter, r *http.Request) {
|
|
statusInfo := StatusInfo{
|
|
ServerStatus: "Offline",
|
|
WatchdogStatus: "Offline",
|
|
}
|
|
if !is.online {
|
|
statusInfo.ServerStatus = "Offline"
|
|
} else {
|
|
statusInfo.ServerStatus = "Online"
|
|
}
|
|
if !is.watchdogConnected {
|
|
statusInfo.WatchdogStatus = "Offline"
|
|
} else {
|
|
statusInfo.WatchdogStatus = "Online"
|
|
}
|
|
SendSuccessResponse(w, "getStatus", statusInfo)
|
|
}
|
|
|
|
func GetSoftwareInfoHandler(w http.ResponseWriter, r *http.Request) {
|
|
SendSuccessResponse(w, "getSoftwareInfo", softwareInfo)
|
|
}
|