More values are configurable

This commit is contained in:
Naim A 2018-10-21 23:39:39 +03:00
parent f5fe87631c
commit 9a31422091
No known key found for this signature in database
GPG key ID: FD7948915D9EF8B9
7 changed files with 110 additions and 29 deletions

10
Cargo.lock generated
View file

@ -1260,6 +1260,14 @@ dependencies = [
"tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "toml"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.1.0" version = "0.1.0"
@ -1364,6 +1372,7 @@ dependencies = [
"bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -1644,6 +1653,7 @@ dependencies = [
"checksum tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3a52f00c97fedb6d535d27f65cccb7181c8dd4c6edc3eda9ea93f6d45d05168e" "checksum tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3a52f00c97fedb6d535d27f65cccb7181c8dd4c6edc3eda9ea93f6d45d05168e"
"checksum tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da941144b816d0dcda4db3a1ba87596e4df5e860a72b70783fe435891f80601c" "checksum tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da941144b816d0dcda4db3a1ba87596e4df5e860a72b70783fe435891f80601c"
"checksum tokio-uds 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22e3aa6d1fcc19e635418dc0a30ab5bd65d347973d6f43f1a37bf8d9d1335fc9" "checksum tokio-uds 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22e3aa6d1fcc19e635418dc0a30ab5bd65d347973d6f43f1a37bf8d9d1335fc9"
"checksum toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4a2ecc31b0351ea18b3fe11274b8db6e4d82bce861bbb22e6dbed40417902c65"
"checksum tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987" "checksum tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987"
"checksum trust-dns-proto 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1525ca4e26f5a09d81b79584f19225e7dba5606ae3a416311c2751c5cea60bb" "checksum trust-dns-proto 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1525ca4e26f5a09d81b79584f19225e7dba5606ae3a416311c2751c5cea60bb"
"checksum trust-dns-proto 0.5.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3fabc184ed90d027afee46386e6418b9c953b7be527f62cc37724a1720e07d68" "checksum trust-dns-proto 0.5.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3fabc184ed90d027afee46386e6418b9c953b7be527f62cc37724a1720e07d68"

View file

@ -7,7 +7,17 @@ pub use tracker::TrackerMode;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct UDPConfig { pub struct UDPConfig {
bind_address: String, bind_address: String,
mode: TrackerMode, announce_interval: u32,
}
impl UDPConfig {
pub fn get_address(&self) -> &str {
self.bind_address.as_str()
}
pub fn get_announce_interval(&self) -> u32 {
self.announce_interval
}
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -16,8 +26,19 @@ pub struct HTTPConfig {
access_tokens: HashMap<String, String>, access_tokens: HashMap<String, String>,
} }
impl HTTPConfig {
pub fn get_address(&self) -> &str {
self.bind_address.as_str()
}
pub fn get_access_tokens(&self) -> &HashMap<String, String> {
&self.access_tokens
}
}
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct Configuration { pub struct Configuration {
mode: TrackerMode,
udp: UDPConfig, udp: UDPConfig,
http: Option<HTTPConfig>, http: Option<HTTPConfig>,
} }
@ -39,7 +60,6 @@ impl std::fmt::Display for ConfigError {
} }
impl std::error::Error for ConfigError {} impl std::error::Error for ConfigError {}
impl Configuration { impl Configuration {
pub fn load(data: &[u8]) -> Result<Configuration, toml::de::Error> { pub fn load(data: &[u8]) -> Result<Configuration, toml::de::Error> {
toml::from_slice(data) toml::from_slice(data)
@ -56,14 +76,27 @@ impl Configuration {
} }
} }
} }
pub fn get_mode(&self) -> &TrackerMode {
&self.mode
}
pub fn get_udp_config(&self) -> &UDPConfig {
&self.udp
}
pub fn get_http_config(&self) -> &Option<HTTPConfig> {
&self.http
}
} }
impl Default for Configuration { impl Default for Configuration {
fn default() -> Configuration { fn default() -> Configuration {
Configuration{ Configuration{
mode: TrackerMode::DynamicMode,
udp: UDPConfig{ udp: UDPConfig{
announce_interval: 120,
bind_address: String::from("0.0.0.0:6969"), bind_address: String::from("0.0.0.0:6969"),
mode: TrackerMode::DynamicMode,
}, },
http: None, http: None,
} }

View file

@ -14,27 +14,25 @@ use config::Configuration;
fn main() { fn main() {
let cfg = match Configuration::load_file("udpt.toml") { let cfg = match Configuration::load_file("udpt.toml") {
Ok(v) => v, Ok(v) => std::sync::Arc::new(v),
Err(e) => { Err(e) => {
eprintln!("failed to open configuration: {}", e); eprintln!("failed to open configuration: {}", e);
return; return;
} }
}; };
let tracker = std::sync::Arc::new(tracker::TorrentTracker::new(cfg.get_mode().clone()));
let tracker = std::sync::Arc::new(tracker::TorrentTracker::new());
// start http server: // start http server:
let mut access_tokens = std::collections::HashMap::new(); if let Some(http_cfg) = cfg.get_http_config() {
access_tokens.insert(String::from("MySpecialToken"), String::from("username")); let http_tracker_ref = tracker.clone();
let cfg_ref = cfg.clone();
std::thread::spawn(move || {
webserver::WebServer::new(http_tracker_ref, cfg_ref);
});
}
let http_tracker_ref = tracker.clone(); let s = std::sync::Arc::new(server::UDPTracker::new(cfg, tracker.clone()).unwrap());
std::thread::spawn(move || {
webserver::WebServer::new(http_tracker_ref);
});
let addr = "0.0.0.0:1212";
let s = std::sync::Arc::new(server::UDPTracker::new(addr, tracker.clone()).unwrap());
loop { loop {
match s.accept_packet() { match s.accept_packet() {

View file

@ -1,4 +1,5 @@
use std; use std;
use std::sync::Arc;
use std::net::{SocketAddr, UdpSocket}; use std::net::{SocketAddr, UdpSocket};
use std::io::Write; use std::io::Write;
@ -7,6 +8,7 @@ use serde::{Serialize, Deserialize};
use tracker; use tracker;
use stackvec::StackVec; use stackvec::StackVec;
use config::Configuration;
// maximum MTU is usually 1500, but our stack allows us to allocate the maximum - so why not? // maximum MTU is usually 1500, but our stack allows us to allocate the maximum - so why not?
const MAX_PACKET_SIZE: usize = 0xffff; const MAX_PACKET_SIZE: usize = 0xffff;
@ -109,11 +111,14 @@ struct UDPAnnounceResponse {
pub struct UDPTracker { pub struct UDPTracker {
server: std::net::UdpSocket, server: std::net::UdpSocket,
tracker: std::sync::Arc<tracker::TorrentTracker>, tracker: std::sync::Arc<tracker::TorrentTracker>,
config: Arc<Configuration>,
} }
impl UDPTracker { impl UDPTracker {
pub fn new<T: std::net::ToSocketAddrs>(bind_address: T, tracker: std::sync::Arc<tracker::TorrentTracker>) -> Result<UDPTracker, std::io::Error> { pub fn new(config: Arc<Configuration>, tracker: std::sync::Arc<tracker::TorrentTracker>) -> Result<UDPTracker, std::io::Error> {
let server = match UdpSocket::bind(bind_address) { let cfg = config.clone();
let server = match UdpSocket::bind(cfg.get_udp_config().get_address()) {
Ok(s) => s, Ok(s) => s,
Err(e) => { Err(e) => {
return Err(e); return Err(e);
@ -123,6 +128,7 @@ impl UDPTracker {
Ok(UDPTracker{ Ok(UDPTracker{
server, server,
tracker, tracker,
config: cfg,
}) })
} }
@ -216,7 +222,7 @@ impl UDPTracker {
transaction_id: packet.header.transaction_id, transaction_id: packet.header.transaction_id,
}, },
seeders, seeders,
interval: 20, interval: self.config.get_udp_config().get_announce_interval(),
leechers, leechers,
}) { }) {
Ok(_) => {}, Ok(_) => {},

View file

@ -2,7 +2,7 @@ use std;
use server::Events; use server::Events;
#[derive(Deserialize)] #[derive(Deserialize, Clone)]
pub enum TrackerMode { pub enum TrackerMode {
/// In static mode torrents are tracked only if they were added ahead of time. /// In static mode torrents are tracked only if they were added ahead of time.
@ -179,9 +179,9 @@ pub enum TorrentStats {
} }
impl TorrentTracker { impl TorrentTracker {
pub fn new() -> TorrentTracker { pub fn new(mode: TrackerMode) -> TorrentTracker {
TorrentTracker{ TorrentTracker{
mode: TrackerMode::DynamicMode, mode,
database: TorrentDatabase{ database: TorrentDatabase{
torrent_peers: std::sync::RwLock::new(std::collections::BTreeMap::new()), torrent_peers: std::sync::RwLock::new(std::collections::BTreeMap::new()),
} }

View file

@ -4,6 +4,7 @@ use std::sync::Arc;
use actix_web; use actix_web;
use binascii; use binascii;
use config;
use tracker; use tracker;
const SERVER: &str = concat!("udpt/", env!("CARGO_PKG_VERSION")); const SERVER: &str = concat!("udpt/", env!("CARGO_PKG_VERSION"));
@ -126,9 +127,25 @@ impl actix_web::middleware::Middleware<UdptState> for UdptMiddleware {
} }
impl WebServer { impl WebServer {
pub fn new(tracker: Arc<tracker::TorrentTracker>) -> WebServer { fn get_access_tokens(cfg: &config::HTTPConfig, tokens: &mut HashMap<String, String>) {
for (user, token) in cfg.get_access_tokens().iter() {
tokens.insert(token.clone(), user.clone());
}
}
pub fn new(tracker: Arc<tracker::TorrentTracker>, cfg: Arc<config::Configuration>) -> WebServer {
let cfg_cp = cfg.clone();
let server = actix_web::server::HttpServer::new(move || { let server = actix_web::server::HttpServer::new(move || {
actix_web::App::<UdptState>::with_state(UdptState::new(tracker.clone(), HashMap::new())) let mut access_tokens = HashMap::new();
if let Some(http_cfg) = cfg_cp.get_http_config() {
Self::get_access_tokens(http_cfg, &mut access_tokens);
}
let state = UdptState::new(tracker.clone(), access_tokens);
actix_web::App::<UdptState>::with_state(state)
.middleware(UdptMiddleware) .middleware(UdptMiddleware)
.resource("/t", |r| r.f(Self::view_torrent_list)) .resource("/t", |r| r.f(Self::view_torrent_list))
.scope(r"/t/{info_hash:[\dA-Fa-f]{40,40}}", |scope| { .scope(r"/t/{info_hash:[\dA-Fa-f]{40,40}}", |scope| {
@ -141,14 +158,20 @@ impl WebServer {
.resource("/", |r| r.method(actix_web::http::Method::GET).f(Self::view_root)) .resource("/", |r| r.method(actix_web::http::Method::GET).f(Self::view_root))
}); });
match server.bind("0.0.0.0:1212") { if let Some(http_cfg) = cfg.get_http_config() {
Ok(v) => { let bind_addr = http_cfg.get_address();
v.run(); match server.bind(bind_addr) {
}, Ok(v) => {
Err(_) => { v.run();
eprintln!("failed to bind server"); },
Err(_) => {
eprintln!("failed to bind server");
}
} }
} }
else {
unreachable!();
}
WebServer{} WebServer{}
} }

11
udpt.toml Normal file
View file

@ -0,0 +1,11 @@
mode = "dynamic"
[udp]
announce_interval = 120 # Two minutes
bind_address = "0.0.0.0:1212"
[http]
bind_address = "127.0.0.1:1212"
[http.access_tokens]
naim = "MyAccessToken"