Xboard config fetched...

This commit is contained in:
CN-JS-HuiBai
2026-04-15 12:16:26 +08:00
parent c570a7c5f2
commit d36e8f5b39
2 changed files with 102 additions and 0 deletions

View File

@@ -104,6 +104,7 @@ type XNodeConfig struct {
ServerName string `json:"server_name,omitempty"`
ServerPortText string `json:"server_port_text,omitempty"`
Network string `json:"network"`
Multiplex *XMultiplexConfig `json:"multiplex,omitempty"`
NetworkSettings json.RawMessage `json:"network_settings"`
NetworkSettings_ json.RawMessage `json:"networkSettings"`
@@ -159,6 +160,7 @@ type XInnerConfig struct {
Dest string `json:"dest,omitempty"`
ServerName string `json:"server_name,omitempty"`
Network string `json:"network"`
Multiplex *XMultiplexConfig `json:"multiplex,omitempty"`
NetworkSettings json.RawMessage `json:"network_settings"`
NetworkSettings_ json.RawMessage `json:"networkSettings"`
StreamSettings json.RawMessage `json:"streamSettings"`
@@ -166,6 +168,22 @@ type XInnerConfig struct {
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 {
Header struct {
Type string `json:"type"`
@@ -403,6 +421,25 @@ func mergedTLSSettings(inner XInnerConfig, config *XNodeConfig) *XTLSSettings {
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 {
if stage != adapter.StartStateStart {
return nil
@@ -556,15 +593,23 @@ func (s *Service) setupNode() error {
if inner.Protocol == "" {
inner.Protocol = config.NodeType
}
portSource := ""
if inner.Port == 0 {
if inner.ServerPort != 0 {
inner.Port = inner.ServerPort
portSource = "inner.server_port"
} else if config.Port != 0 {
inner.Port = config.Port
portSource = "config.port"
} else {
inner.Port = config.ServerPort
if config.ServerPort != 0 {
portSource = "config.server_port"
}
}
} else {
portSource = "inner.port"
}
if inner.Cipher == "" {
inner.Cipher = config.Cipher
}
@@ -574,6 +619,9 @@ func (s *Service) setupNode() error {
if inner.Network == "" {
inner.Network = config.Network
}
if inner.Multiplex == nil {
inner.Multiplex = config.Multiplex
}
if len(inner.NetworkSettings) == 0 {
inner.NetworkSettings = config.NetworkSettings
}
@@ -714,6 +762,20 @@ func (s *Service) setupNode() error {
}
// ── 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
switch protocol {
case "vmess", "vless":
@@ -729,6 +791,7 @@ func (s *Service) setupNode() error {
InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{
TLS: &tlsOptions,
},
Multiplex: multiplex,
}
if transport != nil {
opts.Transport = transport
@@ -740,6 +803,7 @@ func (s *Service) setupNode() error {
InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{
TLS: &tlsOptions,
},
Multiplex: multiplex,
}
if transport != nil {
opts.Transport = transport
@@ -765,6 +829,7 @@ func (s *Service) setupNode() error {
ssOptions := &option.ShadowsocksInboundOptions{
ListenOptions: listen,
Method: method,
Multiplex: multiplex,
}
isSS2022 := strings.Contains(method, "2022")
@@ -805,6 +870,7 @@ func (s *Service) setupNode() error {
InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{
TLS: &tlsOptions,
},
Multiplex: multiplex,
}
if transport != nil {
opts.Transport = transport
@@ -902,6 +968,7 @@ func (s *Service) setupNode() error {
// Remove old if exists
s.inboundManager.Remove(inboundTag)
s.logger.Info("Xboard creating inbound [", inboundTag, "] on ", inner.ListenIP, ":", inner.Port, " (protocol: ", protocol, ")")
// Create new inbound
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
var flatResult XNodeConfig
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
}
@@ -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 {
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
}

View File

@@ -93,3 +93,26 @@ func TestExpandNodeOptions(t *testing.T) {
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)
}
}