mirror of
https://github.com/alireza0/x-ui.git
synced 2026-03-20 15:55:48 +00:00
Bug fix, can't connect after change transmission type from tcp to other types If flow is not equal to "" in transmit except tcp, connection will not be made. This problem occurs when we change the transmission from tcp to another type. Also, if tcp itself is alone and without tls and reality, flow must be empty in it.
206 lines
4.4 KiB
Go
206 lines
4.4 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"sync"
|
|
"x-ui/logger"
|
|
"x-ui/xray"
|
|
|
|
"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
|
|
}
|
|
|
|
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 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.DisableInvalidClients()
|
|
|
|
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)
|
|
clients, ok := settings["clients"].([]interface{})
|
|
if ok {
|
|
// check users active or not
|
|
clientStats := inbound.ClientStats
|
|
for _, clientTraffic := range clientStats {
|
|
|
|
indexDecrease := 0
|
|
for index, client := range clients {
|
|
c := client.(map[string]interface{})
|
|
if c["email"] == clientTraffic.Email {
|
|
if !clientTraffic.Enable {
|
|
clients = RemoveIndex(clients, index-indexDecrease)
|
|
indexDecrease++
|
|
logger.Info("Remove Inbound User", c["email"], "due the expire or traffic limit")
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// clear client config for additional parameters
|
|
var final_clients []interface{}
|
|
|
|
// detect inbound transmission type
|
|
var stream map[string]interface{}
|
|
json.Unmarshal([]byte(inbound.StreamSettings), &stream)
|
|
network, _ := stream["network"].(string)
|
|
security, _ := stream["security"].(string)
|
|
|
|
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" {
|
|
delete(c, key)
|
|
}
|
|
if c["flow"] == "xtls-rprx-vision-udp443" {
|
|
c["flow"] = "xtls-rprx-vision"
|
|
}
|
|
if network != "tcp" || !(security == "tls" || security == "reality") {
|
|
c["flow"] = ""
|
|
}
|
|
}
|
|
final_clients = append(final_clients, interface{}(c))
|
|
}
|
|
|
|
settings["clients"] = final_clients
|
|
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
inbound.Settings = string(modifiedSettings)
|
|
}
|
|
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)
|
|
}
|
|
|
|
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")
|
|
return nil
|
|
}
|
|
p.Stop()
|
|
}
|
|
|
|
p = xray.NewProcess(xrayConfig)
|
|
result = ""
|
|
err = p.Start()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
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.CompareAndSwap(true, false)
|
|
}
|