package service import ( "encoding/json" "errors" "go.uber.org/atomic" "sync" "x-ui/logger" "x-ui/xray" ) var p *xray.Process var lock sync.Mutex var isNeedXrayRestart atomic.Bool var result string type XrayService struct { inboundService InboundService settingService SettingService } func (s *XrayService) IsXrayRunning() bool { return p != nil && p.IsRunning() } func (s *XrayService) GetXrayErr() error { if p == nil { return nil } return p.GetErr() } func (s *XrayService) GetXrayResult() string { if result != "" { return result } if s.IsXrayRunning() { return "" } if p == nil { return "" } result = p.GetResult() return result } func (s *XrayService) GetXrayVersion() string { if p == nil { return "Unknown" } return p.GetVersion() } func (s *XrayService) GetXrayConfig() (*xray.Config, error) { templateConfig, err := s.settingService.GetXrayConfigTemplate() if err != nil { return nil, err } xrayConfig := &xray.Config{} err = json.Unmarshal([]byte(templateConfig), xrayConfig) if err != nil { return nil, err } inbounds, err := s.inboundService.GetAllInbounds() if err != nil { return nil, err } for _, inbound := range inbounds { if !inbound.Enable { continue } inboundConfig := inbound.GenXrayInboundConfig() xrayConfig.InboundConfigs = append(xrayConfig.InboundConfigs, *inboundConfig) } return xrayConfig, nil } func (s *XrayService) GetXrayTraffic() ([]*xray.Traffic, error) { if !s.IsXrayRunning() { return nil, errors.New("xray is not running") } return p.GetTraffic(true) } func (s *XrayService) RestartXray() error { lock.Lock() defer lock.Unlock() logger.Debug("restart xray") xrayConfig, err := s.GetXrayConfig() if err != nil { return err } if p != nil { if p.GetConfig().Equals(xrayConfig) { return nil } p.Stop() } p = xray.NewProcess(xrayConfig) result = "" return p.Start() } func (s *XrayService) StopXray() error { lock.Lock() defer lock.Unlock() logger.Debug("stop xray") if s.IsXrayRunning() { return p.Stop() } return errors.New("xray is not running") } func (s *XrayService) SetToNeedRestart() { isNeedXrayRestart.Store(true) } func (s *XrayService) IsNeedRestartAndSetFalse() bool { return isNeedXrayRestart.CAS(true, false) }