diff --git a/web/service/server.go b/web/service/server.go index 23167fb3..bbdc8989 100644 --- a/web/service/server.go +++ b/web/service/server.go @@ -302,25 +302,22 @@ func (s *ServerService) GetXrayVersions() ([]string, error) { return versions, nil } -func (s *ServerService) StopXrayService() (string error) { +func (s *ServerService) StopXrayService() error { err := s.xrayService.StopXray() if err != nil { logger.Error("stop xray failed:", err) return err } - return nil } -func (s *ServerService) RestartXrayService() (string error) { +func (s *ServerService) RestartXrayService() error { s.xrayService.StopXray() - defer func() { - err := s.xrayService.RestartXray(true) - if err != nil { - logger.Error("start xray failed:", err) - } - }() - + err := s.xrayService.RestartXray(true) + if err != nil { + logger.Error("start xray failed:", err) + return err + } return nil } @@ -507,35 +504,43 @@ func (s *ServerService) ImportDB(file multipart.File) error { return common.NewErrorf("Error resetting file reader: %v", err) } - // Save the file as temporary file + // Save the file as a temporary file tempPath := fmt.Sprintf("%s.temp", config.GetDBPath()) - // Remove the existing fallback file (if any) before creating one - _, err = os.Stat(tempPath) - if err == nil { - errRemove := os.Remove(tempPath) - if errRemove != nil { + + // Remove the existing temporary file (if any) + if _, err := os.Stat(tempPath); err == nil { + if errRemove := os.Remove(tempPath); errRemove != nil { return common.NewErrorf("Error removing existing temporary db file: %v", errRemove) } } + // Create the temporary file tempFile, err := os.Create(tempPath) if err != nil { return common.NewErrorf("Error creating temporary db file: %v", err) } - defer tempFile.Close() - // Remove temp file before returning - defer os.Remove(tempPath) + // Robust deferred cleanup for the temporary file + defer func() { + if tempFile != nil { + if cerr := tempFile.Close(); cerr != nil { + logger.Warningf("Warning: failed to close temp file: %v", cerr) + } + } + if _, err := os.Stat(tempPath); err == nil { + if rerr := os.Remove(tempPath); rerr != nil { + logger.Warningf("Warning: failed to remove temp file: %v", rerr) + } + } + }() // Save uploaded file to temporary file - _, err = io.Copy(tempFile, file) - if err != nil { + if _, err = io.Copy(tempFile, file); err != nil { return common.NewErrorf("Error saving db: %v", err) } - // Check if we can init db or not - err = database.InitDB(tempPath) - if err != nil { + // Check if we can init the db or not + if err = database.InitDB(tempPath); err != nil { return common.NewErrorf("Error checking db: %v", err) } @@ -544,111 +549,113 @@ func (s *ServerService) ImportDB(file multipart.File) error { // Backup the current database for fallback fallbackPath := fmt.Sprintf("%s.backup", config.GetDBPath()) + // Remove the existing fallback file (if any) - _, err = os.Stat(fallbackPath) - if err == nil { - errRemove := os.Remove(fallbackPath) - if errRemove != nil { + if _, err := os.Stat(fallbackPath); err == nil { + if errRemove := os.Remove(fallbackPath); errRemove != nil { return common.NewErrorf("Error removing existing fallback db file: %v", errRemove) } } + // Move the current database to the fallback location - err = os.Rename(config.GetDBPath(), fallbackPath) - if err != nil { - return common.NewErrorf("Error backing up temporary db file: %v", err) + if err = os.Rename(config.GetDBPath(), fallbackPath); err != nil { + return common.NewErrorf("Error backing up current db file: %v", err) } - // Remove the temporary file before returning - defer os.Remove(fallbackPath) + // Defer fallback cleanup ONLY if everything goes well + defer func() { + if _, err := os.Stat(fallbackPath); err == nil { + if rerr := os.Remove(fallbackPath); rerr != nil { + logger.Warningf("Warning: failed to remove fallback file: %v", rerr) + } + } + }() // Move temp to DB path - err = os.Rename(tempPath, config.GetDBPath()) - if err != nil { - errRename := os.Rename(fallbackPath, config.GetDBPath()) - if errRename != nil { + if err = os.Rename(tempPath, config.GetDBPath()); err != nil { + // Restore from fallback + if errRename := os.Rename(fallbackPath, config.GetDBPath()); errRename != nil { return common.NewErrorf("Error moving db file and restoring fallback: %v", errRename) } return common.NewErrorf("Error moving db file: %v", err) } // Migrate DB - err = database.InitDB(config.GetDBPath()) - if err != nil { - errRename := os.Rename(fallbackPath, config.GetDBPath()) - if errRename != nil { + if err = database.InitDB(config.GetDBPath()); err != nil { + if errRename := os.Rename(fallbackPath, config.GetDBPath()); errRename != nil { return common.NewErrorf("Error migrating db and restoring fallback: %v", errRename) } return common.NewErrorf("Error migrating db: %v", err) } + s.inboundService.MigrateDB() // Start Xray - err = s.RestartXrayService() - if err != nil { - return common.NewErrorf("Imported DB but Failed to start Xray: %v", err) + if err = s.RestartXrayService(); err != nil { + return common.NewErrorf("Imported DB but failed to start Xray: %v", err) } return nil } func (s *ServerService) UpdateGeofile(fileName string) error { - files := []struct { - URL string - FileName string - }{ - {"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip.dat"}, - {"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite.dat"}, - {"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat", "geoip_IR.dat"}, - {"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat", "geosite_IR.dat"}, - {"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip_RU.dat"}, - {"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite_RU.dat"}, - } + files := []struct { + URL string + FileName string + }{ + {"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip.dat"}, + {"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite.dat"}, + {"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat", "geoip_IR.dat"}, + {"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat", "geosite_IR.dat"}, + {"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip_RU.dat"}, + {"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite_RU.dat"}, + } - downloadFile := func(url, destPath string) error { - resp, err := http.Get(url) - if err != nil { - return common.NewErrorf("Failed to download Geofile from %s: %v", url, err) - } - defer resp.Body.Close() + downloadFile := func(url, destPath string) error { + resp, err := http.Get(url) + if err != nil { + return common.NewErrorf("Failed to download Geofile from %s: %v", url, err) + } + defer resp.Body.Close() - file, err := os.Create(destPath) - if err != nil { - return common.NewErrorf("Failed to create Geofile %s: %v", destPath, err) - } - defer file.Close() + file, err := os.Create(destPath) + if err != nil { + return common.NewErrorf("Failed to create Geofile %s: %v", destPath, err) + } + defer file.Close() - _, err = io.Copy(file, resp.Body) - if err != nil { - return common.NewErrorf("Failed to save Geofile %s: %v", destPath, err) - } + _, err = io.Copy(file, resp.Body) + if err != nil { + return common.NewErrorf("Failed to save Geofile %s: %v", destPath, err) + } - return nil - } + return nil + } - var fileURL string - for _, file := range files { - if file.FileName == fileName { - fileURL = file.URL - break - } - } + var fileURL string + for _, file := range files { + if file.FileName == fileName { + fileURL = file.URL + break + } + } - if fileURL == "" { - return common.NewErrorf("File '%s' not found in the list of Geofiles", fileName) - } + if fileURL == "" { + return common.NewErrorf("File '%s' not found in the list of Geofiles", fileName) + } - destPath := fmt.Sprintf("%s/%s", config.GetBinFolderPath(), fileName) + destPath := fmt.Sprintf("%s/%s", config.GetBinFolderPath(), fileName) - if err := downloadFile(fileURL, destPath); err != nil { - return common.NewErrorf("Error downloading Geofile '%s': %v", fileName, err) - } + if err := downloadFile(fileURL, destPath); err != nil { + return common.NewErrorf("Error downloading Geofile '%s': %v", fileName, err) + } - err := s.RestartXrayService() - if err != nil { - return common.NewErrorf("Updated Geofile '%s' but Failed to start Xray: %v", fileName, err) - } + err := s.RestartXrayService() + if err != nil { + return common.NewErrorf("Updated Geofile '%s' but Failed to start Xray: %v", fileName, err) + } - return nil + return nil } func (s *ServerService) GetNewX25519Cert() (any, error) {