use crate::protocol::Error;
use crate::protocol::envelope::{Side, opaque};
use crate::protocol::schema::{ArkToHost, HostToArk};
use crate::transport::MAX_MESSAGE_SIZE;
use prost::Message as _;
use prost::bytes::Bytes;
pub fn run(input: &[u8]) -> bool {
#[cfg(feature = "fuzz")]
super::seed::envelope(input);
let Some((&client, bytes)) = input.split_first() else {
return false;
};
check(client & 1 != 0, bytes)
}
fn check(client: bool, bytes: &[u8]) -> bool {
let (side, peer) = match client {
true => (Side::Client, Side::Server),
false => (Side::Server, Side::Client),
};
let Ok(header) = side.decode_header(Bytes::copy_from_slice(bytes)) else {
return false;
};
let Ok((id, body)) = side.decode(bytes) else {
return false;
};
assert_eq!(header.id, id);
assert_eq!(header.failed, body.is_err());
let size = match client {
true => ArkToHost::decode(bytes)
.expect("accepted Ark envelope decodes")
.encoded_len(),
false => HostToArk::decode(bytes)
.expect("accepted host envelope decodes")
.encoded_len(),
};
let encoded = peer.encode(id, body.clone());
if size > MAX_MESSAGE_SIZE {
assert!(
matches!(encoded, Err(Error::TooLarge(actual)) if actual == size),
"oversized envelope must report its encoded size"
);
return true;
}
let bytes = encoded.expect("accepted envelope within the send limit encodes");
assert_eq!(bytes.len(), size);
let (echoed, echo) = side.decode(&bytes).expect("re-encoded envelope decodes");
assert_eq!(echoed, id);
assert_eq!(echo, body);
true
}
pub(super) fn malformed_body(client: bool, id: u64, error: bool) -> Vec<u8> {
let bytes = Bytes::from_static(&[0x80]);
if client {
opaque::ArkToHost {
id,
err: error.then(|| bytes.clone()),
content: (!error).then(|| opaque::ark_to_host::Content::DeviceInfo(bytes)),
}
.encode_to_vec()
} else {
opaque::HostToArk {
id,
err: error.then(|| bytes.clone()),
content: (!error).then(|| opaque::host_to_ark::Content::DeviceInfo(bytes)),
}
.encode_to_vec()
}
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests;