use super::*;
impl Handle {
pub(in crate::engine) async fn snapshot(&self) -> io::Result<SavedState> {
let (reply, result) = oneshot::channel();
self.commands
.send(Command::Snapshot(reply))
.await
.map_err(|_| stopped())?;
result.await.map_err(|_| stopped())
}
pub(super) async fn bootstrap_finished(&self) -> io::Result<()> {
let (reply, result) = oneshot::channel();
self.commands
.send(Command::BootstrapFinished(reply))
.await
.map_err(|_| stopped())?;
result.await.map_err(|_| stopped())
}
pub(super) async fn set_routers(&self, addresses: Vec<SocketAddrV4>) -> io::Result<()> {
let (reply, result) = oneshot::channel();
self.commands
.send(Command::Routers(addresses, reply))
.await
.map_err(|_| stopped())?;
result.await.map_err(|_| stopped())
}
pub(in crate::engine) fn try_ping(&self, address: SocketAddrV4) -> io::Result<()> {
if !crate::engine::network::peer(address.into(), self.allow_local_network) {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"invalid DHT contact",
));
}
self.commands
.try_send(Command::Probe(address))
.map_err(|_| io::Error::new(io::ErrorKind::WouldBlock, "DHT command queue unavailable"))
}
pub(super) async fn closest(&self, target: NodeId) -> io::Result<Vec<NodeV4>> {
let (reply, result) = oneshot::channel();
self.commands
.send(Command::Closest(target, reply))
.await
.map_err(|_| stopped())?;
result.await.map_err(|_| stopped())
}
pub(super) async fn local_peers(
&self,
hash: crate::protocol::identity::InfoHashV1,
) -> io::Result<Vec<SocketAddrV4>> {
let (reply, result) = oneshot::channel();
self.commands
.send(Command::Peers(hash, reply))
.await
.map_err(|_| stopped())?;
result.await.map_err(|_| stopped())
}
pub(in crate::engine) fn local_addr(&self) -> SocketAddrV4 {
self.address
}
pub(in crate::engine) fn id(&self) -> NodeId {
self.id
}
pub(super) async fn refresh_targets(&self) -> io::Result<Vec<NodeId>> {
let (reply, result) = oneshot::channel();
self.commands
.send(Command::RefreshTargets(reply))
.await
.map_err(|_| stopped())?;
result.await.map_err(|_| stopped())
}
pub(super) async fn request_wait(
&self,
address: SocketAddrV4,
query: Query,
) -> io::Result<Reply> {
loop {
match self.request(address, query.clone()).await {
Err(error) if error.kind() == io::ErrorKind::WouldBlock => {
tokio::time::sleep(Duration::from_millis(100)).await;
}
result => return result,
}
}
}
pub(in crate::engine) async fn request(
&self,
address: SocketAddrV4,
query: Query,
) -> io::Result<Reply> {
if matches!(&query, Query::AnnouncePeer { port, token, .. } if *port == 0 || token.len() > 64)
{
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"invalid DHT announce",
));
}
let (reply, result) = oneshot::channel();
self.commands
.send(Command::Request {
address,
query,
reply,
})
.await
.map_err(|_| stopped())?;
result.await.map_err(|_| stopped())?
}
pub(in crate::engine) async fn stats(&self) -> io::Result<Stats> {
let (reply, result) = oneshot::channel();
self.commands
.send(Command::Stats(reply))
.await
.map_err(|_| stopped())?;
result.await.map_err(|_| stopped())
}
}