1#![allow(unused_imports)]
2use crate::error::ConnexaResult;
3use crate::handle::swarm::ConnectionTarget;
4use crate::prelude::swarm::{DialError, ListenError, ListenOpts, SwarmEvent};
5use bytes::Bytes;
6use either::Either;
7use futures::channel::{mpsc, oneshot};
8use futures::future::BoxFuture;
9use futures::stream::BoxStream;
10use indexmap::IndexSet;
11use libp2p::core::ConnectedPoint;
12#[cfg(feature = "gossipsub")]
13use libp2p::gossipsub::{MessageAcceptance, MessageId};
14#[cfg(feature = "kad")]
15use libp2p::kad::{Mode, PeerInfo, PeerRecord, ProviderRecord, Quorum, Record, RecordKey};
16#[cfg(feature = "rendezvous")]
17use libp2p::rendezvous::Cookie;
18#[cfg(feature = "request-response")]
19use libp2p::request_response::InboundRequestId;
20use libp2p::swarm::derive_prelude::ListenerId;
21use libp2p::swarm::dial_opts::DialOpts;
22use libp2p::swarm::{ConnectionError, ConnectionId};
23use libp2p::{Multiaddr, PeerId, StreamProtocol};
24use libp2p_connection_limits::ConnectionLimits;
25use other_error::ArcError;
26use std::collections::HashSet;
27use std::convert::Infallible;
28use std::sync::Arc;
29
30type Result<T> = std::io::Result<T>;
31
32#[derive(Debug)]
33pub enum Command<T = ()> {
34 Swarm(SwarmCommand),
35 #[cfg(feature = "gossipsub")]
36 Gossipsub(GossipsubCommand),
37 #[cfg(feature = "floodsub")]
38 Floodsub(FloodsubCommand),
39 #[cfg(feature = "kad")]
40 Dht(DHTCommand),
41 #[cfg(feature = "request-response")]
42 RequestResponse(RequestResponseCommand),
43 #[cfg(feature = "stream")]
44 Stream(StreamCommand),
45 #[cfg(feature = "rendezvous")]
46 Rendezvous(RendezvousCommand),
47 #[cfg(feature = "autonat")]
48 Autonat(AutonatCommand),
49 #[cfg(feature = "relay")]
50 AutoRelay(AutoRelayCommand),
51 Whitelist(WhitelistCommand),
52 Blacklist(BlacklistCommand),
53 ConnectionLimits(ConnectionLimitsCommand),
54 Peerstore(PeerstoreCommand),
55 Custom(T),
56}
57
58impl<T> From<SwarmCommand> for Command<T> {
59 fn from(cmd: SwarmCommand) -> Self {
60 Command::Swarm(cmd)
61 }
62}
63
64#[cfg(feature = "autonat")]
65impl<T> From<AutonatCommand> for Command<T> {
66 fn from(cmd: AutonatCommand) -> Self {
67 Command::Autonat(cmd)
68 }
69}
70
71#[cfg(feature = "gossipsub")]
72impl<T> From<GossipsubCommand> for Command<T> {
73 fn from(cmd: GossipsubCommand) -> Self {
74 Command::Gossipsub(cmd)
75 }
76}
77
78#[cfg(feature = "floodsub")]
79impl<T> From<FloodsubCommand> for Command<T> {
80 fn from(cmd: FloodsubCommand) -> Self {
81 Command::Floodsub(cmd)
82 }
83}
84
85#[cfg(feature = "kad")]
86impl<T> From<DHTCommand> for Command<T> {
87 fn from(cmd: DHTCommand) -> Self {
88 Command::Dht(cmd)
89 }
90}
91
92#[cfg(feature = "request-response")]
93impl<T> From<RequestResponseCommand> for Command<T> {
94 fn from(cmd: RequestResponseCommand) -> Self {
95 Command::RequestResponse(cmd)
96 }
97}
98
99#[cfg(feature = "stream")]
100impl<T> From<StreamCommand> for Command<T> {
101 fn from(cmd: StreamCommand) -> Self {
102 Command::Stream(cmd)
103 }
104}
105
106#[cfg(feature = "rendezvous")]
107impl<T> From<RendezvousCommand> for Command<T> {
108 fn from(cmd: RendezvousCommand) -> Self {
109 Command::Rendezvous(cmd)
110 }
111}
112
113#[cfg(feature = "relay")]
114impl<T> From<AutoRelayCommand> for Command<T> {
115 fn from(cmd: AutoRelayCommand) -> Self {
116 Command::AutoRelay(cmd)
117 }
118}
119
120impl<T> From<WhitelistCommand> for Command<T> {
121 fn from(cmd: WhitelistCommand) -> Self {
122 Command::Whitelist(cmd)
123 }
124}
125
126impl<T> From<BlacklistCommand> for Command<T> {
127 fn from(cmd: BlacklistCommand) -> Self {
128 Command::Blacklist(cmd)
129 }
130}
131
132impl<T> From<ConnectionLimitsCommand> for Command<T> {
133 fn from(cmd: ConnectionLimitsCommand) -> Self {
134 Command::ConnectionLimits(cmd)
135 }
136}
137
138impl<T> From<PeerstoreCommand> for Command<T> {
139 fn from(value: PeerstoreCommand) -> Self {
140 Command::Peerstore(value)
141 }
142}
143
144#[derive(Debug)]
145pub enum SwarmCommand {
146 Dial {
147 opt: DialOpts,
148 resp: oneshot::Sender<ConnexaResult<ConnectionId>>,
149 },
150 IsConnected {
151 peer_id: PeerId,
152 resp: oneshot::Sender<bool>,
153 },
154 Disconnect {
155 target_type: ConnectionTarget,
156 resp: oneshot::Sender<ConnexaResult<()>>,
157 },
158 ConnectedPeers {
159 resp: oneshot::Sender<Vec<PeerId>>,
160 },
161 ListenOn {
162 address: Multiaddr,
163 resp: oneshot::Sender<ConnexaResult<ListenerId>>,
164 },
165 GetListeningAddress {
166 id: ListenerId,
167 resp: oneshot::Sender<ConnexaResult<Vec<Multiaddr>>>,
168 },
169 RemoveListener {
170 listener_id: ListenerId,
171 resp: oneshot::Sender<ConnexaResult<()>>,
172 },
173 AddExternalAddress {
174 address: Multiaddr,
175 resp: oneshot::Sender<ConnexaResult<()>>,
176 },
177 RemoveExternalAddress {
178 address: Multiaddr,
179 resp: oneshot::Sender<ConnexaResult<()>>,
180 },
181 ListExternalAddresses {
182 resp: oneshot::Sender<Vec<Multiaddr>>,
183 },
184 ListListeningAddresses {
185 resp: oneshot::Sender<Vec<Multiaddr>>,
186 },
187 AddPeerAddress {
188 peer_id: PeerId,
189 address: Multiaddr,
190 resp: oneshot::Sender<ConnexaResult<()>>,
191 },
192 Listener {
193 resp: oneshot::Sender<mpsc::Receiver<ConnexaSwarmEvent>>,
194 },
195}
196
197#[derive(Debug, Clone)]
198pub enum ConnexaSwarmEvent {
199 ConnectionEstablished {
200 peer_id: PeerId,
201 connection_id: ConnectionId,
202 endpoint: ConnectedPoint,
203 established: u32,
204 },
205 ConnectionClosed {
206 peer_id: PeerId,
207 connection_id: ConnectionId,
208 endpoint: ConnectedPoint,
209 num_established: u32,
210 cause: Option<ArcError<ConnectionError>>,
211 },
212 IncomingConnection {
213 connection_id: ConnectionId,
214 local_addr: Multiaddr,
215 send_back_addr: Multiaddr,
216 },
217 IncomingConnectionError {
218 connection_id: ConnectionId,
219 local_addr: Multiaddr,
220 send_back_addr: Multiaddr,
221 error: ArcError<ListenError>,
222 peer_id: Option<PeerId>,
223 },
224 OutgoingConnectionError {
225 connection_id: ConnectionId,
226 peer_id: Option<PeerId>,
227 error: ArcError<DialError>,
228 },
229 NewListenAddr {
230 id: ListenerId,
231 address: Multiaddr,
232 },
233 ListenAddrExpired {
234 id: ListenerId,
235 address: Multiaddr,
236 },
237 ListenAddrClosed {
238 id: ListenerId,
239 addresses: Vec<Multiaddr>,
240 },
241 NewExternalAddr {
242 address: Multiaddr,
243 },
244 ExternalAddrExpired {
245 address: Multiaddr,
246 },
247 ExternalAddrOfPeer {
248 peer_id: PeerId,
249 address: Multiaddr,
250 },
251}
252
253#[cfg(feature = "floodsub")]
254#[derive(Debug)]
255pub enum FloodsubCommand {
256 Subscribe {
257 topic: libp2p::floodsub::Topic,
258 resp: oneshot::Sender<ConnexaResult<()>>,
259 },
260 Unsubscribe {
261 topic: libp2p::floodsub::Topic,
262 resp: oneshot::Sender<ConnexaResult<()>>,
263 },
264 AddNodeToPartialView {
265 peer_id: PeerId,
266 resp: oneshot::Sender<ConnexaResult<()>>,
267 },
268 RemoveNodeFromPartialView {
269 peer_id: PeerId,
270 resp: oneshot::Sender<ConnexaResult<()>>,
271 },
272 FloodsubListener {
273 topic: libp2p::floodsub::Topic,
274 resp: oneshot::Sender<ConnexaResult<mpsc::Receiver<FloodsubEvent>>>,
275 },
276 Publish(PubsubFloodsubPublish, oneshot::Sender<ConnexaResult<()>>),
277}
278
279#[cfg(feature = "gossipsub")]
280#[derive(Debug)]
281pub enum GossipsubCommand {
282 Subscribe {
283 topic: libp2p::gossipsub::TopicHash,
284 resp: oneshot::Sender<ConnexaResult<()>>,
285 },
286 Unsubscribe {
287 topic: libp2p::gossipsub::TopicHash,
288 resp: oneshot::Sender<ConnexaResult<()>>,
289 },
290 Subscribed {
291 resp: oneshot::Sender<ConnexaResult<Vec<libp2p::gossipsub::TopicHash>>>,
292 },
293 Peers {
294 topic: libp2p::gossipsub::TopicHash,
295 resp: oneshot::Sender<ConnexaResult<Vec<PeerId>>>,
296 },
297 GossipsubListener {
298 topic: libp2p::gossipsub::TopicHash,
299 resp: oneshot::Sender<ConnexaResult<mpsc::Receiver<GossipsubEvent>>>,
300 },
301 Publish {
302 topic: libp2p::gossipsub::TopicHash,
303 data: Bytes,
304 resp: oneshot::Sender<ConnexaResult<()>>,
305 },
306 ReportMessage {
307 peer_id: PeerId,
308 message_id: MessageId,
309 accept: MessageAcceptance,
310 resp: oneshot::Sender<ConnexaResult<bool>>,
311 },
312}
313
314#[derive(Debug)]
315pub enum ConnectionLimitsCommand {
316 Get {
317 resp: oneshot::Sender<Result<ConnectionLimits>>,
318 },
319 Set {
320 limits: ConnectionLimits,
321 resp: oneshot::Sender<Result<()>>,
322 },
323}
324
325#[cfg(feature = "floodsub")]
326#[derive(Debug)]
327pub enum PubsubFloodsubPublish {
328 Publish {
329 topic: libp2p::floodsub::Topic,
330 data: Bytes,
331 },
332 PublishAny {
333 topic: libp2p::floodsub::Topic,
334 data: Bytes,
335 },
336 PublishMany {
337 topics: Vec<libp2p::floodsub::Topic>,
338 data: Bytes,
339 },
340 PublishManyAny {
341 topics: Vec<libp2p::floodsub::Topic>,
342 data: Bytes,
343 },
344}
345
346#[cfg(feature = "autonat")]
347#[derive(Debug)]
348pub enum AutonatCommand {
349 PublicAddress {
350 resp: oneshot::Sender<ConnexaResult<Option<Multiaddr>>>,
351 },
352 NatStatus {
353 resp: oneshot::Sender<ConnexaResult<libp2p::autonat::NatStatus>>,
354 },
355 AddServer {
356 peer: PeerId,
357 address: Option<Multiaddr>,
358 resp: oneshot::Sender<ConnexaResult<()>>,
359 },
360 RemoveServer {
361 peer: PeerId,
362 resp: oneshot::Sender<ConnexaResult<()>>,
363 },
364 Probe {
365 address: Multiaddr,
366 resp: oneshot::Sender<ConnexaResult<()>>,
367 },
368}
369
370#[cfg(feature = "kad")]
371#[derive(Debug)]
372pub enum DHTCommand {
373 FindPeer {
374 peer_id: PeerId,
375 resp: oneshot::Sender<ConnexaResult<Vec<PeerInfo>>>,
376 },
377 Bootstrap {
378 lazy: bool,
379 resp: oneshot::Sender<ConnexaResult<()>>,
380 },
381 Provide {
382 key: RecordKey,
383 resp: oneshot::Sender<ConnexaResult<()>>,
384 },
385 StopProviding {
386 key: RecordKey,
387 resp: oneshot::Sender<ConnexaResult<()>>,
388 },
389 GetProviders {
390 key: RecordKey,
391 resp: oneshot::Sender<ConnexaResult<mpsc::Receiver<ConnexaResult<HashSet<PeerId>>>>>,
392 },
393 SetDHTMode {
394 mode: Option<Mode>,
395 resp: oneshot::Sender<ConnexaResult<()>>,
396 },
397 DHTMode {
398 resp: oneshot::Sender<ConnexaResult<Mode>>,
399 },
400
401 AddAddress {
402 peer_id: PeerId,
403 addr: Multiaddr,
404 resp: oneshot::Sender<ConnexaResult<()>>,
405 },
406
407 RemoveAddress {
408 peer_id: PeerId,
409 addr: Multiaddr,
410 resp: oneshot::Sender<ConnexaResult<()>>,
411 },
412
413 RemovePeer {
414 peer_id: PeerId,
415 resp: oneshot::Sender<ConnexaResult<()>>,
416 },
417 Get {
418 key: RecordKey,
419 resp: oneshot::Sender<ConnexaResult<mpsc::Receiver<ConnexaResult<PeerRecord>>>>,
420 },
421 Put {
422 key: RecordKey,
423 data: Bytes,
424 quorum: Quorum,
425 resp: oneshot::Sender<ConnexaResult<()>>,
426 },
427 Remove {
428 key: RecordKey,
429 resp: oneshot::Sender<ConnexaResult<()>>,
430 },
431 PutTo {
432 key: RecordKey,
433 target: Vec<PeerId>,
434 data: Bytes,
435 quorum: Quorum,
436 resp: oneshot::Sender<ConnexaResult<()>>,
437 },
438 Listener {
439 key: Option<RecordKey>,
440 resp: oneshot::Sender<ConnexaResult<mpsc::Receiver<DHTEvent>>>,
441 },
442}
443
444#[cfg(feature = "relay")]
445#[derive(Debug)]
446pub enum AutoRelayCommand {
447 AddStaticRelay {
448 peer_id: PeerId,
449 relay_addr: Multiaddr,
450 resp: oneshot::Sender<Result<bool>>,
451 },
452 RemoveStaticRelay {
453 peer_id: PeerId,
454 resp: oneshot::Sender<Result<bool>>,
455 },
456 DisableRelays {
457 resp: oneshot::Sender<Result<()>>,
458 },
459 ListStaticRelays {
460 resp: oneshot::Sender<Result<Vec<(PeerId, Vec<Multiaddr>)>>>,
461 },
462 GetStaticRelay {
463 peer_id: PeerId,
464 resp: oneshot::Sender<Result<Vec<Multiaddr>>>,
465 },
466 EnableAutoRelay {
467 resp: oneshot::Sender<Result<()>>,
468 },
469 DisableAutoRelay {
470 resp: oneshot::Sender<Result<()>>,
471 },
472}
473
474#[cfg(feature = "request-response")]
475type ResponseStream = BoxStream<'static, (PeerId, ConnexaResult<Bytes>)>;
476#[cfg(feature = "request-response")]
477type ResponseFuture = BoxFuture<'static, ConnexaResult<Bytes>>;
478
479type PeerAddressList = Vec<(PeerId, Vec<Multiaddr>)>;
480
481#[cfg(feature = "rendezvous")]
482type RendezvousDiscoverResponse = ConnexaResult<(Cookie, Vec<(PeerId, Vec<Multiaddr>)>)>;
483
484#[cfg(feature = "request-response")]
485#[derive(Debug)]
486pub enum RequestResponseCommand {
487 SendRequests {
488 protocol: Option<StreamProtocol>,
489 peers: IndexSet<PeerId>,
490 request: Bytes,
491 resp: oneshot::Sender<ConnexaResult<ResponseStream>>,
492 },
493 SendRequest {
494 protocol: Option<StreamProtocol>,
495 peer_id: PeerId,
496 request: Bytes,
497 resp: oneshot::Sender<ConnexaResult<ResponseFuture>>,
498 },
499 SendResponse {
500 protocol: Option<StreamProtocol>,
501 peer_id: PeerId,
502 request_id: InboundRequestId,
503 response: Bytes,
504 resp: oneshot::Sender<ConnexaResult<()>>,
505 },
506 ListenForRequests {
507 protocol: Option<StreamProtocol>,
508 resp: oneshot::Sender<ConnexaResult<mpsc::Receiver<(PeerId, InboundRequestId, Bytes)>>>,
509 },
510}
511
512#[cfg(feature = "stream")]
513#[derive(Debug)]
514pub enum StreamCommand {
515 NewStream {
516 protocol: StreamProtocol,
517 resp: oneshot::Sender<ConnexaResult<libp2p_stream::IncomingStreams>>,
518 },
519 ControlHandle {
520 resp: oneshot::Sender<ConnexaResult<libp2p_stream::Control>>,
521 },
522}
523
524#[cfg(feature = "rendezvous")]
525#[derive(Debug)]
526pub enum RendezvousCommand {
527 Register {
528 namespace: libp2p::rendezvous::Namespace,
529 peer_id: PeerId,
530 ttl: Option<u64>,
531 resp: oneshot::Sender<ConnexaResult<()>>,
532 },
533 Unregister {
534 namespace: libp2p::rendezvous::Namespace,
535 peer_id: PeerId,
536 resp: oneshot::Sender<ConnexaResult<()>>,
537 },
538 Discover {
539 namespace: Option<libp2p::rendezvous::Namespace>,
540 peer_id: PeerId,
541 cookie: Option<Cookie>,
542 ttl: Option<u64>,
543 resp: oneshot::Sender<RendezvousDiscoverResponse>,
544 },
545}
546
547#[cfg(feature = "kad")]
548#[derive(Clone, Debug)]
549pub enum DHTEvent {
550 PutRecord {
551 source: PeerId,
552 record: RecordHandle<Record>,
553 },
554 ProvideRecord {
555 record: RecordHandle<ProviderRecord>,
556 },
557}
558
559#[cfg(feature = "kad")]
560impl DHTEvent {
561 pub(crate) fn set_record_confirmation(&self, ch: oneshot::Sender<Record>) -> Self {
562 let mut event = self.clone();
563 match &mut event {
564 DHTEvent::PutRecord { record, .. } => {
565 record.confirm.replace(ch);
566 event
567 }
568 _ => unreachable!("DHTEvent::PutRecord called on non-PutRecord"),
569 }
570 }
571 pub(crate) fn set_provider_confirmation(&self, ch: oneshot::Sender<ProviderRecord>) -> Self {
572 let mut event = self.clone();
573 match &mut event {
574 DHTEvent::ProvideRecord { record, .. } => {
575 record.confirm.replace(ch);
576 event
577 }
578 _ => unreachable!("DHTEvent::ProvideRecord called on non-ProvideRecord"),
579 }
580 }
581}
582
583#[cfg(feature = "kad")]
584#[derive(Debug)]
585pub struct RecordHandle<R> {
586 pub(crate) record: Option<R>,
589 pub(crate) confirm: Option<oneshot::Sender<R>>,
590}
591
592#[cfg(feature = "kad")]
593impl<R> RecordHandle<R> {
594 pub fn record(&self) -> Option<&R> {
596 self.record.as_ref()
597 }
598
599 pub fn accept(mut self) {
601 if let (Some(ch), Some(record)) = (self.confirm.take(), self.record.take()) {
602 let _ = ch.send(record);
603 }
604 }
605
606 pub fn accept_with(mut self, record: R) {
608 if let Some(ch) = self.confirm.take() {
609 let _ = ch.send(record);
610 }
611 }
612
613 pub fn reject(self) {}
615}
616
617#[cfg(feature = "kad")]
618impl<R: Clone> Clone for RecordHandle<R> {
619 fn clone(&self) -> Self {
620 Self {
621 record: self.record.clone(),
622 confirm: None,
623 }
624 }
625}
626
627#[cfg(feature = "gossipsub")]
628#[derive(Debug, Clone, PartialEq, Eq)]
629pub enum GossipsubEvent {
630 Subscribed { peer_id: PeerId },
631 Unsubscribed { peer_id: PeerId },
632 Message { message: GossipsubMessage },
633}
634
635#[cfg(feature = "floodsub")]
636#[derive(Debug, Clone, PartialEq, Eq)]
637pub enum FloodsubEvent {
638 Subscribed { peer_id: PeerId },
639 Unsubscribed { peer_id: PeerId },
640 Message { message: FloodsubMessage },
641}
642
643#[cfg(feature = "gossipsub")]
644#[derive(Debug, Clone, PartialEq, Eq)]
645#[non_exhaustive]
646pub struct GossipsubMessage {
647 pub message_id: MessageId,
648 pub propagated_source: PeerId,
649 pub source: Option<PeerId>,
650 pub data: Bytes,
651 pub sequence_number: Option<u64>,
652}
653
654#[cfg(feature = "floodsub")]
655#[derive(Debug, Clone, PartialEq, Eq)]
656#[non_exhaustive]
657pub struct FloodsubMessage {
658 pub source: PeerId,
659 pub data: Bytes,
660 pub sequence_number: Vec<u8>,
661}
662
663#[derive(Debug)]
664pub enum WhitelistCommand {
665 Add {
666 peer_id: PeerId,
667 resp: oneshot::Sender<ConnexaResult<()>>,
668 },
669 Remove {
670 peer_id: PeerId,
671 resp: oneshot::Sender<ConnexaResult<()>>,
672 },
673 List {
674 resp: oneshot::Sender<ConnexaResult<Vec<PeerId>>>,
675 },
676}
677
678#[derive(Debug)]
679pub enum BlacklistCommand {
680 Add {
681 peer_id: PeerId,
682 resp: oneshot::Sender<ConnexaResult<()>>,
683 },
684 Remove {
685 peer_id: PeerId,
686 resp: oneshot::Sender<ConnexaResult<()>>,
687 },
688 List {
689 resp: oneshot::Sender<ConnexaResult<Vec<PeerId>>>,
690 },
691}
692
693#[derive(Debug)]
694pub enum PeerstoreCommand {
695 Add {
696 peer_id: PeerId,
697 addr: Multiaddr,
698 resp: oneshot::Sender<ConnexaResult<()>>,
699 },
700 RemoveAddress {
701 peer_id: PeerId,
702 addr: Multiaddr,
703 resp: oneshot::Sender<ConnexaResult<()>>,
704 },
705 Remove {
706 peer_id: PeerId,
707 resp: oneshot::Sender<ConnexaResult<Vec<Multiaddr>>>,
708 },
709 List {
710 peer_id: PeerId,
711 resp: oneshot::Sender<ConnexaResult<Vec<Multiaddr>>>,
712 },
713 ListAll {
714 resp: oneshot::Sender<ConnexaResult<PeerAddressList>>,
715 },
716}