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/// SDP offer or answer signed by the sender's [`crate::Identity`].
14///
15/// The wire form is a base64 string carrying the sender's public key plus
16/// a biscuit token whose verified `sdp` fact contains the actual SDP. This
17/// is what `Peer::start` / `receive_offer` / `receive_answer` produce and
18/// consume.
19#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
20pub struct SignalingPayload {
21    #[serde(
22        serialize_with = "serialize_base64_pubkey",
23        deserialize_with = "deserialize_base64_pubkey"
24    )]
25    pub pubkey: PublicKey,
26    #[serde(
27        serialize_with = "serialize_base64_vec",
28        deserialize_with = "deserialize_base64_vec"
29    )]
30    pub token: Vec<u8>,
31}
32
33impl SignalingPayload {
34    pub fn from_base64(data: &str) -> Result<Self> {
35        let decoded = BASE64_URL_SAFE_NO_PAD.decode(data)?;
36        serde_json::from_slice(&decoded).map_err(|e| anyhow!(e))
37    }
38
39    pub fn to_base64(&self) -> Result<String> {
40        let json = serde_json::to_string(&self).map_err(|e| anyhow!(e))?;
41        Ok(BASE64_URL_SAFE_NO_PAD.encode(json))
42    }
43
44    pub fn peer_id(&self) -> PeerID {
45        PeerID(self.pubkey)
46    }
47
48    /// Verify the payload was signed by `expected_sender` and return the SDP.
49    pub fn get_sdp_verified(&self, expected_sender: &PeerID) -> Result<String> {
50        ensure!(
51            self.pubkey == expected_sender.pubkey(),
52            "pubkey does not match sender PeerID"
53        );
54        let token = Biscuit::from(&self.token, self.pubkey)?;
55        let mut authorizer = AuthorizerBuilder::new()
56            .policy("allow if true")?
57            .set_limits(RunLimits {
58                max_time: Duration::from_millis(100),
59                ..Default::default()
60            })
61            .build(&token)?;
62        let (sdp_b64,): (String,) = authorizer.query_exactly_one("data($s) <- sdp($s)")?;
63        let bytes = BASE64_URL_SAFE_NO_PAD
64            .decode(sdp_b64)
65            .map_err(|e| anyhow!("invalid base64 in token sdp fact: {e}"))?;
66        String::from_utf8(bytes).map_err(|e| anyhow!("invalid utf-8 in token sdp fact: {e}"))
67    }
68}