diff --git a/README.md b/README.md index 449c579..0cc579f 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,9 @@ Unknown unicast from a client is forwarded only to the gateway port; unknown unicast from the gateway is dropped instead of flooded to every remote client. When a peer joins or leaves, the relay sends a reliable lifecycle control event to peers that are still present in the room. Newly joined peers also receive -`PeerJoined` events for peers that were already present. +`PeerJoined` events for peers that were already present. Accepted joins notify +existing peers before the joining peer receives its welcome, so gateways can +seed client MAC state before a freshly accepted client starts sending frames. ### MVP Trust Model diff --git a/crates/lanparty-relay/src/server.rs b/crates/lanparty-relay/src/server.rs index 9aa9ca3..964a4b6 100644 --- a/crates/lanparty-relay/src/server.rs +++ b/crates/lanparty-relay/src/server.rs @@ -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; }