From a3ebf5616f77918accbd3cdd0f5b152c7803605d Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Wed, 8 Apr 2026 11:09:15 +0400 Subject: [PATCH] fix: unified raw room names + merged presence on join 1. CLI client now sends raw room names (no hash), matching Android JNI and Desktop Tauri. All three clients are now consistent. 2. When a client joins a global room, the relay merges federated remote participants into the initial RoomUpdate. Previously, clients that joined after the GlobalRoomActive signal only saw local participants. Now they see everyone immediately. 3. Added get_remote_participants() to FederationManager for querying cached remote participants from all peer links. Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/wzp-client/src/cli.rs | 7 +++---- crates/wzp-relay/src/federation.rs | 20 ++++++++++++++++++++ crates/wzp-relay/src/main.rs | 26 ++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/crates/wzp-client/src/cli.rs b/crates/wzp-client/src/cli.rs index 3b1df69..c983029 100644 --- a/crates/wzp-client/src/cli.rs +++ b/crates/wzp-client/src/cli.rs @@ -250,12 +250,11 @@ async fn main() -> anyhow::Result<()> { "WarzonePhone client" ); - // Hash room name for SNI privacy (or "default" if none specified) + // Use raw room name as SNI (consistent with Android + Desktop clients for federation) let sni = match &cli.room { Some(name) => { - let hashed = wzp_crypto::hash_room_name(name); - info!(room = %name, hashed = %hashed, "room name hashed for SNI"); - hashed + info!(room = %name, "using room name as SNI"); + name.clone() } None => "default".to_string(), }; diff --git a/crates/wzp-relay/src/federation.rs b/crates/wzp-relay/src/federation.rs index 6587b8e..84ac10d 100644 --- a/crates/wzp-relay/src/federation.rs +++ b/crates/wzp-relay/src/federation.rs @@ -241,6 +241,26 @@ impl FederationManager { } } + /// Get all remote participants for a room from all peer links. + pub async fn get_remote_participants(&self, room: &str) -> Vec { + let canonical = self.resolve_global_room(room); + let links = self.peer_links.lock().await; + let mut result = Vec::new(); + for link in links.values() { + // Check canonical name + if let Some(c) = canonical { + if let Some(remote) = link.remote_participants.get(c) { + result.extend(remote.iter().cloned()); + } + } + // Also check raw room name + if let Some(remote) = link.remote_participants.get(room) { + result.extend(remote.iter().cloned()); + } + } + result + } + /// Forward locally-generated media to all connected peers. /// For locally-originated media, we send to ALL peers (they decide whether to deliver). /// For forwarded media (multi-hop), handle_datagram filters by active_rooms. diff --git a/crates/wzp-relay/src/main.rs b/crates/wzp-relay/src/main.rs index 75de5c8..0c302ad 100644 --- a/crates/wzp-relay/src/main.rs +++ b/crates/wzp-relay/src/main.rs @@ -15,7 +15,7 @@ use std::time::Duration; use tokio::sync::Mutex; use tracing::{error, info, warn}; -use wzp_proto::MediaTransport; +use wzp_proto::{MediaTransport, SignalMessage}; use wzp_relay::config::RelayConfig; use wzp_relay::metrics::RelayMetrics; use wzp_relay::pipeline::{PipelineConfig, RelayPipeline}; @@ -741,7 +741,29 @@ async fn main() -> anyhow::Result<()> { Ok((id, update, senders)) => { metrics.active_rooms.set(mgr.list().len() as i64); drop(mgr); // release lock before async broadcast - room::broadcast_signal(&senders, &update).await; + + // Merge federated participants into RoomUpdate if this is a global room + let merged_update = if let Some(ref fm) = federation_mgr { + if fm.is_global_room(&room_name) { + if let SignalMessage::RoomUpdate { count: _, participants: mut local_parts } = update { + let remote = fm.get_remote_participants(&room_name).await; + if !remote.is_empty() { + local_parts.extend(remote); + SignalMessage::RoomUpdate { + count: local_parts.len() as u32, + participants: local_parts, + } + } else { + SignalMessage::RoomUpdate { + count: local_parts.len() as u32, + participants: local_parts, + } + } + } else { update } + } else { update } + } else { update }; + + room::broadcast_signal(&senders, &merged_update).await; id } Err(e) => {