node: move link, direction, and peer address onto the control machine

These three had no counterpart on the control machine, so readers still
reached them through the pending connection. Add machine-side
accessors and repoint every reader, then drop the connection's.

The peer address needed its writes lifted, not just its reads
repointed: the machine's copy was never written. It is now written at
each of the points the connection's copy was — the inbound seed, the
dial, message-2 completion, and the two paths that seed a machine from
a pre-built connection — so promotion and the resend path read a value
with the same provenance at the same time as before.

Link and direction need no lift. Both machine constructors already
seed them from the same arguments the connection is built with, so an
outbound machine carries outbound state and an inbound one inbound,
and the machine's link always equals the connection's. The handshake
operations' direction guards read the machine's copy for the same
reason.

The stale-connection sweep's teardown log and its resend path both now
take the transport and address from the machine, and each keeps its own
check that a pending connection is still attached rather than relying
on the caller to have established it.

Add a test pinning link, direction, and address on the two shapes that
seed a carrier independently — the dial and an accepted message 1. The
cross-connection winner reads both values from a carrier one of those
two already seeded.
This commit is contained in:
Johnathan Corgan
2026-07-18 23:17:21 +00:00
parent 347cbe60bd
commit e7537929ba
9 changed files with 204 additions and 105 deletions
+22 -17
View File
@@ -1978,16 +1978,17 @@ impl Node {
// --- connections (show_connections) ---
let connection_rows: Vec<snap::ConnectionRow> = self
.connections()
.filter_map(|(_, machine)| machine.leg())
.map(|conn| snap::ConnectionRow {
link_id: conn.link_id().as_u64(),
direction: format!("{}", conn.direction()),
handshake_state: self.connection_handshake_state(conn.link_id()).to_string(),
started_at_ms: self.connection_started_at(conn.link_id()),
last_activity_ms: self.connection_last_activity(conn.link_id()),
resend_count: self.connection_resend_count(conn.link_id()),
.map(|(_, machine)| snap::ConnectionRow {
link_id: machine.link_id().as_u64(),
direction: format!("{}", machine.conn_direction()),
handshake_state: self
.connection_handshake_state(machine.link_id())
.to_string(),
started_at_ms: self.connection_started_at(machine.link_id()),
last_activity_ms: self.connection_last_activity(machine.link_id()),
resend_count: self.connection_resend_count(machine.link_id()),
expected_peer: self
.connection_expected_identity(conn.link_id())
.connection_expected_identity(machine.link_id())
.map(|id| id.npub()),
})
.collect();
@@ -2426,7 +2427,7 @@ impl Node {
/// than through the dial or inbound-msg1 paths, which build the machine
/// themselves.
pub fn add_connection(&mut self, connection: PeerConnection) -> Result<(), NodeError> {
let link_id = connection.link_id();
let link_id = connection.state().link_id();
if self
.peer_machines
@@ -2444,8 +2445,8 @@ impl Node {
let machine = self.peer_machines.entry(link_id).or_insert_with(|| {
let now = connection.started_at();
match connection.expected_identity() {
Some(identity) if connection.is_outbound() => {
match connection.state().expected_identity() {
Some(identity) if connection.state().is_outbound() => {
PeerMachine::new_outbound(link_id, *identity, now)
}
_ => PeerMachine::new_inbound(link_id, now),
@@ -2460,6 +2461,9 @@ impl Node {
if let Some(tid) = connection.transport_id() {
machine.set_conn_transport_id(tid);
}
if let Some(addr) = connection.state().source_addr() {
machine.set_conn_source_addr(addr.clone());
}
machine.set_leg(connection);
Ok(())
}
@@ -2492,9 +2496,7 @@ impl Node {
if let Some(id) = seed.transport_id {
connection.set_transport_id(id);
}
if let Some(addr) = seed.source_addr {
connection.set_source_addr(addr);
}
let seeded_source_addr = seed.source_addr.clone();
if let Some(index) = seed.our_index {
connection.set_our_index(index);
}
@@ -2518,8 +2520,8 @@ impl Node {
let machine = self.peer_machines.entry(link_id).or_insert_with(|| {
let now = connection.started_at();
match connection.expected_identity() {
Some(identity) if connection.is_outbound() => {
match connection.state().expected_identity() {
Some(identity) if connection.state().is_outbound() => {
PeerMachine::new_outbound(link_id, *identity, now)
}
_ => PeerMachine::new_inbound(link_id, now),
@@ -2531,6 +2533,9 @@ impl Node {
if let Some(tid) = connection.transport_id() {
machine.set_conn_transport_id(tid);
}
if let Some(addr) = seeded_source_addr {
machine.set_conn_source_addr(addr);
}
machine.set_leg(connection);
Ok(())
}