agent: unify listening and dialing with directed mutual measurements
Replace Probe with Agent across node runtime, Fleet contracts, backend state, API and storage. Report incoming sessions and outgoing link health through each Agent uplink, and retain directed link controls and retry. Update protocol fixtures and end-to-end coverage for the unified model; accept requested cancellation during the Fleet timeout test cleanup.
This commit is contained in:
1 parent
d5ebf29e57
commit
ad5efc62ff
206 files changed
+4202
-4964
No files matched your search
@@ -1,3 +1,4 @@
|
||||
using Fleet.Core;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json.Nodes;
|
||||
using MoShiro.Protocol;
|
||||
@@ -37,15 +38,15 @@ public sealed class AotSmokeTests
|
||||
|
||||
using HttpResponseMessage settingsResponse = await http.PatchAsync("/api/admin/settings", BackendFixture.Json(new JsonObject { ["site.public"] = true }, "application/merge-patch+json"));
|
||||
settingsResponse.EnsureSuccessStatusCode();
|
||||
// Probe:probe 角色的加入令牌 → 节点自己生成密钥并注册
|
||||
using HttpResponseMessage probeJoin = await http.PostAsync("/api/admin/join-tokens", BackendFixture.Json(new JsonObject { ["role"] = "probe", ["max_uses"] = 1 }));
|
||||
probeJoin.EnsureSuccessStatusCode();
|
||||
string probeToken = JsonNode.Parse(await probeJoin.Content.ReadAsStringAsync())!["plaintext"]!.GetValue<string>();
|
||||
using var probeHttp = new HttpClient { Timeout = TimeSpan.FromSeconds(15) };
|
||||
Fleet.Core.Result<Fleet.Enrollment.Client.EnrollmentResult> probeEnrolled = await Fleet.Enrollment.Client.EnrollmentClient.EnrollAsync(
|
||||
probeHttp, baseAddress, probeToken, "aot-probe-" + Guid.NewGuid().ToString("N")[..6], Path.Combine(Path.GetTempPath(), "moshiro-aot-probe-" + Guid.NewGuid().ToString("N")), "0.0.0", null, TimeProvider.System, default);
|
||||
Assert.True(probeEnrolled.IsSuccess, probeEnrolled.IsSuccess ? "" : probeEnrolled.Error.ToString());
|
||||
string probeId = probeEnrolled.Value.NodeId;
|
||||
// 拨号侧 Agent:统一加入令牌 → 节点自己生成密钥并注册
|
||||
using HttpResponseMessage dialerJoin = await http.PostAsync("/api/admin/join-tokens", BackendFixture.Json(new JsonObject { ["role"] = "agent", ["max_uses"] = 1 }));
|
||||
dialerJoin.EnsureSuccessStatusCode();
|
||||
string dialerToken = JsonNode.Parse(await dialerJoin.Content.ReadAsStringAsync())!["plaintext"]!.GetValue<string>();
|
||||
using var dialerHttp = new HttpClient { Timeout = TimeSpan.FromSeconds(15) };
|
||||
Fleet.Core.Result<Fleet.Enrollment.Client.EnrollmentResult> dialerEnrolled = await Fleet.Enrollment.Client.EnrollmentClient.EnrollAsync(
|
||||
dialerHttp, baseAddress, dialerToken, "aot-dialer-" + Guid.NewGuid().ToString("N")[..6], Path.Combine(Path.GetTempPath(), "moshiro-aot-dialer-" + Guid.NewGuid().ToString("N")), "0.0.0", null, TimeProvider.System, default);
|
||||
Assert.True(dialerEnrolled.IsSuccess, dialerEnrolled.IsSuccess ? "" : dialerEnrolled.Error.ToString());
|
||||
string dialerId = dialerEnrolled.Value.NodeId;
|
||||
|
||||
// Agent:加入令牌 → 注册(ECDSA 持有证明)→ WebSocket 签名认证 → 期望状态
|
||||
using HttpResponseMessage joinResponse = await http.PostAsync("/api/admin/join-tokens", BackendFixture.Json(new JsonObject { ["max_uses"] = 1 }));
|
||||
@@ -53,8 +54,8 @@ public sealed class AotSmokeTests
|
||||
string joinToken = JsonNode.Parse(await joinResponse.Content.ReadAsStringAsync())!["plaintext"]!.GetValue<string>();
|
||||
using var anonymous = new HttpClient { BaseAddress = baseAddress, Timeout = TimeSpan.FromSeconds(15) };
|
||||
await using AgentSimulator agent = await AgentSimulator.EnrollAsync(anonymous, joinToken, "aot-" + Guid.NewGuid().ToString("N")[..6]);
|
||||
agent.ProbeForChunks = new ProbeId(probeId);
|
||||
string lineId = $"{agent.NodeId.Value}~{probeId}";
|
||||
agent.DialerForChunks = new NodeId(dialerId);
|
||||
string lineId = $"{agent.NodeId.Value}~{dialerId}";
|
||||
await agent.ConnectAsync(baseAddress);
|
||||
TaskSet tasks = await agent.WaitForTaskSetAsync(s => s.Tasks.Count >= 2);
|
||||
Assert.Contains(tasks.Tasks, t => t.Kind == "udp_echo");
|
||||
@@ -98,8 +99,8 @@ public sealed class AotSmokeTests
|
||||
await using SseClient sse = await SseClient.ConnectAsync(http, $"/api/public/live?topics=nodes,series:{lineId}:1s:udp");
|
||||
await sse.WaitForAsync(e => e.Name == "series");
|
||||
|
||||
// 按需测试:Probe 事件 → 下发 → 状态
|
||||
await agent.SendEventAsync(AgentEventKinds.ProbeConnected, probeId);
|
||||
// 按需测试:Dialer 事件 → 下发 → 状态
|
||||
await agent.SendEventAsync(AgentEventKinds.DialerConnected, dialerId);
|
||||
JsonNode started = null!;
|
||||
long begun = TimeProvider.System.GetTimestamp();
|
||||
while (TimeProvider.System.GetElapsedTime(begun) < TimeSpan.FromSeconds(10))
|
||||
|
||||
Reference in new issue
Block a user