diff --git a/tuic/src/protocol/mod.rs b/tuic/src/protocol/mod.rs index 406ebc3..8368314 100644 --- a/tuic/src/protocol/mod.rs +++ b/tuic/src/protocol/mod.rs @@ -1,11 +1,10 @@ mod address; +mod authenticate; mod connect; mod dissociate; mod heartbeat; mod packet; -pub mod authenticate; - pub use self::{ address::Address, authenticate::Authenticate, connect::Connect, dissociate::Dissociate, heartbeat::Heartbeat, packet::Packet, diff --git a/tuic/src/prototype/authenticate.rs b/tuic/src/prototype/authenticate.rs index fbccf57..fa02069 100644 --- a/tuic/src/prototype/authenticate.rs +++ b/tuic/src/prototype/authenticate.rs @@ -1,20 +1,37 @@ -use super::TaskRegister; +use super::{ + side::{self, Side, SideMarker}, + TaskRegister, +}; use crate::protocol::{Authenticate as AuthenticateHeader, Header}; -pub struct Authenticate { +pub struct Authenticate +where + M: SideMarker, +{ + inner: Side, + _marker: M, +} + +pub struct Tx { header: Header, _task_reg: TaskRegister, } -impl Authenticate { +pub struct Rx; + +impl Authenticate { pub(super) fn new(task_reg: TaskRegister, token: [u8; 8]) -> Self { Self { - header: Header::Authenticate(AuthenticateHeader::new(token)), - _task_reg: task_reg, + inner: Side::Tx(Tx { + header: Header::Authenticate(AuthenticateHeader::new(token)), + _task_reg: task_reg, + }), + _marker: side::Tx, } } pub fn header(&self) -> &Header { - &self.header + let Side::Tx(tx) = &self.inner else { unreachable!() }; + &tx.header } } diff --git a/tuic/src/prototype/connect.rs b/tuic/src/prototype/connect.rs index fddac8e..391c2d0 100644 --- a/tuic/src/prototype/connect.rs +++ b/tuic/src/prototype/connect.rs @@ -1,20 +1,37 @@ -use super::TaskRegister; +use super::{ + side::{self, Side, SideMarker}, + TaskRegister, +}; use crate::protocol::{Address, Connect as ConnectHeader, Header}; -pub struct Connect { +pub struct Connect +where + M: SideMarker, +{ + inner: Side, + _marker: M, +} + +struct Tx { header: Header, _task_reg: TaskRegister, } -impl Connect { +struct Rx; + +impl Connect { pub(super) fn new(task_reg: TaskRegister, addr: Address) -> Self { Self { - header: Header::Connect(ConnectHeader::new(addr)), - _task_reg: task_reg, + inner: Side::Tx(Tx { + header: Header::Connect(ConnectHeader::new(addr)), + _task_reg: task_reg, + }), + _marker: side::Tx, } } pub fn header(&self) -> &Header { - &self.header + let Side::Tx(tx) = &self.inner else { unreachable!() }; + &tx.header } } diff --git a/tuic/src/prototype/dissociate.rs b/tuic/src/prototype/dissociate.rs index abf5cef..c1088f5 100644 --- a/tuic/src/prototype/dissociate.rs +++ b/tuic/src/prototype/dissociate.rs @@ -1,20 +1,32 @@ -use super::TaskRegister; +use super::side::{self, Side, SideMarker}; use crate::protocol::{Dissociate as DissociateHeader, Header}; -pub struct Dissociate { - header: Header, - _task_reg: TaskRegister, +pub struct Dissociate +where + M: SideMarker, +{ + inner: Side, + _marker: M, } -impl Dissociate { - pub(super) fn new(task_reg: TaskRegister, assoc_id: u16) -> Self { +pub struct Tx { + header: Header, +} + +pub struct Rx; + +impl Dissociate { + pub(super) fn new(assoc_id: u16) -> Self { Self { - header: Header::Dissociate(DissociateHeader::new(assoc_id)), - _task_reg: task_reg, + inner: Side::Tx(Tx { + header: Header::Dissociate(DissociateHeader::new(assoc_id)), + }), + _marker: side::Tx, } } pub fn header(&self) -> &Header { - &self.header + let Side::Tx(tx) = &self.inner else { unreachable!() }; + &tx.header } } diff --git a/tuic/src/prototype/heartbeat.rs b/tuic/src/prototype/heartbeat.rs index 369a7ec..17ecdfc 100644 --- a/tuic/src/prototype/heartbeat.rs +++ b/tuic/src/prototype/heartbeat.rs @@ -1,17 +1,32 @@ +use super::side::{self, Side, SideMarker}; use crate::protocol::{Header, Heartbeat as HeartbeatHeader}; -pub struct Heartbeat { +pub struct Heartbeat +where + M: SideMarker, +{ + inner: Side, + _marker: M, +} + +pub struct Tx { header: Header, } -impl Heartbeat { +pub struct Rx; + +impl Heartbeat { pub(super) fn new() -> Self { Self { - header: Header::Heartbeat(HeartbeatHeader::new()), + inner: Side::Tx(Tx { + header: Header::Heartbeat(HeartbeatHeader::new()), + }), + _marker: side::Tx, } } pub fn header(&self) -> &Header { - &self.header + let Side::Tx(tx) = &self.inner else { unreachable!() }; + &tx.header } } diff --git a/tuic/src/prototype/mod.rs b/tuic/src/prototype/mod.rs index b96f414..4f8c5e9 100644 --- a/tuic/src/prototype/mod.rs +++ b/tuic/src/prototype/mod.rs @@ -15,8 +15,11 @@ mod heartbeat; mod packet; pub use self::{ - authenticate::Authenticate, connect::Connect, dissociate::Dissociate, heartbeat::Heartbeat, - packet::Packet, + authenticate::Authenticate, + connect::Connect, + dissociate::Dissociate, + heartbeat::Heartbeat, + packet::{Fragment, Packet}, }; pub struct Connection { @@ -34,31 +37,28 @@ impl Connection { } } - pub fn authenticate(&self, token: [u8; 8]) -> Authenticate { + pub fn send_authenticate(&self, token: [u8; 8]) -> Authenticate { Authenticate::new(self.local_active_task_count.reg(), token) } - pub fn connect(&self, addr: Address) -> Connect { - Connect::new(self.local_active_task_count.reg(), addr) + pub fn send_connect(&self, addr: Address) -> Connect { + Connect::::new(self.local_active_task_count.reg(), addr) } - pub fn packet<'a>( + pub fn send_packet( &self, assoc_id: u16, addr: Address, - payload: &'a [u8], - frag_len: usize, - ) -> Packet<'a> { - self.udp_sessions - .lock() - .send(assoc_id, addr, payload, frag_len) + max_pkt_size: usize, + ) -> Packet { + self.udp_sessions.lock().send(assoc_id, addr, max_pkt_size) } - pub fn dissociate(&self, assoc_id: u16) -> Dissociate { + pub fn send_dissociate(&self, assoc_id: u16) -> Dissociate { self.udp_sessions.lock().dissociate(assoc_id) } - pub fn heartbeat(&self) -> Heartbeat { + pub fn send_heartbeat(&self) -> Heartbeat { Heartbeat::new() } @@ -98,22 +98,16 @@ impl UdpSessions { } } - fn send<'a>( - &mut self, - assoc_id: u16, - addr: Address, - payload: &'a [u8], - frag_len: usize, - ) -> Packet<'a> { + fn send<'a>(&mut self, assoc_id: u16, addr: Address, max_pkt_size: usize) -> Packet { self.sessions .entry(assoc_id) .or_insert_with(|| UdpSession::new(self.local_active_task_count.reg())) - .send(assoc_id, addr, payload, frag_len) + .send(assoc_id, addr, max_pkt_size) } - fn dissociate(&mut self, assoc_id: u16) -> Dissociate { + fn dissociate(&mut self, assoc_id: u16) -> Dissociate { self.sessions.remove(&assoc_id); - Dissociate::new(self.local_active_task_count.reg(), assoc_id) + Dissociate::new(assoc_id) } } @@ -130,19 +124,26 @@ impl UdpSession { } } - fn send<'a>( - &self, - assoc_id: u16, - addr: Address, - payload: &'a [u8], - frag_len: usize, - ) -> Packet<'a> { + fn send<'a>(&self, assoc_id: u16, addr: Address, max_pkt_size: usize) -> Packet { Packet::new( assoc_id, self.next_pkt_id.fetch_add(1, Ordering::AcqRel), addr, - payload, - frag_len, + max_pkt_size, ) } } + +pub mod side { + pub struct Tx; + pub struct Rx; + + pub trait SideMarker {} + impl SideMarker for Tx {} + impl SideMarker for Rx {} + + pub(super) enum Side { + Tx(T), + Rx(R), + } +} diff --git a/tuic/src/prototype/packet.rs b/tuic/src/prototype/packet.rs index ccd17fc..4a139c6 100644 --- a/tuic/src/prototype/packet.rs +++ b/tuic/src/prototype/packet.rs @@ -1,23 +1,60 @@ +use super::side::{self, Side, SideMarker}; use crate::protocol::{Address, Header, Packet as PacketHeader}; -pub struct Packet<'a> { +pub struct Packet +where + M: SideMarker, +{ + inner: Side, + _marker: M, +} + +pub struct Tx { + assoc_id: u16, + pkt_id: u16, + addr: Address, + max_pkt_size: usize, +} + +pub struct Rx; + +impl Packet { + pub(super) fn new(assoc_id: u16, pkt_id: u16, addr: Address, max_pkt_size: usize) -> Self { + Self { + inner: Side::Tx(Tx { + assoc_id, + pkt_id, + addr, + max_pkt_size, + }), + _marker: side::Tx, + } + } + + pub fn into_fragments<'a>(self, payload: &'a [u8]) -> Fragment<'a> { + let Side::Tx(tx) = self.inner else { unreachable!() }; + Fragment::new(tx.assoc_id, tx.pkt_id, tx.addr, tx.max_pkt_size, payload) + } +} + +pub struct Fragment<'a> { assoc_id: u16, pkt_id: u16, addr: Address, - payload: &'a [u8], max_pkt_size: usize, frag_total: u8, next_frag_id: u8, next_frag_start: usize, + payload: &'a [u8], } -impl<'a> Packet<'a> { - pub(super) fn new( +impl<'a> Fragment<'a> { + fn new( assoc_id: u16, pkt_id: u16, addr: Address, - payload: &'a [u8], max_pkt_size: usize, + payload: &'a [u8], ) -> Self { let first_frag_size = max_pkt_size - PacketHeader::len_without_addr() - addr.len(); let frag_size_addr_none = @@ -33,16 +70,16 @@ impl<'a> Packet<'a> { assoc_id, pkt_id, addr, - payload, max_pkt_size, frag_total, next_frag_id: 0, next_frag_start: 0, + payload, } } } -impl<'a> Iterator for Packet<'a> { +impl<'a> Iterator for Fragment<'a> { type Item = (Header, &'a [u8]); fn next(&mut self) -> Option { @@ -72,7 +109,7 @@ impl<'a> Iterator for Packet<'a> { } } -impl ExactSizeIterator for Packet<'_> { +impl ExactSizeIterator for Fragment<'_> { fn len(&self) -> usize { self.frag_total as usize }