use crate::*;
const F_KEEPALIVE: &[u8] = b"keep";
const F_LIMIT_BYTE_NANOS: &[u8] = b"lbrt";
const F_LIMIT_IDLE_MILLIS: &[u8] = b"lidl";
const F_AUTH_REQ: &[u8] = b"areq";
const F_AUTH_RES: &[u8] = b"ares";
const PK_SIZE: usize = 32;
const SIG_SIZE: usize = 64;
const HDR_SIZE: usize = PK_SIZE;
const NONCE_SIZE: usize = 32;
pub(crate) const CMD_PREFIX: &[u8; 28] = &[0; 28];
pub enum SbdCmd {
Message(Payload),
Keepalive,
AuthRes([u8; SIG_SIZE]),
Unknown,
}
impl SbdCmd {
pub fn parse(payload: Payload) -> Result<Self> {
if payload.as_ref().len() < HDR_SIZE {
return Err(Error::other("invalid payload length"));
}
if &payload.as_ref()[..28] == CMD_PREFIX {
match &payload.as_ref()[28..32] {
F_KEEPALIVE => Ok(SbdCmd::Keepalive),
F_AUTH_RES => {
if payload.as_ref().len() != HDR_SIZE + SIG_SIZE {
return Err(Error::other("invalid auth res length"));
}
let mut sig = [0; SIG_SIZE];
sig.copy_from_slice(&payload.as_ref()[HDR_SIZE..]);
Ok(SbdCmd::AuthRes(sig))
}
_ => Ok(SbdCmd::Unknown),
}
} else {
Ok(SbdCmd::Message(payload))
}
}
}
impl SbdCmd {
pub fn limit_byte_nanos(limit_byte_nanos: i32) -> Payload {
let mut out = Vec::with_capacity(HDR_SIZE + 4);
let n = limit_byte_nanos.to_be_bytes();
out.extend_from_slice(CMD_PREFIX);
out.extend_from_slice(F_LIMIT_BYTE_NANOS);
out.extend_from_slice(&n[..]);
Payload::Vec(out)
}
pub fn limit_idle_millis(limit_idle_millis: i32) -> Payload {
let mut out = Vec::with_capacity(HDR_SIZE + 4);
let n = limit_idle_millis.to_be_bytes();
out.extend_from_slice(CMD_PREFIX);
out.extend_from_slice(F_LIMIT_IDLE_MILLIS);
out.extend_from_slice(&n[..]);
Payload::Vec(out)
}
pub fn auth_req(nonce: &[u8; 32]) -> Payload {
let mut out = Vec::with_capacity(HDR_SIZE + NONCE_SIZE);
out.extend_from_slice(CMD_PREFIX);
out.extend_from_slice(F_AUTH_REQ);
out.extend_from_slice(&nonce[..]);
Payload::Vec(out)
}
pub fn ready() -> Payload {
Payload::Vec(vec![
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, b's', b'r', b'd', b'y',
])
}
}