Actually send back peers

This commit is contained in:
Igor Katson 2021-07-13 18:27:32 +01:00
parent 7e4ed79863
commit 9ce76d317b

View file

@ -6,7 +6,8 @@ use std::{
use crate::{ use crate::{
bprotocol::{ bprotocol::{
self, CompactNodeInfo, FindNodeRequest, GetPeersRequest, Message, MessageKind, Node, self, CompactNodeInfo, CompactPeerInfo, FindNodeRequest, GetPeersRequest, Message,
MessageKind, Node,
}, },
routing_table::{InsertResult, RoutingTable}, routing_table::{InsertResult, RoutingTable},
DHT_BOOTSTRAP, DHT_BOOTSTRAP,
@ -17,6 +18,7 @@ use futures::{stream::FuturesUnordered, Stream, StreamExt, TryStreamExt};
use librqbit_core::{id20::Id20, peer_id::generate_peer_id}; use librqbit_core::{id20::Id20, peer_id::generate_peer_id};
use log::{debug, info, trace, warn}; use log::{debug, info, trace, warn};
use parking_lot::Mutex; use parking_lot::Mutex;
use rand::Rng;
use tokio::{ use tokio::{
net::UdpSocket, net::UdpSocket,
sync::mpsc::{channel, unbounded_channel, Sender, UnboundedReceiver, UnboundedSender}, sync::mpsc::{channel, unbounded_channel, Sender, UnboundedReceiver, UnboundedSender},
@ -107,6 +109,25 @@ impl DhtState {
msg: Message<ByteString>, msg: Message<ByteString>,
addr: SocketAddr, addr: SocketAddr,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let generate_compact_nodes = |target| {
let nodes = self
.routing_table
.sorted_by_distance_from(target)
.into_iter()
.filter_map(|r| {
Some(Node {
id: r.id(),
addr: match r.addr() {
SocketAddr::V4(v4) => v4,
SocketAddr::V6(_) => return None,
},
})
})
.take(8)
.collect::<Vec<_>>();
CompactNodeInfo { nodes }
};
match &msg.kind { match &msg.kind {
MessageKind::Error(_) | MessageKind::Response(_) => {} MessageKind::Error(_) | MessageKind::Response(_) => {}
MessageKind::PingRequest(_) => { MessageKind::PingRequest(_) => {
@ -125,30 +146,44 @@ impl DhtState {
self.sender.send((message, addr))?; self.sender.send((message, addr))?;
return Ok(()); return Ok(());
} }
MessageKind::FindNodeRequest(_) | MessageKind::GetPeersRequest(_) => { MessageKind::GetPeersRequest(req) => {
let target = match &msg.kind { let peers = self.seen_peers.get(&req.info_hash).map(|peers| {
MessageKind::FindNodeRequest(req) => req.target, peers
MessageKind::GetPeersRequest(req) => req.info_hash, .iter()
_ => unreachable!(), .copied()
.filter_map(|a| match a {
SocketAddr::V4(v4) => Some(CompactPeerInfo { addr: v4 }),
// this should never happen in practice
SocketAddr::V6(_) => None,
})
.take(50)
.collect::<Vec<_>>()
});
let token = if peers.is_some() {
let mut token = [0u8; 20];
rand::thread_rng().fill(&mut token);
Some(ByteString::from(token.as_ref()))
} else {
None
}; };
// we don't track who is downloading a torrent (we don't have a peer store), let compact_node_info = generate_compact_nodes(req.info_hash);
// so send nodes all the time. let response = bprotocol::Response {
let nodes = self id: self.id,
.routing_table nodes: Some(compact_node_info),
.sorted_by_distance_from(target) values: peers,
.into_iter() token,
.filter_map(|r| { };
Some(Node { let message = Message {
id: r.id(), transaction_id: msg.transaction_id,
addr: match r.addr() { version: None,
SocketAddr::V4(v4) => v4, ip: None,
SocketAddr::V6(_) => return None, kind: MessageKind::Response(response),
}, };
}) self.sender.send((message, addr))?;
}) return Ok(());
.take(8) }
.collect::<Vec<_>>(); MessageKind::FindNodeRequest(req) => {
let compact_node_info = CompactNodeInfo { nodes }; let compact_node_info = generate_compact_nodes(req.target);
let response = bprotocol::Response { let response = bprotocol::Response {
id: self.id, id: self.id,
nodes: Some(compact_node_info), nodes: Some(compact_node_info),
@ -303,6 +338,10 @@ impl DhtState {
self.routing_table.mark_response(&source); self.routing_table.mark_response(&source);
if let Some(peers) = data.values { if let Some(peers) = data.values {
let seen = self.seen_peers.entry(target).or_default();
for peer in peers.iter() {
seen.insert(SocketAddr::V4(peer.addr));
}
let bsender = match self.get_peers_subscribers.get(&target) { let bsender = match self.get_peers_subscribers.get(&target) {
Some(s) => s, Some(s) => s,
None => { None => {