merge main: PresenceList signal for lobby
This commit is contained in:
@@ -138,6 +138,7 @@ pub fn signal_to_call_type(signal: &SignalMessage) -> CallSignalType {
|
||||
| SignalMessage::UpgradeResponse { .. }
|
||||
| SignalMessage::UpgradeConfirm { .. }
|
||||
| SignalMessage::QualityCapability { .. } => CallSignalType::Offer, // quality negotiation
|
||||
SignalMessage::PresenceList { .. } => CallSignalType::Offer, // lobby presence
|
||||
SignalMessage::QualityDirective { .. } => CallSignalType::Offer, // relay-initiated
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ pub use codec_id::{CodecId, QualityProfile};
|
||||
pub use error::*;
|
||||
pub use packet::{
|
||||
CallAcceptMode, HangupReason, MediaHeader, MediaPacket, MiniFrameContext, MiniHeader,
|
||||
QualityReport, RoomParticipant, SignalMessage, TrunkEntry, TrunkFrame, FRAME_TYPE_FULL,
|
||||
PresenceUser, QualityReport, RoomParticipant, SignalMessage, TrunkEntry, TrunkFrame, FRAME_TYPE_FULL,
|
||||
FRAME_TYPE_MINI,
|
||||
};
|
||||
pub use bandwidth::{BandwidthEstimator, CongestionState};
|
||||
|
||||
@@ -156,6 +156,14 @@ impl MediaHeader {
|
||||
}
|
||||
}
|
||||
|
||||
/// A user visible in the signal presence list.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct PresenceUser {
|
||||
pub fingerprint: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub alias: Option<String>,
|
||||
}
|
||||
|
||||
/// Quality report appended to a media packet when Q flag is set (4 bytes).
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct QualityReport {
|
||||
@@ -1020,6 +1028,16 @@ pub enum SignalMessage {
|
||||
reason: Option<String>,
|
||||
},
|
||||
|
||||
// ── Signal presence ───────────────────────────────────────────
|
||||
|
||||
/// Relay broadcasts the list of currently registered signal
|
||||
/// users to all connected clients. Sent on every register/
|
||||
/// deregister so clients can maintain a live lobby user list.
|
||||
PresenceList {
|
||||
/// List of online users. Each entry is { fingerprint, alias }.
|
||||
users: Vec<PresenceUser>,
|
||||
},
|
||||
|
||||
// ── Quality upgrade negotiation (#28, #29) ──────────────────
|
||||
|
||||
/// Peer proposes upgrading to a higher quality profile.
|
||||
|
||||
@@ -1016,6 +1016,13 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
info!(%addr, fingerprint = %client_fp, alias = ?client_alias, "signal client registered");
|
||||
|
||||
// Broadcast updated presence to all signal clients
|
||||
{
|
||||
let hub = signal_hub.lock().await;
|
||||
let presence = hub.presence_list();
|
||||
hub.broadcast(&presence).await;
|
||||
}
|
||||
|
||||
// Signal recv loop
|
||||
loop {
|
||||
match transport.recv_signal().await {
|
||||
@@ -1560,6 +1567,9 @@ async fn main() -> anyhow::Result<()> {
|
||||
{
|
||||
let mut hub = signal_hub.lock().await;
|
||||
hub.unregister(&client_fp);
|
||||
// Broadcast updated presence to remaining clients
|
||||
let presence_msg = hub.presence_list();
|
||||
hub.broadcast(&presence_msg).await;
|
||||
}
|
||||
{
|
||||
let mut reg = presence.lock().await;
|
||||
|
||||
@@ -86,6 +86,26 @@ impl SignalHub {
|
||||
pub fn alias(&self, fp: &str) -> Option<&str> {
|
||||
self.clients.get(fp).and_then(|c| c.alias.as_deref())
|
||||
}
|
||||
|
||||
/// Build a PresenceList message with all online users.
|
||||
pub fn presence_list(&self) -> SignalMessage {
|
||||
let users: Vec<wzp_proto::PresenceUser> = self
|
||||
.clients
|
||||
.values()
|
||||
.map(|c| wzp_proto::PresenceUser {
|
||||
fingerprint: c.fingerprint.clone(),
|
||||
alias: c.alias.clone(),
|
||||
})
|
||||
.collect();
|
||||
SignalMessage::PresenceList { users }
|
||||
}
|
||||
|
||||
/// Broadcast a message to ALL connected signal clients.
|
||||
pub async fn broadcast(&self, msg: &SignalMessage) {
|
||||
for client in self.clients.values() {
|
||||
let _ = client.transport.send_signal(msg).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1451,6 +1451,20 @@ fn do_register_signal(
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(Some(SignalMessage::PresenceList { users })) => {
|
||||
tracing::info!(count = users.len(), "signal: PresenceList received");
|
||||
// Emit to JS frontend for lobby user list
|
||||
let user_list: Vec<serde_json::Value> = users.iter().map(|u| {
|
||||
serde_json::json!({
|
||||
"fingerprint": u.fingerprint,
|
||||
"alias": u.alias,
|
||||
})
|
||||
}).collect();
|
||||
let _ = app_clone.emit("signal-event", serde_json::json!({
|
||||
"type": "presence_list",
|
||||
"users": user_list,
|
||||
}));
|
||||
}
|
||||
Ok(Some(SignalMessage::UpgradeProposal { call_id, proposal_id, proposed_profile, local_loss_pct, local_rtt_ms })) => {
|
||||
tracing::info!(%call_id, %proposal_id, ?proposed_profile, "signal: UpgradeProposal from peer");
|
||||
emit_call_debug(&app_clone, "recv:UpgradeProposal", serde_json::json!({
|
||||
|
||||
Reference in New Issue
Block a user