feat: allow user to choose any outbound for routing rules

This commit is contained in:
VALLIS-NERIA 2023-02-05 20:05:19 +08:00
parent 5e2e45c673
commit f0c03d6103
3 changed files with 112 additions and 5 deletions

View file

@ -179,8 +179,9 @@ namespace v2rayN.Handler
return inbound; return inbound;
} }
private static int routing(Config config, ref V2rayConfig v2rayConfig) private static int routing(Config config, ref V2rayConfig v2rayConfig, out HashSet<string> usedOutboundTags)
{ {
usedOutboundTags = new HashSet<string>();
try try
{ {
if (v2rayConfig.routing != null if (v2rayConfig.routing != null
@ -204,6 +205,7 @@ namespace v2rayN.Handler
if (item.enabled) if (item.enabled)
{ {
routingUserRule(item, ref v2rayConfig); routingUserRule(item, ref v2rayConfig);
usedOutboundTags.Add(item.outboundTag);
} }
} }
} }
@ -302,12 +304,32 @@ namespace v2rayN.Handler
return 0; return 0;
} }
private static int outbound(ProfileItem node, ref V2rayConfig v2rayConfig) private static Outbounds createOutbound(ProfileItem node)
{ {
var outbound = new Outbounds
{
tag = node.remarks,
protocol = node.configType switch
{
EConfigType.VMess => Global.vmessProtocolLite,
EConfigType.Shadowsocks => Global.ssProtocolLite,
EConfigType.VLESS => Global.vlessProtocolLite,
EConfigType.Trojan => Global.trojanProtocolLite,
EConfigType.Socks => Global.socksProtocolLite,
_ => "unknown"
},
settings = new Outboundsettings
{
vnext = new List<VnextItem> { new VnextItem { users = new List<UsersItem>() } },
servers = new List<ServersItem>(),
response = new Response()
},
streamSettings = new StreamSettings(),
mux = new Mux()
};
try try
{ {
var config = LazyConfig.Instance.GetConfig(); var config = LazyConfig.Instance.GetConfig();
Outbounds outbound = v2rayConfig.outbounds[0];
if (node.configType == EConfigType.VMess) if (node.configType == EConfigType.VMess)
{ {
VnextItem vnextItem; VnextItem vnextItem;
@ -534,6 +556,26 @@ namespace v2rayN.Handler
{ {
Utils.SaveLog(ex.Message, ex); Utils.SaveLog(ex.Message, ex);
} }
return outbound;
}
private static int outbound(ProfileItem node, ref V2rayConfig v2rayConfig)
{
try
{
if (v2rayConfig.outbounds.Count <= 0)
{
v2rayConfig.outbounds.Add(createOutbound(node));
}
else
{
v2rayConfig.outbounds[0] = createOutbound(node);
}
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
}
return 0; return 0;
} }
@ -956,7 +998,7 @@ namespace v2rayN.Handler
return 0; return 0;
} }
public static int GenerateClientConfigContent(ProfileItem node, bool blExport, ref V2rayConfig v2rayConfig, out string msg) private static int GenerateClientConfigContent(ProfileItem node, bool blExport, ref V2rayConfig v2rayConfig, out string msg)
{ {
try try
{ {
@ -988,10 +1030,20 @@ namespace v2rayN.Handler
inbound(config, ref v2rayConfig); inbound(config, ref v2rayConfig);
routing(config, ref v2rayConfig); routing(config, ref v2rayConfig, out HashSet<string> usedTags);
v2rayConfig.outbounds.Clear();
//outbound //outbound
outbound(node, ref v2rayConfig); outbound(node, ref v2rayConfig);
// first outbound is current active node, of which name is always "proxy"
v2rayConfig.outbounds[0].tag = Global.agentTag;
// append all outbound used by custom routing rules
var allOutbounds = SqliteHelper.Instance.Table<ProfileItem>().Where(i => usedTags.Contains(i.remarks));
foreach (var item in allOutbounds)
{
v2rayConfig.outbounds.Add(createOutbound(item));
}
//dns //dns
dns(config, ref v2rayConfig); dns(config, ref v2rayConfig);

View file

@ -247,5 +247,56 @@ namespace v2rayN.Mode
public string fingerprint { get; set; } public string fingerprint { get; set; }
public bool displayLog { get; set; } = true; public bool displayLog { get; set; } = true;
// TODO: change ProfileItem and other models to C# records
public override bool Equals(object? obj) {
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((ProfileItem)obj);
}
protected bool Equals(ProfileItem other) {
return indexId == other.indexId && configType == other.configType && configVersion == other.configVersion &&
sort == other.sort && address == other.address && port == other.port && id == other.id &&
alterId == other.alterId && security == other.security && network == other.network &&
remarks == other.remarks && headerType == other.headerType && requestHost == other.requestHost &&
path == other.path && streamSecurity == other.streamSecurity && allowInsecure == other.allowInsecure &&
delay == other.delay && speed == other.speed && subid == other.subid && isSub == other.isSub &&
flow == other.flow && sni == other.sni && alpn == other.alpn && coreType == other.coreType &&
preSocksPort == other.preSocksPort && fingerprint == other.fingerprint && displayLog == other.displayLog;
}
public override int GetHashCode() {
var hashCode = new HashCode();
hashCode.Add(indexId);
hashCode.Add((int)configType);
hashCode.Add(configVersion);
hashCode.Add(sort);
hashCode.Add(address);
hashCode.Add(port);
hashCode.Add(id);
hashCode.Add(alterId);
hashCode.Add(security);
hashCode.Add(network);
hashCode.Add(remarks);
hashCode.Add(headerType);
hashCode.Add(requestHost);
hashCode.Add(path);
hashCode.Add(streamSecurity);
hashCode.Add(allowInsecure);
hashCode.Add(delay);
hashCode.Add(speed);
hashCode.Add(subid);
hashCode.Add(isSub);
hashCode.Add(flow);
hashCode.Add(sni);
hashCode.Add(alpn);
hashCode.Add(coreType);
hashCode.Add(preSocksPort);
hashCode.Add(fingerprint);
hashCode.Add(displayLog);
return hashCode.ToHashCode();
}
} }
} }

View file

@ -20,6 +20,10 @@ namespace v2rayN.Views
cmbOutboundTag.Items.Add(Global.agentTag); cmbOutboundTag.Items.Add(Global.agentTag);
cmbOutboundTag.Items.Add(Global.directTag); cmbOutboundTag.Items.Add(Global.directTag);
cmbOutboundTag.Items.Add(Global.blockTag); cmbOutboundTag.Items.Add(Global.blockTag);
foreach (var profileItem in SqliteHelper.Instance.Table<ProfileItem>())
{
cmbOutboundTag.Items.Add(profileItem.remarks);
}
Global.Protocols.ForEach(it => Global.Protocols.ForEach(it =>
{ {
clbProtocol.Items.Add(it); clbProtocol.Items.Add(it);