p2p/network/select/
p2p_network_select_actions.rs

1use super::{super::*, *};
2use crate::{Data, P2pState, PeerId};
3use openmina_core::ActionEvent;
4use serde::{Deserialize, Serialize};
5
6#[derive(Serialize, Deserialize, Debug, Clone, ActionEvent)]
7#[action_event(fields(display(addr), select_kind = debug(kind), debug(data), fin, debug(token), debug(tokens)))]
8pub enum P2pNetworkSelectAction {
9    /// Initialize protocol selection.
10    ///
11    /// Multistream Select protocol is running multiple times:
12    /// When Pnet protocol is done for newly established TCP connection. We don't have `peer_id` yet.
13    /// When Noise protocol is done and we have a `peer_id`.
14    /// For each yamux stream opened, we have a `peer_id` and `stream_id` at this point.
15    Init {
16        addr: ConnectionAddr,
17        kind: SelectKind,
18        incoming: bool,
19    },
20    #[action_event(level = trace)]
21    IncomingDataAuth {
22        addr: ConnectionAddr,
23        data: Data,
24        fin: bool,
25    },
26    #[action_event(level = trace)]
27    IncomingDataMux {
28        addr: ConnectionAddr,
29        peer_id: Option<PeerId>,
30        data: Data,
31        fin: bool,
32    },
33    #[action_event(level = trace)]
34    IncomingData {
35        addr: ConnectionAddr,
36        peer_id: PeerId,
37        stream_id: StreamId,
38        data: Data,
39        fin: bool,
40    },
41    IncomingPayloadAuth {
42        addr: ConnectionAddr,
43        fin: bool,
44        data: Data,
45    },
46    IncomingPayloadMux {
47        addr: ConnectionAddr,
48        peer_id: Option<PeerId>,
49        fin: bool,
50        data: Data,
51    },
52    IncomingPayload {
53        addr: ConnectionAddr,
54        peer_id: PeerId,
55        stream_id: StreamId,
56        fin: bool,
57        data: Data,
58    },
59    IncomingToken {
60        addr: ConnectionAddr,
61        kind: SelectKind,
62    },
63    OutgoingTokens {
64        addr: ConnectionAddr,
65        kind: SelectKind,
66        tokens: Vec<token::Token>,
67    },
68    Timeout {
69        addr: ConnectionAddr,
70        kind: SelectKind,
71    },
72}
73
74#[derive(Default, Serialize, Deserialize, Debug, Clone, Copy)]
75pub enum SelectKind {
76    #[default]
77    Authentication,
78    MultiplexingNoPeerId,
79    Multiplexing(PeerId),
80    Stream(PeerId, StreamId),
81}
82
83impl SelectKind {
84    pub fn stream_id(&self) -> Option<StreamId> {
85        match self {
86            Self::Authentication => None,
87            Self::MultiplexingNoPeerId => None,
88            Self::Multiplexing(_) => None,
89            Self::Stream(_, v) => Some(*v),
90        }
91    }
92
93    pub fn peer_id(&self) -> Option<PeerId> {
94        match self {
95            Self::Authentication => None,
96            Self::MultiplexingNoPeerId => None,
97            Self::Multiplexing(peer_id) => Some(*peer_id),
98            Self::Stream(peer_id, _) => Some(*peer_id),
99        }
100    }
101
102    #[allow(dead_code)]
103    pub(super) fn forward_data(
104        self,
105        addr: ConnectionAddr,
106        data: Data,
107        fin: bool,
108    ) -> P2pNetworkSelectAction {
109        match self {
110            SelectKind::Authentication => {
111                P2pNetworkSelectAction::IncomingPayloadAuth { addr, fin, data }
112            }
113            SelectKind::Multiplexing(peer_id) => P2pNetworkSelectAction::IncomingPayloadMux {
114                addr,
115                peer_id: Some(peer_id),
116                fin,
117                data,
118            },
119            SelectKind::MultiplexingNoPeerId => P2pNetworkSelectAction::IncomingPayloadMux {
120                addr,
121                peer_id: None,
122                fin,
123                data,
124            },
125            SelectKind::Stream(peer_id, stream_id) => P2pNetworkSelectAction::IncomingPayload {
126                addr,
127                peer_id,
128                stream_id,
129                fin,
130                data,
131            },
132        }
133    }
134}
135
136impl P2pNetworkSelectAction {
137    pub fn addr(&self) -> &ConnectionAddr {
138        match self {
139            Self::Init { addr, .. } => addr,
140            Self::IncomingDataAuth { addr, .. } => addr,
141            Self::IncomingDataMux { addr, .. } => addr,
142            Self::IncomingData { addr, .. } => addr,
143            Self::IncomingPayloadAuth { addr, .. } => addr,
144            Self::IncomingPayloadMux { addr, .. } => addr,
145            Self::IncomingPayload { addr, .. } => addr,
146            Self::IncomingToken { addr, .. } => addr,
147            Self::OutgoingTokens { addr, .. } => addr,
148            Self::Timeout { addr, .. } => addr,
149        }
150    }
151
152    pub fn select_kind(&self) -> SelectKind {
153        match self {
154            Self::Init { kind, .. } => *kind,
155            Self::IncomingDataAuth { .. } => SelectKind::Authentication,
156            Self::IncomingDataMux {
157                peer_id: Some(peer_id),
158                ..
159            } => SelectKind::Multiplexing(*peer_id),
160            Self::IncomingDataMux { peer_id: None, .. } => SelectKind::MultiplexingNoPeerId,
161            Self::IncomingData {
162                peer_id, stream_id, ..
163            } => SelectKind::Stream(*peer_id, *stream_id),
164            Self::IncomingPayloadAuth { .. } => SelectKind::Authentication,
165            Self::IncomingPayloadMux {
166                peer_id: Some(peer_id),
167                ..
168            } => SelectKind::Multiplexing(*peer_id),
169            Self::IncomingPayloadMux { peer_id: None, .. } => SelectKind::MultiplexingNoPeerId,
170            Self::IncomingPayload {
171                peer_id, stream_id, ..
172            } => SelectKind::Stream(*peer_id, *stream_id),
173            Self::IncomingToken { kind, .. } => *kind,
174            Self::OutgoingTokens { kind, .. } => *kind,
175            Self::Timeout { kind, .. } => *kind,
176        }
177    }
178}
179
180impl From<P2pNetworkSelectAction> for crate::P2pAction {
181    fn from(a: P2pNetworkSelectAction) -> Self {
182        Self::Network(a.into())
183    }
184}
185impl redux::EnablingCondition<P2pState> for P2pNetworkSelectAction {
186    fn is_enabled(&self, state: &P2pState, _time: redux::Timestamp) -> bool {
187        if state
188            .network
189            .scheduler
190            .connection_state(self.addr())
191            .and_then(|conn| conn.select_state(&self.select_kind()))
192            .is_none()
193        {
194            return false;
195        }
196
197        match self {
198            Self::Init { .. } => true,
199            Self::IncomingDataAuth { .. } => true,
200            Self::IncomingDataMux { .. } => true,
201            Self::IncomingData { .. } => true,
202            Self::IncomingPayloadAuth { .. } => true,
203            Self::IncomingPayloadMux { .. } => true,
204            Self::IncomingPayload { .. } => true,
205            Self::IncomingToken { .. } => true,
206            Self::OutgoingTokens { .. } => true,
207            Self::Timeout { .. } => true,
208        }
209    }
210}