Skip to content

Commit 224c1c6

Browse files
authored
Exposed adapter constants. Fixed sending UDP and WS sending methods for packet limits (#71)
1 parent 957635c commit 224c1c6

File tree

13 files changed

+88
-122
lines changed

13 files changed

+88
-122
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## Release 0.12.1
4+
- *WebSocket* now can returns when send correctly a `SendStatus::MaxPacketSizeExceeded` instead of `ResourceNotFound` if the packet size is exceeded.
5+
- *UDP* has increases the packet size when send.
6+
Now more bytes per packet can be sent if the OS let it.
7+
- Exported some adapter constants dependent.
8+
- `Transport::max_message_size()` now represents the teorical maximum size (see its related docs).
9+
310
## Release 0.12.0
411
- Node concept: `NodeHandler` and `NodeListener`.
512
- Non-mutable and shared network operations.

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "message-io"
3-
version = "0.12.0"
3+
version = "0.12.1"
44
authors = ["lemunozm <[email protected]>"]
55
edition = "2018"
66
readme = "README.md"

benches/performance.rs

Lines changed: 2 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use message_io::network::{self, Transport, NetworkController, NetworkProcessor, Endpoint};
22
use message_io::util::thread::{NamespacedThread};
33

4-
use criterion::{criterion_group, criterion_main, Criterion, BenchmarkId, Throughput};
4+
use criterion::{criterion_group, criterion_main, Criterion};
55

66
use std::time::{Duration};
77
use std::sync::{
@@ -49,44 +49,6 @@ fn latency_by(c: &mut Criterion, transport: Transport) {
4949
});
5050
}
5151

