p2p/channels/signaling/exchange/
p2p_channels_signaling_exchange_actions.rs1use openmina_core::ActionEvent;
2use serde::{Deserialize, Serialize};
3
4use crate::{
5 channels::P2pChannelsAction,
6 connection::P2pConnectionResponse,
7 identity::PublicKey,
8 webrtc::{EncryptedAnswer, EncryptedOffer, Offer},
9 P2pState, PeerId,
10};
11
12use super::{P2pChannelsSignalingExchangeState, SignalingExchangeState};
13
14#[derive(Debug, Clone, Serialize, Deserialize, ActionEvent)]
15#[action_event(fields(display(peer_id)))]
16pub enum P2pChannelsSignalingExchangeAction {
17 Init {
19 peer_id: PeerId,
20 },
21 Pending {
22 peer_id: PeerId,
23 },
24 Ready {
26 peer_id: PeerId,
27 },
28 RequestSend {
30 peer_id: PeerId,
31 },
32 OfferReceived {
33 peer_id: PeerId,
34 offerer_pub_key: PublicKey,
35 offer: EncryptedOffer,
36 },
37 OfferDecryptError {
38 peer_id: PeerId,
39 },
40 OfferDecryptSuccess {
41 peer_id: PeerId,
42 offer: Offer,
43 },
44 AnswerSend {
45 peer_id: PeerId,
46 answer: P2pConnectionResponse,
47 },
48 RequestReceived {
50 peer_id: PeerId,
51 },
52 OfferSend {
53 peer_id: PeerId,
54 offerer_pub_key: PublicKey,
55 offer: EncryptedOffer,
56 },
57 AnswerReceived {
58 peer_id: PeerId,
59 answer: Option<EncryptedAnswer>,
60 },
61}
62
63impl P2pChannelsSignalingExchangeAction {
64 pub fn peer_id(&self) -> &PeerId {
65 match self {
66 Self::Init { peer_id }
67 | Self::Pending { peer_id }
68 | Self::Ready { peer_id }
69 | Self::RequestSend { peer_id }
70 | Self::OfferReceived { peer_id, .. }
71 | Self::OfferDecryptError { peer_id, .. }
72 | Self::OfferDecryptSuccess { peer_id, .. }
73 | Self::AnswerSend { peer_id, .. }
74 | Self::RequestReceived { peer_id }
75 | Self::OfferSend { peer_id, .. }
76 | Self::AnswerReceived { peer_id, .. } => peer_id,
77 }
78 }
79}
80
81impl redux::EnablingCondition<P2pState> for P2pChannelsSignalingExchangeAction {
82 fn is_enabled(&self, state: &P2pState, _time: redux::Timestamp) -> bool {
83 match self {
84 P2pChannelsSignalingExchangeAction::Init { peer_id } => {
85 state.get_ready_peer(peer_id).is_some_and(|p| {
86 matches!(
87 &p.channels.signaling.exchange,
88 P2pChannelsSignalingExchangeState::Enabled
89 )
90 })
91 }
92 P2pChannelsSignalingExchangeAction::Pending { peer_id } => {
93 state.get_ready_peer(peer_id).is_some_and(|p| {
94 matches!(
95 &p.channels.signaling.exchange,
96 P2pChannelsSignalingExchangeState::Init { .. }
97 )
98 })
99 }
100 P2pChannelsSignalingExchangeAction::Ready { peer_id } => {
101 state.get_ready_peer(peer_id).is_some_and(|p| {
102 matches!(
103 &p.channels.signaling.exchange,
104 P2pChannelsSignalingExchangeState::Pending { .. }
105 )
106 })
107 }
108 P2pChannelsSignalingExchangeAction::RequestSend { peer_id } => {
109 !state.already_has_max_peers()
110 && state.get_ready_peer(peer_id).is_some_and(|p| {
111 match &p.channels.signaling.exchange {
112 P2pChannelsSignalingExchangeState::Ready { local, .. } => matches!(
113 local,
114 SignalingExchangeState::WaitingForRequest { .. }
115 | SignalingExchangeState::Answered { .. },
116 ),
117 _ => false,
118 }
119 })
120 }
121 P2pChannelsSignalingExchangeAction::OfferReceived { peer_id, .. } => state
122 .get_ready_peer(peer_id)
123 .is_some_and(|p| match &p.channels.signaling.exchange {
124 P2pChannelsSignalingExchangeState::Ready { local, .. } => {
125 matches!(local, SignalingExchangeState::Requested { .. })
126 }
127 _ => false,
128 }),
129 P2pChannelsSignalingExchangeAction::OfferDecryptError { peer_id } => state
130 .get_ready_peer(peer_id)
131 .is_some_and(|p| match &p.channels.signaling.exchange {
132 P2pChannelsSignalingExchangeState::Ready { local, .. } => {
133 matches!(local, SignalingExchangeState::Offered { .. })
134 }
135 _ => false,
136 }),
137 P2pChannelsSignalingExchangeAction::OfferDecryptSuccess { peer_id, .. } => state
138 .get_ready_peer(peer_id)
139 .is_some_and(|p| match &p.channels.signaling.exchange {
140 P2pChannelsSignalingExchangeState::Ready { local, .. } => {
141 matches!(local, SignalingExchangeState::Offered { .. })
142 }
143 _ => false,
144 }),
145 P2pChannelsSignalingExchangeAction::AnswerSend { peer_id, .. } => state
146 .get_ready_peer(peer_id)
147 .is_some_and(|p| match &p.channels.signaling.exchange {
148 P2pChannelsSignalingExchangeState::Ready { local, .. } => {
149 matches!(local, SignalingExchangeState::Offered { .. })
150 }
151 _ => false,
152 }),
153 P2pChannelsSignalingExchangeAction::RequestReceived { peer_id } => state
154 .get_ready_peer(peer_id)
155 .is_some_and(|p| match &p.channels.signaling.exchange {
156 P2pChannelsSignalingExchangeState::Ready { remote, .. } => matches!(
157 remote,
158 SignalingExchangeState::WaitingForRequest { .. }
159 | SignalingExchangeState::Answered { .. }
160 ),
161 _ => false,
162 }),
163 P2pChannelsSignalingExchangeAction::OfferSend { peer_id, .. } => state
164 .get_ready_peer(peer_id)
165 .is_some_and(|p| match &p.channels.signaling.exchange {
166 P2pChannelsSignalingExchangeState::Ready { remote, .. } => {
167 matches!(remote, SignalingExchangeState::Requested { .. })
168 }
169 _ => false,
170 }),
171 P2pChannelsSignalingExchangeAction::AnswerReceived { peer_id, .. } => state
172 .get_ready_peer(peer_id)
173 .is_some_and(|p| match &p.channels.signaling.exchange {
174 P2pChannelsSignalingExchangeState::Ready { remote, .. } => {
175 matches!(remote, SignalingExchangeState::Offered { .. })
176 }
177 _ => false,
178 }),
179 }
180 }
181}
182
183impl From<P2pChannelsSignalingExchangeAction> for crate::P2pAction {
184 fn from(action: P2pChannelsSignalingExchangeAction) -> Self {
185 Self::Channels(P2pChannelsAction::SignalingExchange(action))
186 }
187}