hopr_transport_p2p/
lib.rs

1//! # P2P
2//!
3//! The underlying technology for managing the peer-to-peer networking used by this package is the [`rust-libp2p`](https://github.com/libp2p/rust-libp2p) library ([documentation](https://docs.libp2p.io/)).
4//!
5//! ## Modularity
6//!
7//! `rust-libp2p` is highly modular allowing for reimplmenting expected behavior using custom implementations for API
8//! traits.
9//!
10//! This way it is possible to experiment with and combine different components of the library in order to construct a
11//! specific targeted use case.
12//!
13//! ## `rust-libp2p` connectivity
14//!
15//! As per the [official documentation](https://connectivity.libp2p.io/), the connectivity types in the library are divided into the `standalone` (implementation of network over host) and `browser` (implementation of network over browser).
16//!
17//! Nodes that are not located behind a blocking firewall or NAT are designated as **public nodes** and can utilize the
18//! `TCP` or `QUIC` connectivity, with the recommendation to use QUIC if possible.
19//!
20//! Browser based solutions are almost always located behind a private network or a blocking firewall and to open a
21//! connection towards the standalone nodes these utilize either the `WebSocket` approach (by hijacking the `TCP`
22//! connection) or the (not yet fully speced up) `WebTransport` (by hijacking the `QUIC` connection).
23
24/// Constants exported by the crate.
25pub mod constants;
26
27/// Errors generated by the crate.
28pub mod errors;
29
30/// Raw swarm definition for the HOPR network.
31pub mod swarm;
32
33/// P2P behavior definitions for the transport level interactions not related to the HOPR protocol
34mod behavior;
35
36use std::fmt::Debug;
37
38pub use behavior::discovery::Event as DiscoveryEvent;
39use futures::{AsyncRead, AsyncWrite, Stream};
40use hopr_internal_types::prelude::*;
41use hopr_transport_identity::PeerId;
42use hopr_transport_protocol::PeerDiscovery;
43use libp2p::{StreamProtocol, autonat, swarm::NetworkBehaviour};
44use rand::rngs::OsRng;
45
46pub const MSG_ACK_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
47pub const NAT_SERVER_PROBE_INTERVAL: std::time::Duration = std::time::Duration::from_secs(30);
48
49// Control object for the streams over the HOPR protocols
50#[derive(Clone)]
51pub struct HoprStreamProtocolControl {
52    control: libp2p_stream::Control,
53    protocol: StreamProtocol,
54}
55
56impl HoprStreamProtocolControl {
57    pub fn new(control: libp2p_stream::Control, protocol: &'static str) -> Self {
58        Self {
59            control,
60            protocol: StreamProtocol::new(protocol),
61        }
62    }
63}
64
65impl std::fmt::Debug for HoprStreamProtocolControl {
66    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67        f.debug_struct("HoprStreamProtocolControl")
68            .field("protocol", &self.protocol)
69            .finish()
70    }
71}
72
73#[async_trait::async_trait]
74impl hopr_transport_protocol::stream::BidirectionalStreamControl for HoprStreamProtocolControl {
75    fn accept(
76        mut self,
77    ) -> Result<impl Stream<Item = (PeerId, impl AsyncRead + AsyncWrite + Send)> + Send, impl std::error::Error> {
78        self.control.accept(self.protocol)
79    }
80
81    async fn open(mut self, peer: PeerId) -> Result<impl AsyncRead + AsyncWrite + Send, impl std::error::Error> {
82        self.control.open_stream(peer, self.protocol).await
83    }
84}
85
86/// Network Behavior definition for aggregated HOPR network functionality.
87///
88/// Individual network behaviors from the libp2p perspectives are aggregated
89/// under this type in order to create an aggregated network behavior capable
90/// of generating events for all component behaviors.
91#[derive(NetworkBehaviour)]
92#[behaviour(to_swarm = "HoprNetworkBehaviorEvent")]
93pub struct HoprNetworkBehavior {
94    discovery: behavior::discovery::Behaviour,
95    streams: libp2p_stream::Behaviour,
96    pub autonat_client: autonat::v2::client::Behaviour,
97    pub autonat_server: autonat::v2::server::Behaviour,
98}
99
100impl Debug for HoprNetworkBehavior {
101    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102        f.debug_struct("HoprNetworkBehavior").finish()
103    }
104}
105
106impl HoprNetworkBehavior {
107    pub fn new<T>(me: PeerId, onchain_events: T) -> Self
108    where
109        T: Stream<Item = PeerDiscovery> + Send + 'static,
110    {
111        Self {
112            streams: libp2p_stream::Behaviour::new(),
113            discovery: behavior::discovery::Behaviour::new(me, onchain_events),
114            autonat_client: autonat::v2::client::Behaviour::new(
115                OsRng,
116                autonat::v2::client::Config::default().with_probe_interval(NAT_SERVER_PROBE_INTERVAL), /* TODO (jean): make this configurable */
117            ),
118            autonat_server: autonat::v2::server::Behaviour::new(OsRng),
119        }
120    }
121}
122
123/// Aggregated network behavior event inheriting the component behaviors' events.
124///
125/// Necessary to allow the libp2p handler to properly distribute the events for
126/// processing in the business logic loop.
127#[derive(Debug)]
128pub enum HoprNetworkBehaviorEvent {
129    Discovery(behavior::discovery::Event),
130    TicketAggregation(
131        libp2p::request_response::Event<Vec<TransferableWinningTicket>, std::result::Result<Ticket, String>>,
132    ),
133    AutonatClient(autonat::v2::client::Event),
134    AutonatServer(autonat::v2::server::Event),
135}
136
137// Unexpected libp2p_stream event
138impl From<()> for HoprNetworkBehaviorEvent {
139    fn from(_: ()) -> Self {
140        panic!("Unexpected event: ()")
141    }
142}
143
144impl From<behavior::discovery::Event> for HoprNetworkBehaviorEvent {
145    fn from(event: behavior::discovery::Event) -> Self {
146        Self::Discovery(event)
147    }
148}
149
150impl From<libp2p::request_response::Event<Vec<TransferableWinningTicket>, std::result::Result<Ticket, String>>>
151    for HoprNetworkBehaviorEvent
152{
153    fn from(
154        event: libp2p::request_response::Event<Vec<TransferableWinningTicket>, std::result::Result<Ticket, String>>,
155    ) -> Self {
156        Self::TicketAggregation(event)
157    }
158}
159
160impl From<autonat::v2::client::Event> for HoprNetworkBehaviorEvent {
161    fn from(event: autonat::v2::client::Event) -> Self {
162        Self::AutonatClient(event)
163    }
164}
165
166impl From<autonat::v2::server::Event> for HoprNetworkBehaviorEvent {
167    fn from(event: autonat::v2::server::Event) -> Self {
168        Self::AutonatServer(event)
169    }
170}
171
172pub use swarm::HoprSwarm;