portal_solutions_extism_compat/
lib.rs

1use std::{collections::BTreeMap, sync::{LazyLock, Mutex}};
2
3use base64::Engine;
4use extism_pdk::*;
5#[link(wasm_import_module = "_ext")]
6unsafe extern "C" {
7    fn read_guest(id: u32, idx: u64) -> u8;
8    fn write_guest(id: u32, idx: u64, value: u8);
9    fn len_guest(id: u32) -> u64;
10}
11
12#[unsafe(export_name = "_px_app_core")]
13extern "C" fn core_call() {}
14
15pub static pollers: LazyLock<Mutex<BTreeMap<[u8; 32], ([u8; 32], String)>>> =
16    LazyLock::new(|| Mutex::new(Default::default()));
17
18pub fn do_login_poll(name: &str) -> Result<BTreeMap<[u8; 32], [u8; 32]>, Error> {
19    let mut p = pollers.lock().unwrap();
20    let mut m: BTreeMap<[u8; 32], [u8; 32]> = BTreeMap::new();
21    let mut blob = format!("");
22    let mut idxs = vec![];
23    for (k, (v, s)) in p.iter() {
24        if s != name {
25            continue;
26        }
27        blob = format!(
28            "{blob}${}",
29            base64::engine::general_purpose::URL_SAFE.encode(k)
30        );
31        idxs.push(*k);
32        // m.insert(*k)
33    }
34    let r = http::request::<Memory>(
35        &HttpRequest {
36            url: format!("{name}/login/auto/poll/b64/{blob}"),
37            headers: Default::default(),
38            method: Some(format!("GET")),
39        },
40        None,
41    )?;
42    for (c, k) in r.body().chunks(32).zip(idxs) {
43        let c: [u8; 32] = c.try_into().unwrap();
44        if c == [0u8; 32] {
45            continue;
46        }
47        let Some((v, _)) = p.remove(&k) else {
48            continue;
49        };
50        let v = std::array::from_fn(|i| c[i] ^ v[i]);
51        m.insert(k, v);
52    }
53    Ok(m)
54}