Skip to main content

calimero_network/handlers/commands/
dial.rs

1use std::collections::hash_map::Entry;
2
3use actix::{Context, Handler, Message, Response};
4use calimero_network_primitives::messages::Dial;
5use eyre::eyre;
6use multiaddr::Protocol;
7use tokio::sync::oneshot;
8
9use crate::NetworkManager;
10
11impl Handler<Dial> for NetworkManager {
12    type Result = Response<<Dial as Message>::Result>;
13
14    fn handle(&mut self, Dial(mut peer_addr): Dial, _ctx: &mut Context<Self>) -> Self::Result {
15        let Some(Protocol::P2p(peer_id)) = peer_addr.pop() else {
16            return Response::reply(Err(eyre!("No peer ID in address: {}", peer_addr)));
17        };
18
19        let (sender, receiver) = oneshot::channel();
20
21        match self.pending_dial.entry(peer_id) {
22            Entry::Occupied(_) => {
23                // todo! await the existing receiver
24                return Response::reply(Ok(()));
25            }
26            Entry::Vacant(entry) => {
27                let _ignored = self
28                    .swarm
29                    .behaviour_mut()
30                    .kad
31                    .add_address(&peer_id, peer_addr.clone());
32
33                match self.swarm.dial(peer_addr) {
34                    Ok(()) => {
35                        let _ignored = entry.insert(sender);
36                    }
37                    Err(e) => {
38                        return Response::reply(Err(eyre!(e)));
39                    }
40                }
41            }
42        }
43
44        Response::fut(async { receiver.await.expect("Sender not to be dropped.") })
45    }
46}