adding UDP packet fragmentation
This commit is contained in:
parent
f7e2926051
commit
99e48ca276
@ -1,5 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fmt::{Display, Formatter, Result as FmtResult},
|
fmt::{Display, Formatter, Result as FmtResult},
|
||||||
|
mem,
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -56,6 +57,10 @@ impl Address {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn take(&mut self) -> Self {
|
||||||
|
mem::take(self)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_none(&self) -> bool {
|
pub fn is_none(&self) -> bool {
|
||||||
matches!(self, Self::None)
|
matches!(self, Self::None)
|
||||||
}
|
}
|
||||||
@ -82,3 +87,9 @@ impl Display for Address {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Address {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -35,6 +35,10 @@ impl Packet {
|
|||||||
addr,
|
addr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn len_without_addr() -> usize {
|
||||||
|
2 + 2 + 1 + 1 + 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command for Packet {
|
impl Command for Packet {
|
||||||
|
@ -13,4 +13,8 @@ impl Authenticate {
|
|||||||
_task_reg: task_reg,
|
_task_reg: task_reg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn header(&self) -> &Header {
|
||||||
|
&self.header
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,4 +13,8 @@ impl Connect {
|
|||||||
_task_reg: task_reg,
|
_task_reg: task_reg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn header(&self) -> &Header {
|
||||||
|
&self.header
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,4 +13,8 @@ impl Dissociate {
|
|||||||
_task_reg: task_reg,
|
_task_reg: task_reg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn header(&self) -> &Header {
|
||||||
|
&self.header
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,4 +10,8 @@ impl Heartbeat {
|
|||||||
header: Header::Heartbeat(HeartbeatHeader::new()),
|
header: Header::Heartbeat(HeartbeatHeader::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn header(&self) -> &Header {
|
||||||
|
&self.header
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
use crate::protocol::Address;
|
use crate::protocol::Address;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::Entry, HashMap},
|
collections::HashMap,
|
||||||
sync::{Arc, Weak},
|
sync::{
|
||||||
|
atomic::{AtomicU16, Ordering},
|
||||||
|
Arc, Weak,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod authenticate;
|
mod authenticate;
|
||||||
@ -102,14 +105,10 @@ impl UdpSessions {
|
|||||||
payload: &'a [u8],
|
payload: &'a [u8],
|
||||||
frag_len: usize,
|
frag_len: usize,
|
||||||
) -> Packet<'a> {
|
) -> Packet<'a> {
|
||||||
match self.sessions.entry(assoc_id) {
|
self.sessions
|
||||||
Entry::Occupied(_) => {}
|
.entry(assoc_id)
|
||||||
Entry::Vacant(entry) => {
|
.or_insert_with(|| UdpSession::new(self.local_active_task_count.reg()))
|
||||||
entry.insert(UdpSession::new(self.local_active_task_count.reg()));
|
.send(assoc_id, addr, payload, frag_len)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet::new(assoc_id, addr, payload, frag_len)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dissociate(&mut self, assoc_id: u16) -> Dissociate {
|
fn dissociate(&mut self, assoc_id: u16) -> Dissociate {
|
||||||
@ -119,13 +118,31 @@ impl UdpSessions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct UdpSession {
|
struct UdpSession {
|
||||||
|
next_pkt_id: AtomicU16,
|
||||||
_task_reg: TaskRegister,
|
_task_reg: TaskRegister,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdpSession {
|
impl UdpSession {
|
||||||
fn new(task_reg: TaskRegister) -> Self {
|
fn new(task_reg: TaskRegister) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
next_pkt_id: AtomicU16::new(0),
|
||||||
_task_reg: task_reg,
|
_task_reg: task_reg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send<'a>(
|
||||||
|
&self,
|
||||||
|
assoc_id: u16,
|
||||||
|
addr: Address,
|
||||||
|
payload: &'a [u8],
|
||||||
|
frag_len: usize,
|
||||||
|
) -> Packet<'a> {
|
||||||
|
Packet::new(
|
||||||
|
assoc_id,
|
||||||
|
self.next_pkt_id.fetch_add(1, Ordering::AcqRel),
|
||||||
|
addr,
|
||||||
|
payload,
|
||||||
|
frag_len,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,79 @@
|
|||||||
use crate::protocol::Address;
|
use crate::protocol::{Address, Header, Packet as PacketHeader};
|
||||||
|
|
||||||
pub struct Packet<'a> {
|
pub struct Packet<'a> {
|
||||||
assoc_id: u16,
|
assoc_id: u16,
|
||||||
|
pkt_id: u16,
|
||||||
addr: Address,
|
addr: Address,
|
||||||
payload: &'a [u8],
|
payload: &'a [u8],
|
||||||
frag_len: usize,
|
max_pkt_size: usize,
|
||||||
|
frag_total: u8,
|
||||||
|
next_frag_id: u8,
|
||||||
|
next_frag_start: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Packet<'a> {
|
impl<'a> Packet<'a> {
|
||||||
pub(super) fn new(assoc_id: u16, addr: Address, payload: &'a [u8], frag_len: usize) -> Self {
|
pub(super) fn new(
|
||||||
|
assoc_id: u16,
|
||||||
|
pkt_id: u16,
|
||||||
|
addr: Address,
|
||||||
|
payload: &'a [u8],
|
||||||
|
max_pkt_size: usize,
|
||||||
|
) -> Self {
|
||||||
|
let first_frag_size = max_pkt_size - PacketHeader::len_without_addr() - addr.len();
|
||||||
|
let frag_size_addr_none =
|
||||||
|
max_pkt_size - PacketHeader::len_without_addr() - Address::None.len();
|
||||||
|
|
||||||
|
let frag_total = if first_frag_size < payload.len() {
|
||||||
|
(1 + (payload.len() - first_frag_size) / frag_size_addr_none + 1) as u8
|
||||||
|
} else {
|
||||||
|
1u8
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
assoc_id,
|
assoc_id,
|
||||||
|
pkt_id,
|
||||||
addr,
|
addr,
|
||||||
payload,
|
payload,
|
||||||
frag_len,
|
max_pkt_size,
|
||||||
|
frag_total,
|
||||||
|
next_frag_id: 0,
|
||||||
|
next_frag_start: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for Packet<'a> {
|
||||||
|
type Item = (Header, &'a [u8]);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.next_frag_id < self.frag_total {
|
||||||
|
let payload_size =
|
||||||
|
self.max_pkt_size - PacketHeader::len_without_addr() - self.addr.len();
|
||||||
|
let next_frag_end = (self.next_frag_start + payload_size).min(self.payload.len());
|
||||||
|
|
||||||
|
let header = Header::Packet(PacketHeader::new(
|
||||||
|
self.assoc_id,
|
||||||
|
self.pkt_id,
|
||||||
|
self.frag_total,
|
||||||
|
self.next_frag_id,
|
||||||
|
(next_frag_end - self.next_frag_start) as u16,
|
||||||
|
self.addr.take(),
|
||||||
|
));
|
||||||
|
|
||||||
|
let payload = &self.payload[self.next_frag_start..next_frag_end];
|
||||||
|
|
||||||
|
self.next_frag_id += 1;
|
||||||
|
self.next_frag_start = next_frag_end;
|
||||||
|
|
||||||
|
Some((header, payload))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExactSizeIterator for Packet<'_> {
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.frag_total as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user