fleet: count only admitted peers against the session limit so silent connections cannot lock the roster out
This commit is contained in:
1 parent
fee236fe56
commit
4a9608ead4
2 files changed
+92
-5
No files matched your search
@@ -303,7 +303,7 @@ public sealed class LinkTests
|
||||
private readonly CancellationTokenSource _stop = new();
|
||||
private readonly NodeIdentity _identity;
|
||||
|
||||
public PeerFixture(Func<string, byte[]?> lookup, Func<PeerSessionInfo, IRpcTransport, CancellationToken, Task>? onSession = null)
|
||||
public PeerFixture(Func<string, byte[]?> lookup, Func<PeerSessionInfo, IRpcTransport, CancellationToken, Task>? onSession = null, int maxSessions = 64)
|
||||
{
|
||||
Certificate = NodeCertificate.LoadPfx(NodeCertificate.CreateSelfSignedPfx("agent", TimeSpan.FromDays(30), TimeProvider.System));
|
||||
_identity = NodeIdentity.FromPkcs8(Certificate.GetECDsaPrivateKey()!.ExportPkcs8PrivateKey());
|
||||
@@ -314,6 +314,7 @@ public sealed class LinkTests
|
||||
Certificate = Certificate,
|
||||
LookupPeerKey = lookup,
|
||||
Knock = new KnockGate(_identity, () => KnockPeers, TimeProvider.System),
|
||||
MaxSessions = maxSessions,
|
||||
},
|
||||
onSession ?? ((_, transport, ct) => KeepOpenAsync(transport, ct)),
|
||||
NullNodeLog.Instance, TimeProvider.System);
|
||||
@@ -462,6 +463,65 @@ public sealed class LinkTests
|
||||
await ok.DisposeAsync();
|
||||
}
|
||||
|
||||
/// <summary>名额只数通过敲门的会话:一堆还没敲门的连接占着,名册里的拨号方照样连得上(之前它们共用一个上限,节点多了之后后到的拨号方被永远拒绝)。</summary>
|
||||
[Fact]
|
||||
public async Task PeerListener_SessionLimitCountsOnlyAdmittedPeers_SoSilentConnectionsCannotLockOutTheRoster()
|
||||
{
|
||||
using NodeIdentity first = NodeIdentity.Generate();
|
||||
using NodeIdentity second = NodeIdentity.Generate();
|
||||
using NodeIdentity third = NodeIdentity.Generate();
|
||||
await using var agent = new PeerFixture(id => id == "dlr_1" ? first.PublicKeySpki : id == "dlr_2" ? second.PublicKeySpki : third.PublicKeySpki, maxSessions: 2);
|
||||
agent.KnockPeers.AddRange([first.PublicKeySpki, second.PublicKeySpki, third.PublicKeySpki]);
|
||||
await agent.Listener.Started.Task;
|
||||
|
||||
// 20 个什么都不说的连接:占着待敲门的名额,但不占会话名额
|
||||
var silent = new List<TcpClient>();
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
var client = new TcpClient();
|
||||
await client.ConnectAsync(IPAddress.Loopback, agent.Listener.Port);
|
||||
silent.Add(client);
|
||||
}
|
||||
|
||||
(_, TlsFrameTransport a) = await PeerConnector.ConnectAsync("127.0.0.1", agent.Listener.Port, agent.PublicKey, first, "dlr_1", null, 1 << 20, TimeProvider.System, default);
|
||||
(_, TlsFrameTransport b) = await PeerConnector.ConnectAsync("127.0.0.1", agent.Listener.Port, agent.PublicKey, second, "dlr_2", null, 1 << 20, TimeProvider.System, default);
|
||||
|
||||
// 会话名额(2)满了:第三个在名册里的拨号方被拒绝,一个会话结束之后又能连上
|
||||
await Assert.ThrowsAnyAsync<Exception>(async () =>
|
||||
{
|
||||
(_, TlsFrameTransport refused) = await PeerConnector.ConnectAsync("127.0.0.1", agent.Listener.Port, agent.PublicKey, third, "dlr_3", null, 1 << 20, TimeProvider.System, default);
|
||||
await refused.DisposeAsync();
|
||||
});
|
||||
await a.DisposeAsync();
|
||||
bool reconnected = false;
|
||||
for (int attempt = 0; attempt < 50 && !reconnected; attempt++)
|
||||
{
|
||||
try
|
||||
{
|
||||
(_, TlsFrameTransport again) = await PeerConnector.ConnectAsync("127.0.0.1", agent.Listener.Port, agent.PublicKey, third, "dlr_3", null, 1 << 20, TimeProvider.System, default);
|
||||
await again.DisposeAsync();
|
||||
reconnected = true;
|
||||
}
|
||||
catch (Exception ex) when (ex is IOException or System.Security.Authentication.AuthenticationException or InvalidOperationException)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
Assert.True(reconnected);
|
||||
await b.DisposeAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (TcpClient client in silent)
|
||||
{
|
||||
client.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PeerListener_WritesNothingToStrangers_NotEvenATlsServerHello()
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user