message_io/network/
adapter.rs

1use crate::network::transport::{TransportConnect, TransportListen};
2
3use super::remote_addr::{RemoteAddr};
4use super::poll::{Readiness};
5
6use mio::event::{Source};
7
8use std::net::{SocketAddr};
9use std::io::{self};
10
11/// High level trait to represent an adapter for a transport protocol.
12/// The adapter is only used to identify the resources of your adapter.
13pub trait Adapter: Send + Sync {
14    /// Resource type used to identify remote connections and send/receive
15    /// from remote this endpoints (e.g. TcpStream)
16    /// This can be considerered the resource used for client connections.
17    type Remote: Remote;
18
19    /// Resource type used to accept new connections (e.g. TcpListener)
20    /// This can be considerered the resource used for server listenings.
21    type Local: Local<Remote = Self::Remote>;
22}
23
24/// A `Resource` is defined as an object that can return a mutable reference to a [`Source`].
25/// `Source` is the trait that [`mio`] uses to register in the poll in order to wake up
26/// asynchronously from events.
27/// Your [`Remote`] and [`Local`] entities must implement `Resource`.
28pub trait Resource: Send + Sync {
29    /// Returns a mutable reference to the internal `Source`.
30    /// Note: All `mio` network element implements [`Source`], you probably wants to use
31    /// one of them as a base for your non-blocking transport.
32    /// See [`Source`].
33    fn source(&mut self) -> &mut dyn Source;
34}
35
36/// Plain struct used as a returned value of [`Remote::connect_with()`]
37pub struct ConnectionInfo<R: Remote> {
38    /// The new created remote resource
39    pub remote: R,
40
41    /// Local address of the interal resource used.
42    pub local_addr: SocketAddr,
43
44    /// Peer address of the interal resource used.
45    pub peer_addr: SocketAddr,
46}
47
48/// Plain struct used as a returned value of [`Local::listen_with()`]
49pub struct ListeningInfo<L: Local> {
50    /// The new created local resource
51    pub local: L,
52
53    /// Local address generated after perform the listening action.
54    pub local_addr: SocketAddr,
55}
56
57/// The following represents the posible status that [`crate::network::NetworkController::send()`]
58/// call can return.
59/// The library do not encourage to perform the check of this status for each `send()` call,
60/// only in that cases where you need extra information about how the sending method was.
61#[derive(Clone, Copy, PartialEq, Eq, Debug)]
62pub enum SendStatus {
63    /// This status is received when the entire data has been sent.
64    /// It does not guarantees that the packet have been successfully received by the endpoint.
65    /// It means that the correspond adapter has sent the message to the OS without errors.
66    Sent,
67
68    /// This status is received in packet-based protocols where there is a limit in the bytes
69    /// that a packet can have.
70    MaxPacketSizeExceeded,
71
72    /// It means that the message could not be sent by the specified `ResourceId`.
73    /// This implies that a [`crate::network::NetEvent::Disconnected`] has happened or that
74    /// the resource never existed.
75    ResourceNotFound,
76
77    /// The resource can not perform the required send operation.
78    /// Usually this is due because it is performing the handshake.
79    ResourceNotAvailable,
80}
81
82/// Returned as a result of [`Remote::receive()`]
83#[derive(Debug)]
84pub enum ReadStatus {
85    /// This status must be returned if the resource has been disconnected or there was an error.
86    /// The resource will be removed after this call and
87    /// no more [`Remote::receive()`] calls will be produced by this resource.
88    Disconnected,
89
90    /// This status must be returned when a the resource (treated as a non-bloking) would wait for
91    /// process the next event.
92    /// Usually, this status is returned if the resource receives
93    /// a [`std::io::ErrorKind::WouldBlock`].
94    WaitNextEvent,
95}
96
97#[derive(Debug, Clone, PartialEq, Eq)]
98pub enum PendingStatus {
99    /// The resource is no longer considered as a pending resource.
100    /// It it came from a listener, a [`crate::network::NetEvent::Accepted`] event will be generated.
101    /// It it came from a explicit connection, a [`crate::network::NetEvent::Connected`]
102    /// with its flag to `true` will be generated.
103    /// No more calls to [`Remote::pending()`] will be performed.
104    Ready,
105
106    /// The resource needs more data to be considered as established.
107    Incomplete,
108
109    /// The resource has not be able to perform the connection.
110    /// It it came from a listener, no event will be generated.
111    /// It it came from a explicit connection, a [`crate::network::NetEvent::Connected`]
112    /// with its flag to `false` will be generated.
113    /// No more calls to [`Remote::pending()`] will be performed and the resource will be removed.
114    Disconnected,
115}
116
117/// The resource used to represent a remote.
118/// It usually is a wrapper over a socket/stream.
119pub trait Remote: Resource + Sized {
120    /// Called when the user performs a connection request to an specific remote address.
121    /// The **implementator** is in change of creating the corresponding remote resource.
122    /// The [`TransportConnect`] wraps custom transport options for transports that support it. It
123    /// is guaranteed by the upper level to be of the variant matching the adapter. Therefore other
124    /// variants can be safely ignored.
125    /// The [`RemoteAddr`] contains either a [`SocketAddr`] or a [`url::Url`].
126    /// It is in charge of deciding what to do in both cases.
127    /// It also must return the extracted address as `SocketAddr`.
128    fn connect_with(
129        config: TransportConnect,
130        remote_addr: RemoteAddr,
131    ) -> io::Result<ConnectionInfo<Self>>;
132
133    /// Called when a remote resource received an event.
134    /// The resource must be *ready* to receive this call.
135    /// It means that it has available data to read,
136    /// or there is some connection related issue, as a disconnection.
137    /// The **implementator** is in charge of processing that action and returns a [`ReadStatus`].
138    ///
139    /// The `process_data` function must be called for each data chunk that represents a message.
140    /// This call will produce a [`crate::network::NetEvent::Message`] API event.
141    /// Note that `receive()` could imply more than one call to `read`.
142    /// The implementator must be read all data from the resource.
143    /// For most of the cases it means read until the network resource returns `WouldBlock`.
144    fn receive(&self, process_data: impl FnMut(&[u8])) -> ReadStatus;
145
146    /// Sends raw data from a resource.
147    /// The resource must be *ready* to receive this call.
148    /// The **implementator** is in charge to send the entire `data`.
149    /// The [`SendStatus`] will contain the status of this attempt.
150    fn send(&self, data: &[u8]) -> SendStatus;
151
152    /// Called when a `Remote` is created (explicity of by a listener)
153    /// and it is not consider ready yet.
154    /// A remote resource **is considered ready** when it is totally connected
155    /// and can be used for writing data.
156    /// It implies that the user has received the `Connected` or `Accepted` method for that resource.
157    ///
158    /// This method is in charge to determine if a resource is ready or not.
159    /// No `Connected` or `Accepted` events will be generated until this function return
160    /// `PendingStatus::Ready`.
161    /// The method wil be called several times with different `Readiness` until the **implementator**
162    /// returns a `PendingStatus::Ready` or `PendingStatus::Disconnected`.
163    fn pending(&self, readiness: Readiness) -> PendingStatus;
164
165    /// The resource is available to write.
166    /// It must be *ready* to receive this call.
167    /// Here the **implementator** optionally can try to write any pending data.
168    /// The return value is an identification of the operation result.
169    /// If the method returns `true`, the operation was successful, otherwise, the resource will
170    /// be disconnected and removed.
171    fn ready_to_write(&self) -> bool {
172        true
173    }
174}
175
176/// Used as a parameter callback in [`Local::accept()`]
177pub enum AcceptedType<'a, R> {
178    /// The listener has accepted a remote (`R`) with the specified addr.
179    /// The remote will be registered in order to generate read events. (calls to
180    /// [`Remote::receive()`]).
181    /// A [`crate::network::NetEvent::Accepted`] will be generated once this remote resource
182    /// is considered *ready*.
183    Remote(SocketAddr, R),
184
185    /// The listener has accepted data that can be packed into a message from a specified addr.
186    /// Despite of `Remote`, accept as a `Data` will not register any Remote.
187    /// This will produce a [`crate::network::NetEvent::Message`] event.
188    /// The endpoint of this event will be unique containing the specified addr and the listener
189    /// whom generates it.
190    Data(SocketAddr, &'a [u8]),
191}
192
193/// The resource used to represent a local listener.
194/// It usually is a wrapper over a socket/listener.
195pub trait Local: Resource + Sized {
196    /// The type of the Remote accepted by the [`Self::accept()`] function.
197    /// It must be the same as the adapter's `Remote`.
198    type Remote: Remote;
199
200    /// Called when the user performs a listening request from an specific address.
201    /// The **implementator** is in change of creating the corresponding local resource.
202    /// It also must returned the listening address since it could not be the same as param `addr`
203    /// (e.g. listening from port `0`).
204    /// The [`TransportListen`] wraps custom transport options for transports that support it. It
205    /// is guaranteed by the upper level to be of the variant matching the adapter. Therefore other
206    /// variants can be safely ignored.
207    fn listen_with(config: TransportListen, addr: SocketAddr) -> io::Result<ListeningInfo<Self>>;
208
209    /// Called when a local resource received an event.
210    /// It means that some resource have tried to connect.
211    /// The **implementator** is in charge of accepting this connection.
212    /// The `accept_remote` must be called for each accept request in the local resource.
213    /// Note that an accept event could imply to process more than one remote.
214    /// This function is called when the local resource has one or more pending connections.
215    /// The **implementator** must process all these pending connections in this call.
216    /// For most of the cases it means accept connections until the network
217    /// resource returns `WouldBlock`.
218    fn accept(&self, accept_remote: impl FnMut(AcceptedType<'_, Self::Remote>));
219
220    /// Sends a raw data from a resource.
221    /// Similar to [`Remote::send()`] but the resource that sends the data is a `Local`.
222    /// This behaviour usually happens when the transport to implement is not connection oriented.
223    ///
224    /// The **implementator** must **only** implement this function if the local resource can
225    /// also send data.
226    fn send_to(&self, _addr: SocketAddr, _data: &[u8]) -> SendStatus {
227        panic!("Adapter not configured to send messages directly from the local resource")
228    }
229}