43 lines
1.7 KiB
Rust
43 lines
1.7 KiB
Rust
// (Shared with relay/.)
|
|
#![allow(dead_code)]
|
|
// One frame on the lasting connection between an AnyBot and the account server (a WebSocket):
|
|
// a small JSON header, then the body as raw bytes (no base64), in one binary message.
|
|
//
|
|
// Headers ("t" says which):
|
|
// server → AnyBot job {id, method, path, query, user, role, z, z_ok} a request for this AnyBot
|
|
// AnyBot → server reply {id, status, ctype, headers, z} its answer
|
|
// AnyBot → server call {id, to, method, path, query, z} a request for another AnyBot of the account
|
|
// server → AnyBot ret {id, status, ctype, z} that one's answer
|
|
// AnyBot → server hello {brain} what this AnyBot shows
|
|
// "z": the body is deflate-compressed. "z_ok": the asker can read a compressed answer.
|
|
|
|
use serde_json::Value;
|
|
|
|
pub fn pack(head: &Value, body: &[u8]) -> Vec<u8> {
|
|
let h = head.to_string();
|
|
let mut out = Vec::with_capacity(4 + h.len() + body.len());
|
|
out.extend_from_slice(&(h.len() as u32).to_be_bytes());
|
|
out.extend_from_slice(h.as_bytes());
|
|
out.extend_from_slice(body);
|
|
out
|
|
}
|
|
|
|
pub fn unpack(b: &[u8]) -> Option<(Value, Vec<u8>)> {
|
|
let n = u32::from_be_bytes(b.get(..4)?.try_into().ok()?) as usize;
|
|
let head = serde_json::from_slice(b.get(4..4 + n)?).ok()?;
|
|
Some((head, b[4 + n..].to_vec()))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
#[test]
|
|
fn frames_round_trip() {
|
|
let head = serde_json::json!({"t": "job", "id": "a"});
|
|
let f = super::pack(&head, b"\x00\x01body");
|
|
let (h, b) = super::unpack(&f).unwrap();
|
|
assert_eq!(h, head);
|
|
assert_eq!(b, b"\x00\x01body");
|
|
assert!(super::unpack(&f[..3]).is_none());
|
|
}
|
|
}
|