1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use crate::framing::{CloudProtoError, CloudProtoVersion};
use crate::services::CloudProtoMagic;
use byteorder::{ReadBytesExt, BE};
use std::io::Cursor;
pub(crate) const COMMON_HDR_LEN: usize = 8;
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct CloudProtoPacket {
pub magic: CloudProtoMagic,
pub kind: u8,
pub version: CloudProtoVersion,
pub payload: Vec<u8>,
}
impl CloudProtoPacket {
pub(crate) fn from_buf(buf: &[u8]) -> Result<Self, CloudProtoError> {
let mut reader = Cursor::new(buf);
let magic = reader.read_u8()?.into();
let kind = reader.read_u8()?;
let version = reader.read_u16::<BE>()?.into();
let pkt_size = reader.read_u32::<BE>()? as usize - COMMON_HDR_LEN;
let remaining_size = buf.len() - reader.position() as usize;
if remaining_size != pkt_size {
return Err(CloudProtoError::BadFrameSize(remaining_size, pkt_size));
}
let payload = buf[reader.position() as usize..].to_vec();
Ok(Self {
magic,
kind,
version,
payload,
})
}
pub(crate) fn to_buf(&self) -> Vec<u8> {
use byteorder::WriteBytesExt;
use std::io::Write;
let mut buf = Vec::new();
let mut writer = Cursor::new(&mut buf);
writer.write_u8(self.magic.into()).unwrap();
writer.write_u8(self.kind).unwrap();
writer.write_u16::<BE>(self.version.into()).unwrap();
writer
.write_u32::<BE>((self.payload.len() + COMMON_HDR_LEN) as u32)
.unwrap();
writer.write_all(&self.payload).unwrap();
writer.flush().unwrap();
buf
}
}
#[cfg(test)]
mod test {
use crate::framing::packet::CloudProtoPacket;
use crate::framing::CloudProtoVersion;
use crate::services::CloudProtoMagic;
use anyhow::Result;
#[test_log::test]
fn to_from_buf_serialization() -> Result<()> {
let pkt = CloudProtoPacket {
magic: CloudProtoMagic::Other(0xFF),
kind: 0x73,
version: CloudProtoVersion::Other(0x10E9),
payload: b"Hello world".to_vec(),
};
let pkt2 = CloudProtoPacket::from_buf(&pkt.to_buf())?;
assert_eq!(pkt, pkt2);
Ok(())
}
}