Skip to content

Commit ed5361c

Browse files
authored
Network engine refactorization (lemunozm#24)
* Unified adapter threads. Generalize architecture. * Fixed decode function. Minor change * Fixed tests * Added logger to test and check the timeouts * cargo fmt * Minnor refactorization. * Adjust some net constants * Added adapter trait * Fixed cargo clippy * Compiled in rust stable! * Minnor change. Documented adapter. * Updated readme: add adapters.
1 parent 9c13184 commit ed5361c

File tree

16 files changed

+768
-459
lines changed

16 files changed

+768
-459
lines changed

CHANGELOG.md

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

3+
## Release 0.6.1
4+
- Internal improvements in order to use one thread for all adapters.
5+
- Clean architecture to implement new adapters easier.
6+
37
## Release 0.6.0
48
- Added concurrent writing and reading from socket/streams in UDP and TCP protocols.
59
- Removed UDP enconding (improved speed)

Cargo.lock

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

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "message-io"
3-
version = "0.6.0"
3+
version = "0.6.1"
44
authors = ["lemunozm <lemunozm@gmail.com>"]
55
edition = "2018"
66
readme = "README.md"
@@ -22,6 +22,7 @@ crossbeam = "0.8"
2222
log = "0.4"
2323
net2 = "0.2.34"
2424
num_enum = "0.5.1"
25+
strum = { version = "0.20", features = ["derive"] }
2526

2627
#![cfg_attr(test, feature(proc_macro))]
2728
#[cfg(test)]
@@ -30,6 +31,7 @@ lazy_static = "1.4.0"
3031
[dev-dependencies]
3132
criterion = "0.3"
3233
serde-big-array = "0.3"
34+
simple_logger = "1.11.0"
3335

3436
[[bench]]
3537
name = "performance"

README.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
<img src="https://docs.google.com/drawings/d/e/2PACX-1vSPmycMsWoQq60MPEODcakFQVPkDwVy98AnduTswFNPGBB5dpbIsSCHHBhS2iEuSUtbVaYQb7zgfgjO/pub?w=653&h=305" width="653"/>
1111
</p>
1212

13+
Also, it can be understanding as a **generic manager network**.
14+
This means that you can implement your own protocol following some rules
15+
and `message-io` will manage the tedious asynchrony and thread management for you.
16+
See more [here](#custom-adapter).
17+
1318
**Any contribution is welcome!**
1419

1520
## Who is this project for?
@@ -162,12 +167,16 @@ In other terminals, run one or more clients:
162167
cargo run --example tcp client <name>
163168
```
164169

165-
## Not found the transport protocol you need? Add it easily!
170+
## Do you need a transport protocol that `message-io` doesn't have? Add it! <span id="custom-adapter"><span>
171+
172+
If the protocol can be built in top on [`mio`](https://github.com/tokio-rs/mio#platforms)
173+
(most of the existing protocol libraries can), then you can add it to `message-io` **really easy**:
174+
175+
1. Add your *adapter* file in `src/adapters/<my-transport-protocol>.rs` that implements the
176+
traits that you can found in [`src/adapter.rs`](src/adapter.rs).
177+
178+
1. Add a new field in the `Transport` enum found in [`src/network.rs`] to register your new adapter.
166179

167-
- Add your *adapter* file in `src/adapters/<my-transport-protocol>.rs`
168-
- Modify the `src/network.rs` in two ways:
169-
- Add a new entry of the `Transport` enum with your transport name.
170-
- Fill the main functions with your transport calls following the existing pattern.
180+
That's all! You can use your new transport in the `message-io` API like any other.
171181

172-
Of course, any contribution of any kind: ideas, fixing bugs, adding tests, examples...
173-
is really appreciated.
182+
Oops, one step more, you can make a *Pull request* for everyone to use it :)

src/adapter.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use crate::endpoint::{Endpoint};
2+
use crate::resource_id::{ResourceId};
3+
use crate::poll::{PollRegister};
4+
use crate::util::{SendingStatus};
5+
6+
use std::net::{SocketAddr};
7+
use std::io::{self};
8+
9+
/// Struct used to pack the events generated by the adapter.
10+
/// The upper layer will traduce this event into a [crate::network::NetEvent]
11+
/// that the user can manage.
12+
pub enum AdapterEvent<'a> {
13+
Added,
14+
Data(&'a [u8]),
15+
Removed,
16+
}
17+
18+
/// High level trait to represent an adapter for a transport protocol.
19+
/// The adapter is used to pack a [`Controller`] and [`Adapter`].
20+
/// Two traits to describes how an adapter behaves.
21+
pub trait Adapter<C>
22+
where C: FnMut(Endpoint, AdapterEvent<'_>)
23+
{
24+
type Controller: Controller + Send;
25+
type Processor: Processor<C> + Send;
26+
27+
/// Creates a [`Controller`] and [`Processor`] that represents the adapter.
28+
/// The **implementator** must create their [`Controller`] and [`Processor`] here.
29+
fn split(self, poll_register: PollRegister) -> (Self::Controller, Self::Processor);
30+
}
31+
32+
/// It is in change to perform direct actions from the user.
33+
pub trait Controller {
34+
/// The user performs a connection request to an specific address.
35+
/// The **implementator** is in change of creating the corresponding instance in order
36+
/// to manage it later.
37+
fn connect(&mut self, addr: SocketAddr) -> io::Result<Endpoint>;
38+
39+
/// The user performs a listening request from an specific address.
40+
/// The **implementator** is in change of creating the corresponding instance in order
41+
/// to manage it later.
42+
fn listen(&mut self, addr: SocketAddr) -> io::Result<(ResourceId, SocketAddr)>;
43+
44+
/// The user performs a remove action in order to remove a resource generated by
45+
/// [connect()] and [listen()] functions.
46+
/// The **implementator** must remove the resource here.
47+
fn remove(&mut self, id: ResourceId) -> Option<()>;
48+
49+
/// The user wants to get the local address of some resource (listener or remote).
50+
/// The **implementator** must return that address or None if the resource is not found.
51+
/// Note: The *peer* address can be retreived from the Endpoint that the user already has.
52+
fn local_addr(&self, id: ResourceId) -> Option<SocketAddr>;
53+
54+
/// Sends a raw message by the specific endpoint.
55+
/// The **implementator** is in charge to send the `data` using the instance represented by
56+
/// `endpoint.resource_id()`.
57+
fn send(&mut self, endpoint: Endpoint, data: &[u8]) -> SendingStatus;
58+
}
59+
60+
/// It is in change to perform eventual actions comming from the internal network engine.
61+
/// The `event_callback` is the action that will be performed when an [AdapterEvent] is
62+
/// generated for some `Endpoint`.
63+
pub trait Processor<C>
64+
where C: FnMut(Endpoint, AdapterEvent<'_>)
65+
{
66+
/// Called when a listener received an event.
67+
/// It means that an endpoint has try to connect and the connection should accept.
68+
/// The `id` represents the listener that have generated the event.
69+
/// The **implementator** is in charge of retrive the instance represented by this `id`
70+
/// to accept that connection.
71+
fn process_listener(&mut self, id: ResourceId, event_callback: &mut C);
72+
73+
/// Called when a remote endpoint received an event.
74+
/// It means that the endpoint has available data to read,
75+
/// or there is some connection related issue, as a disconnection.
76+
/// The `id` represents the remote entity that has generated the event.
77+
/// The **implementator** is in charge of retrive the instance represented by this `id`
78+
/// and process the event.
79+
fn process_remote(&mut self, id: ResourceId, event_callback: &mut C);
80+
}

0 commit comments

Comments
 (0)