This commit is contained in:
DHR60 2026-05-04 15:25:56 +08:00
parent 744c175029
commit 298f370f72
3 changed files with 110 additions and 19 deletions

View file

@ -0,0 +1,46 @@
using AwesomeAssertions;
using ServiceLib.Handler.Fmt;
using Xunit;
namespace ServiceLib.Tests.Fmt;
public class WireguardFmtTests
{
[Fact]
public void ResolveConfig_ShouldParsePeersAndIgnoreInlineComments()
{
var config = """
[Interface]
PrivateKey = interface-private-key
Address = 10.0.0.2/32, fd00::2/128 ; inline comment
MTU = 1420
[Peer]
PublicKey = peer-public-key
PresharedKey = peer-preshared-key
Reserved = 1, 2, 3 # inline comment
Endpoint = [2001:db8::1]:51820 # inline comment
[Peer]
PublicKey = peer-public-key-2
Endpoint = example.com:12345
""";
var resolved = WireguardFmt.ResolveConfig(config);
resolved.Should().NotBeNull();
resolved.Should().HaveCount(2);
var first = resolved![0];
first.Address.Should().Be("2001:db8::1");
first.Port.Should().Be(51820);
first.Password.Should().Be("interface-private-key");
first.GetProtocolExtra().WgReserved.Should().Be("1, 2, 3");
first.GetProtocolExtra().WgInterfaceAddress.Should().Be("10.0.0.2/32, fd00::2/128");
first.GetProtocolExtra().WgMtu.Should().Be(1420);
var second = resolved[1];
second.Address.Should().Be("example.com");
second.Port.Should().Be(12345);
}
}

View file

@ -790,12 +790,17 @@ public static class ConfigHandler
profileItem.Address = profileItem.Address.TrimEx();
profileItem.Password = profileItem.Password.TrimEx();
var wgReserved = profileItem.GetProtocolExtra().WgReserved?.TrimEx();
if (!wgReserved.IsNullOrEmpty())
{
wgReserved = wgReserved.Replace(", ", ",");
}
profileItem.SetProtocolExtra(profileItem.GetProtocolExtra() with
{
WgPublicKey = profileItem.GetProtocolExtra().WgPublicKey?.TrimEx(),
WgPresharedKey = profileItem.GetProtocolExtra().WgPresharedKey?.TrimEx(),
WgInterfaceAddress = profileItem.GetProtocolExtra().WgInterfaceAddress?.TrimEx(),
WgReserved = profileItem.GetProtocolExtra().WgReserved?.TrimEx(),
WgReserved = wgReserved,
WgMtu = profileItem.GetProtocolExtra().WgMtu is null or <= 0 ? Global.TunMtus.First() : profileItem.GetProtocolExtra().WgMtu,
});

View file

@ -76,7 +76,6 @@ public class WireguardFmt : BaseFmt
public static List<ProfileItem>? ResolveConfig(string strData)
{
//var dic = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var interfaceDic = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var peerDicList = new List<Dictionary<string, string>>();
var currentDicRef = interfaceDic;
@ -117,17 +116,7 @@ public class WireguardFmt : BaseFmt
var key = line[..idx].Trim();
var value = line[(idx + 1)..].Trim();
// Remove inline comments starting with # or ;
var commentPos = -1;
var commentChars = new[] { '#', ';' };
foreach (var cc in commentChars)
{
var p = value.IndexOf(cc);
if (p >= 0 && (commentPos < 0 || p < commentPos))
{
commentPos = p;
}
}
var commentPos = value.IndexOfAny(['#', ';']);
if (commentPos >= 0)
{
value = value[..commentPos].TrimEnd();
@ -155,20 +144,17 @@ public class WireguardFmt : BaseFmt
continue;
}
var endpointParts = endpoint.Split(':');
var peerAddress = endpointParts[0].Trim();
if (peerAddress.StartsWith('[')) // IPv6 address
if (!TryParseEndpoint(endpoint, out var peerAddress, out var peerPort))
{
peerAddress = peerAddress.Trim('[', ']');
continue;
}
var peerPort = endpointParts.Length > 1 && int.TryParse(endpointParts[1].Trim(), out var portVal) && portVal is > 0 and <= 65535 ? portVal : 2408;
var protoExtra = new ProtocolExtraItem
{
WgPublicKey = (peerDic.TryGetValue("PublicKey", out var publicKey) ? publicKey : string.Empty).NullIfEmpty(),
WgPresharedKey = (peerDic.TryGetValue("PresharedKey", out var presharedKey) ? presharedKey : string.Empty).NullIfEmpty(),
WgInterfaceAddress = wgInterfaceAddress,
WgReserved = (peerDic.TryGetValue("Reserved", out var reserved) ? reserved : string.Empty).Replace(", ", ",").NullIfEmpty(),
WgReserved = (peerDic.TryGetValue("Reserved", out var reserved) ? reserved : string.Empty).NullIfEmpty(),
WgMtu = wgMtu > 0 ? wgMtu : null,
};
@ -188,4 +174,58 @@ public class WireguardFmt : BaseFmt
return resultList;
}
private static bool TryParseEndpoint(string endpoint, out string address, out int port)
{
address = string.Empty;
port = 2408;
var trimmedEndpoint = endpoint.Trim();
if (trimmedEndpoint.IsNullOrEmpty())
{
return false;
}
if (trimmedEndpoint[0] == '[')
{
var closeIndex = trimmedEndpoint.IndexOf(']');
if (closeIndex <= 1)
{
return false;
}
address = trimmedEndpoint[1..closeIndex].Trim();
var portIndex = closeIndex + 1;
if (portIndex < trimmedEndpoint.Length && trimmedEndpoint[portIndex] == ':' &&
int.TryParse(trimmedEndpoint[(portIndex + 1)..].Trim(), out var bracketedPort) && bracketedPort is > 0 and <= 65535)
{
port = bracketedPort;
}
return address.IsNotEmpty();
}
var lastColonIndex = trimmedEndpoint.LastIndexOf(':');
if (lastColonIndex <= 0)
{
address = trimmedEndpoint;
return true;
}
address = trimmedEndpoint[..lastColonIndex].Trim();
var portText = trimmedEndpoint[(lastColonIndex + 1)..].Trim();
if (address.IsNullOrEmpty())
{
return false;
}
if (int.TryParse(portText, out var parsedPortValue) && parsedPortValue is > 0 and <= 65535)
{
port = parsedPortValue;
return true;
}
address = trimmedEndpoint;
return true;
}
}