Skip to content

Commit

Permalink
Merge pull request #72 from jabedude/bep52-magnet-support
Browse files Browse the repository at this point in the history
Add support for BTv2 magnet links
  • Loading branch information
ikatson authored Jan 8, 2024
2 parents 6a49ae7 + 0836b65 commit c8189de
Show file tree
Hide file tree
Showing 21 changed files with 217 additions and 138 deletions.
2 changes: 1 addition & 1 deletion crates/dht/examples/dht.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async fn main() -> anyhow::Result<()> {
.nth(1)
.expect("first argument should be a magnet link");
let magnet = Magnet::parse(&magnet).unwrap();
let info_hash = magnet.info_hash;
let info_hash = magnet.as_id20().context("Supplied magnet link didn't contain a BTv1 infohash")?;

tracing_subscriber::fmt::init();

Expand Down
4 changes: 2 additions & 2 deletions crates/dht/src/bprotocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{

use bencode::{ByteBuf, ByteString};
use clone_to_owned::CloneToOwned;
use librqbit_core::id20::Id20;
use librqbit_core::hash_id::Id20;
use serde::{
de::{IgnoredAny, Unexpected},
Deserialize, Deserializer, Serialize,
Expand Down Expand Up @@ -229,7 +229,7 @@ impl<'de> Deserialize<'de> for CompactNodeInfo {
let ip = Ipv4Addr::new(chunk[20], chunk[21], chunk[22], chunk[23]);
let port = ((chunk[24] as u16) << 8) + chunk[25] as u16;
buf.push(Node {
id: Id20(node_id),
id: Id20::new(node_id),
addr: SocketAddrV4::new(ip, port),
})
}
Expand Down
2 changes: 1 addition & 1 deletion crates/dht/src/dht.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use futures::{stream::FuturesUnordered, Stream, StreamExt, TryFutureExt};

use leaky_bucket::RateLimiter;
use librqbit_core::{
id20::Id20,
hash_id::Id20,
peer_id::generate_peer_id,
spawn_utils::{spawn, spawn_with_cancel},
};
Expand Down
2 changes: 1 addition & 1 deletion crates/dht/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::time::Duration;

pub use crate::dht::DhtStats;
pub use crate::dht::{DhtConfig, DhtState, RequestPeersStream};
pub use librqbit_core::id20::Id20;
pub use librqbit_core::hash_id::Id20;
pub use persistence::{PersistentDht, PersistentDhtConfig};

pub type Dht = Arc<DhtState>;
Expand Down
2 changes: 1 addition & 1 deletion crates/dht/src/peer_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{

use bencode::ByteString;
use chrono::{DateTime, Utc};
use librqbit_core::id20::Id20;
use librqbit_core::hash_id::Id20;
use parking_lot::RwLock;
use rand::RngCore;
use serde::{
Expand Down
20 changes: 10 additions & 10 deletions crates/dht/src/routing_table.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{net::SocketAddr, time::Instant};

use librqbit_core::id20::Id20;
use librqbit_core::hash_id::Id20;
use rand::RngCore;
use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer};
use tracing::{debug, trace};
Expand Down Expand Up @@ -132,7 +132,7 @@ impl<'a> Iterator for BucketTreeIterator<'a> {
pub fn generate_random_id(start: &Id20, bits: u8) -> Id20 {
let mut data = [0u8; 20];
rand::thread_rng().fill_bytes(&mut data);
let mut data = Id20(data);
let mut data = Id20::new(data);
let remaining_bits = 160 - bits;
for bit in 0..remaining_bits {
data.set_bit(bit, start.get_bit(bit));
Expand Down Expand Up @@ -199,8 +199,8 @@ impl BucketTree {
BucketTree {
data: vec![BucketTreeNode {
bits: 160,
start: Id20([0u8; 20]),
end_inclusive: Id20([0xff; 20]),
start: Id20::new([0u8; 20]),
end_inclusive: Id20::new([0xff; 20]),
data: BucketTreeNodeData::Leaf(Default::default()),
}],
size: 0,
Expand Down Expand Up @@ -583,7 +583,7 @@ mod tests {
str::FromStr,
};

use librqbit_core::id20::Id20;
use librqbit_core::hash_id::Id20;
use rand::Rng;

use crate::routing_table::compute_split_start_end;
Expand All @@ -592,8 +592,8 @@ mod tests {

#[test]
fn compute_split_start_end_root() {
let start = Id20([0u8; 20]);
let end = Id20([0xff; 20]);
let start = Id20::new([0u8; 20]);
let end = Id20::new([0xff; 20]);
assert_eq!(
compute_split_start_end(start, end, 160),
(
Expand All @@ -612,7 +612,7 @@ mod tests {
#[test]
fn compute_split_start_end_second_split() {
let start = Id20::from_str("8000000000000000000000000000000000000000").unwrap();
let end = Id20([0xff; 20]);
let end = Id20::new([0xff; 20]);
assert_eq!(
compute_split_start_end(start, end, 159),
(
Expand All @@ -631,7 +631,7 @@ mod tests {
#[test]
fn compute_split_start_end_3() {
let start = Id20::from_str("8000000000000000000000000000000000000000").unwrap();
let end = Id20([0xff; 20]);
let end = Id20::new([0xff; 20]);
assert_eq!(
compute_split_start_end(start, end, 159),
(
Expand All @@ -650,7 +650,7 @@ mod tests {
fn random_id_20() -> Id20 {
let mut id20 = [0u8; 20];
rand::thread_rng().fill(&mut id20);
Id20(id20)
Id20::new(id20)
}

fn generate_socket_addr() -> SocketAddr {
Expand Down
2 changes: 1 addition & 1 deletion crates/dht/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use librqbit_core::id20::Id20;
use librqbit_core::hash_id::Id20;
use serde::Serializer;

pub fn serialize_id20<S>(id: &Id20, ser: S) -> Result<S::Ok, S::Error>
Expand Down
2 changes: 1 addition & 1 deletion crates/librqbit/src/dht_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use tracing::debug;
use crate::{
peer_connection::PeerConnectionOptions, peer_info_reader, spawn_utils::BlockingSpawner,
};
use librqbit_core::id20::Id20;
use librqbit_core::hash_id::Id20;

#[derive(Debug)]
pub enum ReadMetainfoResult<Rx> {
Expand Down
6 changes: 3 additions & 3 deletions crates/librqbit/src/peer_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
use anyhow::{bail, Context};
use buffers::{ByteBuf, ByteString};
use clone_to_owned::CloneToOwned;
use librqbit_core::{id20::Id20, lengths::ChunkInfo, peer_id::try_decode_peer_id};
use librqbit_core::{hash_id::Id20, lengths::ChunkInfo, peer_id::try_decode_peer_id};
use parking_lot::RwLock;
use peer_binary_protocol::{
extended::{handshake::ExtendedHandshake, ExtendedMessage},
Expand Down Expand Up @@ -120,7 +120,7 @@ impl<H: PeerConnectionHandler> PeerConnection<H> {

trace!(
"incoming connection: id={:?}",
try_decode_peer_id(Id20(handshake.peer_id))
try_decode_peer_id(Id20::new(handshake.peer_id))
);

let mut write_buf = Vec::<u8>::with_capacity(PIECE_MESSAGE_DEFAULT_LEN);
Expand Down Expand Up @@ -181,7 +181,7 @@ impl<H: PeerConnectionHandler> PeerConnection<H> {
.await
.context("error reading handshake")?;
let h_supports_extended = h.supports_extended();
trace!("connected: id={:?}", try_decode_peer_id(Id20(h.peer_id)));
trace!("connected: id={:?}", try_decode_peer_id(Id20::new(h.peer_id)));
if h.info_hash != self.info_hash.0 {
anyhow::bail!("info hash does not match");
}
Expand Down
4 changes: 2 additions & 2 deletions crates/librqbit/src/peer_info_reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bencode::from_bytes;
use buffers::{ByteBuf, ByteString};
use librqbit_core::{
constants::CHUNK_SIZE,
id20::Id20,
hash_id::Id20,
lengths::{ceil_div_u64, last_element_size_u64, ChunkInfo},
torrent_metainfo::TorrentMetaV1Info,
};
Expand Down Expand Up @@ -226,7 +226,7 @@ impl PeerConnectionHandler for Handler {
mod tests {
use std::{net::SocketAddr, str::FromStr, sync::Once};

use librqbit_core::id20::Id20;
use librqbit_core::hash_id::Id20;
use librqbit_core::peer_id::generate_peer_id;

use crate::spawn_utils::BlockingSpawner;
Expand Down
10 changes: 4 additions & 6 deletions crates/librqbit/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ impl Session {
));
}

bail!("didn't find a matching torrent for {:?}", Id20(h.info_hash))
bail!("didn't find a matching torrent for {:?}", Id20::new(h.info_hash))
}

async fn task_tcp_listener(self: Arc<Self>, l: TcpListener) -> anyhow::Result<()> {
Expand Down Expand Up @@ -753,18 +753,16 @@ impl Session {

let (info_hash, info, dht_rx, trackers, initial_peers) = match add {
AddTorrent::Url(magnet) if magnet.starts_with("magnet:") => {
let Magnet {
info_hash,
trackers,
} = Magnet::parse(&magnet).context("provided path is not a valid magnet URL")?;
let magnet = Magnet::parse(&magnet).context("provided path is not a valid magnet URL")?;
let info_hash = magnet.as_id20().context("magnet link didn't contain a BTv1 infohash")?;

let dht_rx = self
.dht
.as_ref()
.context("magnet links without DHT are not supported")?
.get_peers(info_hash, announce_port)?;

let trackers = trackers
let trackers = magnet.trackers
.into_iter()
.filter_map(|url| match reqwest::Url::parse(&url) {
Ok(url) => Some(url),
Expand Down
8 changes: 4 additions & 4 deletions crates/librqbit/src/torrent_state/live/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ use clone_to_owned::CloneToOwned;
use futures::{stream::FuturesUnordered, StreamExt};
use itertools::Itertools;
use librqbit_core::{
id20::Id20,
hash_id::Id20,
lengths::{ChunkInfo, Lengths, ValidPieceIndex},
spawn_utils::spawn_with_cancel,
speed_estimator::SpeedEstimator,
Expand Down Expand Up @@ -383,7 +383,7 @@ impl TorrentStateLive {
let peer = occ.get_mut();
peer.state
.incoming_connection(
Id20(checked_peer.handshake.peer_id),
Id20::new(checked_peer.handshake.peer_id),
tx.clone(),
&self.peers.stats,
)
Expand All @@ -393,7 +393,7 @@ impl TorrentStateLive {
Entry::Vacant(vac) => {
atomic_inc(&self.peers.stats.seen);
let peer = Peer::new_live_for_incoming_connection(
Id20(checked_peer.handshake.peer_id),
Id20::new(checked_peer.handshake.peer_id),
tx.clone(),
&self.peers.stats,
);
Expand Down Expand Up @@ -597,7 +597,7 @@ impl TorrentStateLive {
fn set_peer_live<B>(&self, handle: PeerHandle, h: Handshake<B>) {
self.peers.with_peer_mut(handle, "set_peer_live", |p| {
p.state
.connecting_to_live(Id20(h.peer_id), &self.peers.stats);
.connecting_to_live(Id20::new(h.peer_id), &self.peers.stats);
});
}

Expand Down
2 changes: 1 addition & 1 deletion crates/librqbit/src/torrent_state/live/peer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub mod stats;

use std::collections::HashSet;

use librqbit_core::id20::Id20;
use librqbit_core::hash_id::Id20;
use librqbit_core::lengths::{ChunkInfo, ValidPieceIndex};

use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
Expand Down
2 changes: 1 addition & 1 deletion crates/librqbit/src/torrent_state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use anyhow::bail;
use anyhow::Context;
use buffers::ByteString;
use dht::RequestPeersStream;
use librqbit_core::id20::Id20;
use librqbit_core::hash_id::Id20;
use librqbit_core::lengths::Lengths;
use librqbit_core::peer_id::generate_peer_id;

Expand Down
6 changes: 3 additions & 3 deletions crates/librqbit/src/tracker_comms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{
str::FromStr,
};

use librqbit_core::id20::Id20;
use librqbit_core::hash_id::Id20;

#[derive(Clone, Copy)]
pub enum TrackerRequestEvent {
Expand Down Expand Up @@ -207,10 +207,10 @@ mod tests {
use super::*;
#[test]
fn test_serialize() {
let info_hash = Id20([
let info_hash = Id20::new([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
]);
let peer_id = Id20([
let peer_id = Id20::new([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
]);
let request = TrackerRequest {
Expand Down
Loading

0 comments on commit c8189de

Please sign in to comment.