fix(relay): seed peers before join welcome

The gateway authorizes remote-to-LAN frames from the relay lifecycle table. A
new client can start sending Ethernet datagrams as soon as it receives its
welcome, so the relay should notify already-present peers before returning that
welcome to the joining peer.

Register the accepted peer, send the PeerJoined event to existing peers, and
then send the welcome to the joining peer. If the welcome write fails after the
pre-notification, remove the accepted peer and send PeerLeft so existing peers
do not retain stale client MAC state.

This still is not a cross-connection delivery proof, but it puts the relay-side
ordering in the right direction for first DHCP/ARP frames after a client joins.

Test Plan:
- cargo test -p lanparty-relay
- cargo fmt --check
- cargo test --workspace
- cargo clippy --workspace --all-targets -- -D warnings
- git diff --check
- git diff --cached --check

Refs: PLAN.md MVP relay lifecycle and gateway MAC learning
This commit is contained in:
2026-05-22 06:31:39 +02:00
parent ab8bda4bdf
commit 1d469d437b
2 changed files with 14 additions and 3 deletions
+11 -2
View File
@@ -275,18 +275,27 @@ async fn accept_control_handshake(
let (accepted, response) = build_handshake_response(rooms, connection, frame.as_slice()).await;
if let Some(accepted) = &accepted {
register_peer(sessions, accepted, connection.clone()).await;
// Seed existing peers before the joining peer can send Ethernet datagrams.
notify_peer_joined(sessions, accepted).await;
}
if let Err(error) = send_control_message(&mut send, &response).await {
if let Some(accepted) = &accepted {
leave_peer(rooms, sessions, &accepted.room, accepted.peer.peer_id()).await?;
let leave =
leave_peer(rooms, sessions, &accepted.room, accepted.peer.peer_id()).await?;
notify_peer_left(
sessions,
&accepted.room,
leave.peer().peer_id(),
DisconnectReason::Normal,
)
.await;
}
return Err(error);
}
if let Some(accepted) = &accepted {
notify_peer_joined(sessions, accepted).await;
notify_existing_peers_to_joined_peer(rooms, connection, accepted).await;
}