3x-ui/web/service/xray.go

217 lines
4.7 KiB
Go
Raw Normal View History

2023-02-09 22:18:06 +03:00
package service
import (
"encoding/json"
"errors"
"sync"
"x-ui/logger"
"x-ui/xray"
2023-02-18 15:37:32 +03:00
2023-02-09 22:18:06 +03:00
"go.uber.org/atomic"
)
var p *xray.Process
var lock sync.Mutex
var isNeedXrayRestart atomic.Bool
var result string
type XrayService struct {
inboundService InboundService
settingService SettingService
xrayAPI xray.XrayAPI
2023-02-09 22:18:06 +03:00
}
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()
}
2023-02-18 15:37:32 +03:00
2023-02-09 22:18:06 +03:00
func RemoveIndex(s []interface{}, index int) []interface{} {
return append(s[:index], s[index+1:]...)
}
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
}
s.inboundService.AddTraffic(nil, nil)
2023-02-09 22:18:06 +03:00
inbounds, err := s.inboundService.GetAllInbounds()
if err != nil {
return nil, err
}
for _, inbound := range inbounds {
if !inbound.Enable {
continue
}
// get settings clients
settings := map[string]interface{}{}
json.Unmarshal([]byte(inbound.Settings), &settings)
2023-02-18 15:37:32 +03:00
clients, ok := settings["clients"].([]interface{})
2023-02-09 22:18:06 +03:00
if ok {
// check users active or not
clientStats := inbound.ClientStats
for _, clientTraffic := range clientStats {
2023-02-18 15:37:32 +03:00
indexDecrease := 0
2023-02-09 22:18:06 +03:00
for index, client := range clients {
c := client.(map[string]interface{})
if c["email"] == clientTraffic.Email {
2023-02-18 15:37:32 +03:00
if !clientTraffic.Enable {
clients = RemoveIndex(clients, index-indexDecrease)
indexDecrease++
2023-02-18 15:37:32 +03:00
logger.Info("Remove Inbound User", c["email"], "due the expire or traffic limit")
2023-02-09 22:18:06 +03:00
}
}
}
}
// clear client config for additional parameters
var final_clients []interface{}
for _, client := range clients {
c := client.(map[string]interface{})
if c["enable"] != nil {
if enable, ok := c["enable"].(bool); ok && !enable {
continue
}
}
for key := range c {
if key != "email" && key != "id" && key != "password" && key != "flow" && key != "method" {
delete(c, key)
}
if c["flow"] == "xtls-rprx-vision-udp443" {
c["flow"] = "xtls-rprx-vision"
}
}
final_clients = append(final_clients, interface{}(c))
}
settings["clients"] = final_clients
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
2023-02-09 22:18:06 +03:00
if err != nil {
return nil, err
}
2023-02-18 15:37:32 +03:00
2023-02-09 22:18:06 +03:00
inbound.Settings = string(modifiedSettings)
}
// Unmarshal stream JSON
var stream map[string]interface{}
json.Unmarshal([]byte(inbound.StreamSettings), &stream)
// Remove the "settings" field under "tlsSettings" and "realitySettings"
tlsSettings, ok1 := stream["tlsSettings"].(map[string]interface{})
realitySettings, ok2 := stream["realitySettings"].(map[string]interface{})
if ok1 || ok2 {
if ok1 {
delete(tlsSettings, "settings")
} else if ok2 {
delete(realitySettings, "settings")
}
newStream, err := json.MarshalIndent(stream, "", " ")
if err != nil {
return nil, err
}
inbound.StreamSettings = string(newStream)
}
2023-02-09 22:18:06 +03:00
inboundConfig := inbound.GenXrayInboundConfig()
xrayConfig.InboundConfigs = append(xrayConfig.InboundConfigs, *inboundConfig)
}
return xrayConfig, nil
}
func (s *XrayService) GetXrayTraffic() ([]*xray.Traffic, []*xray.ClientTraffic, error) {
if !s.IsXrayRunning() {
return nil, nil, errors.New("xray is not running")
}
s.xrayAPI.Init(p.GetAPIPort())
defer s.xrayAPI.Close()
return s.xrayAPI.GetTraffic(true)
2023-02-09 22:18:06 +03:00
}
func (s *XrayService) RestartXray(isForce bool) error {
lock.Lock()
defer lock.Unlock()
logger.Debug("restart xray, force:", isForce)
xrayConfig, err := s.GetXrayConfig()
if err != nil {
return err
}
if p != nil && p.IsRunning() {
if !isForce && p.GetConfig().Equals(xrayConfig) {
logger.Debug("It does not need to restart xray")
2023-02-09 22:18:06 +03:00
return nil
}
p.Stop()
}
p = xray.NewProcess(xrayConfig)
result = ""
err = p.Start()
if err != nil {
return err
}
return nil
2023-02-09 22:18:06 +03:00
}
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 {
2023-03-17 19:07:49 +03:00
return isNeedXrayRestart.CompareAndSwap(true, false)
2023-02-09 22:18:06 +03:00
}