1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
use super::remote_addr::{RemoteAddr};
use super::poll::{Readiness};

use mio::event::{Source};

use std::net::{SocketAddr};
use std::io::{self};

/// High level trait to represent an adapter for a transport protocol.
/// The adapter is only used to identify the resources of your adapter.
pub trait Adapter: Send + Sync {
    /// Resource type used to identify remote connections and send/receive
    /// from remote this endpoints (e.g. TcpStream)
    /// This can be considerered the resource used for client connections.
    type Remote: Remote;

    /// Resource type used to accept new connections (e.g. TcpListener)
    /// This can be considerered the resource used for server listenings.
    type Local: Local<Remote = Self::Remote>;
}

/// A `Resource` is defined as an object that can return a mutable reference to a [`Source`].
/// `Source` is the trait that [`mio`] uses to register in the poll in order to wake up
/// asynchronously from events.
/// Your [`Remote`] and [`Local`] entities must implement `Resource`.
pub trait Resource: Send + Sync {
    /// Returns a mutable reference to the internal `Source`.
    /// Note: All `mio` network element implements [`Source`], you probably wants to use
    /// one of them as a base for your non-blocking transport.
    /// See [`Source`].
    fn source(&mut self) -> &mut dyn Source;
}

/// Plain struct used as a returned value of [`Remote::connect()`]
pub struct ConnectionInfo<R: Remote> {
    /// The new created remote resource
    pub remote: R,

    /// Local address of the interal resource used.
    pub local_addr: SocketAddr,

    /// Peer address of the interal resource used.
    pub peer_addr: SocketAddr,
}

/// Plain struct used as a returned value of [`Local::listen()`]
pub struct ListeningInfo<L: Local> {
    /// The new created local resource
    pub local: L,

    /// Local address generated after perform the listening action.
    pub local_addr: SocketAddr,
}

/// The following represents the posible status that [`crate::network::NetworkController::send()`]
/// call can return.
/// The library do not encourage to perform the check of this status for each `send()` call,
/// only in that cases where you need extra information about how the sending method was.
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum SendStatus {
    /// This status is received when the entire data has been sent.
    /// It does not guarantees that the packet have been successfully received by the endpoint.
    /// It means that the correspond adapter has sent the message to the OS without errors.
    Sent,

    /// This status is received in packet-based protocols where there is a limit in the bytes
    /// that a packet can have.
    MaxPacketSizeExceeded,

    /// It means that the message could not be sent by the specified `ResourceId`.
    /// This implies that a [`crate::network::NetEvent::Disconnected`] has happened or that
    /// the resource never existed.
    ResourceNotFound,

    /// The resource can not perform the required send operation.
    /// Usually this is due because it is performing the handshake.
    ResourceNotAvailable,
}

/// Returned as a result of [`Remote::receive()`]
#[derive(Debug)]
pub enum ReadStatus {
    /// This status must be returned if the resource has been disconnected or there was an error.
    /// The resource will be removed after this call and
    /// no more [`Remote::receive()`] calls will be produced by this resource.
    Disconnected,

    /// This status must be returned when a the resource (treated as a non-bloking) would wait for
    /// process the next event.
    /// Usually, this status is returned if the resource receives
    /// a [`std::io::ErrorKind::WouldBlock`].
    WaitNextEvent,
}

#[derive(Debug, Clone, PartialEq)]
pub enum PendingStatus {
    /// The resource is no longer considered as a pending resource.
    /// It it came from a listener, a [`crate::network::NetEvent::Accepted`] event will be generated.
    /// It it came from a explicit connection, a [`crate::network::NetEvent::Connected`]
    /// with its flag to `true` will be generated.
    /// No more calls to [`Remote::pending()`] will be performed.
    Ready,

    /// The resource needs more data to be considered as established.
    Incomplete,

    /// The resource has not be able to perform the connection.
    /// It it came from a listener, no event will be generated.
    /// It it came from a explicit connection, a [`crate::network::NetEvent::Connected`]
    /// with its flag to `false` will be generated.
    /// No more calls to [`Remote::pending()`] will be performed and the resource will be removed.
    Disconnected,
}

/// The resource used to represent a remote.
/// It usually is a wrapper over a socket/stream.
pub trait Remote: Resource + Sized {
    /// Called when the user performs a connection request to an specific remote address.
    /// The **implementator** is in change of creating the corresponding remote resource.
    /// The [`RemoteAddr`] contains either a [`SocketAddr`] or a [`url::Url`].
    /// It is in charge of deciding what to do in both cases.
    /// It also must return the extracted address as `SocketAddr`.
    fn connect(remote_addr: RemoteAddr) -> io::Result<ConnectionInfo<Self>>;

    /// Called when a remote resource received an event.
    /// The resource must be *ready* to receive this call.
    /// It means that it has available data to read,
    /// or there is some connection related issue, as a disconnection.
    /// The **implementator** is in charge of processing that action and returns a [`ReadStatus`].
    ///
    /// The `process_data` function must be called for each data chunk that represents a message.
    /// This call will produce a [`crate::network::NetEvent::Message`] API event.
    /// Note that `receive()` could imply more than one call to `read`.
    /// The implementator must be read all data from the resource.
    /// For most of the cases it means read until the network resource returns `WouldBlock`.
    fn receive(&self, process_data: impl FnMut(&[u8])) -> ReadStatus;

    /// Sends raw data from a resource.
    /// The resource must be *ready* to receive this call.
    /// The **implementator** is in charge to send the entire `data`.
    /// The [`SendStatus`] will contain the status of this attempt.
    fn send(&self, data: &[u8]) -> SendStatus;

    /// Called when a `Remote` is created (explicity of by a listener)
    /// and it is not consider ready yet.
    /// A remote resource **is considered ready** when it is totally connected
    /// and can be used for writing data.
    /// It implies that the user has received the `Connected` or `Accepted` method for that resource.
    ///
    /// This method is in charge to determine if a resource is ready or not.
    /// No `Connected` or `Accepted` events will be generated until this function return
    /// `PendingStatus::Ready`.
    /// The method wil be called several times with different `Readiness` until the **implementator**
    /// returns a `PendingStatus::Ready` or `PendingStatus::Disconnected`.
    fn pending(&self, readiness: Readiness) -> PendingStatus;

    /// The resource is available to write.
    /// It must be *ready* to receive this call.
    /// Here the **implementator** optionally can try to write any pending data.
    /// The return value is an identification of the operation result.
    /// If the method returns `true`, the operation was successful, otherwise, the resource will
    /// be disconnected and removed.
    fn ready_to_write(&self) -> bool {
        true
    }
}

/// Used as a parameter callback in [`Local::accept()`]
pub enum AcceptedType<'a, R> {
    /// The listener has accepted a remote (`R`) with the specified addr.
    /// The remote will be registered in order to generate read events. (calls to
    /// [`Remote::receive()`]).
    /// A [`crate::network::NetEvent::Accepted`] will be generated once this remote resource
    /// is considered *ready*.
    Remote(SocketAddr, R),

    /// The listener has accepted data that can be packed into a message from a specified addr.
    /// Despite of `Remote`, accept as a `Data` will not register any Remote.
    /// This will produce a [`crate::network::NetEvent::Message`] event.
    /// The endpoint of this event will be unique containing the specified addr and the listener
    /// whom generates it.
    Data(SocketAddr, &'a [u8]),
}

/// The resource used to represent a local listener.
/// It usually is a wrapper over a socket/listener.
pub trait Local: Resource + Sized {
    /// The type of the Remote accepted by the [`Self::accept()`] function.
    /// It must be the same as the adapter's `Remote`.
    type Remote: Remote;

    /// Called when the user performs a listening request from an specific address.
    /// The **implementator** is in change of creating the corresponding local resource.
    /// It also must returned the listening address since it could not be the same as param `addr`
    /// (e.g. listening from port `0`).
    fn listen(addr: SocketAddr) -> io::Result<ListeningInfo<Self>>;

    /// Called when a local resource received an event.
    /// It means that some resource have tried to connect.
    /// The **implementator** is in charge of accepting this connection.
    /// The `accept_remote` must be called for each accept request in the local resource.
    /// Note that an accept event could imply to process more than one remote.
    /// This function is called when the local resource has one or more pending connections.
    /// The **implementator** must process all these pending connections in this call.
    /// For most of the cases it means accept connections until the network
    /// resource returns `WouldBlock`.
    fn accept(&self, accept_remote: impl FnMut(AcceptedType<'_, Self::Remote>));

    /// Sends a raw data from a resource.
    /// Similar to [`Remote::send()`] but the resource that sends the data is a `Local`.
    /// This behaviour usually happens when the transport to implement is not connection oriented.
    ///
    /// The **implementator** must **only** implement this function if the local resource can
    /// also send data.
    fn send_to(&self, _addr: SocketAddr, _data: &[u8]) -> SendStatus {
        panic!("Adapter not configured to send messages directly from the local resource")
    }
}