changed the protocol
This commit is contained in:
parent
a100c64e4c
commit
777bf2ef1d
@ -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秒发送一次
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
#![allow(unused)]
|
||||
|
||||
use sdlan_sn_rs::peer::Peer;
|
||||
|
||||
use dashmap::DashMap;
|
||||
|
||||
@ -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<u8> {
|
||||
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<u16> for PacketType {
|
||||
fn from(value: u16) -> Self {
|
||||
impl std::convert::From<u8> for PacketType {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
// 0 => Self::PacketInvalid,
|
||||
1 => Self::PKTRegisterSuper,
|
||||
@ -79,7 +81,7 @@ impl std::convert::From<u16> 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<T: serde::Serialize>(cmn: &Common, pkt: &T) -> Result<Vec<u8>> {
|
||||
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))
|
||||
}
|
||||
|
||||
@ -36,8 +36,18 @@ pub fn encode_i64(v: &mut Vec<u8>, value: u64) {
|
||||
v.extend_from_slice(&val);
|
||||
}
|
||||
|
||||
pub fn encode_buf_withoud_size(v: &mut Vec<u8>, buf: &[u8]) {
|
||||
pub fn encode_buf_without_size(v: &mut Vec<u8>, 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<u8>, buf: &[u8]) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user