mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +00:00
Move some code from aquatic_udp into aquatic_common
This commit is contained in:
parent
1b8d74e26d
commit
5c83af9f88
10 changed files with 111 additions and 82 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
|
@ -21,10 +21,19 @@ version = "1.0.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff"
|
checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aquatic_common"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aquatic_udp"
|
name = "aquatic_udp"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aquatic_common",
|
||||||
"bittorrent_udp",
|
"bittorrent_udp",
|
||||||
"cli_helpers",
|
"cli_helpers",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
|
|
@ -82,7 +91,7 @@ dependencies = [
|
||||||
name = "aquatic_ws"
|
name = "aquatic_ws"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aquatic_udp",
|
"aquatic_common",
|
||||||
"bittorrent_udp",
|
"bittorrent_udp",
|
||||||
"cli_helpers",
|
"cli_helpers",
|
||||||
"flume",
|
"flume",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
|
"aquatic_common",
|
||||||
"aquatic_udp",
|
"aquatic_udp",
|
||||||
"aquatic_udp_bench",
|
"aquatic_udp_bench",
|
||||||
"aquatic_udp_load_test",
|
"aquatic_udp_load_test",
|
||||||
|
|
|
||||||
13
aquatic_common/Cargo.toml
Normal file
13
aquatic_common/Cargo.toml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "aquatic_common"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "aquatic_common"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
indexmap = "1"
|
||||||
|
rand = { version = "0.7", features = ["small_rng"] }
|
||||||
80
aquatic_common/src/lib.rs
Normal file
80
aquatic_common/src/lib.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
use indexmap::IndexMap;
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
|
||||||
|
/// Peer or connection valid until this instant
|
||||||
|
///
|
||||||
|
/// Used instead of "last seen" or similar to hopefully prevent arithmetic
|
||||||
|
/// overflow when cleaning.
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct ValidUntil(pub Instant);
|
||||||
|
|
||||||
|
|
||||||
|
impl ValidUntil {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(offset_seconds: u64) -> Self {
|
||||||
|
Self(Instant::now() + Duration::from_secs(offset_seconds))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Extract response peers
|
||||||
|
///
|
||||||
|
/// If there are more peers in map than `max_num_peers_to_take`, do a
|
||||||
|
/// half-random selection of peers from first and second halves of map,
|
||||||
|
/// in order to avoid returning too homogeneous peers.
|
||||||
|
///
|
||||||
|
/// Don't care if we send back announcing peer.
|
||||||
|
#[inline]
|
||||||
|
pub fn extract_response_peers<K, V, R, F>(
|
||||||
|
rng: &mut impl Rng,
|
||||||
|
peer_map: &IndexMap<K, V>,
|
||||||
|
max_num_peers_to_take: usize,
|
||||||
|
peer_conversion_function: F
|
||||||
|
) -> Vec<R>
|
||||||
|
where
|
||||||
|
K: Eq + ::std::hash::Hash,
|
||||||
|
F: Fn(&V) -> R
|
||||||
|
{
|
||||||
|
let peer_map_len = peer_map.len();
|
||||||
|
|
||||||
|
if peer_map_len <= max_num_peers_to_take {
|
||||||
|
peer_map.values()
|
||||||
|
.map(peer_conversion_function)
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
let half_num_to_take = max_num_peers_to_take / 2;
|
||||||
|
let half_peer_map_len = peer_map_len / 2;
|
||||||
|
|
||||||
|
let offset_first_half = rng.gen_range(
|
||||||
|
0,
|
||||||
|
(half_peer_map_len + (peer_map_len % 2)) - half_num_to_take
|
||||||
|
);
|
||||||
|
let offset_second_half = rng.gen_range(
|
||||||
|
half_peer_map_len,
|
||||||
|
peer_map_len - half_num_to_take
|
||||||
|
);
|
||||||
|
|
||||||
|
let end_first_half = offset_first_half + half_num_to_take;
|
||||||
|
let end_second_half = offset_second_half + half_num_to_take + (max_num_peers_to_take % 2);
|
||||||
|
|
||||||
|
let mut peers: Vec<R> = Vec::with_capacity(max_num_peers_to_take);
|
||||||
|
|
||||||
|
for i in offset_first_half..end_first_half {
|
||||||
|
if let Some((_, peer)) = peer_map.get_index(i){
|
||||||
|
peers.push(peer_conversion_function(peer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i in offset_second_half..end_second_half {
|
||||||
|
if let Some((_, peer)) = peer_map.get_index(i){
|
||||||
|
peers.push(peer_conversion_function(peer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert_eq!(peers.len(), max_num_peers_to_take);
|
||||||
|
|
||||||
|
peers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ path = "src/lib/lib.rs"
|
||||||
name = "aquatic_udp"
|
name = "aquatic_udp"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
aquatic_common = { path = "../aquatic_common" }
|
||||||
bittorrent_udp = { path = "../bittorrent_udp" }
|
bittorrent_udp = { path = "../bittorrent_udp" }
|
||||||
cli_helpers = { path = "../cli_helpers" }
|
cli_helpers = { path = "../cli_helpers" }
|
||||||
crossbeam-channel = "0.4"
|
crossbeam-channel = "0.4"
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,17 @@
|
||||||
use std::net::{SocketAddr, IpAddr};
|
use std::net::{SocketAddr, IpAddr};
|
||||||
use std::sync::{Arc, atomic::AtomicUsize};
|
use std::sync::{Arc, atomic::AtomicUsize};
|
||||||
use std::time::{Duration, Instant};
|
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
|
pub use aquatic_common::ValidUntil;
|
||||||
pub use bittorrent_udp::types::*;
|
pub use bittorrent_udp::types::*;
|
||||||
|
|
||||||
|
|
||||||
pub const MAX_PACKET_SIZE: usize = 4096;
|
pub const MAX_PACKET_SIZE: usize = 4096;
|
||||||
|
|
||||||
|
|
||||||
/// Peer or connection valid until this instant
|
|
||||||
///
|
|
||||||
/// Used instead of "last seen" or similar to hopefully prevent arithmetic
|
|
||||||
/// overflow when cleaning.
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct ValidUntil(pub Instant);
|
|
||||||
|
|
||||||
|
|
||||||
impl ValidUntil {
|
|
||||||
pub fn new(offset_seconds: u64) -> Self {
|
|
||||||
Self(Instant::now() + Duration::from_secs(offset_seconds))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct ConnectionKey {
|
pub struct ConnectionKey {
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ use std::time::Duration;
|
||||||
use std::vec::Drain;
|
use std::vec::Drain;
|
||||||
|
|
||||||
use crossbeam_channel::{Sender, Receiver};
|
use crossbeam_channel::{Sender, Receiver};
|
||||||
use indexmap::IndexMap;
|
|
||||||
use parking_lot::MutexGuard;
|
use parking_lot::MutexGuard;
|
||||||
use rand::{SeedableRng, Rng, rngs::{SmallRng, StdRng}};
|
use rand::{SeedableRng, Rng, rngs::{SmallRng, StdRng}};
|
||||||
|
|
||||||
|
use aquatic_common::extract_response_peers;
|
||||||
use bittorrent_udp::types::*;
|
use bittorrent_udp::types::*;
|
||||||
|
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
@ -305,67 +305,6 @@ pub fn handle_scrape_requests(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Extract response peers
|
|
||||||
///
|
|
||||||
/// If there are more peers in map than `max_num_peers_to_take`, do a
|
|
||||||
/// half-random selection of peers from first and second halves of map,
|
|
||||||
/// in order to avoid returning too homogeneous peers.
|
|
||||||
///
|
|
||||||
/// Don't care if we send back announcing peer.
|
|
||||||
#[inline]
|
|
||||||
pub fn extract_response_peers<K, V, R, F>(
|
|
||||||
rng: &mut impl Rng,
|
|
||||||
peer_map: &IndexMap<K, V>,
|
|
||||||
max_num_peers_to_take: usize,
|
|
||||||
peer_conversion_function: F
|
|
||||||
) -> Vec<R>
|
|
||||||
where
|
|
||||||
K: Eq + ::std::hash::Hash,
|
|
||||||
F: Fn(&V) -> R
|
|
||||||
|
|
||||||
{
|
|
||||||
let peer_map_len = peer_map.len();
|
|
||||||
|
|
||||||
if peer_map_len <= max_num_peers_to_take {
|
|
||||||
peer_map.values()
|
|
||||||
.map(peer_conversion_function)
|
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
let half_num_to_take = max_num_peers_to_take / 2;
|
|
||||||
let half_peer_map_len = peer_map_len / 2;
|
|
||||||
|
|
||||||
let offset_first_half = rng.gen_range(
|
|
||||||
0,
|
|
||||||
(half_peer_map_len + (peer_map_len % 2)) - half_num_to_take
|
|
||||||
);
|
|
||||||
let offset_second_half = rng.gen_range(
|
|
||||||
half_peer_map_len,
|
|
||||||
peer_map_len - half_num_to_take
|
|
||||||
);
|
|
||||||
|
|
||||||
let end_first_half = offset_first_half + half_num_to_take;
|
|
||||||
let end_second_half = offset_second_half + half_num_to_take + (max_num_peers_to_take % 2);
|
|
||||||
|
|
||||||
let mut peers: Vec<R> = Vec::with_capacity(max_num_peers_to_take);
|
|
||||||
|
|
||||||
for i in offset_first_half..end_first_half {
|
|
||||||
if let Some((_, peer)) = peer_map.get_index(i){
|
|
||||||
peers.push(peer_conversion_function(peer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i in offset_second_half..end_second_half {
|
|
||||||
if let Some((_, peer)) = peer_map.get_index(i){
|
|
||||||
peers.push(peer_conversion_function(peer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_assert_eq!(peers.len(), max_num_peers_to_take);
|
|
||||||
|
|
||||||
peers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn calc_max_num_peers_to_take(
|
fn calc_max_num_peers_to_take(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ name = "aquatic_ws"
|
||||||
path = "src/bin/main.rs"
|
path = "src/bin/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aquatic_udp = { path = "../aquatic_udp" }
|
aquatic_common = { path = "../aquatic_common" }
|
||||||
bittorrent_udp = { path = "../bittorrent_udp" }
|
bittorrent_udp = { path = "../bittorrent_udp" }
|
||||||
cli_helpers = { path = "../cli_helpers" }
|
cli_helpers = { path = "../cli_helpers" }
|
||||||
flume = "0.7"
|
flume = "0.7"
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use indexmap::IndexMap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use mio::Token;
|
use mio::Token;
|
||||||
|
|
||||||
pub use aquatic_udp::common::ValidUntil;
|
pub use aquatic_common::ValidUntil;
|
||||||
|
|
||||||
use crate::protocol::*;
|
use crate::protocol::*;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use hashbrown::HashMap;
|
||||||
use parking_lot::MutexGuard;
|
use parking_lot::MutexGuard;
|
||||||
use rand::{Rng, SeedableRng, rngs::SmallRng};
|
use rand::{Rng, SeedableRng, rngs::SmallRng};
|
||||||
|
|
||||||
use aquatic_udp::handlers::extract_response_peers;
|
use aquatic_common::extract_response_peers;
|
||||||
|
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
use crate::protocol::*;
|
use crate::protocol::*;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue