implement blocking (un)marshal for protocol
This commit is contained in:
parent
6229a08e61
commit
8b985b1586
@ -5,6 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
async_marshal = ["bytes", "futures-util"]
|
async_marshal = ["bytes", "futures-util"]
|
||||||
|
marshal = ["bytes"]
|
||||||
model = ["parking_lot", "thiserror"]
|
model = ["parking_lot", "thiserror"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@ -14,4 +15,4 @@ parking_lot = { version = "0.12.1", default-features = false, optional = true }
|
|||||||
thiserror = { version = "1.0.38", default-features = false, optional = true }
|
thiserror = { version = "1.0.38", default-features = false, optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tuic = { path = ".", features = ["async_marshal", "model"] }
|
tuic = { path = ".", features = ["async_marshal", "marshal", "model"] }
|
||||||
|
@ -6,13 +6,13 @@ pub use self::protocol::{
|
|||||||
Address, Authenticate, Connect, Dissociate, Header, Heartbeat, Packet, VERSION,
|
Address, Authenticate, Connect, Dissociate, Header, Heartbeat, Packet, VERSION,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "async_marshal")]
|
#[cfg(any(feature = "async_marshal", feature = "marshal"))]
|
||||||
mod marshal;
|
mod marshal;
|
||||||
|
|
||||||
#[cfg(feature = "async_marshal")]
|
#[cfg(any(feature = "async_marshal", feature = "marshal"))]
|
||||||
mod unmarshal;
|
mod unmarshal;
|
||||||
|
|
||||||
#[cfg(feature = "async_marshal")]
|
#[cfg(any(feature = "async_marshal", feature = "marshal"))]
|
||||||
pub use self::unmarshal::UnmarshalError;
|
pub use self::unmarshal::UnmarshalError;
|
||||||
|
|
||||||
#[cfg(feature = "model")]
|
#[cfg(feature = "model")]
|
||||||
|
@ -3,15 +3,26 @@ use crate::protocol::{
|
|||||||
};
|
};
|
||||||
use bytes::BufMut;
|
use bytes::BufMut;
|
||||||
use futures_util::{AsyncWrite, AsyncWriteExt};
|
use futures_util::{AsyncWrite, AsyncWriteExt};
|
||||||
use std::{io::Error as IoError, net::SocketAddr};
|
use std::{
|
||||||
|
io::{Error as IoError, Write},
|
||||||
|
net::SocketAddr,
|
||||||
|
};
|
||||||
|
|
||||||
impl Header {
|
impl Header {
|
||||||
|
#[cfg(feature = "async_marshal")]
|
||||||
pub async fn async_marshal(&self, s: &mut (impl AsyncWrite + Unpin)) -> Result<(), IoError> {
|
pub async fn async_marshal(&self, s: &mut (impl AsyncWrite + Unpin)) -> Result<(), IoError> {
|
||||||
let mut buf = vec![0; self.len()];
|
let mut buf = vec![0; self.len()];
|
||||||
self.write(&mut buf);
|
self.write(&mut buf);
|
||||||
s.write_all(&buf).await
|
s.write_all(&buf).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "marshal")]
|
||||||
|
pub fn marshal(&self, s: &mut impl Write) -> Result<(), IoError> {
|
||||||
|
let mut buf = vec![0; self.len()];
|
||||||
|
self.write(&mut buf);
|
||||||
|
s.write_all(&buf)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write(&self, buf: &mut impl BufMut) {
|
pub fn write(&self, buf: &mut impl BufMut) {
|
||||||
buf.put_u8(VERSION);
|
buf.put_u8(VERSION);
|
||||||
buf.put_u8(self.type_code());
|
buf.put_u8(self.type_code());
|
||||||
|
@ -2,10 +2,15 @@ use crate::protocol::{
|
|||||||
Address, Authenticate, Connect, Dissociate, Header, Heartbeat, Packet, VERSION,
|
Address, Authenticate, Connect, Dissociate, Header, Heartbeat, Packet, VERSION,
|
||||||
};
|
};
|
||||||
use futures_util::{AsyncRead, AsyncReadExt};
|
use futures_util::{AsyncRead, AsyncReadExt};
|
||||||
use std::{io::Error as IoError, net::SocketAddr, string::FromUtf8Error};
|
use std::{
|
||||||
|
io::{Error as IoError, Read},
|
||||||
|
net::SocketAddr,
|
||||||
|
string::FromUtf8Error,
|
||||||
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
impl Header {
|
impl Header {
|
||||||
|
#[cfg(feature = "async_marshal")]
|
||||||
pub async fn async_unmarshal(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
pub async fn async_unmarshal(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
||||||
let mut buf = [0; 1];
|
let mut buf = [0; 1];
|
||||||
s.read_exact(&mut buf).await?;
|
s.read_exact(&mut buf).await?;
|
||||||
@ -30,9 +35,34 @@ impl Header {
|
|||||||
_ => Err(UnmarshalError::InvalidCommand(cmd)),
|
_ => Err(UnmarshalError::InvalidCommand(cmd)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "marshal")]
|
||||||
|
pub fn unmarshal(s: &mut impl Read) -> Result<Self, UnmarshalError> {
|
||||||
|
let mut buf = [0; 1];
|
||||||
|
s.read_exact(&mut buf)?;
|
||||||
|
let ver = buf[0];
|
||||||
|
|
||||||
|
if ver != VERSION {
|
||||||
|
return Err(UnmarshalError::InvalidVersion(ver));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf = [0; 1];
|
||||||
|
s.read_exact(&mut buf)?;
|
||||||
|
let cmd = buf[0];
|
||||||
|
|
||||||
|
match cmd {
|
||||||
|
Header::TYPE_CODE_AUTHENTICATE => Authenticate::read(s).map(Self::Authenticate),
|
||||||
|
Header::TYPE_CODE_CONNECT => Connect::read(s).map(Self::Connect),
|
||||||
|
Header::TYPE_CODE_PACKET => Packet::read(s).map(Self::Packet),
|
||||||
|
Header::TYPE_CODE_DISSOCIATE => Dissociate::read(s).map(Self::Dissociate),
|
||||||
|
Header::TYPE_CODE_HEARTBEAT => Heartbeat::read(s).map(Self::Heartbeat),
|
||||||
|
_ => Err(UnmarshalError::InvalidCommand(cmd)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Address {
|
impl Address {
|
||||||
|
#[cfg(feature = "async_marshal")]
|
||||||
async fn async_read(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
async fn async_read(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
||||||
let mut buf = [0; 1];
|
let mut buf = [0; 1];
|
||||||
s.read_exact(&mut buf).await?;
|
s.read_exact(&mut buf).await?;
|
||||||
@ -80,23 +110,87 @@ impl Address {
|
|||||||
_ => Err(UnmarshalError::InvalidAddressType(type_code)),
|
_ => Err(UnmarshalError::InvalidAddressType(type_code)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "marshal")]
|
||||||
|
fn read(s: &mut impl Read) -> Result<Self, UnmarshalError> {
|
||||||
|
let mut buf = [0; 1];
|
||||||
|
s.read_exact(&mut buf)?;
|
||||||
|
let type_code = buf[0];
|
||||||
|
|
||||||
|
match type_code {
|
||||||
|
Address::TYPE_CODE_NONE => Ok(Self::None),
|
||||||
|
Address::TYPE_CODE_DOMAIN => {
|
||||||
|
let mut buf = [0; 1];
|
||||||
|
s.read_exact(&mut buf)?;
|
||||||
|
let len = buf[0] as usize;
|
||||||
|
|
||||||
|
let mut buf = vec![0; len + 2];
|
||||||
|
s.read_exact(&mut buf)?;
|
||||||
|
let port = u16::from_be_bytes([buf[len], buf[len + 1]]);
|
||||||
|
buf.truncate(len);
|
||||||
|
let domain = String::from_utf8(buf)?;
|
||||||
|
|
||||||
|
Ok(Self::DomainAddress(domain, port))
|
||||||
|
}
|
||||||
|
Address::TYPE_CODE_IPV4 => {
|
||||||
|
let mut buf = [0; 6];
|
||||||
|
s.read_exact(&mut buf)?;
|
||||||
|
let ip = [buf[0], buf[1], buf[2], buf[3]];
|
||||||
|
let port = u16::from_be_bytes([buf[4], buf[5]]);
|
||||||
|
Ok(Self::SocketAddress(SocketAddr::from((ip, port))))
|
||||||
|
}
|
||||||
|
Address::TYPE_CODE_IPV6 => {
|
||||||
|
let mut buf = [0; 18];
|
||||||
|
s.read_exact(&mut buf)?;
|
||||||
|
let ip = [
|
||||||
|
u16::from_be_bytes([buf[0], buf[1]]),
|
||||||
|
u16::from_be_bytes([buf[2], buf[3]]),
|
||||||
|
u16::from_be_bytes([buf[4], buf[5]]),
|
||||||
|
u16::from_be_bytes([buf[6], buf[7]]),
|
||||||
|
u16::from_be_bytes([buf[8], buf[9]]),
|
||||||
|
u16::from_be_bytes([buf[10], buf[11]]),
|
||||||
|
u16::from_be_bytes([buf[12], buf[13]]),
|
||||||
|
u16::from_be_bytes([buf[14], buf[15]]),
|
||||||
|
];
|
||||||
|
let port = u16::from_be_bytes([buf[16], buf[17]]);
|
||||||
|
|
||||||
|
Ok(Self::SocketAddress(SocketAddr::from((ip, port))))
|
||||||
|
}
|
||||||
|
_ => Err(UnmarshalError::InvalidAddressType(type_code)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Authenticate {
|
impl Authenticate {
|
||||||
|
#[cfg(feature = "async_marshal")]
|
||||||
async fn async_read(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
async fn async_read(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
||||||
let mut buf = [0; 8];
|
let mut buf = [0; 8];
|
||||||
s.read_exact(&mut buf).await?;
|
s.read_exact(&mut buf).await?;
|
||||||
Ok(Self::new(buf))
|
Ok(Self::new(buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "marshal")]
|
||||||
|
fn read(s: &mut impl Read) -> Result<Self, UnmarshalError> {
|
||||||
|
let mut buf = [0; 8];
|
||||||
|
s.read_exact(&mut buf)?;
|
||||||
|
Ok(Self::new(buf))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Connect {
|
impl Connect {
|
||||||
|
#[cfg(feature = "async_marshal")]
|
||||||
async fn async_read(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
async fn async_read(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
||||||
Ok(Self::new(Address::async_read(s).await?))
|
Ok(Self::new(Address::async_read(s).await?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "marshal")]
|
||||||
|
fn read(s: &mut impl Read) -> Result<Self, UnmarshalError> {
|
||||||
|
Ok(Self::new(Address::read(s)?))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Packet {
|
impl Packet {
|
||||||
|
#[cfg(feature = "async_marshal")]
|
||||||
async fn async_read(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
async fn async_read(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
||||||
let mut buf = [0; 8];
|
let mut buf = [0; 8];
|
||||||
s.read_exact(&mut buf).await?;
|
s.read_exact(&mut buf).await?;
|
||||||
@ -110,21 +204,51 @@ impl Packet {
|
|||||||
|
|
||||||
Ok(Self::new(assoc_id, pkt_id, frag_total, frag_id, size, addr))
|
Ok(Self::new(assoc_id, pkt_id, frag_total, frag_id, size, addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "marshal")]
|
||||||
|
fn read(s: &mut impl Read) -> Result<Self, UnmarshalError> {
|
||||||
|
let mut buf = [0; 8];
|
||||||
|
s.read_exact(&mut buf)?;
|
||||||
|
|
||||||
|
let assoc_id = u16::from_be_bytes([buf[0], buf[1]]);
|
||||||
|
let pkt_id = u16::from_be_bytes([buf[2], buf[3]]);
|
||||||
|
let frag_total = buf[4];
|
||||||
|
let frag_id = buf[5];
|
||||||
|
let size = u16::from_be_bytes([buf[6], buf[7]]);
|
||||||
|
let addr = Address::read(s)?;
|
||||||
|
|
||||||
|
Ok(Self::new(assoc_id, pkt_id, frag_total, frag_id, size, addr))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dissociate {
|
impl Dissociate {
|
||||||
|
#[cfg(feature = "async_marshal")]
|
||||||
async fn async_read(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
async fn async_read(s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
||||||
let mut buf = [0; 2];
|
let mut buf = [0; 2];
|
||||||
s.read_exact(&mut buf).await?;
|
s.read_exact(&mut buf).await?;
|
||||||
let assoc_id = u16::from_be_bytes(buf);
|
let assoc_id = u16::from_be_bytes(buf);
|
||||||
Ok(Self::new(assoc_id))
|
Ok(Self::new(assoc_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "marshal")]
|
||||||
|
fn read(s: &mut impl Read) -> Result<Self, UnmarshalError> {
|
||||||
|
let mut buf = [0; 2];
|
||||||
|
s.read_exact(&mut buf)?;
|
||||||
|
let assoc_id = u16::from_be_bytes(buf);
|
||||||
|
Ok(Self::new(assoc_id))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Heartbeat {
|
impl Heartbeat {
|
||||||
|
#[cfg(feature = "async_marshal")]
|
||||||
async fn async_read(_s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
async fn async_read(_s: &mut (impl AsyncRead + Unpin)) -> Result<Self, UnmarshalError> {
|
||||||
Ok(Self::new())
|
Ok(Self::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "marshal")]
|
||||||
|
fn read(_s: &mut impl Read) -> Result<Self, UnmarshalError> {
|
||||||
|
Ok(Self::new())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user