sdlan-lib-rs/src/tcp/tcp_codec.rs
2026-04-09 17:55:21 +08:00

279 lines
6.3 KiB
Rust
Executable File

use std::sync::atomic::Ordering;
use quinn::RecvStream;
use tokio::{
io::{AsyncReadExt},
};
use num_enum::TryFromPrimitive;
use tracing::{debug, error};
use crate::{network::Node, pb::{SdlStunRequest, Sdlv6Info, encode_to_udp_message}, utils::send_to_sock};
#[derive(Debug)]
pub struct SdlanTcp {
// pub _packet_id: u32,
pub packet_type: PacketType,
pub current_packet: Vec<u8>,
}
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
#[repr(u8)]
pub enum EventType {
KnownIP = 0x01,
DropIP = 0x02,
NatChanged = 0x03,
SendRegister = 0x04,
NetworkShutdown = 0xFF,
}
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
#[repr(u8)]
pub enum StunProbeAttr {
None = 0,
Port = 1,
Peer = 2,
}
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
#[repr(u8)]
pub enum NatType {
Blocked = 0,
NoNat = 1,
FullCone = 2,
PortRestricted = 3,
ConeRestricted = 4,
Symmetric = 5,
Invalid = 0xff,
}
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
#[repr(u8)]
pub enum NakMsgCode {
InvalidToken = 1,
NodeDisabled = 2,
NoIpAddress = 3,
NetworkFault = 4,
InternalFault = 5,
}
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
#[repr(u8)]
pub enum PacketType {
Empty = 0x00,
RegisterSuper = 0x01,
RegisterSuperACK = 0x02,
RegisterSuperNAK = 0x04,
UnRegisterSuper = 0x05,
QueryInfo = 0x06,
PeerInfo = 0x07,
Ping = 0x08,
Pong = 0x09,
Event = 0x10,
Command = 0x11,
CommandACK = 0x12,
FlowTracer = 0x15,
Register = 0x20,
RegisterACK = 0x21,
StunRequest = 0x30,
StunReply = 0x31,
StunProbe = 0x32,
StunProbeReply = 0x33,
Welcome = 0x4f,
ArpRequest = 0x50,
ArpResponse = 0x51,
PolicyRequest = 0xb0,
PolicyReply = 0xb1,
Data = 0xff,
}
pub async fn send_stun_request(eee: &Node) {
let sdl_v6_info = match *eee.ipv6.read().unwrap() {
Some(ref l) => Some(Sdlv6Info {
port: l.port as u32,
v6: Vec::from(l.v6),
}),
None => None,
};
let req = SdlStunRequest {
session_token: Vec::from(eee.session_token.get()),
// cookie: 0,
client_id: eee.config.node_uuid.clone(),
network_id: eee.network_id.load(Ordering::Relaxed),
ip: eee.device_config.get_ip(),
mac: Vec::from(eee.device_config.get_mac()),
nat_type: eee.get_nat_type() as u32,
v6_info: sdl_v6_info,
};
debug!("stun request: {:?}", req);
let msg = encode_to_udp_message(Some(req), PacketType::StunRequest as u8).unwrap();
if let Err(e) = send_to_sock(
eee,
&msg,
&eee.config.super_nodes[eee.config.super_node_index.load(Ordering::Relaxed) as usize],
)
.await
{
error!("failed to send to sock: {:?}", e);
}
}
pub async fn read_a_packet(
reader: &mut RecvStream,
) -> Result<SdlanTcp, std::io::Error> {
// debug!("read a packet");
let payload_size = reader.read_u16().await?;
// debug!("payload size: {}", payload_size);
let packet_type = reader.read_u8().await?;
// debug!("packet type: 0x{:02x}", packet_type);
if payload_size < 1 {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"size less than five",
));
}
let bufsize = (payload_size - 1) as usize;
let mut binary = vec![0; bufsize];
let mut to_read = bufsize;
loop {
if to_read == 0 {
break;
}
let size_got = reader.read(&mut binary[(bufsize - to_read)..]).await?;
if size_got.is_none() {
break;
}
let size_got = size_got.unwrap();
if size_got == 0 {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"read got zero bytes",
));
}
to_read -= size_got;
}
let Ok(packet_type) = packet_type.try_into() else {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("packet type error: 0x{:02x}", packet_type),
));
};
let result = SdlanTcp {
// _packet_id: packet_id,
packet_type,
current_packet: binary,
};
Ok(result)
}
/*
pub async fn read_a_packet2(reader: &mut OwnedReadHalf) -> Result<SdlanTcp, std::io::Error> {
debug!("read a packet");
let size = reader.read_u16().await?;
debug!("1");
let packet_id = reader.read_u32().await?;
debug!("2");
let packet_type = reader.read_u8().await?;
debug!("3");
if size < 5 {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"size less than five",
));
}
let mut binary = vec![0; (size - 5) as usize];
let mut bytes_read = 0;
loop {
let size_got = reader.read(&mut binary[bytes_read..]).await?;
if size_got == 0 {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"read got zero bytes",
));
}
bytes_read += size_got;
if bytes_read == (size - 5) as usize {
break;
}
}
let Ok(packet_type) = packet_type.try_into() else {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"packet type error",
));
};
let result = SdlanTcp {
_packet_id: packet_id,
packet_type,
current_packet: binary,
};
Ok(result)
}
impl SdlanTcpCodec {
pub fn new() -> Self {
Self
}
}
#[derive(Debug)]
pub enum Item {
Data(Vec<u8>),
}
impl Decoder for SdlanTcpCodec {
type Item = SdlanTcp;
type Error = std::io::Error;
fn decode(
&mut self,
src: &mut tokio_util::bytes::BytesMut,
) -> Result<Option<Self::Item>, Self::Error> {
if src.is_empty() {
return Ok(None);
}
let size = src.get_u16();
let packet_id = src.get_u32();
let packet_type = src.get_u8();
let mut binary = Vec::with_capacity((size - 5).into());
for i in 0..(size - 5) {
let data = src.get_u8();
binary.push(data);
}
let Ok(packet_type) = packet_type.try_into() else {
return Ok(None);
};
let result = SdlanTcp {
_packet_id: packet_id,
packet_type,
current_packet: binary,
};
Ok(Some(result))
}
}
*/