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) => {