openrtc/
protocol_config.rs1use std::collections::HashSet;
4
5pub const OPENRTC_ALPN: &[u8] = b"plutonium/p2p/1";
6pub const MAX_ROUTER_PROTOCOLS: usize = 32;
7pub const MAX_ALPN_BYTES: usize = 255;
8
9pub fn router_alpns(
10 extra_alpns: Vec<Vec<u8>>,
11 include_standard_protocols: bool,
12) -> anyhow::Result<Vec<Vec<u8>>> {
13 let mut alpns = extra_alpns;
14 alpns.push(OPENRTC_ALPN.to_vec());
15 if include_standard_protocols {
16 #[cfg(feature = "iroh-protocols-wasm")]
17 alpns.extend([
18 iroh_blobs::ALPN.to_vec(),
19 iroh_gossip::ALPN.to_vec(),
20 iroh_docs::ALPN.to_vec(),
21 ]);
22 #[cfg(not(feature = "iroh-protocols-wasm"))]
23 anyhow::bail!("standard Iroh protocols are not compiled into this runtime");
24 }
25 anyhow::ensure!(
26 alpns.len() <= MAX_ROUTER_PROTOCOLS,
27 "Iroh router protocol count exceeds {MAX_ROUTER_PROTOCOLS}"
28 );
29 let mut seen = HashSet::with_capacity(alpns.len());
30 for alpn in &alpns {
31 anyhow::ensure!(!alpn.is_empty(), "Iroh ALPN must not be empty");
32 anyhow::ensure!(
33 alpn.len() <= MAX_ALPN_BYTES,
34 "Iroh ALPN exceeds {MAX_ALPN_BYTES} bytes"
35 );
36 anyhow::ensure!(seen.insert(alpn.clone()), "duplicate Iroh ALPN");
37 }
38 Ok(alpns)
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn router_alpns_rejects_duplicate_and_invalid_values() {
47 assert!(router_alpns(vec![OPENRTC_ALPN.to_vec()], false).is_err());
48 assert!(router_alpns(vec![Vec::new()], false).is_err());
49 assert!(router_alpns(vec![vec![1; MAX_ALPN_BYTES + 1]], false).is_err());
50 }
51
52 #[test]
53 fn router_alpns_preserves_declared_order_and_adds_openrtc() {
54 assert_eq!(
55 router_alpns(vec![b"example/custom/1".to_vec()], false).unwrap(),
56 vec![b"example/custom/1".to_vec(), OPENRTC_ALPN.to_vec()]
57 );
58 }
59
60 #[cfg(feature = "iroh-protocols-wasm")]
61 #[test]
62 fn standard_protocols_are_declared_once() {
63 let alpns = router_alpns(Vec::new(), true).unwrap();
64 assert_eq!(alpns.len(), 4);
65 assert!(alpns.contains(&iroh_docs::ALPN.to_vec()));
66 assert!(alpns.contains(&iroh_blobs::ALPN.to_vec()));
67 assert!(alpns.contains(&iroh_gossip::ALPN.to_vec()));
68 }
69}