From 777bf2ef1d336e63dd83da0c3099e024b657414e Mon Sep 17 00:00:00 2001 From: asxalex Date: Sat, 17 Feb 2024 23:16:04 +0800 Subject: [PATCH] changed the protocol --- docs/protocol.md | 48 +++++++++---------- examples/benchmark_peer/main.rs | 2 + src/packet/common.rs | 83 ++++++++++++++++++--------------- src/utils/encode_decode.rs | 12 ++++- 4 files changed, 80 insertions(+), 65 deletions(-) diff --git a/docs/protocol.md b/docs/protocol.md index f4a4e58..81a5d74 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -2,45 +2,41 @@ sdlan协议的总体格式如下: ``` -+---------+-------------------+----------+ -| 消息头 | 四字节的消息体长度 | 消息体 | -+---------+-------------------+----------+ ++-----------+------------+--------+----------+ +| 2字节的长度 | 2字节消息id | 消息头 | 消息体 | ++-----------+------------+--------+----------+ ``` +## 长度 +2字节长度包含后面的所有字节的长度(不包括自身) + +## 消息id +用于匹配请求和响应,占用2字节,目前可以都先填写0 + ## 消息头 在sdlan中,有一个common头使用二进制协议,消息头主要包含了协议版本,消息来源id(从哪个节点发出的节点标识),消息ttl,以及一些协议的flag(flag标志以后可以扩充) 消息头二进制格式如下: ``` -+---------+---------+----+-----+------+ -| version | id的长度 | id | ttl | flag | -+---------+---------+----+-----+------+ ++---------+----+-----+------+-----+ +| version | id | ttl | flag | pc | ++---------+----+-----+------+-----+ ``` -其中,version占用一个字节,用于标识协议版本,id长度占用一个字节,用于表示后面id的长度,后面的id用于唯一标识某个客户端(长度在256以内,这里不固定长度,而使用一个字节的id长度标识,方便以后兼容长度不同的情况),之后的ttl占用一个字节,当ttl为0,则直接丢弃该数据包。最后的flag占用2字节,这两个字节分布如下: +其中,version占用一个字节,用于标识协议版本。id用于唯一标识某个客户端,为长度为32字节的uuid,之后的ttl占用一个字节,当ttl为0,则直接丢弃该数据包。后面的flag占用2字节,用于标识数据包属性,目前拥有的标识如下: -``` -+----------------+------------+ -| 9 bit | 5 bit | -+----------------+------------+ -``` +* `from_sn`: `0x0020`,表示这个数据包是从服务端发送过来的。 +* `socket`: `0x0040`,表示这个数据包里面包含了socket信息(待定,因为后面实际的数据包使用了json,这个标识应该没用了)。 -前面9bit用于标识数据包,目前拥有的标识如下: +最后的pc表示后面数据包的类型,目前数据包类型如下: -* `from_sn`: `0xffe0 & 0x0020`,表示这个数据包是从服务端发送过来的。 -* `socket`: `0xffe0 & 0x0040`,表示这个数据包里面包含了socket信息(待定,因为后面实际的数据包使用了json,这个标识应该没用了)。 - -后面5bit表示数据包类型,至多可以表示32种不同的数据包类型。 +* `0` —— `invalid pkt type`,表示无效的数据包类型 +* `1` —— `register super`,表示客户端像服务端发送的注册请求 +* ... TODO ## 消息体 -在消息头之后,消息体格式如下: - -``` -+------------------+--------------------+ -| 四字节的消息体长度 | json化后的消息体 | -+------------------+--------------------+ -``` - -紧接着消息头,是四字节的消息体,所以json化之后的消息体最大长度为$2^{32}$,之后是json化之后的具体的消息结构体。 +消息提根据协议头中的pc不同,拥有不同的结构,结构体在json化之后,添加到消息体的位置。 +### RegisterSuper +`register super`,表示客户端像服务端发送的注册请求,该请求每隔15-20秒发送一次 diff --git a/examples/benchmark_peer/main.rs b/examples/benchmark_peer/main.rs index b0197a1..eda86d3 100644 --- a/examples/benchmark_peer/main.rs +++ b/examples/benchmark_peer/main.rs @@ -1,3 +1,5 @@ +#![allow(unused)] + use sdlan_sn_rs::peer::Peer; use dashmap::DashMap; diff --git a/src/packet/common.rs b/src/packet/common.rs index 18fc188..ded10cf 100644 --- a/src/packet/common.rs +++ b/src/packet/common.rs @@ -1,4 +1,3 @@ -use crate::config; use crate::utils::Result; use byteorder::{BigEndian, ByteOrder}; @@ -21,41 +20,44 @@ impl<'a> Common<'a> { pub fn encode(&self) -> Vec { let mut result = vec![]; encode_u8(&mut result, self.version); - encode_buf_with_size_1(&mut result, self.id.as_bytes()); + + encode_buf_without_size(&mut result, &self.id.as_bytes(), 32); + // encode_buf_with_size_1(&mut result, self.id.as_bytes()); + encode_u8(&mut result, self.ttl); - let mut flag = self.pc.to_u16() & config::FLAGS_TYPE_MASK; - flag |= self.flags & config::FLAGS_BITS_MASK; - encode_u16(&mut result, flag); + encode_u16(&mut result, self.flags); + + let flag = self.pc.to_u8(); + encode_u8(&mut result, flag); result } pub fn from_slice(value: &'a [u8]) -> Result<(Common<'a>, &'a [u8])> { - if value.len() < 2 { + let id_len = 32; + + if value.len() < 5 + id_len { return Err("common header length error".into()); } let version = value[0]; - let id_len = value[1] as usize; - if value.len() < (id_len + 5) as usize { - return Err("common header id length error".into()); - } - let v1 = &value[2..2 + id_len]; - let id = match std::str::from_utf8(v1) { + + let v1 = &value[1..1 + id_len]; + let mut id = match std::str::from_utf8(v1) { Ok(s) => s, Err(e) => return Err(SDLanError::ConvertError(e.to_string())), }; - let ttl = value[2 + id_len]; - let flags = BigEndian::read_u16(&value[3 + id_len..5 + id_len]); - let pc = flags & config::FLAGS_TYPE_MASK; - let flag = flags & config::FLAGS_BITS_MASK; + id = id.trim_end_matches('\0'); + let ttl = value[1 + id_len]; + let flags = BigEndian::read_u16(&value[2 + id_len..4 + id_len]); + let pc = value[4 + id_len]; let common = Self { version, id, ttl, pc: pc.into(), - flags: flag, + flags: flags, }; Ok((common, &value[5 + id_len..])) } @@ -68,8 +70,8 @@ pub enum PacketType { PKTRegisterSuper, } -impl std::convert::From for PacketType { - fn from(value: u16) -> Self { +impl std::convert::From for PacketType { + fn from(value: u8) -> Self { match value { // 0 => Self::PacketInvalid, 1 => Self::PKTRegisterSuper, @@ -79,7 +81,7 @@ impl std::convert::From for PacketType { } impl PacketType { - pub fn to_u16(&self) -> u16 { + pub fn to_u8(&self) -> u8 { match *self { Self::PKTInvalid => 0, Self::PKTRegisterSuper => 1, @@ -113,32 +115,37 @@ mod test { } pub fn encode_packet(cmn: &Common, pkt: &T) -> Result> { - let mut res = cmn.encode(); + // header + let hdr = cmn.encode(); + // body + let body = serde_json::to_vec(pkt)?; - let content = serde_json::to_vec(pkt)?; + let mut result = Vec::with_capacity(4 + hdr.len() + body.len()); + let total_size = (2 + hdr.len() + body.len()) as u16; + // insert total size + result.extend_from_slice(&total_size.to_be_bytes()); + // packet_id + result.extend_from_slice(&[0, 0]); + // insert header + result.extend_from_slice(&hdr); + // insert body + result.extend_from_slice(&body); - dbg!(std::str::from_utf8(&content)); - - let size = content.len() as u32; - // add size bytes - res.extend_from_slice(&size.to_be_bytes()); - res.extend_from_slice(&content); - Ok(res) + Ok(result) } pub fn decode_packet<'a, T: serde::Deserialize<'a>>(value: &'a [u8]) -> Result<(Common<'a>, T)> { - let (cmn, value2) = Common::from_slice(value)?; - if value2.len() < 4 { + if value.len() < 4 { return Err(SDLanError::NormalError("decode pkt length error")); } - let size_bytes = value2[0..4].try_into().expect("never goes here"); - let size = u32::from_be_bytes(size_bytes) as usize; - let value2 = &value2[4..]; - // if value2.len() < size { - if size > value2.len() { - return Err(SDLanError::NormalError("decode pkt size error")); + let size_bytes = value[0..2].try_into().expect("never goes here"); + let size = u16::from_be_bytes(size_bytes); + if value.len() < 2 + size as usize { + return Err(SDLanError::NormalError("decode pkt header size error")); } - let res = serde_json::from_slice(&value2[..size])?; + let value2 = &value[4..2 + size as usize]; + let (cmn, value2) = Common::from_slice(value2)?; + let res = serde_json::from_slice(value2)?; Ok((cmn, res)) } diff --git a/src/utils/encode_decode.rs b/src/utils/encode_decode.rs index ca4fdc1..640d4ae 100644 --- a/src/utils/encode_decode.rs +++ b/src/utils/encode_decode.rs @@ -36,8 +36,18 @@ pub fn encode_i64(v: &mut Vec, value: u64) { v.extend_from_slice(&val); } -pub fn encode_buf_withoud_size(v: &mut Vec, buf: &[u8]) { +pub fn encode_buf_without_size(v: &mut Vec, mut buf: &[u8], size: usize) { + let res_size; + if buf.len() >= size { + buf = &buf[..size]; + res_size = 0; + } else { + res_size = size - buf.len(); + } v.extend_from_slice(buf); + if res_size > 0 { + v.extend_from_slice(&vec![0; res_size]); + } } pub fn encode_buf_with_size_1(v: &mut Vec, buf: &[u8]) {