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 payload = MessagePayload::from_bincode(msg)?;
158 if !(payload.verify() && payload.transaction.verify()) {
159 tracing::error!("Cannot verify msg or it's expired: {:?}", payload);
160 return Err("Cannot verify msg or it's expired".into());
161 }
162 self.callback.on_validate(&payload).await?;
163 self.handle_payload(cid, &payload).await
164 }
165
166 async fn on_peer_connection_state_change(
167 &self,
168 cid: &str,
169 s: WebrtcConnectionState,
170 ) -> Result<(), CallbackError> {
171 let Ok(did) = Did::from_str(cid) else {
172 tracing::warn!("on_peer_connection_state_change parse did failed: {}", cid);
173 return Ok(());
174 };
175
176 match s {
177 WebrtcConnectionState::Failed | WebrtcConnectionState::Closed => {
180 self.message_handler.leave_dht(did).await?;
181 }
182 WebrtcConnectionState::Disconnected => {
189 tracing::info!("Connection to {did} is disconnected, waiting for recovery");
190 }
191 _ => {}
192 };
193
194 if s != WebrtcConnectionState::Connected {
198 self.callback
199 .on_event(&SwarmEvent::ConnectionStateChange {
200 peer: did,
201 state: s,
202 })
203 .await?
204 }
205
206 Ok(())
207 }
208
209 async fn on_data_channel_open(&self, cid: &str) -> Result<(), CallbackError> {
210 let Ok(did) = Did::from_str(cid) else {
211 tracing::warn!("on_data_channel_open parse did failed: {}", cid);
212 return Ok(());
213 };
214
215 self.message_handler.join_dht(did).await?;
216
217 self.callback
221 .on_event(&SwarmEvent::ConnectionStateChange {
222 peer: did,
223 state: WebrtcConnectionState::Connected,
224 })
225 .await
226 }
227
228 async fn on_data_channel_close(&self, cid: &str) -> Result<(), CallbackError> {
229 let Ok(did) = Did::from_str(cid) else {
230 tracing::warn!("on_data_channel_close parse did failed: {}", cid);
231 return Ok(());
232 };
233
234 self.message_handler.leave_dht(did).await?;
240 Ok(())
241 }
242}