p2p/connection/outgoing/
p2p_connection_outgoing_state.rs

1use malloc_size_of_derive::MallocSizeOf;
2use redux::{Callback, Timestamp};
3use serde::{Deserialize, Serialize};
4
5use openmina_core::requests::RpcId;
6
7use crate::{connection::RejectionReason, webrtc, P2pTimeouts, PeerId};
8
9use super::P2pConnectionOutgoingInitOpts;
10
11#[derive(Serialize, Deserialize, Debug, Clone, MallocSizeOf)]
12pub enum P2pConnectionOutgoingState {
13    Init {
14        #[ignore_malloc_size_of = "doesn't allocate"]
15        time: Timestamp,
16        opts: P2pConnectionOutgoingInitOpts,
17        rpc_id: Option<RpcId>,
18        #[ignore_malloc_size_of = "negligible"]
19        on_success: Option<Callback<(PeerId, Option<RpcId>)>>,
20    },
21    OfferSdpCreatePending {
22        #[ignore_malloc_size_of = "doesn't allocate"]
23        time: Timestamp,
24        opts: P2pConnectionOutgoingInitOpts,
25        rpc_id: Option<RpcId>,
26        #[ignore_malloc_size_of = "negligible"]
27        on_success: Option<Callback<(PeerId, Option<RpcId>)>>,
28    },
29    OfferSdpCreateSuccess {
30        #[ignore_malloc_size_of = "doesn't allocate"]
31        time: Timestamp,
32        opts: P2pConnectionOutgoingInitOpts,
33        sdp: String,
34        rpc_id: Option<RpcId>,
35        #[ignore_malloc_size_of = "negligible"]
36        on_success: Option<Callback<(PeerId, Option<RpcId>)>>,
37    },
38    OfferReady {
39        #[ignore_malloc_size_of = "doesn't allocate"]
40        time: Timestamp,
41        opts: P2pConnectionOutgoingInitOpts,
42        offer: Box<webrtc::Offer>,
43        rpc_id: Option<RpcId>,
44        #[ignore_malloc_size_of = "negligible"]
45        on_success: Option<Callback<(PeerId, Option<RpcId>)>>,
46    },
47    OfferSendSuccess {
48        #[ignore_malloc_size_of = "doesn't allocate"]
49        time: Timestamp,
50        opts: P2pConnectionOutgoingInitOpts,
51        offer: Box<webrtc::Offer>,
52        rpc_id: Option<RpcId>,
53        #[ignore_malloc_size_of = "negligible"]
54        on_success: Option<Callback<(PeerId, Option<RpcId>)>>,
55    },
56    AnswerRecvPending {
57        #[ignore_malloc_size_of = "doesn't allocate"]
58        time: Timestamp,
59        opts: P2pConnectionOutgoingInitOpts,
60        offer: Box<webrtc::Offer>,
61        rpc_id: Option<RpcId>,
62        #[ignore_malloc_size_of = "negligible"]
63        on_success: Option<Callback<(PeerId, Option<RpcId>)>>,
64    },
65    AnswerRecvSuccess {
66        #[ignore_malloc_size_of = "doesn't allocate"]
67        time: Timestamp,
68        opts: P2pConnectionOutgoingInitOpts,
69        offer: Box<webrtc::Offer>,
70        answer: Box<webrtc::Answer>,
71        rpc_id: Option<RpcId>,
72        #[ignore_malloc_size_of = "negligible"]
73        on_success: Option<Callback<(PeerId, Option<RpcId>)>>,
74    },
75    FinalizePending {
76        #[ignore_malloc_size_of = "doesn't allocate"]
77        time: Timestamp,
78        opts: P2pConnectionOutgoingInitOpts,
79        offer: Option<Box<webrtc::Offer>>,
80        answer: Option<Box<webrtc::Answer>>,
81        rpc_id: Option<RpcId>,
82        #[ignore_malloc_size_of = "negligible"]
83        on_success: Option<Callback<(PeerId, Option<RpcId>)>>,
84    },
85    FinalizeSuccess {
86        #[ignore_malloc_size_of = "doesn't allocate"]
87        time: Timestamp,
88        opts: P2pConnectionOutgoingInitOpts,
89        offer: Option<Box<webrtc::Offer>>,
90        answer: Option<Box<webrtc::Answer>>,
91        rpc_id: Option<RpcId>,
92        #[ignore_malloc_size_of = "negligible"]
93        on_success: Option<Callback<(PeerId, Option<RpcId>)>>,
94    },
95    Error {
96        #[ignore_malloc_size_of = "doesn't allocate"]
97        time: Timestamp,
98        error: P2pConnectionOutgoingError,
99        rpc_id: Option<RpcId>,
100    },
101    Success {
102        #[ignore_malloc_size_of = "doesn't allocate"]
103        time: Timestamp,
104        offer: Option<Box<webrtc::Offer>>,
105        answer: Option<Box<webrtc::Answer>>,
106        rpc_id: Option<RpcId>,
107    },
108}
109
110impl P2pConnectionOutgoingState {
111    pub fn time(&self) -> Timestamp {
112        match self {
113            Self::Init { time, .. } => *time,
114            Self::OfferSdpCreatePending { time, .. } => *time,
115            Self::OfferSdpCreateSuccess { time, .. } => *time,
116            Self::OfferReady { time, .. } => *time,
117            Self::OfferSendSuccess { time, .. } => *time,
118            Self::AnswerRecvPending { time, .. } => *time,
119            Self::AnswerRecvSuccess { time, .. } => *time,
120            Self::FinalizePending { time, .. } => *time,
121            Self::FinalizeSuccess { time, .. } => *time,
122            Self::Error { time, .. } => *time,
123            Self::Success { time, .. } => *time,
124        }
125    }
126
127    pub fn rpc_id(&self) -> Option<RpcId> {
128        match self {
129            Self::Init { rpc_id, .. } => *rpc_id,
130            Self::OfferSdpCreatePending { rpc_id, .. } => *rpc_id,
131            Self::OfferSdpCreateSuccess { rpc_id, .. } => *rpc_id,
132            Self::OfferReady { rpc_id, .. } => *rpc_id,
133            Self::OfferSendSuccess { rpc_id, .. } => *rpc_id,
134            Self::AnswerRecvPending { rpc_id, .. } => *rpc_id,
135            Self::AnswerRecvSuccess { rpc_id, .. } => *rpc_id,
136            Self::FinalizePending { rpc_id, .. } => *rpc_id,
137            Self::FinalizeSuccess { rpc_id, .. } => *rpc_id,
138            Self::Error { rpc_id, .. } => *rpc_id,
139            Self::Success { rpc_id, .. } => *rpc_id,
140        }
141    }
142
143    pub fn is_timed_out(&self, now: Timestamp, timeouts: &P2pTimeouts) -> bool {
144        !matches!(self, Self::Error { .. })
145            && now
146                .checked_sub(self.time())
147                .and_then(|dur| timeouts.outgoing_connection_timeout.map(|to| dur >= to))
148                .unwrap_or(false)
149    }
150}
151
152#[derive(Serialize, Deserialize, Debug, Clone, thiserror::Error, MallocSizeOf)]
153pub enum P2pConnectionOutgoingError {
154    #[error("error creating SDP: {0}")]
155    SdpCreateError(String),
156    #[error("rejected: {0}")]
157    Rejected(RejectionReason),
158    #[error("remote signal decryption failed")]
159    RemoteSignalDecryptionFailed,
160    #[error("remote internal error")]
161    RemoteInternalError,
162    #[error("finalization error: {0}")]
163    FinalizeError(String),
164    #[error("connection authorization error")]
165    ConnectionAuthError,
166    #[error("timeout error")]
167    Timeout,
168}