xray.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. package service
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "sync"
  6. "x-ui/logger"
  7. "x-ui/xray"
  8. "go.uber.org/atomic"
  9. )
  10. var (
  11. p *xray.Process
  12. lock sync.Mutex
  13. isNeedXrayRestart atomic.Bool
  14. result string
  15. )
  16. type XrayService struct {
  17. inboundService InboundService
  18. settingService SettingService
  19. xrayAPI xray.XrayAPI
  20. }
  21. func (s *XrayService) IsXrayRunning() bool {
  22. return p != nil && p.IsRunning()
  23. }
  24. func (s *XrayService) GetXrayErr() error {
  25. if p == nil {
  26. return nil
  27. }
  28. return p.GetErr()
  29. }
  30. func (s *XrayService) GetXrayResult() string {
  31. if result != "" {
  32. return result
  33. }
  34. if s.IsXrayRunning() {
  35. return ""
  36. }
  37. if p == nil {
  38. return ""
  39. }
  40. result = p.GetResult()
  41. return result
  42. }
  43. func (s *XrayService) GetXrayVersion() string {
  44. if p == nil {
  45. return "Unknown"
  46. }
  47. return p.GetVersion()
  48. }
  49. func RemoveIndex(s []interface{}, index int) []interface{} {
  50. return append(s[:index], s[index+1:]...)
  51. }
  52. func (s *XrayService) GetXrayConfig() (*xray.Config, error) {
  53. templateConfig, err := s.settingService.GetXrayConfigTemplate()
  54. if err != nil {
  55. return nil, err
  56. }
  57. xrayConfig := &xray.Config{}
  58. err = json.Unmarshal([]byte(templateConfig), xrayConfig)
  59. if err != nil {
  60. return nil, err
  61. }
  62. s.inboundService.AddTraffic(nil, nil)
  63. inbounds, err := s.inboundService.GetAllInbounds()
  64. if err != nil {
  65. return nil, err
  66. }
  67. for _, inbound := range inbounds {
  68. if !inbound.Enable {
  69. continue
  70. }
  71. // get settings clients
  72. settings := map[string]interface{}{}
  73. json.Unmarshal([]byte(inbound.Settings), &settings)
  74. clients, ok := settings["clients"].([]interface{})
  75. if ok {
  76. // check users active or not
  77. clientStats := inbound.ClientStats
  78. for _, clientTraffic := range clientStats {
  79. indexDecrease := 0
  80. for index, client := range clients {
  81. c := client.(map[string]interface{})
  82. if c["email"] == clientTraffic.Email {
  83. if !clientTraffic.Enable {
  84. clients = RemoveIndex(clients, index-indexDecrease)
  85. indexDecrease++
  86. logger.Infof("Remove Inbound User %s due to expiration or traffic limit", c["email"])
  87. }
  88. }
  89. }
  90. }
  91. // clear client config for additional parameters
  92. var final_clients []interface{}
  93. for _, client := range clients {
  94. c := client.(map[string]interface{})
  95. if c["enable"] != nil {
  96. if enable, ok := c["enable"].(bool); ok && !enable {
  97. continue
  98. }
  99. }
  100. for key := range c {
  101. if key != "email" && key != "id" && key != "password" && key != "flow" && key != "method" {
  102. delete(c, key)
  103. }
  104. if c["flow"] == "xtls-rprx-vision-udp443" {
  105. c["flow"] = "xtls-rprx-vision"
  106. }
  107. }
  108. final_clients = append(final_clients, interface{}(c))
  109. }
  110. settings["clients"] = final_clients
  111. modifiedSettings, err := json.MarshalIndent(settings, "", " ")
  112. if err != nil {
  113. return nil, err
  114. }
  115. inbound.Settings = string(modifiedSettings)
  116. }
  117. if len(inbound.StreamSettings) > 0 {
  118. // Unmarshal stream JSON
  119. var stream map[string]interface{}
  120. json.Unmarshal([]byte(inbound.StreamSettings), &stream)
  121. // Remove the "settings" field under "tlsSettings" and "realitySettings"
  122. tlsSettings, ok1 := stream["tlsSettings"].(map[string]interface{})
  123. realitySettings, ok2 := stream["realitySettings"].(map[string]interface{})
  124. if ok1 || ok2 {
  125. if ok1 {
  126. delete(tlsSettings, "settings")
  127. } else if ok2 {
  128. delete(realitySettings, "settings")
  129. }
  130. }
  131. delete(stream, "externalProxy")
  132. newStream, err := json.MarshalIndent(stream, "", " ")
  133. if err != nil {
  134. return nil, err
  135. }
  136. inbound.StreamSettings = string(newStream)
  137. }
  138. inboundConfig := inbound.GenXrayInboundConfig()
  139. xrayConfig.InboundConfigs = append(xrayConfig.InboundConfigs, *inboundConfig)
  140. }
  141. return xrayConfig, nil
  142. }
  143. func (s *XrayService) GetXrayTraffic() ([]*xray.Traffic, []*xray.ClientTraffic, error) {
  144. if !s.IsXrayRunning() {
  145. err := errors.New("xray is not running")
  146. logger.Debug("Attempted to fetch Xray traffic, but Xray is not running:", err)
  147. return nil, nil, err
  148. }
  149. apiPort := p.GetAPIPort()
  150. s.xrayAPI.Init(apiPort)
  151. defer s.xrayAPI.Close()
  152. traffic, clientTraffic, err := s.xrayAPI.GetTraffic(true)
  153. if err != nil {
  154. logger.Debug("Failed to fetch Xray traffic:", err)
  155. return nil, nil, err
  156. }
  157. return traffic, clientTraffic, nil
  158. }
  159. func (s *XrayService) RestartXray(isForce bool) error {
  160. lock.Lock()
  161. defer lock.Unlock()
  162. logger.Debug("restart xray, force:", isForce)
  163. xrayConfig, err := s.GetXrayConfig()
  164. if err != nil {
  165. return err
  166. }
  167. if s.IsXrayRunning() {
  168. if !isForce && p.GetConfig().Equals(xrayConfig) {
  169. logger.Debug("It does not need to restart xray")
  170. return nil
  171. }
  172. p.Stop()
  173. }
  174. p = xray.NewProcess(xrayConfig)
  175. result = ""
  176. err = p.Start()
  177. if err != nil {
  178. return err
  179. }
  180. return nil
  181. }
  182. func (s *XrayService) StopXray() error {
  183. lock.Lock()
  184. defer lock.Unlock()
  185. logger.Debug("Attempting to stop Xray...")
  186. if s.IsXrayRunning() {
  187. return p.Stop()
  188. }
  189. return errors.New("xray is not running")
  190. }
  191. func (s *XrayService) SetToNeedRestart() {
  192. isNeedXrayRestart.Store(true)
  193. }
  194. func (s *XrayService) IsNeedRestartAndSetFalse() bool {
  195. return isNeedXrayRestart.CompareAndSwap(true, false)
  196. }