|
@@ -302,25 +302,22 @@ func (s *ServerService) GetXrayVersions() ([]string, error) {
|
|
return versions, nil
|
|
return versions, nil
|
|
}
|
|
}
|
|
|
|
|
|
-func (s *ServerService) StopXrayService() (string error) {
|
|
|
|
|
|
+func (s *ServerService) StopXrayService() error {
|
|
err := s.xrayService.StopXray()
|
|
err := s.xrayService.StopXray()
|
|
if err != nil {
|
|
if err != nil {
|
|
logger.Error("stop xray failed:", err)
|
|
logger.Error("stop xray failed:", err)
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
-
|
|
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-func (s *ServerService) RestartXrayService() (string error) {
|
|
|
|
|
|
+func (s *ServerService) RestartXrayService() error {
|
|
s.xrayService.StopXray()
|
|
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
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
@@ -507,35 +504,43 @@ func (s *ServerService) ImportDB(file multipart.File) error {
|
|
return common.NewErrorf("Error resetting file reader: %v", err)
|
|
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())
|
|
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)
|
|
return common.NewErrorf("Error removing existing temporary db file: %v", errRemove)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
// Create the temporary file
|
|
// Create the temporary file
|
|
tempFile, err := os.Create(tempPath)
|
|
tempFile, err := os.Create(tempPath)
|
|
if err != nil {
|
|
if err != nil {
|
|
return common.NewErrorf("Error creating temporary db file: %v", err)
|
|
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
|
|
// 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)
|
|
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)
|
|
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
|
|
// Backup the current database for fallback
|
|
fallbackPath := fmt.Sprintf("%s.backup", config.GetDBPath())
|
|
fallbackPath := fmt.Sprintf("%s.backup", config.GetDBPath())
|
|
|
|
+
|
|
// Remove the existing fallback file (if any)
|
|
// 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)
|
|
return common.NewErrorf("Error removing existing fallback db file: %v", errRemove)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
// Move the current database to the fallback location
|
|
// 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
|
|
// 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 and restoring fallback: %v", errRename)
|
|
}
|
|
}
|
|
return common.NewErrorf("Error moving db file: %v", err)
|
|
return common.NewErrorf("Error moving db file: %v", err)
|
|
}
|
|
}
|
|
|
|
|
|
// Migrate DB
|
|
// 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 and restoring fallback: %v", errRename)
|
|
}
|
|
}
|
|
return common.NewErrorf("Error migrating db: %v", err)
|
|
return common.NewErrorf("Error migrating db: %v", err)
|
|
}
|
|
}
|
|
|
|
+
|
|
s.inboundService.MigrateDB()
|
|
s.inboundService.MigrateDB()
|
|
|
|
|
|
// Start Xray
|
|
// 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
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
func (s *ServerService) UpdateGeofile(fileName string) error {
|
|
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"},
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- 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()
|
|
|
|
-
|
|
|
|
- _, err = io.Copy(file, resp.Body)
|
|
|
|
- if err != nil {
|
|
|
|
- return common.NewErrorf("Failed to save Geofile %s: %v", destPath, err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return nil
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- 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)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- 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)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- err := s.RestartXrayService()
|
|
|
|
- if err != nil {
|
|
|
|
- return common.NewErrorf("Updated Geofile '%s' but Failed to start Xray: %v", fileName, err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return nil
|
|
|
|
|
|
+ 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()
|
|
|
|
+
|
|
|
|
+ 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)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ err := s.RestartXrayService()
|
|
|
|
+ if err != nil {
|
|
|
|
+ return common.NewErrorf("Updated Geofile '%s' but Failed to start Xray: %v", fileName, err)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return nil
|
|
}
|
|
}
|
|
|
|
|
|
func (s *ServerService) GetNewX25519Cert() (any, error) {
|
|
func (s *ServerService) GetNewX25519Cert() (any, error) {
|