-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmigration.zig
More file actions
64 lines (56 loc) · 2.93 KB
/
Copy pathmigration.zig
File metadata and controls
64 lines (56 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//! migration - connection IDs let a session survive its network address changing under
//! it (a phone moving Wi-Fi → cellular, a NAT rebinding a port). The peer is addressed
//! by an opaque connection id, not its IP, so the server simply follows it to the new
//! address and delivery continues in order, uninterrupted.
const std = @import("std");
const magnet = @import("magnet");
const sim = magnet.runtime.sim;
const transport = magnet.runtime.transport;
const Schema = magnet.proto.channels(.{ .rel = .{ .mode = .reliable_ordered, .Message = u32 } });
const Cfg = magnet.Config{ .channels = Schema, .protocol_id = 0xC1D, .security = .{ .mode = .aead, .connection_ids = true } };
const Endpoint = magnet.Endpoint(Cfg);
const psk = [_]u8{0x5A} ** 32;
const challenge_secret = [_]u8{0xC0} ** 16;
const server_addr = 2;
const addr_before = (0x0A00_0001 << 32) | 5000; // 10.0.0.1:5000
const addr_after = (0x0A00_0001 << 32) | 6000; // …:6000 - same IP, new port
pub fn main(init: std.process.Init) !void {
const gpa = std.heap.page_allocator;
const link = try gpa.create(sim.DefaultLink);
defer gpa.destroy(link);
link.* = sim.DefaultLink.init(.{ .latency_ms = 20, .seed = 1 });
const client = try gpa.create(Endpoint);
defer gpa.destroy(client);
client.init();
const server = try gpa.create(Endpoint);
defer gpa.destroy(server);
server.init();
server.secSetup(psk, challenge_secret);
var local_secret: [16]u8 = undefined;
try std.Io.randomSecure(init.io, &local_secret);
_ = client.connectTo(server_addr, psk, local_secret);
var to_srv: sim.Transport(sim.DefaultLink) = .{ .link = link, .recv_dir = .to_a, .send_dir = .to_b, .peer_addr = server_addr };
var to_cli: sim.Transport(sim.DefaultLink) = .{ .link = link, .recv_dir = .to_b, .send_dir = .to_a, .peer_addr = addr_before };
var scratch: [1200]u8 = undefined;
var out: [64]u8 = undefined;
var sent: u32 = 0;
var expected: u32 = 0;
var in_order = true;
var now: i64 = 0;
while (expected < 30 and now < 8000) : (now += 5) {
while (sent < 30) : (sent += 1) client.sendRawTo(server_addr, .rel, std.mem.asBytes(&sent)) catch break;
if (expected == 12) to_cli.peer_addr = addr_after; // ← the client's address changes mid-stream
transport.flush(client, &to_srv, &scratch, now);
transport.drain(server, &to_cli, &scratch, now);
transport.flush(server, &to_cli, &scratch, now);
transport.drain(client, &to_srv, &scratch, now);
if (server.connection(to_cli.peer_addr)) |c| {
while (c.receiveRaw(.rel, &out)) |_| {
if (std.mem.readInt(u32, out[0..4], .little) != expected) in_order = false;
expected += 1;
}
}
}
std.debug.print("migration: address changed at msg 12; {d}/30 delivered in order = {}\n", .{ expected, in_order });
std.debug.print(" one connection throughout = {}\n", .{server.liveCount() == 1});
}