Skip to main content

shared_store

Function shared_store 

Source
pub fn shared_store<S: LeafStore + 'static>(store: S) -> SharedStore
Expand description

Wraps a store in the handle a LeafDevice takes.

use offline_protocol_leaf::{shared_store, LeafDevice, MemoryStore};

let device = LeafDevice::open(shared_store(MemoryStore::new()), "com.example.lock")?;
Examples found in repository?
examples/wasi_host_shim.rs (line 123)
112fn run() -> Result<(), String> {
113    let args: Vec<String> = std::env::args().skip(1).collect();
114    let [app_id, peer, now] = args.as_slice() else {
115        return Err(USAGE.to_string());
116    };
117    let now_unix_secs: u64 = now
118        .parse()
119        .map_err(|_| format!("now_unix_secs must be a whole number of seconds, got {now:?}"))?;
120
121    // `shared_store` rather than `Arc::new`: it is the one constructor that
122    // builds on every target the crate supports, so it is the route to copy.
123    let store = shared_store(MemoryStore::new());
124
125    // Provisioning draws from the getrandom backend the target selects. On
126    // WASI that is the runtime's `random_get`; see the header.
127    let mut device =
128        LeafDevice::open(store, app_id).map_err(|error| format!("opening the device: {error}"))?;
129    eprintln!("address {}", device.address());
130
131    let stdout = io::stdout();
132    let mut out = stdout.lock();
133
134    // Pairing starts with the device's key package. The time is supplied, not
135    // read: with `now_unix_secs` the package's validity window is real, and
136    // without it the library would stamp 1970.
137    let advertisement = device
138        .key_package_frame(peer, now_unix_secs)
139        .map_err(|error| format!("minting the key package: {error}"))?;
140    emit(&mut out, &advertisement)?;
141
142    // Steady state: frames arrive, the device verifies each, opens it if it is
143    // sealed, persists, and only then hands back what it owes in reply.
144    for (index, line) in io::stdin().lock().lines().enumerate() {
145        let line = line.map_err(|error| format!("reading standard input: {error}"))?;
146        if line.trim().is_empty() {
147            continue;
148        }
149        let inbound = Message::from_json(&line)
150            .map_err(|error| format!("line {}: not a frame: {error}", index + 1))?;
151        match device.handle(&inbound, now_unix_secs) {
152            Ok(handled) => {
153                for event in &handled.events {
154                    eprintln!("event {event:?}");
155                }
156                for frame in &handled.outbound {
157                    emit(&mut out, frame)?;
158                }
159            }
160            Err(error) => eprintln!("line {}: refused: {error}", index + 1),
161        }
162    }
163
164    // Answering. The persist is inside `seal`, before it returns anything, so
165    // there is no ordering here to get wrong. Without the phone's Welcome
166    // there is no session, and the crate says so rather than sealing into a
167    // group that does not exist.
168    match device.seal(peer, GREETING, now_unix_secs) {
169        Ok(frame) => emit(&mut out, &frame),
170        Err(LeafError::NoSession(_)) => {
171            eprintln!(
172                "no session with {peer}: nothing sealed. A session exists only after the \
173                 phone's Welcome, and no frame on standard input carried one."
174            );
175            Ok(())
176        }
177        Err(error) => Err(format!("sealing to {peer}: {error}")),
178    }
179}