1#![warn(missing_docs)]
2
3mod builder;
6pub mod callback;
8pub(crate) mod transport;
9
10use std::sync::Arc;
11use std::sync::RwLock;
12
13pub use builder::SwarmBuilder;
14
15use self::callback::InnerSwarmCallback;
16use crate::dht::Did;
17use crate::dht::PeerRing;
18use crate::dht::Stabilizer;
19use crate::ecc::PublicKey;
20use crate::error::Error;
21use crate::error::Result;
22use crate::inspect::ConnectionInspect;
23use crate::inspect::SwarmInspect;
24use crate::message::Message;
25use crate::message::MessagePayload;
26use crate::message::MessageVerificationExt;
27use crate::message::PayloadSender;
28use crate::swarm::callback::SharedSwarmCallback;
29use crate::swarm::transport::SwarmTransport;
30
31pub struct Swarm {
33 pub(crate) dht: Arc<PeerRing>,
35 pub(crate) transport: Arc<SwarmTransport>,
37 callback: RwLock<SharedSwarmCallback>,
38}
39
40impl Swarm {
41 pub fn did(&self) -> Did {
43 self.dht.did
44 }
45
46 pub fn account_pubkey(&self) -> Result<PublicKey<33>> {
48 self.transport.session_sk().session().account_pubkey()
49 }
50
51 pub fn dht(&self) -> Arc<PeerRing> {
53 self.dht.clone()
54 }
55
56 fn callback(&self) -> Result<SharedSwarmCallback> {
57 Ok(self
58 .callback
59 .read()
60 .map_err(|_| Error::CallbackSyncLockError)?
61 .clone())
62 }
63
64 fn inner_callback(&self) -> Result<InnerSwarmCallback> {
65 Ok(InnerSwarmCallback::new(
66 self.transport.clone(),
67 self.callback()?,
68 ))
69 }
70
71 pub fn set_callback(&self, callback: SharedSwarmCallback) -> Result<()> {
73 let mut inner = self
74 .callback
75 .write()
76 .map_err(|_| Error::CallbackSyncLockError)?;
77
78 *inner = callback;
79
80 Ok(())
81 }
82
83 pub fn stabilizer(&self) -> Stabilizer {
85 Stabilizer::new(self.transport.clone())
86 }
87
88 pub async fn disconnect(&self, peer: Did) -> Result<()> {
93 self.transport.disconnect(peer).await
94 }
95
96 pub async fn connect(&self, peer: Did) -> Result<()> {
100 if peer == self.did() {
101 return Err(Error::ShouldNotConnectSelf);
102 }
103 self.transport.connect(peer, self.inner_callback()?).await
104 }
105
106 pub async fn send_message(&self, msg: Message, destination: Did) -> Result<uuid::Uuid> {
108 self.transport.send_message(msg, destination).await
109 }
110
111 pub fn peers(&self) -> Vec<ConnectionInspect> {
113 self.transport
114 .get_connections()
115 .iter()
116 .map(|(did, c)| ConnectionInspect {
117 did: did.to_string(),
118 state: format!("{:?}", c.webrtc_connection_state()),
119 })
120 .collect()
121 }
122
123 pub async fn inspect(&self) -> SwarmInspect {
125 SwarmInspect::inspect(self).await
126 }
127}
128
129impl Swarm {
130 pub async fn create_offer(&self, peer: Did) -> Result<MessagePayload> {
133 let offer_msg = self
134 .transport
135 .prepare_connection_offer(peer, self.inner_callback()?)
136 .await?;
137
138 let payload = MessagePayload::new_send(
141 Message::ConnectNodeSend(offer_msg),
142 self.transport.session_sk(),
143 self.did(),
144 peer,
145 )?;
146
147 Ok(payload)
148 }
149
150 pub async fn answer_offer(&self, offer_payload: MessagePayload) -> Result<MessagePayload> {
153 if !offer_payload.verify() {
154 return Err(Error::VerifySignatureFailed);
155 }
156
157 let Message::ConnectNodeSend(msg) = offer_payload.transaction.data()? else {
158 return Err(Error::InvalidMessage(
159 "Should be ConnectNodeSend".to_string(),
160 ));
161 };
162
163 let peer = offer_payload.transaction.signer();
164 let answer_msg = self
165 .transport
166 .answer_remote_connection(peer, self.inner_callback()?, &msg)
167 .await?;
168
169 let answer_payload = MessagePayload::new_send(
172 Message::ConnectNodeReport(answer_msg),
173 self.transport.session_sk(),
174 self.did(),
175 self.did(),
176 )?;
177
178 Ok(answer_payload)
179 }
180
181 pub async fn accept_answer(&self, answer_payload: MessagePayload) -> Result<()> {
184 if !answer_payload.verify() {
185 return Err(Error::VerifySignatureFailed);
186 }
187
188 let Message::ConnectNodeReport(ref msg) = answer_payload.transaction.data()? else {
189 return Err(Error::InvalidMessage(
190 "Should be ConnectNodeReport".to_string(),
191 ));
192 };
193
194 let peer = answer_payload.transaction.signer();
195 self.transport.accept_remote_connection(peer, msg).await
196 }
197}