fix: unified raw room names + merged presence on join
Some checks failed
Mirror to GitHub / mirror (push) Failing after 42s
Build Release Binaries / build-amd64 (push) Failing after 2m1s

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) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-04-08 11:09:15 +04:00
parent ff6d0444c0
commit a3ebf5616f
3 changed files with 47 additions and 6 deletions

View File

@@ -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(),
};

View File

@@ -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<wzp_proto::packet::RoomParticipant> {
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.

View File

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