libertaria-stack/capsule-core/src/peer_table.zig

71 lines
2.1 KiB
Zig

//! RFC-0120 S5.2: Peer Table
//! Manages a list of known nodes on the network and their health/trust metrics.
const std = @import("std");
const net = std.net;
pub const Peer = struct {
address: net.Address,
did_short: [8]u8, // Short hash of DID (RFC-0120 S4.1)
last_seen: i64,
trust_score: f32 = 1.0,
is_active: bool = true,
};
pub const PeerTable = struct {
allocator: std.mem.Allocator,
peers: std.AutoHashMap([8]u8, Peer),
mutex: std.Thread.Mutex,
pub fn init(allocator: std.mem.Allocator) PeerTable {
return PeerTable{
.allocator = allocator,
.peers = std.AutoHashMap([8]u8, Peer).init(allocator),
.mutex = .{},
};
}
pub fn deinit(self: *PeerTable) void {
self.peers.deinit();
}
/// Update or add a peer to the table
pub fn updatePeer(self: *PeerTable, did_short: [8]u8, address: net.Address) !void {
self.mutex.lock();
defer self.mutex.unlock();
const now = std.time.timestamp();
if (self.peers.getPtr(did_short)) |peer| {
peer.address = address;
peer.last_seen = now;
peer.is_active = true;
} else {
try self.peers.put(did_short, Peer{
.address = address,
.did_short = did_short,
.last_seen = now,
});
std.log.info("Discovered new peer: {x} at {f}", .{ did_short, address });
}
}
/// Mark peers as inactive if not seen for a while (Decay)
pub fn tick(self: *PeerTable) void {
self.mutex.lock();
defer self.mutex.unlock();
const now = std.time.timestamp();
const timeout = 300; // 5 minutes
var it = self.peers.iterator();
while (it.next()) |entry| {
if (now - entry.value_ptr.last_seen > timeout) {
if (entry.value_ptr.is_active) {
entry.value_ptr.is_active = false;
std.log.debug("Peer timed out: {x}", .{entry.key_ptr.*});
}
}
}
}
};