1
0

sharing abstraction between command Tx and Rx

This commit is contained in:
EAimTY 2023-01-24 19:20:11 +09:00
parent a707943d5a
commit 46ad3068d2
7 changed files with 166 additions and 68 deletions

View File

@ -1,11 +1,10 @@
mod address; mod address;
mod authenticate;
mod connect; mod connect;
mod dissociate; mod dissociate;
mod heartbeat; mod heartbeat;
mod packet; mod packet;
pub mod authenticate;
pub use self::{ pub use self::{
address::Address, authenticate::Authenticate, connect::Connect, dissociate::Dissociate, address::Address, authenticate::Authenticate, connect::Connect, dissociate::Dissociate,
heartbeat::Heartbeat, packet::Packet, heartbeat::Heartbeat, packet::Packet,

View File

@ -1,20 +1,37 @@
use super::TaskRegister; use super::{
side::{self, Side, SideMarker},
TaskRegister,
};
use crate::protocol::{Authenticate as AuthenticateHeader, Header}; use crate::protocol::{Authenticate as AuthenticateHeader, Header};
pub struct Authenticate { pub struct Authenticate<M>
where
M: SideMarker,
{
inner: Side<Tx, Rx>,
_marker: M,
}
pub struct Tx {
header: Header, header: Header,
_task_reg: TaskRegister, _task_reg: TaskRegister,
} }
impl Authenticate { pub struct Rx;
impl Authenticate<side::Tx> {
pub(super) fn new(task_reg: TaskRegister, token: [u8; 8]) -> Self { pub(super) fn new(task_reg: TaskRegister, token: [u8; 8]) -> Self {
Self { Self {
header: Header::Authenticate(AuthenticateHeader::new(token)), inner: Side::Tx(Tx {
_task_reg: task_reg, header: Header::Authenticate(AuthenticateHeader::new(token)),
_task_reg: task_reg,
}),
_marker: side::Tx,
} }
} }
pub fn header(&self) -> &Header { pub fn header(&self) -> &Header {
&self.header let Side::Tx(tx) = &self.inner else { unreachable!() };
&tx.header
} }
} }

View File

@ -1,20 +1,37 @@
use super::TaskRegister; use super::{
side::{self, Side, SideMarker},
TaskRegister,
};
use crate::protocol::{Address, Connect as ConnectHeader, Header}; use crate::protocol::{Address, Connect as ConnectHeader, Header};
pub struct Connect { pub struct Connect<M>
where
M: SideMarker,
{
inner: Side<Tx, Rx>,
_marker: M,
}
struct Tx {
header: Header, header: Header,
_task_reg: TaskRegister, _task_reg: TaskRegister,
} }
impl Connect { struct Rx;
impl Connect<side::Tx> {
pub(super) fn new(task_reg: TaskRegister, addr: Address) -> Self { pub(super) fn new(task_reg: TaskRegister, addr: Address) -> Self {
Self { Self {
header: Header::Connect(ConnectHeader::new(addr)), inner: Side::Tx(Tx {
_task_reg: task_reg, header: Header::Connect(ConnectHeader::new(addr)),
_task_reg: task_reg,
}),
_marker: side::Tx,
} }
} }
pub fn header(&self) -> &Header { pub fn header(&self) -> &Header {
&self.header let Side::Tx(tx) = &self.inner else { unreachable!() };
&tx.header
} }
} }

View File

@ -1,20 +1,32 @@
use super::TaskRegister; use super::side::{self, Side, SideMarker};
use crate::protocol::{Dissociate as DissociateHeader, Header}; use crate::protocol::{Dissociate as DissociateHeader, Header};
pub struct Dissociate { pub struct Dissociate<M>
header: Header, where
_task_reg: TaskRegister, M: SideMarker,
{
inner: Side<Tx, Rx>,
_marker: M,
} }
impl Dissociate { pub struct Tx {
pub(super) fn new(task_reg: TaskRegister, assoc_id: u16) -> Self { header: Header,
}
pub struct Rx;
impl Dissociate<side::Tx> {
pub(super) fn new(assoc_id: u16) -> Self {
Self { Self {
header: Header::Dissociate(DissociateHeader::new(assoc_id)), inner: Side::Tx(Tx {
_task_reg: task_reg, header: Header::Dissociate(DissociateHeader::new(assoc_id)),
}),
_marker: side::Tx,
} }
} }
pub fn header(&self) -> &Header { pub fn header(&self) -> &Header {
&self.header let Side::Tx(tx) = &self.inner else { unreachable!() };
&tx.header
} }
} }

View File

@ -1,17 +1,32 @@
use super::side::{self, Side, SideMarker};
use crate::protocol::{Header, Heartbeat as HeartbeatHeader}; use crate::protocol::{Header, Heartbeat as HeartbeatHeader};
pub struct Heartbeat { pub struct Heartbeat<M>
where
M: SideMarker,
{
inner: Side<Tx, Rx>,
_marker: M,
}
pub struct Tx {
header: Header, header: Header,
} }
impl Heartbeat { pub struct Rx;
impl Heartbeat<side::Tx> {
pub(super) fn new() -> Self { pub(super) fn new() -> Self {
Self { Self {
header: Header::Heartbeat(HeartbeatHeader::new()), inner: Side::Tx(Tx {
header: Header::Heartbeat(HeartbeatHeader::new()),
}),
_marker: side::Tx,
} }
} }
pub fn header(&self) -> &Header { pub fn header(&self) -> &Header {
&self.header let Side::Tx(tx) = &self.inner else { unreachable!() };
&tx.header
} }
} }

View File

@ -15,8 +15,11 @@ mod heartbeat;
mod packet; mod packet;
pub use self::{ pub use self::{
authenticate::Authenticate, connect::Connect, dissociate::Dissociate, heartbeat::Heartbeat, authenticate::Authenticate,
packet::Packet, connect::Connect,
dissociate::Dissociate,
heartbeat::Heartbeat,
packet::{Fragment, Packet},
}; };
pub struct Connection { 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<side::Tx> {
Authenticate::new(self.local_active_task_count.reg(), token) Authenticate::new(self.local_active_task_count.reg(), token)
} }
pub fn connect(&self, addr: Address) -> Connect { pub fn send_connect(&self, addr: Address) -> Connect<side::Tx> {
Connect::new(self.local_active_task_count.reg(), addr) Connect::<side::Tx>::new(self.local_active_task_count.reg(), addr)
} }
pub fn packet<'a>( pub fn send_packet(
&self, &self,
assoc_id: u16, assoc_id: u16,
addr: Address, addr: Address,
payload: &'a [u8], max_pkt_size: usize,
frag_len: usize, ) -> Packet<side::Tx> {
) -> Packet<'a> { self.udp_sessions.lock().send(assoc_id, addr, max_pkt_size)
self.udp_sessions
.lock()
.send(assoc_id, addr, payload, frag_len)
} }
pub fn dissociate(&self, assoc_id: u16) -> Dissociate { pub fn send_dissociate(&self, assoc_id: u16) -> Dissociate<side::Tx> {
self.udp_sessions.lock().dissociate(assoc_id) self.udp_sessions.lock().dissociate(assoc_id)
} }
pub fn heartbeat(&self) -> Heartbeat { pub fn send_heartbeat(&self) -> Heartbeat<side::Tx> {
Heartbeat::new() Heartbeat::new()
} }
@ -98,22 +98,16 @@ impl UdpSessions {
} }
} }
fn send<'a>( fn send<'a>(&mut self, assoc_id: u16, addr: Address, max_pkt_size: usize) -> Packet<side::Tx> {
&mut self,
assoc_id: u16,
addr: Address,
payload: &'a [u8],
frag_len: usize,
) -> Packet<'a> {
self.sessions self.sessions
.entry(assoc_id) .entry(assoc_id)
.or_insert_with(|| UdpSession::new(self.local_active_task_count.reg())) .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<side::Tx> {
self.sessions.remove(&assoc_id); 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>( fn send<'a>(&self, assoc_id: u16, addr: Address, max_pkt_size: usize) -> Packet<side::Tx> {
&self,
assoc_id: u16,
addr: Address,
payload: &'a [u8],
frag_len: usize,
) -> Packet<'a> {
Packet::new( Packet::new(
assoc_id, assoc_id,
self.next_pkt_id.fetch_add(1, Ordering::AcqRel), self.next_pkt_id.fetch_add(1, Ordering::AcqRel),
addr, addr,
payload, max_pkt_size,
frag_len,
) )
} }
} }
pub mod side {
pub struct Tx;
pub struct Rx;
pub trait SideMarker {}
impl SideMarker for Tx {}
impl SideMarker for Rx {}
pub(super) enum Side<T, R> {
Tx(T),
Rx(R),
}
}

