Feature: Xray ServerName(sni) Support

Refactor Generate Xray config file
This commit is contained in:
ChsBuffer
2021-07-05 20:29:45 +08:00
parent 4836e4c913
commit e3b1ae0621
9 changed files with 268 additions and 487 deletions

View File

@@ -1,57 +1,21 @@
#nullable disable
using System.Collections.Generic;
// ReSharper disable InconsistentNaming
namespace Netch.Servers.Models
namespace Netch.Servers.V2ray.Models
{
public class V2rayConfig
public struct V2rayConfig
{
public List<Inbounds> inbounds { get; } = new();
public object[] inbounds { get; set; }
public List<Outbounds> outbounds { get; } = new();
public Routing routing { get; } = new();
public Outbound[] outbounds { get; set; }
}
public class Inbounds
{
public string tag { get; set; }
public ushort port { get; set; }
public string listen { get; set; }
public string protocol { get; set; }
public Sniffing sniffing { get; set; }
public Inboundsettings settings { get; set; }
public StreamSettings streamSettings { get; set; }
}
public class Inboundsettings
{
public string auth { get; set; }
public bool udp { get; set; }
public string ip { get; set; }
public string address { get; set; }
public List<UsersItem> clients { get; set; }
public string decryption { get; set; }
}
public class UsersItem
public class User
{
public string id { get; set; }
public int alterId { get; set; }
public string email { get; set; }
public string security { get; set; }
public string encryption { get; set; }
@@ -59,33 +23,22 @@ namespace Netch.Servers.Models
public string flow { get; set; }
}
public class Sniffing
public class Outbound
{
public bool enabled { get; set; }
public List<string> destOverride { get; set; }
}
public class Outbounds
{
public string tag { get; set; }
public string protocol { get; set; }
public Outboundsettings settings { get; set; }
public OutboundConfiguration settings { get; set; }
public StreamSettings streamSettings { get; set; }
public Mux mux { get; set; }
}
public class Outboundsettings
public class OutboundConfiguration
{
public List<VnextItem> vnext { get; set; }
public VnextItem[] vnext { get; set; }
public List<ServersItem> servers { get; set; }
public Response response { get; set; }
public object[] servers { get; set; }
}
public class VnextItem
@@ -94,35 +47,7 @@ namespace Netch.Servers.Models
public ushort port { get; set; }
public List<UsersItem> users { get; set; }
}
public class ServersItem
{
public string email { get; set; }
public string address { get; set; }
public string method { get; set; }
public bool ota { get; set; }
public string password { get; set; }
public ushort port { get; set; }
public int level { get; set; }
public List<SocksUsersItem> users { get; set; }
}
public class SocksUsersItem
{
public string user { get; set; }
public string pass { get; set; }
public int level { get; set; }
public User[] users { get; set; }
}
public class Mux
@@ -132,38 +57,6 @@ namespace Netch.Servers.Models
public int concurrency { get; set; }
}
public class Response
{
public string type { get; set; }
}
public class Dns
{
public List<string> servers { get; set; }
}
public class RulesItem
{
public string type { get; set; }
public string port { get; set; }
public List<string> inboundTag { get; set; }
public string outboundTag { get; set; }
public List<string> ip { get; set; }
public List<string> domain { get; set; }
}
public class Routing
{
public string domainStrategy { get; set; }
public List<RulesItem> rules { get; } = new();
}
public class StreamSettings
{
public string network { get; set; }
@@ -187,6 +80,8 @@ namespace Netch.Servers.Models
public GrpcSettings grpcSettings { get; set; }
}
#region Transport
public class TlsSettings
{
public bool allowInsecure { get; set; }
@@ -196,40 +91,14 @@ namespace Netch.Servers.Models
public class TcpSettings
{
public Header header { get; set; }
public object header { get; set; }
}
public class Header
public class WsSettings
{
public string type { get; set; }
public string path { get; set; }
public TCPRequest request { get; set; }
public object response { get; set; }
}
public class TCPRequest
{
public TCPRequestHeaders headers { get; set; }
public string method { get; set; } = "GET";
public string path { get; set; } = "/";
public string version { get; set; } = "1.1";
}
public class TCPRequestHeaders
{
//public string User_Agent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36";
public string Accept_Encoding { get; set; } = "gzip, deflate";
public string Connection { get; set; } = "keep-alive";
public string Host { get; set; }
public string Pragma { get; set; } = "no-cache";
public object headers { get; set; }
}
public class KcpSettings
@@ -248,28 +117,16 @@ namespace Netch.Servers.Models
public int writeBufferSize { get; set; }
public Header header { get; set; }
public object header { get; set; }
public string seed { get; set; }
}
public class WsSettings
{
public string path { get; set; }
public Headers headers { get; set; }
}
public class Headers
{
public string Host { get; set; }
}
public class HttpSettings
{
public string path { get; set; }
public List<string> host { get; set; }
public string[] host { get; set; }
}
public class QuicSettings
@@ -278,7 +135,7 @@ namespace Netch.Servers.Models
public string key { get; set; }
public Header header { get; set; }
public object header { get; set; }
}
public class GrpcSettings
@@ -287,4 +144,6 @@ namespace Netch.Servers.Models
public bool multiMode { get; set; }
}
#endregion
}

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Text.Json;
using Netch.Models;
using Netch.Servers.Models;
using V2rayConfig = Netch.Servers.Models.V2rayConfig;
using Netch.Servers.V2ray.Models;
using Netch.Utils;
using V2rayConfig = Netch.Servers.V2ray.Models.V2rayConfig;
namespace Netch.Servers.Utils
{
@@ -11,342 +11,252 @@ namespace Netch.Servers.Utils
{
public static string GenerateClientConfig(Server server)
{
var v2rayConfig = new V2rayConfig();
inbound(server, ref v2rayConfig);
routing(server, ref v2rayConfig);
var v2rayConfig = new V2rayConfig
{
inbounds = new object[]
{
new
{
port = Global.Settings.Socks5LocalPort,
protocol = "socks",
listen = Global.Settings.LocalAddress,
settings = new
{
udp = true
}
}
}
};
outbound(server, ref v2rayConfig);
return JsonSerializer.Serialize(v2rayConfig, Global.NewDefaultJsonSerializerOptions);
}
private static void inbound(Server server, ref V2rayConfig v2rayConfig)
{
try
{
var inbound = new Inbounds
{
port = Global.Settings.Socks5LocalPort,
protocol = "socks",
listen = Global.Settings.LocalAddress,
settings = new Inboundsettings
{
udp = true
}
};
v2rayConfig.inbounds.Add(inbound);
}
catch
{
// ignored
}
}
private static void routing(Server server, ref V2rayConfig v2rayConfig)
{
try
{
var directRuleObject = new RulesItem
{
type = "field",
ip = new List<string>(),
domain = new List<string>(),
outboundTag = "direct"
};
var blockRuleObject = new RulesItem
{
type = "field",
ip = new List<string>(),
domain = new List<string>(),
outboundTag = "block"
};
static bool CheckRuleItem(ref RulesItem rulesItem)
{
bool ipResult, domainResult;
if (!(ipResult = rulesItem.ip?.Any() ?? false))
rulesItem.ip = null;
if (!(domainResult = rulesItem.domain?.Any() ?? false))
rulesItem.domain = null;
return ipResult || domainResult;
}
if (CheckRuleItem(ref directRuleObject))
v2rayConfig.routing.rules.Add(directRuleObject);
if (CheckRuleItem(ref blockRuleObject))
v2rayConfig.routing.rules.Add(blockRuleObject);
}
catch
{
// ignored
}
}
private static void outbound(Server server, ref V2rayConfig v2rayConfig)
{
try
var outbound = new Outbound
{
var outbound = new Outbounds
settings = new OutboundConfiguration(),
mux = new Mux(),
streamSettings = new StreamSettings
{
settings = new Outboundsettings(),
mux = new Mux(),
streamSettings = new StreamSettings
{
network = "tcp"
}
};
network = "tcp"
}
};
switch (server)
v2rayConfig.outbounds = new[] { outbound };
switch (server)
{
case Socks5 socks5:
{
case Socks5 socks5:
outbound.protocol = "socks";
outbound.settings.servers = new object[]
{
outbound.settings.servers = new List<ServersItem>
new
{
new()
{
users = socks5.Auth()
? new List<SocksUsersItem>
users = socks5.Auth()
? new []
{
new
{
new()
{
user = socks5.Username,
pass = socks5.Password,
level = 1
}
user = socks5.Username,
pass = socks5.Password,
level = 1
}
: null,
address = server.AutoResolveHostname(),
port = server.Port
}
};
}
: null,
address = server.AutoResolveHostname(),
port = server.Port
}
};
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
break;
}
case VLESS vless:
{
outbound.protocol = "vless";
outbound.settings.vnext = new[]
{
new VnextItem
{
address = server.AutoResolveHostname(),
port = server.Port,
users = new[]
{
new User
{
id = vless.UserID,
alterId = 0,
flow = vless.Flow.ValueOrDefault(),
encryption = vless.EncryptMethod
}
}
}
};
var streamSettings = outbound.streamSettings;
boundStreamSettings(vless, ref streamSettings);
if (vless.TLSSecureType == "xtls")
{
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
outbound.protocol = "socks";
break;
}
case VLESS vless:
else
{
var vnextItem = new VnextItem
{
users = new List<UsersItem>(),
address = server.AutoResolveHostname(),
port = server.Port
};
outbound.settings.vnext = new List<VnextItem> { vnextItem };
var usersItem = new UsersItem
{
id = vless.UserID,
alterId = 0,
flow = string.Empty,
encryption = vless.EncryptMethod
};
vnextItem.users.Add(usersItem);
var streamSettings = outbound.streamSettings;
boundStreamSettings(vless, ref streamSettings);
if (vless.TLSSecureType == "xtls")
{
usersItem.flow = string.IsNullOrEmpty(vless.Flow) ? "xtls-rprx-origin" : vless.Flow;
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
}
else
{
outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
}
outbound.protocol = "vless";
outbound.settings.servers = null;
break;
outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
}
case VMess.VMess vmess:
{
var vnextItem = new VnextItem
{
users = new List<UsersItem>(),
address = server.AutoResolveHostname(),
port = server.Port
};
outbound.settings.vnext = new List<VnextItem> { vnextItem };
var usersItem = new UsersItem
{
id = vmess.UserID,
alterId = vmess.AlterID,
security = vmess.EncryptMethod
};
vnextItem.users.Add(usersItem);
var streamSettings = outbound.streamSettings;
boundStreamSettings(vmess, ref streamSettings);
outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
outbound.protocol = "vmess";
break;
}
break;
}
v2rayConfig.outbounds.AddRange(new[]
case VMess vmess:
{
outbound,
new()
outbound.protocol = "vmess";
outbound.settings.vnext = new[]
{
tag = "direct", protocol = "freedom"
},
new()
{
tag = "block", protocol = "blackhole"
}
});
}
catch
{
// ignored
new VnextItem
{
address = server.AutoResolveHostname(),
port = server.Port,
users = new[]
{
new User
{
id = vmess.UserID,
alterId = vmess.AlterID,
security = vmess.EncryptMethod
}
}
}
};
var streamSettings = outbound.streamSettings;
boundStreamSettings(vmess, ref streamSettings);
outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
break;
}
}
}
private static void boundStreamSettings(VMess.VMess server, ref StreamSettings streamSettings)
private static void boundStreamSettings(VMess server, ref StreamSettings streamSettings)
{
try
streamSettings.network = server.TransferProtocol;
streamSettings.security = server.TLSSecureType;
if (server.TLSSecureType != "none")
{
streamSettings.network = server.TransferProtocol;
if ((streamSettings.security = server.TLSSecureType) != "none")
var tlsSettings = new TlsSettings
{
var tlsSettings = new TlsSettings
{
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure
};
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure,
serverName = server.ServerName.ValueOrDefault() ?? server.Hostname
};
if (!string.IsNullOrWhiteSpace(server.Host))
tlsSettings.serverName = server.Host;
else if (Global.Settings.ResolveServerHostname)
tlsSettings.serverName = server.Hostname;
switch (server.TLSSecureType)
{
case "tls":
streamSettings.tlsSettings = tlsSettings;
break;
case "xtls":
streamSettings.xtlsSettings = tlsSettings;
break;
}
}
switch (server.TransferProtocol)
switch (server.TLSSecureType)
{
case "kcp":
var kcpSettings = new KcpSettings
{
mtu = Global.Settings.V2RayConfig.KcpConfig.mtu,
tti = Global.Settings.V2RayConfig.KcpConfig.tti,
uplinkCapacity = Global.Settings.V2RayConfig.KcpConfig.uplinkCapacity,
downlinkCapacity = Global.Settings.V2RayConfig.KcpConfig.downlinkCapacity,
congestion = Global.Settings.V2RayConfig.KcpConfig.congestion,
readBufferSize = Global.Settings.V2RayConfig.KcpConfig.readBufferSize,
writeBufferSize = Global.Settings.V2RayConfig.KcpConfig.writeBufferSize,
header = new Header
{
type = server.FakeType
},
seed = !string.IsNullOrWhiteSpace(server.Path) ? server.Path : null
};
streamSettings.kcpSettings = kcpSettings;
case "tls":
streamSettings.tlsSettings = tlsSettings;
break;
case "ws":
var wsSettings = new WsSettings
{
headers = !string.IsNullOrWhiteSpace(server.Host) ? new Headers { Host = server.Host } : null,
path = !string.IsNullOrWhiteSpace(server.Path) ? server.Path : null
};
streamSettings.wsSettings = wsSettings;
break;
case "h2":
var httpSettings = new HttpSettings
{
host = new List<string>
{
string.IsNullOrWhiteSpace(server.Host) ? server.Hostname : server.Host!
},
path = server.Path
};
streamSettings.httpSettings = httpSettings;
break;
case "quic":
var quicSettings = new QuicSettings
{
security = server.QUICSecure,
key = server.QUICSecret,
header = new Header
{
type = server.FakeType
}
};
if (server.TLSSecureType != "none")
// tls or xtls
streamSettings.tlsSettings.serverName = server.Hostname;
streamSettings.quicSettings = quicSettings;
break;
case "grpc":
var grpcSettings = new GrpcSettings
{
serviceName = server.Path,
multiMode = server.FakeType == "multi"
};
streamSettings.grpcSettings = grpcSettings;
break;
default:
if (server.FakeType == "http")
{
var tcpSettings = new TcpSettings
{
header = new Header
{
type = server.FakeType,
request = new TCPRequest
{
path = string.IsNullOrWhiteSpace(server.Path) ? "/" : server.Path,
headers = new TCPRequestHeaders
{
Host = string.IsNullOrWhiteSpace(server.Host) ? server.Hostname : server.Host
}
}
}
};
streamSettings.tcpSettings = tcpSettings;
}
case "xtls":
streamSettings.xtlsSettings = tlsSettings;
break;
}
}
catch
switch (server.TransferProtocol)
{
// ignored
case "tcp":
if (server.FakeType == "http")
{
streamSettings.tcpSettings = new TcpSettings
{
header = new
{
request = new
{
path = server.Path.SplitOrDefault(),
headers = new
{
Host = server.Host.SplitOrDefault()
}
}
}
};
}
else
{
throw new MessageException($"invalid tcp type {server.FakeType}");
}
break;
case "ws":
streamSettings.wsSettings = new WsSettings
{
path = server.Path.ValueOrDefault(),
headers = new { Host = server.Host.ValueOrDefault() },
};
break;
case "kcp":
streamSettings.kcpSettings = new KcpSettings
{
mtu = Global.Settings.V2RayConfig.KcpConfig.mtu,
tti = Global.Settings.V2RayConfig.KcpConfig.tti,
uplinkCapacity = Global.Settings.V2RayConfig.KcpConfig.uplinkCapacity,
downlinkCapacity = Global.Settings.V2RayConfig.KcpConfig.downlinkCapacity,
congestion = Global.Settings.V2RayConfig.KcpConfig.congestion,
readBufferSize = Global.Settings.V2RayConfig.KcpConfig.readBufferSize,
writeBufferSize = Global.Settings.V2RayConfig.KcpConfig.writeBufferSize,
header = new
{
type = server.FakeType
},
seed = server.Path.ValueOrDefault()
};
break;
case "h2":
streamSettings.httpSettings = new HttpSettings
{
host = server.Host.SplitOrDefault(),
path = server.Path.ValueOrDefault()
};
break;
case "quic":
streamSettings.quicSettings = new QuicSettings
{
security = server.QUICSecure,
key = server.QUICSecret,
header = new
{
type = server.FakeType
}
};
break;
case "grpc":
streamSettings.grpcSettings = new GrpcSettings
{
serviceName = server.Path,
multiMode = server.FakeType == "multi"
};
break;
default:
Trace.Assert(false);
break;
}
}
}

