Skip to main content

antenna_protocol/handshake/
signaling.rs

1use crate::{
2    deserialize_base64_pubkey, deserialize_base64_vec, serialize_base64_pubkey,
3    serialize_base64_vec,
4};
5use anyhow::{Result, anyhow, ensure};
6use base64::{Engine, prelude::BASE64_URL_SAFE_NO_PAD};
7use biscuit_auth::{Biscuit, PublicKey, builder::AuthorizerBuilder, datalog::RunLimits};
8use serde::{Deserialize, Serialize};
9use std::time::Duration;
10
11use crate::PeerID;
12
13#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
14pub struct SignalingPayload {
15    #[serde(
16        serialize_with = "serialize_base64_pubkey",
17        deserialize_with = "deserialize_base64_pubkey"
18    )]
19    pub pubkey: PublicKey,
20    #[serde(
21        serialize_with = "serialize_base64_vec",
22        deserialize_with = "deserialize_base64_vec"
23    )]
24    pub token: Vec<u8>,
25}
26
27impl SignalingPayload {
28    pub fn from_base64(data: &str) -> Result<Self> {
29        let decoded = BASE64_URL_SAFE_NO_PAD.decode(data)?;
30        serde_json::from_slice(&decoded).map_err(|e| anyhow!(e))
31    }
32
33    pub fn to_base64(&self) -> Result<String> {
34        let json = serde_json::to_string(&self).map_err(|e| anyhow!(e))?;
35        Ok(BASE64_URL_SAFE_NO_PAD.encode(json))
36    }
37
38    pub fn peer_id(&self) -> PeerID {
39        PeerID(self.pubkey)
40    }
41
42    /// Verify the payload was signed by `expected_sender` and return the SDP.
43    pub fn get_sdp_verified(&self, expected_sender: &PeerID) -> Result<String> {
44        ensure!(
45            self.pubkey == expected_sender.pubkey(),
46            "pubkey does not match sender PeerID"
47        );
48        let token = Biscuit::from(&self.token, self.pubkey)?;
49        let mut authorizer = AuthorizerBuilder::new()
50            .policy("allow if true")?
51            .set_limits(RunLimits {
52                max_time: Duration::from_millis(100),
53                ..Default::default()
54            })
55            .build(&token)?;
56        let (sdp_b64,): (String,) = authorizer.query_exactly_one("data($s) <- sdp($s)")?;
57        let bytes = BASE64_URL_SAFE_NO_PAD
58            .decode(sdp_b64)
59            .map_err(|e| anyhow!("invalid base64 in token sdp fact: {e}"))?;
60        String::from_utf8(bytes).map_err(|e| anyhow!("invalid utf-8 in token sdp fact: {e}"))
61    }
62}