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