Xboard config fetched...
This commit is contained in:
@@ -104,6 +104,7 @@ type XNodeConfig struct {
|
|||||||
ServerName string `json:"server_name,omitempty"`
|
ServerName string `json:"server_name,omitempty"`
|
||||||
ServerPortText string `json:"server_port_text,omitempty"`
|
ServerPortText string `json:"server_port_text,omitempty"`
|
||||||
Network string `json:"network"`
|
Network string `json:"network"`
|
||||||
|
Multiplex *XMultiplexConfig `json:"multiplex,omitempty"`
|
||||||
NetworkSettings json.RawMessage `json:"network_settings"`
|
NetworkSettings json.RawMessage `json:"network_settings"`
|
||||||
NetworkSettings_ json.RawMessage `json:"networkSettings"`
|
NetworkSettings_ json.RawMessage `json:"networkSettings"`
|
||||||
|
|
||||||
@@ -159,6 +160,7 @@ type XInnerConfig struct {
|
|||||||
Dest string `json:"dest,omitempty"`
|
Dest string `json:"dest,omitempty"`
|
||||||
ServerName string `json:"server_name,omitempty"`
|
ServerName string `json:"server_name,omitempty"`
|
||||||
Network string `json:"network"`
|
Network string `json:"network"`
|
||||||
|
Multiplex *XMultiplexConfig `json:"multiplex,omitempty"`
|
||||||
NetworkSettings json.RawMessage `json:"network_settings"`
|
NetworkSettings json.RawMessage `json:"network_settings"`
|
||||||
NetworkSettings_ json.RawMessage `json:"networkSettings"`
|
NetworkSettings_ json.RawMessage `json:"networkSettings"`
|
||||||
StreamSettings json.RawMessage `json:"streamSettings"`
|
StreamSettings json.RawMessage `json:"streamSettings"`
|
||||||
@@ -166,6 +168,22 @@ type XInnerConfig struct {
|
|||||||
DownMbps int `json:"down_mbps"`
|
DownMbps int `json:"down_mbps"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type XMultiplexConfig struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
Protocol string `json:"protocol,omitempty"`
|
||||||
|
MaxConnections int `json:"max_connections,omitempty"`
|
||||||
|
MinStreams int `json:"min_streams,omitempty"`
|
||||||
|
MaxStreams int `json:"max_streams,omitempty"`
|
||||||
|
Padding bool `json:"padding,omitempty"`
|
||||||
|
Brutal *XBrutalConfig `json:"brutal,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type XBrutalConfig struct {
|
||||||
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
|
UpMbps int `json:"up_mbps,omitempty"`
|
||||||
|
DownMbps int `json:"down_mbps,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type HttpNetworkConfig struct {
|
type HttpNetworkConfig struct {
|
||||||
Header struct {
|
Header struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
@@ -403,6 +421,25 @@ func mergedTLSSettings(inner XInnerConfig, config *XNodeConfig) *XTLSSettings {
|
|||||||
return tlsSettings
|
return tlsSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildInboundMultiplex(config *XMultiplexConfig) *option.InboundMultiplexOptions {
|
||||||
|
if config == nil || !config.Enabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var brutal *option.BrutalOptions
|
||||||
|
if config.Brutal != nil {
|
||||||
|
brutal = &option.BrutalOptions{
|
||||||
|
Enabled: config.Brutal.Enabled,
|
||||||
|
UpMbps: config.Brutal.UpMbps,
|
||||||
|
DownMbps: config.Brutal.DownMbps,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &option.InboundMultiplexOptions{
|
||||||
|
Enabled: config.Enabled,
|
||||||
|
Padding: config.Padding,
|
||||||
|
Brutal: brutal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) Start(stage adapter.StartStage) error {
|
func (s *Service) Start(stage adapter.StartStage) error {
|
||||||
if stage != adapter.StartStateStart {
|
if stage != adapter.StartStateStart {
|
||||||
return nil
|
return nil
|
||||||
@@ -556,14 +593,22 @@ func (s *Service) setupNode() error {
|
|||||||
if inner.Protocol == "" {
|
if inner.Protocol == "" {
|
||||||
inner.Protocol = config.NodeType
|
inner.Protocol = config.NodeType
|
||||||
}
|
}
|
||||||
|
portSource := ""
|
||||||
if inner.Port == 0 {
|
if inner.Port == 0 {
|
||||||
if inner.ServerPort != 0 {
|
if inner.ServerPort != 0 {
|
||||||
inner.Port = inner.ServerPort
|
inner.Port = inner.ServerPort
|
||||||
|
portSource = "inner.server_port"
|
||||||
} else if config.Port != 0 {
|
} else if config.Port != 0 {
|
||||||
inner.Port = config.Port
|
inner.Port = config.Port
|
||||||
|
portSource = "config.port"
|
||||||
} else {
|
} else {
|
||||||
inner.Port = config.ServerPort
|
inner.Port = config.ServerPort
|
||||||
|
if config.ServerPort != 0 {
|
||||||
|
portSource = "config.server_port"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
portSource = "inner.port"
|
||||||
}
|
}
|
||||||
if inner.Cipher == "" {
|
if inner.Cipher == "" {
|
||||||
inner.Cipher = config.Cipher
|
inner.Cipher = config.Cipher
|
||||||
@@ -574,6 +619,9 @@ func (s *Service) setupNode() error {
|
|||||||
if inner.Network == "" {
|
if inner.Network == "" {
|
||||||
inner.Network = config.Network
|
inner.Network = config.Network
|
||||||
}
|
}
|
||||||
|
if inner.Multiplex == nil {
|
||||||
|
inner.Multiplex = config.Multiplex
|
||||||
|
}
|
||||||
if len(inner.NetworkSettings) == 0 {
|
if len(inner.NetworkSettings) == 0 {
|
||||||
inner.NetworkSettings = config.NetworkSettings
|
inner.NetworkSettings = config.NetworkSettings
|
||||||
}
|
}
|
||||||
@@ -714,6 +762,20 @@ func (s *Service) setupNode() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Build inbound per protocol (matching V2bX core/sing/node.go) ──
|
// ── Build inbound per protocol (matching V2bX core/sing/node.go) ──
|
||||||
|
multiplex := buildInboundMultiplex(inner.Multiplex)
|
||||||
|
s.logger.Info(
|
||||||
|
"Xboard node config resolved. protocol=", protocol,
|
||||||
|
", listen_ip=", inner.ListenIP,
|
||||||
|
", listen_port=", inner.Port,
|
||||||
|
" (source=", portSource, ")",
|
||||||
|
", inner_server_port=", inner.ServerPort,
|
||||||
|
", config_port=", config.Port,
|
||||||
|
", config_server_port=", config.ServerPort,
|
||||||
|
", network=", networkType,
|
||||||
|
", tls=", securityType,
|
||||||
|
", multiplex=", multiplex != nil,
|
||||||
|
)
|
||||||
|
|
||||||
var inboundOptions any
|
var inboundOptions any
|
||||||
switch protocol {
|
switch protocol {
|
||||||
case "vmess", "vless":
|
case "vmess", "vless":
|
||||||
@@ -729,6 +791,7 @@ func (s *Service) setupNode() error {
|
|||||||
InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{
|
InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{
|
||||||
TLS: &tlsOptions,
|
TLS: &tlsOptions,
|
||||||
},
|
},
|
||||||
|
Multiplex: multiplex,
|
||||||
}
|
}
|
||||||
if transport != nil {
|
if transport != nil {
|
||||||
opts.Transport = transport
|
opts.Transport = transport
|
||||||
@@ -740,6 +803,7 @@ func (s *Service) setupNode() error {
|
|||||||
InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{
|
InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{
|
||||||
TLS: &tlsOptions,
|
TLS: &tlsOptions,
|
||||||
},
|
},
|
||||||
|
Multiplex: multiplex,
|
||||||
}
|
}
|
||||||
if transport != nil {
|
if transport != nil {
|
||||||
opts.Transport = transport
|
opts.Transport = transport
|
||||||
@@ -765,6 +829,7 @@ func (s *Service) setupNode() error {
|
|||||||
ssOptions := &option.ShadowsocksInboundOptions{
|
ssOptions := &option.ShadowsocksInboundOptions{
|
||||||
ListenOptions: listen,
|
ListenOptions: listen,
|
||||||
Method: method,
|
Method: method,
|
||||||
|
Multiplex: multiplex,
|
||||||
}
|
}
|
||||||
|
|
||||||
isSS2022 := strings.Contains(method, "2022")
|
isSS2022 := strings.Contains(method, "2022")
|
||||||
@@ -805,6 +870,7 @@ func (s *Service) setupNode() error {
|
|||||||
InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{
|
InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{
|
||||||
TLS: &tlsOptions,
|
TLS: &tlsOptions,
|
||||||
},
|
},
|
||||||
|
Multiplex: multiplex,
|
||||||
}
|
}
|
||||||
if transport != nil {
|
if transport != nil {
|
||||||
opts.Transport = transport
|
opts.Transport = transport
|
||||||
@@ -902,6 +968,7 @@ func (s *Service) setupNode() error {
|
|||||||
|
|
||||||
// Remove old if exists
|
// Remove old if exists
|
||||||
s.inboundManager.Remove(inboundTag)
|
s.inboundManager.Remove(inboundTag)
|
||||||
|
s.logger.Info("Xboard creating inbound [", inboundTag, "] on ", inner.ListenIP, ":", inner.Port, " (protocol: ", protocol, ")")
|
||||||
|
|
||||||
// Create new inbound
|
// Create new inbound
|
||||||
err = s.inboundManager.Create(s.ctx, s.router, s.logger, inboundTag, protocol, inboundOptions)
|
err = s.inboundManager.Create(s.ctx, s.router, s.logger, inboundTag, protocol, inboundOptions)
|
||||||
@@ -983,6 +1050,12 @@ func (s *Service) fetchConfig() (*XNodeConfig, error) {
|
|||||||
// Try unmarshaling WITHOUT "data" wrapper
|
// Try unmarshaling WITHOUT "data" wrapper
|
||||||
var flatResult XNodeConfig
|
var flatResult XNodeConfig
|
||||||
if err2 := json.Unmarshal(body, &flatResult); err2 == nil {
|
if err2 := json.Unmarshal(body, &flatResult); err2 == nil {
|
||||||
|
s.logger.Info(
|
||||||
|
"Xboard config fetched (flat). protocol=", flatResult.Protocol,
|
||||||
|
", node_type=", flatResult.NodeType,
|
||||||
|
", port=", flatResult.Port,
|
||||||
|
", server_port=", flatResult.ServerPort,
|
||||||
|
)
|
||||||
return &flatResult, nil
|
return &flatResult, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -995,6 +1068,12 @@ func (s *Service) fetchConfig() (*XNodeConfig, error) {
|
|||||||
if result.Data.Protocol == "" && len(result.Data.ServerConfig) == 0 && len(result.Data.Config) == 0 && result.Data.NodeType == "" && result.Data.ServerPort == 0 {
|
if result.Data.Protocol == "" && len(result.Data.ServerConfig) == 0 && len(result.Data.Config) == 0 && result.Data.NodeType == "" && result.Data.ServerPort == 0 {
|
||||||
s.logger.Error("Xboard config mapping failed (fields missing). Data: ", string(body))
|
s.logger.Error("Xboard config mapping failed (fields missing). Data: ", string(body))
|
||||||
}
|
}
|
||||||
|
s.logger.Info(
|
||||||
|
"Xboard config fetched. protocol=", result.Data.Protocol,
|
||||||
|
", node_type=", result.Data.NodeType,
|
||||||
|
", port=", result.Data.Port,
|
||||||
|
", server_port=", result.Data.ServerPort,
|
||||||
|
)
|
||||||
|
|
||||||
return &result.Data, nil
|
return &result.Data, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,3 +93,26 @@ func TestExpandNodeOptions(t *testing.T) {
|
|||||||
t.Fatalf("second node = %+v", nodes[1])
|
t.Fatalf("second node = %+v", nodes[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuildInboundMultiplex(t *testing.T) {
|
||||||
|
config := &XMultiplexConfig{
|
||||||
|
Enabled: true,
|
||||||
|
Padding: true,
|
||||||
|
Brutal: &XBrutalConfig{
|
||||||
|
Enabled: true,
|
||||||
|
UpMbps: 100,
|
||||||
|
DownMbps: 200,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
got := buildInboundMultiplex(config)
|
||||||
|
if got == nil {
|
||||||
|
t.Fatal("buildInboundMultiplex() returned nil")
|
||||||
|
}
|
||||||
|
if !got.Enabled || !got.Padding {
|
||||||
|
t.Fatalf("buildInboundMultiplex() = %+v", got)
|
||||||
|
}
|
||||||
|
if got.Brutal == nil || !got.Brutal.Enabled || got.Brutal.UpMbps != 100 || got.Brutal.DownMbps != 200 {
|
||||||
|
t.Fatalf("buildInboundMultiplex() brutal = %+v", got.Brutal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user