diff --git a/src/node/mod.rs b/src/node/mod.rs index 0f43293..454a08c 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -303,8 +303,23 @@ struct PendingConnect { /// carried by its per-peer control machine (`peer_machines`), indexed by LinkId /// 2. **Active phase** (`peers`): Authenticated, indexed by NodeAddr /// -/// The `addr_to_link` map enables dispatching incoming packets to the right -/// connection before authentication completes. +/// The `addr_to_link` map is a reverse lookup from `(transport, address)` to +/// link. It is **not** a packet-dispatch path, despite what this comment used +/// to say: `find_link_by_addr` has no callers outside its own tests, and +/// encrypted frames are dispatched by session index. Its live readers are the +/// `should_admit_msg1` fast path and the duplicate-inbound-handshake check in +/// `handle_msg1`. +/// +/// **Do not key a peer-identity question on it.** The address form is not +/// canonical: an outbound dial registers the literal configured string, which +/// may be a hostname (`"node-b:2121"`), while an inbound packet carries the +/// resolved form (`"10.128.2.4:2121"`). `TransportAddr` compares byte-wise, so +/// those never match, and a lookup keyed on an inbound address silently returns +/// "no such link" for every hostname-configured peer rather than failing. The +/// entry is also single-valued per key, so an inbound handshake overwrites an +/// outbound dial's entry for the same address. The readers above tolerate this +/// because each compares a key written in the same form it reads; a new reader +/// that does not will be quietly wrong. // Discovery lookup constants moved to config: node.lookup.attempt_timeouts_secs, node.lookup.ttl pub struct Node { // === Immutable Context ===