Skip to main content

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 processing::types::FrameInspector;
43pub use protocol::{FrameAcknowledgements, FrameId, Segment, SegmentId, SegmentRequest, SeqIndicator};
44#[cfg(feature = "telemetry")]
45pub use socket::telemetry::{NoopTracker, SessionMessageDiscriminants, SessionTelemetryTracker};
46pub use socket::{
47    SessionSocket, SessionSocketConfig,
48    ack_state::{AcknowledgementMode, AcknowledgementState, AcknowledgementStateConfig},
49    state::{SocketComponents, SocketState, Stateless},
50};
51
52// Enable exports of additional Session protocol types
53#[cfg(feature = "session-types")]
54pub mod types {
55    pub use super::protocol::*;
56}
57
58/// Represents a stateless (and therefore unreliable) socket.
59pub type UnreliableSocket<const C: usize> = SessionSocket<C, Stateless<C>>;
60
61/// Represents a socket with reliable delivery.
62pub type ReliableSocket<const C: usize> = SessionSocket<C, AcknowledgementState<C>>;
63
64/// Computes the Session Socket MTU, given the MTU `C` of the underlying socket.
65pub const fn session_socket_mtu<const C: usize>() -> usize {
66    C - protocol::SessionMessage::<C>::SEGMENT_OVERHEAD
67}
68
69/// Adaptors for [`futures::io::AsyncRead`] + [`futures::io::AsyncWrite`] transport to use Session protocol.
70///
71/// Use `compat` first when the underlying transport is Tokio-based.
72pub trait SessionSocketExt: futures::io::AsyncRead + futures::io::AsyncWrite + Send + Unpin {
73    /// Runs a [reliable](ReliableSocket) Session protocol on self.
74    fn reliable_session<const MTU: usize>(
75        self,
76        ack: AcknowledgementState<MTU>,
77        cfg: SessionSocketConfig,
78    ) -> errors::Result<ReliableSocket<MTU>>
79    where
80        Self: Sized + 'static,
81    {
82        #[cfg(feature = "telemetry")]
83        {
84            SessionSocket::new(self, ack, cfg, NoopTracker)
85        }
86        #[cfg(not(feature = "telemetry"))]
87        {
88            SessionSocket::new(self, ack, cfg)
89        }
90    }
91
92    /// Runs [unreliable](UnreliableSocket) Session protocol on self.
93    fn unreliable_session<const MTU: usize>(
94        self,
95        id: &str,
96        cfg: SessionSocketConfig,
97    ) -> errors::Result<UnreliableSocket<MTU>>
98    where
99        Self: Sized + 'static,
100    {
101        #[cfg(feature = "telemetry")]
102        {
103            SessionSocket::new_stateless(id, self, cfg, NoopTracker)
104        }
105        #[cfg(not(feature = "telemetry"))]
106        {
107            SessionSocket::new_stateless(id, self, cfg)
108        }
109    }
110}
111
112impl<T: ?Sized> SessionSocketExt for T where T: futures::io::AsyncRead + futures::io::AsyncWrite + Send + Unpin {}