diff --git a/crates/librqbit/src/lib.rs b/crates/librqbit/src/lib.rs index 110781d..f8543c9 100644 --- a/crates/librqbit/src/lib.rs +++ b/crates/librqbit/src/lib.rs @@ -93,10 +93,14 @@ pub use librqbit_core::torrent_metainfo::*; mod tests; /// The cargo version of librqbit. -pub fn version() -> &'static str { +pub const fn version() -> &'static str { env!("CARGO_PKG_VERSION") } +pub const fn client_name_and_version() -> &'static str { + concat!("rqbit ", env!("CARGO_PKG_VERSION")) +} + pub fn try_increase_nofile_limit() -> anyhow::Result { Ok(rlimit::increase_nofile_limit(1024 * 1024)?) } diff --git a/crates/librqbit/src/peer_connection.rs b/crates/librqbit/src/peer_connection.rs index 04a1be4..e39b3bf 100644 --- a/crates/librqbit/src/peer_connection.rs +++ b/crates/librqbit/src/peer_connection.rs @@ -200,7 +200,7 @@ impl PeerConnection { .context("error reading handshake")?; let h_supports_extended = h.supports_extended(); trace!( - peer_id=?h.peer_id, + peer_id=?Id20::new(h.peer_id), decoded_id=?try_decode_peer_id(Id20::new(h.peer_id)), "connected", ); @@ -247,6 +247,7 @@ impl PeerConnection { if supports_extended { let mut my_extended = ExtendedHandshake::new(); + my_extended.v = Some(ByteBuf(crate::client_name_and_version().as_bytes())); self.handler .update_my_extended_handshake(&mut my_extended)?; let my_extended = Message::Extended(ExtendedMessage::Handshake(my_extended)); diff --git a/crates/librqbit_core/src/peer_id.rs b/crates/librqbit_core/src/peer_id.rs index 3bf96ae..6f2ce60 100644 --- a/crates/librqbit_core/src/peer_id.rs +++ b/crates/librqbit_core/src/peer_id.rs @@ -5,6 +5,9 @@ pub enum AzureusStyleKind { Deluge, LibTorrent, Transmission, + QBittorrent, + UTorrent, + RQBit, Other([char; 2]), } @@ -20,6 +23,9 @@ impl AzureusStyleKind { b"DE" => AzureusStyleKind::Deluge, b"lt" | b"LT" => AzureusStyleKind::LibTorrent, b"TR" => AzureusStyleKind::Transmission, + b"qB" => AzureusStyleKind::QBittorrent, + b"UT" => AzureusStyleKind::UTorrent, + b"rQ" => AzureusStyleKind::RQBit, _ => AzureusStyleKind::Other([b1 as char, b2 as char]), } } @@ -53,7 +59,7 @@ pub fn generate_peer_id() -> Id20 { let u = uuid::Uuid::new_v4(); peer_id[4..20].copy_from_slice(&u.as_bytes()[..]); - peer_id[..8].copy_from_slice(b"-rQ0001-"); + peer_id[..8].copy_from_slice(b"-rQ7000-"); Id20::new(peer_id) } diff --git a/crates/peer_binary_protocol/src/extended/ut_pex.rs b/crates/peer_binary_protocol/src/extended/ut_pex.rs index 73698f2..8e1b0a8 100644 --- a/crates/peer_binary_protocol/src/extended/ut_pex.rs +++ b/crates/peer_binary_protocol/src/extended/ut_pex.rs @@ -3,7 +3,6 @@ use std::net::{IpAddr, SocketAddr}; use byteorder::{ByteOrder, BE}; use bytes::Bytes; use clone_to_owned::CloneToOwned; -use itertools::{EitherOrBoth, Itertools}; use serde::{Deserialize, Serialize}; pub struct PexPeerInfo { @@ -23,16 +22,20 @@ impl core::fmt::Debug for PexPeerInfo { #[derive(Serialize, Default, Deserialize)] pub struct UtPex { - added: B, + #[serde(skip_serializing_if = "Option::is_none")] + added: Option, #[serde(rename = "added.f")] #[serde(skip_serializing_if = "Option::is_none")] added_f: Option, - added6: B, + #[serde(skip_serializing_if = "Option::is_none")] + added6: Option, #[serde(rename = "added6.f")] #[serde(skip_serializing_if = "Option::is_none")] added6_f: Option, - dropped: B, - dropped6: B, + #[serde(skip_serializing_if = "Option::is_none")] + dropped: Option, + #[serde(skip_serializing_if = "Option::is_none")] + dropped6: Option, } impl core::fmt::Debug for UtPex @@ -79,28 +82,31 @@ where { fn added_peers_inner<'a>( &'a self, - buf: &'a B, + buf: &'a Option, flags: &'a Option, ip_len: usize, ) -> impl Iterator + Clone + 'a { - let addrs = buf.as_ref().chunks_exact(ip_len + 2).map(move |c| { - let ip = match ip_len { - 4 => IpAddr::from(TryInto::<[u8; 4]>::try_into(&c[..4]).unwrap()), - 16 => IpAddr::from(TryInto::<[u8; 16]>::try_into(&c[..16]).unwrap()), - _ => unreachable!(), - }; - let port = BE::read_u16(&c[ip_len..]); - SocketAddr::new(ip, port) - }); - let flags = flags + const PORT_LEN: usize = 2; + const DEFAULT_FLAGS: u8 = 0; + let addrs = buf .as_ref() - .map(|b| b.as_ref().iter().copied()) .into_iter() - .flatten(); - addrs.zip_longest(flags).filter_map(|eob| match eob { - EitherOrBoth::Both(addr, flags) => Some(PexPeerInfo { flags, addr }), - EitherOrBoth::Left(addr) => Some(PexPeerInfo { flags: 0, addr }), - EitherOrBoth::Right(_) => None, + .flat_map(move |it| it.as_ref().chunks_exact(ip_len + PORT_LEN)) + .map(move |c| { + let ip = match ip_len { + 4 => IpAddr::from(TryInto::<[u8; 4]>::try_into(&c[..4]).unwrap()), + 16 => IpAddr::from(TryInto::<[u8; 16]>::try_into(&c[..16]).unwrap()), + _ => unreachable!(), + }; + let port = BE::read_u16(&c[ip_len..]); + SocketAddr::new(ip, port) + }); + addrs.enumerate().map(move |(id, addr)| PexPeerInfo { + addr, + flags: flags + .as_ref() + .and_then(|f| f.as_ref().get(id).copied()) + .unwrap_or(DEFAULT_FLAGS), }) }