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
use crate::remote_addr::{RemoteAddr};

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 `Resourcepp can be 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 {
    /// This is the only method required to make your element a resource.
    /// Note: Any `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;
}

/// The following represents the posible status that a `send()`/`send_all()` 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 datagram-based protocols where there is a limit in the bytes
    /// that a packet can have.
    /// The first value is the length of the data that was attempt to send
    /// and the second one is the maximun offers by the datagram based protocol used.
    MaxPacketSizeExceeded(usize, usize),

    /// It means that the connection is not able for sending the message.
    /// This implies that a [`crate::network::NetEvent::Disconnected`] has been or will be
    /// generated.
    /// The library encourage to manage the disconnection error in the event queue based with
    /// the RemoveEndpoint received, and left this status to determinated in some cases
    /// if the message was not sent.
    ResourceNotFound,
}

/// Returned as a result of [`Remote::receive()`]
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,
}

/// 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<(Self, SocketAddr)>;

    /// Called when a remote endpoint received an event.
    /// It means that the resource 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 `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: &dyn Fn(&[u8])) -> ReadStatus;

    /// Sends a raw data from a resource.
    /// 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;
}

/// 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()`]).
    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 `Message` API event.
    /// The endpoint along this event will be unique if base of the specified addr and the listener
    /// whom generates it.
    /// This means that the user can treat the [`crate::network::Endpoint`] as if
    /// it was an internal resource.
    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<(Self, SocketAddr)>;

    /// 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: &dyn Fn(AcceptedType<'_, Self::Remote>));

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