View File

@@ -1,10 +1,10 @@
using Netch.Models;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using Netch.Models;
using Netch.Utils;
namespace Netch.Servers
{
@@ -13,7 +13,7 @@ namespace Netch.Servers
public static IEnumerable<Server> ParseVUri(string text)
{
var scheme = ShareLink.GetUriScheme(text).ToLower();
var server = scheme switch { "vmess" => new VMess.VMess(), "vless" => new VLESS(), _ => throw new ArgumentOutOfRangeException() };
var server = scheme switch { "vmess" => new VMess(), "vless" => new VLESS(), _ => throw new ArgumentOutOfRangeException() };
if (text.Contains("#"))
{
server.Remark = Uri.UnescapeDataString(text.Split('#')[1]);
@@ -56,7 +56,7 @@ namespace Netch.Servers
server.TLSSecureType = parameter.Get("security") ?? "none";
if (server.TLSSecureType != "none")
{
server.Host = parameter.Get("sni") ?? "";
server.ServerName = parameter.Get("sni") ?? "";
if (server.TLSSecureType == "xtls")
((VLESS)server).Flow = parameter.Get("flow") ?? "";
}
@@ -77,7 +77,7 @@ namespace Netch.Servers
public static string GetVShareLink(Server s, string scheme = "vmess")
{
// https://github.com/XTLS/Xray-core/issues/91
var server = (VMess.VMess)s;
var server = (VMess)s;
var parameter = new Dictionary<string, string>();
// protocol-specific fields
parameter.Add("type", server.TransferProtocol);
@@ -97,13 +97,13 @@ namespace Netch.Servers
break;
case "ws":
parameter.Add("path", Uri.EscapeDataString(server.Path.IsNullOrWhiteSpace() ? "/" : server.Path!));
parameter.Add("path", Uri.EscapeDataString(server.Path.ValueOrDefault() ?? "/"));
if (!server.Host.IsNullOrWhiteSpace())
parameter.Add("host", Uri.EscapeDataString(server.Host!));
break;
case "h2":
parameter.Add("path", Uri.EscapeDataString(server.Path.IsNullOrWhiteSpace() ? "/" : server.Path!));
parameter.Add("path", Uri.EscapeDataString(server.Path.ValueOrDefault() ?? "/"));
if (!server.Host.IsNullOrWhiteSpace())
parameter.Add("host", Uri.EscapeDataString(server.Host!));
@@ -113,7 +113,6 @@ namespace Netch.Servers
{
parameter.Add("quicSecurity", server.QUICSecure);
parameter.Add("key", server.QUICSecret!);
// TODO Import and Create null value Check
}
if (server.FakeType != "none")
@@ -124,7 +123,7 @@ namespace Netch.Servers
if (!string.IsNullOrEmpty(server.Path))
parameter.Add("serviceName", server.Path);
if (server.FakeType == "gun" || server.FakeType == "multi")
if (server.FakeType is "gun" or "multi")
parameter.Add("mode", server.FakeType);
break;
@@ -146,7 +145,7 @@ namespace Netch.Servers
}
return
$"{scheme}://{server.UserID}@{server.Hostname}:{server.Port}?{string.Join("&", parameter.Select(p => $"{p.Key}={p.Value}"))}{(server.Remark.IsNullOrWhiteSpace() ? "" : $"#{Uri.EscapeDataString(server.Remark)}")}";
$"{scheme}://{server.UserID}@{server.Hostname}:{server.Port}?{string.Join("&", parameter.Select(p => $"{p.Key}={p.Value}"))}{(!server.Remark.IsNullOrWhiteSpace() ? $"#{Uri.EscapeDataString(server.Remark)}" : "")}";
}
}
}

