hopr_protocol_session/lib.rs
1//! Contains implementation of a `Session` message protocol.
2//!
3//! The implementation in this crate follows
4//! the HOPR [`RFC-0007`](https://github.com/hoprnet/rfc/tree/main/rfcs/RFC-0007-session-protocol).
5//!
6//! # What is `Session` protocol?
7//! `Session` protocol is a simple protocol for unreliable networks that implements
8//! basic TCP-like features, such as segmentation, retransmission and acknowledgement.
9//!
10//! The goal of this protocol is to establish a read-write session between two parties,
11//! where one is a message sender and the other one is the receiver. The messages are called
12//! *frames* which are split and are delivered as *segments* from the sender to the recipient.
13//! The session has some reliability guarantees given by the retransmission and acknowledgement
14//! capabilities of individual segments.
15//!
16//! The [`UnreliableSocket`] acts as an unreliable Session protocol socket, taking care only of
17//! segmentation, reassembly and sequencing.
18//!
19//! The [`ReliableSocket`] has (in addition to segmentation, reassembly and sequencing) an
20//! internal state that allows acknowledging frames, retransmit unacknowledged frames and/or
21//! requesting of missing frame segments. It therefore offers data some delivery guarantees
22//! up to the pre-defined frame expiration time.
23//!
24//! The above sockets can be constructed on top of any transport that implements
25//! [`futures::io::AsyncRead`] and [`futures::io::AsyncWrite`],
26//! also using the [extension](SessionSocketExt) methods.
27//!
28//! ## Overview of the crate
29//! - Protocol messages are defined in the `protocol` submodule.
30//! - Socket-like Session interface is defined in `socket` submodule.
31//! - Frames and segments are defined in the `frames` module.
32//! - Segmentation, reassembly and sequencing are defined in the `processing` submodule.
33
34/// Contains errors thrown from this module.
35pub mod errors;
36#[allow(dead_code)]
37mod processing;
38mod protocol;
39mod socket;
40pub(crate) mod utils;
41
42pub use socket::{
43 SessionSocket, SessionSocketConfig,
44 ack_state::{AcknowledgementMode, AcknowledgementState, AcknowledgementStateConfig},
45 state::{SocketState, Stateless},
46};
47
48// Enable exports of additional Session protocol types
49#[cfg(feature = "session-types")]
50pub mod types {
51 pub use super::protocol::*;
52}
53
54/// Represents a stateless (and therefore unreliable) socket.
55pub type UnreliableSocket<const C: usize> = SessionSocket<C, Stateless<C>>;
56
57/// Represents a socket with reliable delivery.
58pub type ReliableSocket<const C: usize> = SessionSocket<C, AcknowledgementState<C>>;
59
60/// Computes the Session Socket MTU, given the MTU `C` of the underlying socket.
61pub const fn session_socket_mtu<const C: usize>() -> usize {
62 C - protocol::SessionMessage::<C>::SEGMENT_OVERHEAD
63}
64
65/// Adaptors for [`futures::io::AsyncRead`] + [`futures::io::AsyncWrite`] transport to use Session protocol.
66///
67/// Use `compat` first when the underlying transport is Tokio-based.
68pub trait SessionSocketExt: futures::io::AsyncRead + futures::io::AsyncWrite + Send + Unpin {
69 /// Runs a [reliable](ReliableSocket) Session protocol on self.
70 fn reliable_session<const MTU: usize>(
71 self,
72 ack: AcknowledgementState<MTU>,
73 cfg: SessionSocketConfig,
74 ) -> errors::Result<ReliableSocket<MTU>>
75 where
76 Self: Sized + 'static,
77 {
78 SessionSocket::new(self, ack, cfg)
79 }
80
81 /// Runs [unreliable](UnreliableSocket) Session protocol on self.
82 fn unreliable_session<const MTU: usize>(
83 self,
84 id: &str,
85 cfg: SessionSocketConfig,
86 ) -> errors::Result<UnreliableSocket<MTU>>
87 where
88 Self: Sized + 'static,
89 {
90 SessionSocket::new_stateless(id, self, cfg)
91 }
92}
93
94impl<T: ?Sized> SessionSocketExt for T where T: futures::io::AsyncRead + futures::io::AsyncWrite + Send + Unpin {}