52-
fn throughput_by(c: &mut Criterion, transport: Transport) {
53-
let sizes = [1, 2, 4, 8, 16, 32, 64, 128]
54-
.iter()
55-
.map(|i| i * 1024)
56-
.filter(|&size| size < transport.max_message_size());
57-
58-
for block_size in sizes {
59-
let mut group = c.benchmark_group(format!("throughput by {}", transport));
60-
group.throughput(Throughput::Bytes(block_size as u64));
61-
group.bench_with_input(BenchmarkId::from_parameter(block_size), &block_size, |b, &size| {
62-
let (controller, mut processor, endpoint) = init_connection(transport);
63-
64-
let thread_running = Arc::new(AtomicBool::new(true));
65-
let running = thread_running.clone();
66-
let (tx, rx) = std::sync::mpsc::channel();
67-
let mut thread = NamespacedThread::spawn("perf-sender", move || {
68-
let message = (0..size).map(|_| 0xFF).collect::<Vec<u8>>();
69-
tx.send(()).unwrap(); // receiving thread ready
70-
while running.load(Ordering::Relaxed) {
71-
controller.send(endpoint, &message);
72-
}
73-
});
74-
rx.recv().unwrap();
75-
76-
b.iter(|| {
77-
// FIX IT:
78-
// Because the sender do not stop sends, the receiver has always data.
79-
// This means that only one poll event is generated for all messages, and
80-
// process_poll_event will call the callback continuously without ends.
81-
processor.process_poll_event(Some(*TIMEOUT), |_| ());
82-
});
83-
84-
thread_running.store(true, Ordering::Relaxed);
85-
thread.join();
86-
});
87-
}
88-
}
89-
9052
fn latency(c: &mut Criterion) {
9153
#[cfg(feature = "udp")]
9254
latency_by(c, Transport::Udp);
@@ -98,18 +60,5 @@ fn latency(c: &mut Criterion) {
9860
latency_by(c, Transport::Ws);
9961
}
10062

101-
#[allow(dead_code)] //TODO: remove when the throughput test works fine
102-
fn throughput(c: &mut Criterion) {
103-
#[cfg(feature = "udp")]
104-
throughput_by(c, Transport::Udp);
105-
// TODO: Fix this test: How to read inside of criterion iter() an stream protocol?
106-
// #[cfg(feature = "tcp")]
107-
// throughput_by(c, Transport::Tcp);
108-
#[cfg(feature = "tcp")]
109-
throughput_by(c, Transport::FramedTcp);
110-
#[cfg(feature = "websocket")]
111-
throughput_by(c, Transport::Ws);
112-
}
113-
114-
criterion_group!(benches, latency /*throughput*/,);
63+
criterion_group!(benches, latency);
11564
criterion_main!(benches);

src/adapters.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ pub mod framed_tcp;
66
#[cfg(feature = "udp")]
77
pub mod udp;
88
#[cfg(feature = "websocket")]
9-
pub mod web_socket;
9+
pub mod ws;
1010
// Add new adapters here
1111
// ...

src/adapters/framed_tcp.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,15 @@ use std::ops::{Deref};
1414
use std::cell::{RefCell};
1515
use std::mem::{MaybeUninit};
1616

17-
const INPUT_BUFFER_SIZE: usize = 65535; // 2^16 - 1
17+
const INPUT_BUFFER_SIZE: usize = u16::MAX as usize; // 2^16 - 1
1818

19-
/// The max packet value for tcp.
20-
/// Although this size is very high, it is preferred send data in smaller chunks with a rate
21-
/// to not saturate the receiver thread in the endpoint.
22-
pub const MAX_TCP_PAYLOAD_LEN: usize = usize::MAX;
23-
24-
pub struct FramedTcpAdapter;
19+
pub(crate) struct FramedTcpAdapter;
2520
impl Adapter for FramedTcpAdapter {
2621
type Remote = RemoteResource;
2722
type Local = LocalResource;
2823
}
2924

30-
pub struct RemoteResource {
25+
pub(crate) struct RemoteResource {
3126
stream: TcpStream,
3227
decoder: RefCell<Decoder>,
3328
}
@@ -119,7 +114,7 @@ impl Remote for RemoteResource {
119114
}
120115
}
121116

122-
pub struct LocalResource {
117+
pub(crate) struct LocalResource {
123118
listener: TcpListener,
124119
}
125120

src/adapters/tcp.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,18 @@ use std::io::{self, ErrorKind, Read, Write};
1212
use std::ops::{Deref};
1313
use std::mem::{MaybeUninit};
1414

15-
pub const INPUT_BUFFER_SIZE: usize = 65535; // 2^16 - 1
15+
/// Size of the internal reading buffer.
16+
/// It implies that at most the generated [`crate::network::NetEvent::Message`]
17+
/// will contains a chunk of data of this value.
18+
pub const INPUT_BUFFER_SIZE: usize = u16::MAX as usize; // 2^16 - 1
1619

17-
pub struct TcpAdapter;
20+
pub(crate) struct TcpAdapter;
1821
impl Adapter for TcpAdapter {
1922
type Remote = RemoteResource;
2023
type Local = LocalResource;
2124
}
2225

23-
pub struct RemoteResource {
26+
pub(crate) struct RemoteResource {
2427
stream: TcpStream,
2528
}
2629

@@ -97,7 +100,7 @@ impl Remote for RemoteResource {
97100
}
98101
}
99102

100-
pub struct LocalResource {
103+
pub(crate) struct LocalResource {
101104
listener: TcpListener,
102105
}
103106

src/adapters/template.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ use mio::event::{Source};
1111
use std::net::{SocketAddr};
1212
use std::io::{self};
1313

14-
pub struct MyAdapter;
14+
pub(crate) struct MyAdapter;
1515
impl Adapter for MyAdapter {
1616
type Remote = RemoteResource;
1717
type Local = LocalResource;
1818
}
1919

20-
pub struct RemoteResource;
20+
pub(crate) struct RemoteResource;
2121
impl Resource for RemoteResource {
2222
fn source(&mut self) -> &mut dyn Source {
2323
todo!();
@@ -38,7 +38,7 @@ impl Remote for RemoteResource {
3838
}
3939
}
4040

41-
pub struct LocalResource;
41+
pub(crate) struct LocalResource;
4242
impl Resource for LocalResource {
4343
fn source(&mut self) -> &mut dyn Source {
4444
todo!();

src/adapters/udp.rs

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,26 @@ use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
1313
use std::io::{self, ErrorKind};
1414
use std::mem::{MaybeUninit};
1515

16-
/// Maximun payload that a UDP packet can send safety in main OS.
17-
/// - 9216: MTU of the OS with the minimun MTU: OSX
18-
/// - 20: max IP header
19-
/// - 8: max udp header
20-
/// The serialization of your message must not exceed this value.
21-
pub const MAX_UDP_PAYLOAD_LEN: usize = 9216 - 20 - 8;
16+
/// Maximun payload that UDP can send.
17+
/// The following payload works on Linux and Windows, but overcome the MacOS limits.
18+
/// To more safety limit, see: `MAX_COMPATIBLE_UDP_PAYLOAD_LEN`.
19+
// - 20: max IP header
20+
// - 8: max udp header
21+
pub const MAX_PAYLOAD_LEN: usize = 65535 - 20 - 8;
2222

23-
// The reception buffer can reach the UDP standard size.
24-
const INPUT_BUFFER_SIZE: usize = 65535 - 20 - 8;
23+
/// Maximun payload that UDP can send safety in main OS.
24+
// 9216: MTU of the OS with the minimun MTU: OSX
25+
pub const MAX_COMPATIBLE_PAYLOAD_LEN: usize = 9216 - 20 - 8;
2526

26-
pub struct UdpAdapter;
27+
const INPUT_BUFFER_SIZE: usize = 65535; // 2^16 - 1
28+
29+
pub(crate) struct UdpAdapter;
2730
impl Adapter for UdpAdapter {
2831
type Remote = RemoteResource;
2932
type Local = LocalResource;
3033
}
3134

32-
pub struct RemoteResource {
35+
pub(crate) struct RemoteResource {
3336
socket: UdpSocket,
3437
}
3538

@@ -75,7 +78,7 @@ impl Remote for RemoteResource {
7578
}
7679
}
7780

78-
pub struct LocalResource {
81+
pub(crate) struct LocalResource {
7982
socket: UdpSocket,
8083
}
8184

@@ -136,28 +139,27 @@ impl Drop for LocalResource {
136139
}
137140

138141
fn send_packet(data: &[u8], send_method: impl Fn(&[u8]) -> io::Result<usize>) -> SendStatus {
139-
if data.len() > MAX_UDP_PAYLOAD_LEN {
140-
log::error!(
141-
"The UDP message could not be sent because it exceeds the MTU. \
142-
Current size: {}, MTU: {}",
143-
data.len(),
144-
MAX_UDP_PAYLOAD_LEN
145-
);
146-
SendStatus::MaxPacketSizeExceeded(data.len(), MAX_UDP_PAYLOAD_LEN)
147-
}
148-
else {
149-
loop {
150-
match send_method(data) {
151-
Ok(_) => break SendStatus::Sent,
152-
// Avoid ICMP generated error to be logged
153-
Err(ref err) if err.kind() == ErrorKind::ConnectionRefused => {
154-
break SendStatus::ResourceNotFound
155-
}
156-
Err(ref err) if err.kind() == ErrorKind::WouldBlock => continue,
157-
Err(err) => {
158-
log::error!("UDP send error: {}", err);
159-
break SendStatus::ResourceNotFound // should not happen
142+
loop {
143+
match send_method(data) {
144+
Ok(_) => break SendStatus::Sent,
145+
// Avoid ICMP generated error to be logged
146+
Err(ref err) if err.kind() == ErrorKind::ConnectionRefused => {
147+
break SendStatus::ResourceNotFound
148+
}
149+
Err(ref err) if err.kind() == ErrorKind::WouldBlock => continue,
150+
Err(ref err) if err.kind() == ErrorKind::Other => {
151+
let expected_assumption = if data.len() > MAX_PAYLOAD_LEN {
152+
MAX_PAYLOAD_LEN
160153
}
154+
else {
155+
// e.g. MacOS do not support the MAX UDP MTU.
156+
MAX_COMPATIBLE_PAYLOAD_LEN
157+
};
158+
break SendStatus::MaxPacketSizeExceeded(data.len(), expected_assumption)
159+
}
160+
Err(err) => {
161+
log::error!("UDP send error: {}", err);
162+
break SendStatus::ResourceNotFound // should not happen
161163
}
162164
}
163165
}

src/adapters/web_socket.rs renamed to src/adapters/ws.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ use std::ops::{DerefMut};
2626

2727
/// Max message size for default config
2828
// From https://docs.rs/tungstenite/0.13.0/src/tungstenite/protocol/mod.rs.html#65
29-
pub const MAX_WS_PAYLOAD_LEN: usize = 32 << 20;
29+
pub const MAX_PAYLOAD_LEN: usize = 32 << 20;
3030

31-
pub struct WsAdapter;
31+
pub(crate) struct WsAdapter;
3232
impl Adapter for WsAdapter {
3333
type Remote = RemoteResource;
3434
type Local = LocalResource;
@@ -44,7 +44,7 @@ enum RemoteState {
4444
Handshake(Option<PendingHandshake>),
4545
}
4646

47-
pub struct RemoteResource {
47+
pub(crate) struct RemoteResource {
4848
state: Mutex<RemoteState>,
4949
}
5050

@@ -181,6 +181,9 @@ impl RemoteResource {
181181
Err(Error::Io(ref err)) if err.kind() == ErrorKind::WouldBlock => {
182182
result = web_socket.write_pending();
183183
}
184+
Err(Error::Capacity(_)) => {
185+
break SendStatus::MaxPacketSizeExceeded(data.len(), MAX_PAYLOAD_LEN)
186+
}
184187
Err(err) => {
185188
log::error!("WS send error: {}", err);
186189
break SendStatus::ResourceNotFound // should not happen
@@ -190,7 +193,7 @@ impl RemoteResource {
190193
}
191194
}
192195

193-
pub struct LocalResource {
196+
pub(crate) struct LocalResource {
194197
listener: TcpListener,
195198
}
196199

0 commit comments

Comments
 (0)