zenkey_fleet/session.rs
1//! Session setup for un-namespaced observers (RFC 09 §5).
2
3use anyhow::{Context, Result};
4use zenoh::Session;
5
6/// Open a session for a read-only explorer.
7///
8/// RFC 09 §5: debug tools run *without* the session namespace and spell full
9/// keys — "which is also the honest view of what is on the wire". So we never
10/// set `namespace`, and every key this tool prints is the real one.
11///
12/// Scouting defaults to **off**. A bus explorer that multicast-scouts will join
13/// whatever mesh it can find, which is how a throwaway session ends up
14/// contaminating a live fleet; opt in explicitly with `--scouting` when you
15/// mean it.
16pub async fn open(connect: &[String], listen: &[String], scouting: bool) -> Result<Session> {
17 let mut config = zenoh::Config::default();
18 let json_list = |v: &[String]| {
19 let items: Vec<String> = v.iter().map(|e| format!("{e:?}")).collect();
20 format!("[{}]", items.join(","))
21 };
22 config
23 .insert_json5("scouting/multicast/enabled", &scouting.to_string())
24 .ok();
25 if !connect.is_empty() {
26 config
27 .insert_json5("connect/endpoints", &json_list(connect))
28 .ok();
29 }
30 if !listen.is_empty() {
31 config
32 .insert_json5("listen/endpoints", &json_list(listen))
33 .ok();
34 }
35 zenoh::open(config)
36 .await
37 .map_err(|e| anyhow::anyhow!("{e}"))
38 .context("failed to open Zenoh session")
39}