use std::io;
use libp2p::{
swarm::{DialError, NetworkInfo},
Multiaddr, PeerId, TransportError,
};
use tokio::sync::oneshot;
use crate::{satellite::Message, Shoji, ShojiError, TatamiError};
#[derive(Debug)]
pub enum ShojiCommand {
GetClosestPeers(PeerId),
LocalPeerId(oneshot::Sender<PeerId>),
DialPeer(PeerId, oneshot::Sender<Result<(), DialError>>),
DialAddress(Multiaddr, oneshot::Sender<Result<(), DialError>>),
Listeners(oneshot::Sender<Vec<Multiaddr>>),
ListenOn(
Multiaddr,
oneshot::Sender<Result<(), TransportError<io::Error>>>,
),
BanPeerId(PeerId),
UnbanPeerId(PeerId),
ConnectedPeers(oneshot::Sender<Vec<PeerId>>),
DisconnectPeerId(PeerId, oneshot::Sender<Result<(), TatamiError>>),
IsConnected(PeerId, oneshot::Sender<bool>),
NetworkInfo(oneshot::Sender<NetworkInfo>),
AddAddress(PeerId, Multiaddr),
PublishMessage(Message, oneshot::Sender<Result<(), TatamiError>>),
Publish(Vec<u8>, oneshot::Sender<Result<(), TatamiError>>),
}
impl Shoji {
pub async fn local_peer_id(&self) -> Result<PeerId, ShojiError> {
let (sender, receiver) = oneshot::channel();
self.commander
.send(ShojiCommand::LocalPeerId(sender))
.await?;
Ok(receiver.await?)
}
pub async fn get_closest_peers(&self, peer_id: PeerId) -> Result<(), ShojiError> {
Ok(self
.commander
.send(ShojiCommand::GetClosestPeers(peer_id))
.await?)
}
pub async fn dial_peer(&self, peer_id: PeerId) -> Result<(), ShojiError> {
let (sender, receiver) = oneshot::channel();
self.commander
.send(ShojiCommand::DialPeer(peer_id, sender))
.await?;
Ok(receiver.await??)
}
pub async fn dial_address(&self, address: Multiaddr) -> Result<(), ShojiError> {
let (sender, receiver) = oneshot::channel();
self.commander
.send(ShojiCommand::DialAddress(address, sender))
.await?;
Ok(receiver.await??)
}
pub async fn disconnect_peer_id(&self, peer_id: PeerId) -> Result<(), ShojiError> {
let (sender, receiver) = oneshot::channel();
self.commander
.send(ShojiCommand::DisconnectPeerId(peer_id, sender))
.await?;
receiver.await?.or(Err(ShojiError::Generic))
}
pub async fn publish_message(&self, message: Message) -> Result<(), TatamiError> {
let (sender, receiver) = oneshot::channel();
self.commander
.send(ShojiCommand::PublishMessage(message, sender))
.await?;
receiver.await?
}
pub async fn publish(&self, payload: Vec<u8>) -> Result<(), TatamiError> {
let (sender, receiver) = oneshot::channel();
self.commander
.send(ShojiCommand::Publish(payload, sender))
.await?;
receiver.await?
}
pub async fn listeners(&self) -> Result<Vec<Multiaddr>, ShojiError> {
let (sender, receiver) = oneshot::channel();
self.commander.send(ShojiCommand::Listeners(sender)).await?;
Ok(receiver.await?)
}
pub async fn connected_peers(&self) -> Result<Vec<PeerId>, ShojiError> {
let (sender, receiver) = oneshot::channel();
self.commander
.send(ShojiCommand::ConnectedPeers(sender))
.await?;
Ok(receiver.await?)
}
pub async fn listen_on(&self, address: Multiaddr) -> Result<(), ShojiError> {
let (sender, receiver) = oneshot::channel();
self.commander
.send(ShojiCommand::ListenOn(address, sender))
.await?;
Ok(receiver.await??)
}
pub async fn ban_peer(&self, peer_id: PeerId) -> Result<(), ShojiError> {
self.commander
.send(ShojiCommand::BanPeerId(peer_id))
.await?;
Ok(())
}
pub async fn is_connected(&self, peer_id: PeerId) -> Result<bool, ShojiError> {
let (sender, receiver) = oneshot::channel();
self.commander
.send(ShojiCommand::IsConnected(peer_id, sender))
.await?;
Ok(receiver.await?)
}
pub async fn unban_peer(&self, peer_id: PeerId) -> Result<(), ShojiError> {
self.commander
.send(ShojiCommand::UnbanPeerId(peer_id))
.await?;
Ok(())
}
pub async fn network_info(&self) -> Result<NetworkInfo, ShojiError> {
let (sender, receiver) = oneshot::channel();
self.commander
.send(ShojiCommand::NetworkInfo(sender))
.await?;
Ok(receiver.await?)
}
pub async fn add_address(
&self,
peer_id: PeerId,
multiaddr: Multiaddr,
) -> Result<(), ShojiError> {
self.commander
.send(ShojiCommand::AddAddress(peer_id, multiaddr))
.await?;
Ok(())
}
}