feat(relay): ephemeral delivery, call wake-ups and TURN credentials
Protocol and relay groundwork for typing indicators and 1:1 calls. - ContentHint.EPHEMERAL: delivered only to an online recipient, never queued or pushed; the sender gets Receipt.STATUS_DROPPED otherwise. - ContentHint.CALL: a call offer is queued like a normal message, but an offline recipient is woken immediately — a PushKit VoIP push on iOS (priority 10, 45 s expiry) or a short-lived FCM data message on Android. The relay learns that a device is being called, not by whom. - RegisterPush.voip_token stores the iOS VoIP token next to the regular APNs token (migration 0004). - TurnRequest/TurnCredentials: logged-in devices receive time-limited coturn credentials (use-auth-secret REST scheme, HMAC-SHA1), so the TURN server is never an open relay. Configured with SEPOT_TURN_URLS and SEPOT_TURN_SECRET or SEPOT_TURN_SECRET_FILE; without them calls fall back to direct connections and STUN.
This commit is contained in:
@@ -314,9 +314,13 @@ async fn handle(state: Arc<AppState>, socket: WebSocket) {
|
||||
} else {
|
||||
let endpoint =
|
||||
(!reg.endpoint.is_empty()).then_some(reg.endpoint.as_slice());
|
||||
// VoIP token dává smysl jen vedle APNs (PushKit je iOS).
|
||||
let voip = (platform == crate::push::PLATFORM_APNS
|
||||
&& !reg.voip_token.is_empty())
|
||||
.then_some(reg.voip_token.as_slice());
|
||||
// Endpoint se ZÁMĚRNĚ neloguje (metadatový bod).
|
||||
if let Err(e) =
|
||||
state.register_push(device, platform, endpoint).await
|
||||
state.register_push(device, platform, endpoint, voip).await
|
||||
{
|
||||
tracing::warn!("register_push selhal: {e}");
|
||||
}
|
||||
@@ -351,6 +355,16 @@ async fn handle(state: Arc<AppState>, socket: WebSocket) {
|
||||
}
|
||||
}
|
||||
|
||||
Some(v1::client_frame::Frame::TurnRequest(_)) if authed_address.is_some() => {
|
||||
let frame = match &state.turn {
|
||||
Some(turn) => server_frame(v1::server_frame::Frame::TurnCredentials(
|
||||
turn.credentials(chrono::Utc::now().timestamp()),
|
||||
)),
|
||||
None => error_frame(503, "TURN není nakonfigurován"),
|
||||
};
|
||||
let _ = tx.send(frame).await;
|
||||
}
|
||||
|
||||
Some(v1::client_frame::Frame::Pong(_)) => {}
|
||||
|
||||
_ => {
|
||||
|
||||
Reference in New Issue
Block a user