WIP: udp: add ipv6 support

Returning IPv6 peers doesn't really work with UDP. It is not supported by
https://libtorrent.org/udp_tracker_protocol.html. There is a suggestion in
https://web.archive.org/web/20170503181830/http://opentracker.blog.h3q.com/2007/12/28/the-ipv6-situation/
of using action number 4 and returning IPv6 octets just like for IPv4
addresses. Clients seem not to support it very well, but due to a lack of
alternative solutions, it is implemented here
This commit is contained in:
Joakim Frostegård 2020-07-31 05:37:58 +02:00
parent bdb6aced1c
commit a3a1d1606b
8 changed files with 230 additions and 111 deletions

View file

@ -1,5 +1,6 @@
use std::net::{SocketAddr, IpAddr};
use std::net::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
use std::sync::{Arc, atomic::AtomicUsize};
use std::hash::Hash;
use hashbrown::HashMap;
use indexmap::IndexMap;
@ -12,6 +13,24 @@ pub use aquatic_udp_protocol::types::*;
pub const MAX_PACKET_SIZE: usize = 4096;
pub trait Ip: Hash + PartialEq + Eq + Clone + Copy {
fn ip_addr(self) -> IpAddr;
}
impl Ip for Ipv4Addr {
fn ip_addr(self) -> IpAddr {
IpAddr::V4(self)
}
}
impl Ip for Ipv6Addr {
fn ip_addr(self) -> IpAddr {
IpAddr::V6(self)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ConnectionKey {
@ -52,19 +71,19 @@ impl PeerStatus {
#[derive(Clone, Debug)]
pub struct Peer {
pub ip_address: IpAddr,
pub struct Peer<I: Ip> {
pub ip_address: I,
pub port: Port,
pub status: PeerStatus,
pub valid_until: ValidUntil
}
impl Peer {
impl <I: Ip>Peer<I> {
#[inline(always)]
pub fn to_response_peer(&self) -> ResponsePeer {
ResponsePeer {
ip_address: self.ip_address,
ip_address: self.ip_address.ip_addr(),
port: self.port
}
}
@ -72,23 +91,23 @@ impl Peer {
#[derive(PartialEq, Eq, Hash, Clone)]
pub struct PeerMapKey {
pub ip: IpAddr,
pub struct PeerMapKey<I: Ip> {
pub ip: I,
pub peer_id: PeerId
}
pub type PeerMap = IndexMap<PeerMapKey, Peer>;
pub type PeerMap<I> = IndexMap<PeerMapKey<I>, Peer<I>>;
pub struct TorrentData {
pub peers: PeerMap,
pub struct TorrentData<I: Ip> {
pub peers: PeerMap<I>,
pub num_seeders: usize,
pub num_leechers: usize,
}
impl Default for TorrentData {
impl <I: Ip>Default for TorrentData<I> {
fn default() -> Self {
Self {
peers: IndexMap::new(),
@ -99,7 +118,14 @@ impl Default for TorrentData {
}
pub type TorrentMap = HashMap<InfoHash, TorrentData>;
pub type TorrentMap<I> = HashMap<InfoHash, TorrentData<I>>;
#[derive(Default)]
pub struct TorrentMaps {
pub ipv4: TorrentMap<Ipv4Addr>,
pub ipv6: TorrentMap<Ipv6Addr>,
}
#[derive(Default)]
@ -115,7 +141,7 @@ pub struct Statistics {
#[derive(Clone)]
pub struct State {
pub connections: Arc<Mutex<ConnectionMap>>,
pub torrents: Arc<Mutex<TorrentMap>>,
pub torrents: Arc<Mutex<TorrentMaps>>,
pub statistics: Arc<Statistics>,
}
@ -124,7 +150,7 @@ impl State {
pub fn new() -> Self {
Self {
connections: Arc::new(Mutex::new(HashMap::new())),
torrents: Arc::new(Mutex::new(HashMap::new())),
torrents: Arc::new(Mutex::new(TorrentMaps::default())),
statistics: Arc::new(Statistics::default()),
}
}