View File

@ -1,23 +1,60 @@
use super::side::{self, Side, SideMarker};
use crate::protocol::{Address, Header, Packet as PacketHeader}; use crate::protocol::{Address, Header, Packet as PacketHeader};
pub struct Packet<'a> { pub struct Packet<M>
where
M: SideMarker,
{
inner: Side<Tx, Rx>,
_marker: M,
}
pub struct Tx {
assoc_id: u16,
pkt_id: u16,
addr: Address,
max_pkt_size: usize,
}
pub struct Rx;
impl Packet<side::Tx> {
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, assoc_id: u16,
pkt_id: u16, pkt_id: u16,
addr: Address, addr: Address,
payload: &'a [u8],
max_pkt_size: usize, max_pkt_size: usize,
frag_total: u8, frag_total: u8,
next_frag_id: u8, next_frag_id: u8,
next_frag_start: usize, next_frag_start: usize,
payload: &'a [u8],
} }
impl<'a> Packet<'a> { impl<'a> Fragment<'a> {
pub(super) fn new( fn new(
assoc_id: u16, assoc_id: u16,
pkt_id: u16, pkt_id: u16,
addr: Address, addr: Address,
payload: &'a [u8],
max_pkt_size: usize, max_pkt_size: usize,
payload: &'a [u8],
) -> Self { ) -> Self {
let first_frag_size = max_pkt_size - PacketHeader::len_without_addr() - addr.len(); let first_frag_size = max_pkt_size - PacketHeader::len_without_addr() - addr.len();
let frag_size_addr_none = let frag_size_addr_none =
@ -33,16 +70,16 @@ impl<'a> Packet<'a> {
assoc_id, assoc_id,
pkt_id, pkt_id,
addr, addr,
payload,
max_pkt_size, max_pkt_size,
frag_total, frag_total,
next_frag_id: 0, next_frag_id: 0,
next_frag_start: 0, next_frag_start: 0,
payload,
} }
} }
} }
impl<'a> Iterator for Packet<'a> { impl<'a> Iterator for Fragment<'a> {
type Item = (Header, &'a [u8]); type Item = (Header, &'a [u8]);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -72,7 +109,7 @@ impl<'a> Iterator for Packet<'a> {
} }
} }
impl ExactSizeIterator for Packet<'_> { impl ExactSizeIterator for Fragment<'_> {
fn len(&self) -> usize { fn len(&self) -> usize {
self.frag_total as usize self.frag_total as usize
} }