View File

@@ -1,9 +1,8 @@
using Netch.Servers.VMess;
using System.Collections.Generic;
namespace Netch.Servers
{
public class VLESS : VMess.VMess
public class VLESS : VMess
{
public override string Type { get; } = "VLESS";

View File

@@ -1,5 +1,5 @@
using Netch.Forms;
using System.Collections.Generic;
using Netch.Forms;
namespace Netch.Servers.VLESSForm
{
@@ -9,6 +9,7 @@ namespace Netch.Servers.VLESSForm
{
server ??= new VLESS();
Server = server;
CreateTextBox("Sni", "ServerName(Sni)", s => true, s => server.ServerName = s, server.ServerName);
CreateTextBox("UUID", "UUID", s => true, s => server.UserID = s, server.UserID);
CreateTextBox("EncryptMethod",
"Encrypt Method",

View File

@@ -1,7 +1,7 @@
using Netch.Forms;
using System.Collections.Generic;
using System.Collections.Generic;
using Netch.Forms;
namespace Netch.Servers.VMess.Form
namespace Netch.Servers.Form
{
public class VMessForm : ServerForm
{
@@ -9,6 +9,7 @@ namespace Netch.Servers.VMess.Form
{
server ??= new VMess();
Server = server;
CreateTextBox("Sni", "ServerName(Sni)", s => true, s => server.ServerName = s, server.ServerName);
CreateTextBox("UserId", "User ID", s => true, s => server.UserID = s, server.UserID);
CreateTextBox("AlterId", "Alter ID", s => int.TryParse(s, out _), s => server.AlterID = int.Parse(s), server.AlterID.ToString(), 76);
CreateComboBox("EncryptMethod", "Encrypt Method", VMessGlobal.EncryptMethods, s => server.EncryptMethod = s, server.EncryptMethod);

View File

@@ -1,13 +1,14 @@
using System.Collections.Generic;
using Netch.Models;
namespace Netch.Servers.VMess
namespace Netch.Servers
{
public class VMess : Server
{
private string _tlsSecureType = VMessGlobal.TLSSecure[0];
public override string Type { get; } = "VMess";
public override string MaskedData()
{
var maskedData = $"{EncryptMethod} + {TransferProtocol} + {FakeType}";
@@ -25,6 +26,7 @@ namespace Netch.Servers.VMess
case "kcp":
break;
}
return maskedData;
}
@@ -91,7 +93,9 @@ namespace Netch.Servers.VMess
/// <summary>
/// Mux 多路复用
/// </summary>
public bool? UseMux { get; set; } = false;
public bool? UseMux { get; set; }
public string? ServerName { get; set; } = string.Empty;
}
public class VMessGlobal

View File

@@ -5,12 +5,11 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers;
using Netch.Servers.Form;
using Netch.Servers.Models;
using Netch.Servers.VMess.Form;
using Netch.Utils;
namespace Netch.Servers.VMess
namespace Netch.Servers
{
public class VMessUtil : IServerUtil
{
@@ -92,7 +91,6 @@ namespace Netch.Servers.VMess
data.Remark = vmess.ps;
data.Hostname = vmess.add;
data.Port = vmess.port;
data.UserID = vmess.id;
data.AlterID = vmess.aid;
data.TransferProtocol = vmess.net;
data.FakeType = vmess.type;

View File

@@ -72,5 +72,15 @@ namespace Netch.Utils
{
return value.Split(separator, StringSplitOptions.RemoveEmptyEntries);
}
public static string? ValueOrDefault(this string? value)
{
return string.IsNullOrWhiteSpace(value) ? null : value;
}
public static string[]? SplitOrDefault(this string? value)
{
return !string.IsNullOrWhiteSpace(value) ? value.Split(',') : default;
}
}
}