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 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
//! Networking things that are not specific to either transport.
pub use crate::header::TcpHeader;
use serde::{Deserialize, Serialize};
use std::any::Any;
use std::fmt::{Debug, Display, Formatter};
use std::io;
use std::io::Error;
use std::ops::Deref;
use std::time::Duration;
/// The maximum safe message size that can be sent on udp,
/// after taking off the possible overheads from the transport.
///
/// The data must be `MAX_SAFE_MESSAGE_SIZE` or less to be guaranteed to
/// be deliverable on udp.
/// [source](https://newbedev.com/what-is-the-largest-safe-udp-packet-size-on-the-internet/)
pub const MAX_SAFE_MESSAGE_SIZE: usize = 504;
/// An enum representing the 2 possible transports.
///
/// - TCP is reliable but slower.
/// - UDP is unreliable but quicker.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Transport {
TCP,
UDP,
}
/// The function used to deserialize a message.
///
/// fn(&[u8]) -> Result<Box<dyn Any + Send + Sync>, io::Error>
pub type DeserFn = fn(&[u8]) -> Result<Box<dyn Any + Send + Sync>, io::Error>;
/// The function used to serialize a message.
///
/// fn(&(dyn Any + Send + Sync)) -> Result<Vec<u8>, io::Error>
pub type SerFn = fn(&(dyn Any + Send + Sync)) -> Result<Vec<u8>, io::Error>;
#[derive(Debug)]
/// An enum for the possible states of a connection.
pub enum Status {
/// The connection is still live.
Connected,
/// The connection is closed because the peer disconnected by sending a disconnection message.
Disconnected(Box<dyn Any + Send + Sync>),
/// The connection is closed because we chose to close the connection.
Closed,
/// The connection was dropped without sending a disconnection message.
Dropped(Error),
}
impl Display for Status {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Connected => write!(f, "Connected"),
Self::Disconnected(_) => write!(f, "Disconnected gracefully"),
Self::Closed => write!(f, "Closed"),
Self::Dropped(e) => write!(f, "Dropped with error {}", e),
}
}
}
impl Status {
/// Returns whether the status is [`Status::Connected`].
pub fn connected(&self) -> bool {
match self {
Status::Connected => true,
_ => false,
}
}
/// Turns this into an option with the disconnect message.
///
/// ### Panics
/// Panics if the generic parameter `D` isn't the disconnect message type (the same `D` that
/// you passed into `MsgTable::build`).
pub fn disconnected<D: Any + Send + Sync>(&self) -> Option<&D> {
match self {
Status::Disconnected(d) => Some(d.downcast_ref().expect("The generic parameter `D` must be the disconnection message type (the same `D` that you passed into `MsgTable::build`).")),
_ => None,
}
}
/// Turns this into an option with the disconnect message.
pub fn disconnected_dyn(&self) -> Option<&Box<dyn Any + Send + Sync>> {
match self {
Status::Disconnected(d) => Some(d),
_ => None,
}
}
/// Turns this into an option with the drop error.
pub fn dropped(&self) -> Option<&Error> {
match self {
Status::Dropped(e) => Some(e),
_ => None,
}
}
/// Returns whether the status is [`Status::Closed`].
pub fn closed(&self) -> bool {
match self {
Status::Closed => true,
_ => false,
}
}
}
/// Message ID.
pub type MId = usize;
/// Connection ID.
pub type CId = u32;
/// A way to specify the valid [`CId`]s for an operation.
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
pub enum CIdSpec {
/// Matches all [`CId`]s
All,
/// Matches no [`CId`]s.
None,
/// Matches all except the inner [`CId`]
Except(CId),
/// Matches only the inner [`CId`]
Only(CId),
}
impl CIdSpec {
/// Weather the given cid matches the pattern.
pub fn matches(&self, cid: CId) -> bool {
match self {
CIdSpec::All => true,
CIdSpec::None => false,
CIdSpec::Except(o) => cid != *o,
CIdSpec::Only(o) => cid == *o,
}
}
/// Checks if the `other` [`CIdSpec`] overlaps (shares at least on common [`CId`]).
pub fn overlaps(&self, other: CIdSpec) -> bool {
use CIdSpec::*;
match (*self, other) {
(None, _) => false,
(_, None) => false,
(All, _) => true,
(_, All) => true,
(Except(_), Except(_)) => true,
(Only(o1), Only(o2)) => o1 == o2,
(Only(only), Except(except)) => only != except,
(Except(except), Only(only)) => only != except,
}
}
}
/// Configuration for a client or server.
///
/// This needs to be defined before starting up the server.
///
/// Contains all configurable information about the server.
#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub struct Config {
/// The timeout for handling new connections. The time to wait for a connection message
/// after establishing a tcp connection.
pub timeout: Duration,
/// The maximum number of connections that this can handle at the same time.
pub max_con_handle: usize,
/// The maximum message size in bytes. This is used for sizing the buffer for TCP and UDP.
/// Any attempts to send messages over this size will be discarded. Keep in mind, there is
/// still a soft limit for UDP messages (`MAX_SAFE_MSG_SIZE`)
pub max_msg_size: usize,
}
impl Config {
/// Creates a new Server configuration.
pub fn new(timeout: Duration, max_con_handle: usize, max_msg_size: usize) -> Self {
Config {
timeout,
max_con_handle,
max_msg_size,
}
}
}
impl Default for Config {
fn default() -> Self {
Config {
timeout: Duration::from_millis(5_000),
max_con_handle: 4,
max_msg_size: 2048,
}
}
}
/// An untyped network message containing the message content, along with the metadata associated.
#[derive(Debug)]
pub(crate) struct ErasedNetMsg {
/// The [`CId`] that the message was sent from.
pub(crate) cid: CId,
/// The timestamp that the message was sent in unix millis.
///
/// This is always `Some` if the message was sent with UDP, and always `None` if sent with TCP.
pub(crate) time: Option<u32>,
/// The actual message.
pub(crate) msg: Box<dyn Any + Send + Sync>,
}
impl ErasedNetMsg {
/// Converts this to NetMsg, borrowed from this.
pub(crate) fn to_typed<T: Any + Send + Sync>(&self) -> Option<NetMsg<T>> {
let msg = self.msg.downcast_ref()?;
Some(NetMsg {
cid: self.cid,
time: self.time,
m: msg,
})
}
}
/// A network message containing the message content, along with the metadata associated.
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub struct NetMsg<'n, T: Any + Send + Sync> {
/// The [`CId`] that the message was sent from.
pub cid: CId,
/// The timestamp that the message was sent in unix millis.
///
/// This is always `Some` if the message was sent with UDP, and always `None` if sent with TCP.
pub time: Option<u32>,
/// The actual message.
///
/// Borrowed from the client or server.
pub m: &'n T,
}
impl<'n, T: Any + Send + Sync> Deref for NetMsg<'n, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.m
}
}