Actually send back peers
This commit is contained in:
parent
7e4ed79863
commit
9ce76d317b
1 changed files with 63 additions and 24 deletions
|
|
@ -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 {
|
||||||
// we don't track who is downloading a torrent (we don't have a peer store),
|
SocketAddr::V4(v4) => Some(CompactPeerInfo { addr: v4 }),
|
||||||
// so send nodes all the time.
|
// this should never happen in practice
|
||||||
let nodes = self
|
SocketAddr::V6(_) => None,
|
||||||
.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(50)
|
||||||
.take(8)
|
.collect::<Vec<_>>()
|
||||||
.collect::<Vec<_>>();
|
});
|
||||||
let compact_node_info = CompactNodeInfo { nodes };
|
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
|
||||||
|
};
|
||||||
|
let compact_node_info = generate_compact_nodes(req.info_hash);
|
||||||
|
let response = bprotocol::Response {
|
||||||
|
id: self.id,
|
||||||
|
nodes: Some(compact_node_info),
|
||||||
|
values: peers,
|
||||||
|
token,
|
||||||
|
};
|
||||||
|
let message = Message {
|
||||||
|
transaction_id: msg.transaction_id,
|
||||||
|
version: None,
|
||||||
|
ip: None,
|
||||||
|
kind: MessageKind::Response(response),
|
||||||
|
};
|
||||||
|
self.sender.send((message, addr))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
MessageKind::FindNodeRequest(req) => {
|
||||||
|
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 => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue