use std::net::SocketAddr;
use crate::error::{Error, ErrorKind};
use super::{Node, krpc, rpc::DhtRpc};
pub async fn find_node(
rpc: &DhtRpc, addr: SocketAddr, tid: krpc::TransactionId, node_id: &[u8; 20], target: &[u8; 20],
) -> Result<Vec<Node>, Error> {
tracing::debug!("DHT find_node to {}", addr);
let data = krpc::build_find_node(tid, node_id, target);
let response = rpc.query(addr, tid, &data).await?;
match &response {
krpc::KrpcMessage::Response { result, .. } => {
if let Some(nodes_bytes) = krpc::dict_get_bytes(result, b"nodes") {
Ok(krpc::parse_compact_nodes(nodes_bytes))
} else {
Err(Error::new(ErrorKind::Protocol))
}
}
_ => Err(Error::new(ErrorKind::Protocol)),
}
}
pub async fn get_peers(
rpc: &DhtRpc, addr: SocketAddr, tid: krpc::TransactionId, node_id: &[u8; 20],
info_hash: &[u8; 20],
) -> Result<krpc::GetPeersResult, Error> {
tracing::debug!("DHT get_peers to {}", addr);
let data = krpc::build_get_peers(tid, node_id, info_hash);
let response = rpc.query(addr, tid, &data).await?;
krpc::parse_get_peers_response(&response)
}
pub async fn announce_peer(
rpc: &DhtRpc, addr: SocketAddr, tid: krpc::TransactionId, node_id: &[u8; 20],
info_hash: &[u8; 20], port: u16, token: &[u8],
) -> Result<(), Error> {
tracing::debug!("DHT announce_peer to {} (port {})", addr, port);
let data = krpc::build_announce_peer(tid, node_id, info_hash, port, token);
let response = rpc.query(addr, tid, &data).await?;
if matches!(&response, krpc::KrpcMessage::Error { .. }) {
return Err(Error::new(ErrorKind::Protocol));
}
Ok(())
}