p2p/channels/signaling/
mod.rs

1//! There are 2 state machines in this module:
2//! 1. `discovery` - used for discovering a new target peer and initiating
3//!    signaling process.
4//! 2. `exchange` - used by intermediary peer to relay an offer to the
5//!    target peer and receive an answer from it.
6//!
7//! These are the overall steps that happens in these state machines in
8//! order to connect two (dialer and listener) peers to each other using
9//! intermediary peer (relayer):
10//! 1. [discovery] Dialer asks relayer to discover an available peer.
11//! 2. [discovery] Relayer responds with available peer's (listener's) public key.
12//! 3. [discovery] Dialer accepts/rejects the target peer (listener).
13//! 4. [discovery] If dialer accepts the peer, it sends webrtc offer to relayer.
14//! 5. [exchange] Relayer relays received webrtc offer to the listener peer.
15//! 6. [exchange] Relayer receives webrtc answer from the listener peer.
16//! 7. [discovery] Relayer relays the answer to the dialer.
17
18pub mod discovery;
19pub mod exchange;
20
21mod p2p_channels_signaling_state;
22pub use p2p_channels_signaling_state::*;
23
24use std::collections::BTreeSet;
25
26use discovery::P2pChannelsSignalingDiscoveryAction;
27
28impl crate::P2pState {
29    pub(super) fn webrtc_discovery_respond_with_availble_peers<Action, State>(
30        &self,
31        dispatcher: &mut redux::Dispatcher<Action, State>,
32        time: redux::Timestamp,
33    ) where
34        State: crate::P2pStateTrait,
35        Action: crate::P2pActionTrait<State>,
36    {
37        let (mut available_peers, requests) = self.ready_peers_iter().fold(
38            (BTreeSet::new(), BTreeSet::new()),
39            |(mut available, mut requests), (peer_id, peer)| {
40                if peer.channels.signaling.is_looking_for_incoming_peer() {
41                    available.insert(peer_id);
42                }
43                if peer.channels.signaling.is_looking_for_peer() {
44                    requests.insert(peer_id);
45                } else if let Some(peer_id) = peer.channels.signaling.sent_discovered_peer_id() {
46                    available.remove(&peer_id);
47                }
48                (available, requests)
49            },
50        );
51
52        /// random shuffle available peers
53        use rand::prelude::*;
54        let mut rng = rand::rngs::StdRng::seed_from_u64(time.into());
55        let mut available_peers_ordered = available_peers.iter().copied().collect::<Vec<_>>();
56        available_peers_ordered.shuffle(&mut rng);
57
58        for &requester in requests {
59            if available_peers.is_empty() {
60                break;
61            }
62            for &&target_peer_id in &available_peers_ordered {
63                if target_peer_id == requester || !available_peers.contains(&target_peer_id) {
64                    continue;
65                }
66                let action = P2pChannelsSignalingDiscoveryAction::DiscoveredSend {
67                    peer_id: requester,
68                    target_public_key: target_peer_id.to_public_key().unwrap(),
69                };
70                if redux::EnablingCondition::is_enabled(&action, self, time) {
71                    dispatcher.push(action);
72                    available_peers.remove(&target_peer_id);
73                }
74            }
75        }
76    }
77}