rings_core/swarm/
callback.rs1use std::str::FromStr;
2use std::sync::Arc;
3
4use async_trait::async_trait;
5use futures::lock::Mutex as FuturesMutex;
6use rings_transport::core::callback::TransportCallback;
7use rings_transport::core::transport::WebrtcConnectionState;
8
9use crate::chunk::MessageReassembler;
10use crate::dht::Did;
11use crate::message::HandleMsg;
12use crate::message::Message;
13use crate::message::MessageHandler;
14use crate::message::MessagePayload;
15use crate::message::MessageVerificationExt;
16use crate::swarm::transport::SwarmTransport;
17
18type CallbackError = Box<dyn std::error::Error>;
19
20#[cfg(feature = "wasm")]
22pub type SharedSwarmCallback = Arc<dyn SwarmCallback>;
23
24#[cfg(not(feature = "wasm"))]
26pub type SharedSwarmCallback = Arc<dyn SwarmCallback + Send + Sync>;
27
28#[derive(Debug)]
30#[non_exhaustive]
31pub enum SwarmEvent {
32 ConnectionStateChange {
34 peer: Did,
36 state: WebrtcConnectionState,
38 },
39}
40
41#[cfg_attr(feature = "wasm", async_trait(?Send))]
43#[cfg_attr(not(feature = "wasm"), async_trait)]
44pub trait SwarmCallback {
45 async fn on_validate(&self, _payload: &MessagePayload) -> Result<(), CallbackError> {
47 Ok(())
48 }
49
50 async fn on_inbound(&self, _payload: &MessagePayload) -> Result<(), CallbackError> {
53 Ok(())
54 }
55
56 async fn on_event(&self, _event: &SwarmEvent) -> Result<(), CallbackError> {
58 Ok(())
59 }
60}
61
62pub struct InnerSwarmCallback {
64 transport: Arc<SwarmTransport>,
65 message_handler: MessageHandler,
66 callback: SharedSwarmCallback,
67 reassembler: FuturesMutex<MessageReassembler>,
68}
69
70impl InnerSwarmCallback {
71 pub fn new(transport: Arc<SwarmTransport>, callback: SharedSwarmCallback) -> Self {
73 let message_handler = MessageHandler::new(transport.clone(), callback.clone());
74 let reassembler = MessageReassembler::with_limits(transport.reassembly_limits());
75 Self {
76 transport,
77 message_handler,
78 callback,
79 reassembler: FuturesMutex::new(reassembler),
80 }
81 }
82
83 async fn handle_payload(
84 &self,
85 cid: &str,
86 payload: &MessagePayload,
87 ) -> Result<(), CallbackError> {
88 let message: Message = payload.transaction.data()?;
89
90 let result = match &message {
91 Message::ConnectNodeSend(ref msg) => self.message_handler.handle(payload, msg).await,
92 Message::ConnectNodeReport(ref msg) => self.message_handler.handle(payload, msg).await,
93 Message::FindSuccessorSend(ref msg) => self.message_handler.handle(payload, msg).await,
94 Message::FindSuccessorReport(ref msg) => {
95 self.message_handler.handle(payload, msg).await
96 }
97 Message::NotifyPredecessorSend(ref msg) => {
98 self.message_handler.handle(payload, msg).await
99 }
100 Message::NotifyPredecessorReport(ref msg) => {
101 self.message_handler.handle(payload, msg).await
102 }
103 Message::SearchEntry(ref msg) => self.message_handler.handle(payload, msg).await,
104 Message::FoundEntry(ref msg) => self.message_handler.handle(payload, msg).await,
105 Message::SyncEntriesWithSuccessor(ref msg) => {
106 self.message_handler.handle(payload, msg).await
107 }
108 Message::SyncEntriesWithSuccessorReport(ref msg) => {
109 self.message_handler.handle(payload, msg).await
110 }
111 Message::OperateEntry(ref msg) => self.message_handler.handle(payload, msg).await,
112 Message::CustomMessage(ref msg) => self.message_handler.handle(payload, msg).await,
113 Message::E2eHandshakeRequest(ref msg) => {
114 self.message_handler.handle(payload, msg).await
115 }
116 Message::E2eHandshakeResponse(ref msg) => {
117 self.message_handler.handle(payload, msg).await
118 }
119 Message::E2eStreamFrame(ref msg) => self.message_handler.handle(payload, msg).await,
120 Message::QueryForTopoInfoSend(ref msg) => {
121 self.message_handler.handle(payload, msg).await
122 }
123 Message::QueryForTopoInfoReport(ref msg) => {
124 self.message_handler.handle(payload, msg).await
125 }
126 Message::Chunk(ref msg) => {
127 if let Some(data) = self.reassembler.lock().await.handle(msg.clone()) {
132 return self.on_message(cid, &data).await;
133 }
134 return Ok(());
135 }
136 };
137
138 if let Err(e) = result {
141 tracing::error!("Failed to handle_payload: {e:?}");
142 return Err(e.into());
143 }
144
145 if payload.transaction.destination == self.transport.dht.did {
146 self.callback.on_inbound(payload).await?;
147 }
148
149 Ok(())
150 }
151}
152
153#[cfg_attr(feature = "wasm", async_trait(?Send))]
154#[cfg_attr(not(feature = "wasm"), async_trait)]
155impl TransportCallback for InnerSwarmCallback {
156 async fn on_message(&self, cid: &str, msg: &[u8]) -> Result<(), CallbackError> {
157 let peer = Did::from_str(cid).ok();
158 let payload = match MessagePayload::from_bincode(msg) {
159 Ok(payload) => payload,
160 Err(e) => {
161 if let Some(peer) = peer {
162 self.transport
163 .record_peer_message_receive_failed(peer)
164 .await;
165 }
166 return Err(e.into());
167 }
168 };
169 if !(payload.verify() && payload.transaction.verify()) {
170 tracing::error!("Cannot verify msg or it's expired: {:?}", payload);
171 if let Some(peer) = peer {
172 self.transport
173 .record_peer_message_receive_failed(peer)
174 .await;
175 }
176 return Err("Cannot verify msg or it's expired".into());
177 }
178 if let Some(peer) = peer {
179 self.transport.record_peer_message_received(peer).await;
180 }
181 self.callback.on_validate(&payload).await?;
182 self.handle_payload(cid, &payload).await
183 }
184
185 async fn on_peer_connection_state_change(
186 &self,
187 cid: &str,
188 s: WebrtcConnectionState,
189 ) -> Result<(), CallbackError> {
190 let Ok(did) = Did::from_str(cid) else {
191 tracing::warn!("on_peer_connection_state_change parse did failed: {}", cid);
192 return Ok(());
193 };
194
195 match s {
196 WebrtcConnectionState::Failed | WebrtcConnectionState::Closed => {
199 self.transport.record_peer_disconnected(did).await;
200 self.message_handler.leave_dht(did).await?;
201 }
202 WebrtcConnectionState::Disconnected => {
209 self.transport.record_peer_disconnected(did).await;
210 tracing::info!("Connection to {did} is disconnected, waiting for recovery");
211 }
212 _ => {}
213 };
214
215 if s != WebrtcConnectionState::Connected {
219 self.callback
220 .on_event(&SwarmEvent::ConnectionStateChange {
221 peer: did,
222 state: s,
223 })
224 .await?
225 }
226
227 Ok(())
228 }
229
230 async fn on_data_channel_open(&self, cid: &str) -> Result<(), CallbackError> {
231 let Ok(did) = Did::from_str(cid) else {
232 tracing::warn!("on_data_channel_open parse did failed: {}", cid);
233 return Ok(());
234 };
235
236 self.transport.record_peer_connected(did).await;
237 self.message_handler.join_dht(did).await?;
238
239 self.callback
243 .on_event(&SwarmEvent::ConnectionStateChange {
244 peer: did,
245 state: WebrtcConnectionState::Connected,
246 })
247 .await
248 }
249
250 async fn on_data_channel_close(&self, cid: &str) -> Result<(), CallbackError> {
251 let Ok(did) = Did::from_str(cid) else {
252 tracing::warn!("on_data_channel_close parse did failed: {}", cid);
253 return Ok(());
254 };
255
256 self.transport.record_peer_disconnected(did).await;
262 self.message_handler.leave_dht(did).await?;
263 Ok(())
264 }
265}