diff --git a/Cargo.lock b/Cargo.lock index 9494e7a..5a252d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -711,12 +711,6 @@ dependencies = [ "ahash", ] -[[package]] -name = "haversine" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef9482608b217d89a3caeb5fe2336a0491d1dc0be5d89c67125ea514b1f6a660" - [[package]] name = "hermit-abi" version = "0.1.19" @@ -1949,7 +1943,6 @@ name = "speedtest-rs" version = "0.1.0" dependencies = [ "dotenv", - "haversine", "ipinfo", "rand 0.8.4", "regex", diff --git a/Cargo.toml b/Cargo.toml index b793662..0052d93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,3 @@ ipinfo = "0.2.0" serde_with = { version = "1.10.0", features = ["json"] } rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", rev = "a062933" } dotenv = "0.15.0" -haversine = "0.2.1" diff --git a/src/empty.rs b/src/empty.rs index 9cad7f7..08b7a73 100644 --- a/src/empty.rs +++ b/src/empty.rs @@ -11,10 +11,9 @@ pub struct EmptyResponder { #[post("/empty", data = "")] pub async fn empty(data: Data<'_>) -> EmptyResponder { - match data.open(1.gigabytes()).stream_to(io::sink()).await { - Ok(_) => print!(""), - Err(_) => print!(""), - }; + match data.open(25.megabytes()).stream_to(io::sink()).await { + _ => {} + } EmptyResponder { inner: (), @@ -22,11 +21,6 @@ pub async fn empty(data: Data<'_>) -> EmptyResponder { } } -#[options("/empty")] -pub async fn empty_options() -> Status { - Status::NoContent -} - #[post("/backend/empty", data = "")] pub async fn backend_empty(data: Data<'_>) -> EmptyResponder { empty(data).await diff --git a/src/garbage.rs b/src/garbage.rs index 9b8e5b2..c634bc3 100644 --- a/src/garbage.rs +++ b/src/garbage.rs @@ -19,7 +19,7 @@ pub async fn garbage(opts: GarbageOptions) -> ByteStream![Vec] { let chunks = match opts.ckSize { i if i > 1024 => 1024, - _ => opts.ckSize, + i => i, }; ByteStream! { diff --git a/src/get_ip.rs b/src/get_ip.rs index 56e9276..b36e28c 100644 --- a/src/get_ip.rs +++ b/src/get_ip.rs @@ -3,34 +3,17 @@ use regex::Regex; use rocket::serde::{json::Json, Serialize}; use rocket_client_addr::ClientRealAddr; use std::env::var; -use std::fmt; +use crate::haversine::Units; use crate::serialized_ip_info::IpDetailsDef; use crate::util::{get_client_server_distance_string, get_ip_type}; -#[derive(FromFormField, PartialEq)] -pub enum Distance { - Km, - Mi, - Nm, -} - -impl fmt::Display for Distance { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Distance::Km => write!(f, "km"), - Distance::Mi => write!(f, "mi"), - Distance::Nm => write!(f, "NM"), - } - } -} - #[derive(FromForm)] pub struct GetIPOptions { #[field(default = true)] isp: bool, - #[field(default = Distance::Km)] - distance: Distance, + #[field(default = Units::Kilometers)] + distance: Units, } #[serde_as] diff --git a/src/haversine.rs b/src/haversine.rs new file mode 100644 index 0000000..95ef661 --- /dev/null +++ b/src/haversine.rs @@ -0,0 +1,46 @@ +use std::fmt; + +#[derive(Default)] +pub struct Location { + pub latitude: f64, + pub longitude: f64, +} + +#[derive(FromFormField, PartialEq)] +pub enum Units { + Miles, + Kilometers, + NauticalMiles, + Mi, + Km, + Nm, +} + +impl fmt::Display for Units { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Units::Kilometers | Units::Km => write!(f, "km"), + Units::Miles | Units::Mi => write!(f, "mi"), + Units::NauticalMiles | Units::Nm => write!(f, "NM"), + } + } +} + +pub fn distance(start: Location, end: Location, units: &Units) -> f64 { + let r = match units { + Units::Miles | Units::Km => 3958.8, + Units::Kilometers | Units::Mi => 6371.0, + Units::NauticalMiles | Units::Nm => 3440.1, + }; + + let d_lat: f64 = (end.latitude - start.latitude).to_radians(); + let d_lon: f64 = (end.longitude - start.longitude).to_radians(); + let lat1: f64 = (start.latitude).to_radians(); + let lat2: f64 = (end.latitude).to_radians(); + + let a: f64 = ((d_lat / 2.0).sin()) * ((d_lat / 2.0).sin()) + + ((d_lon / 2.0).sin()) * ((d_lon / 2.0).sin()) * (lat1.cos()) * (lat2.cos()); + let c: f64 = 2.0 * ((a.sqrt()).atan2((1.0 - a).sqrt())); + + return r * c; +} diff --git a/src/main.rs b/src/main.rs index 76ac82a..be72519 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ extern crate serde_with; pub mod empty; pub mod garbage; pub mod get_ip; +pub mod haversine; pub mod serialized_ip_info; pub mod util; @@ -26,7 +27,7 @@ use get_ip::*; async fn main() -> Result<(), Box> { dotenv().ok(); - let cors = setup_cors().await.unwrap(); + let cors = setup_cors().await?; let routes = routes![get_ip::get_ip, get_backend_ip_php]; let garbage_routes = routes![ @@ -40,34 +41,24 @@ async fn main() -> Result<(), Box> { empty::empty, backend_empty, get_empty, - empty_options, empty_php, backend_empty_php, get_backend_empty_php ]; + let routes = vec![routes, garbage_routes, empty_routes].concat(); + + let mut rocketship = rocket::build().attach(cors).mount("/", routes); + let asset_path = relative!("assets"); if Path::new(asset_path).exists() { let fileserver = FileServer::from(asset_path); - rocket::build() - .attach(cors) - .mount("/", routes) - .mount("/", empty_routes) - .mount("/", garbage_routes) - .mount("/", fileserver) - .launch() - .await?; - } else { - rocket::build() - .attach(cors) - .mount("/", routes) - .mount("/", empty_routes) - .mount("/", garbage_routes) - .launch() - .await?; + rocketship = rocketship.mount("/", fileserver); } + rocketship.launch().await?; + Ok(()) } diff --git a/src/util.rs b/src/util.rs index daaed3f..c141d8b 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,38 +1,34 @@ use std::env::var; -use haversine::{distance, Location, Units}; +use crate::haversine::{distance, Location, Units}; use regex::Regex; -use crate::get_ip::Distance; - pub fn get_ip_type(ip: &str) -> (String, bool) { - let private_regex: Regex = Regex::new(r"^172\.(1[6-9]|2\d|3[01])\.").unwrap(); + let private_regex = Regex::new(r"^172\.(1[6-9]|2\d|3[01])\.").unwrap(); + let cgnat_regex = Regex::new(r"^100\.([6-9][0-9]|1[0-2][0-7])\.").unwrap(); let mut is_special_ip: bool = true; - let processed_string = if ip == "::1" { - format!("{} - localhost IPv6 access", &ip) - } else if ip.starts_with("fe80:") { - format!("{} - link-local IPv6 access", &ip) - } else if ip.starts_with("127.") { - format!("{} - localhost IPv4 access", &ip) - } else if ip.starts_with("10.") { - format!("{} - private IPv4 access", &ip) - } else if private_regex.is_match(&ip) { - format!("{} - private IPv4 access", &ip) - } else if ip.starts_with("192.168.") { - format!("{} - private IPv4 access", &ip) - } else if ip.starts_with("192.168.") { - format!("{} - private IPv4 access", &ip) - } else { - is_special_ip = false; - ip.to_string() + + let processed_string = match ip { + n if n == "::1" => format!("{} - localhost IPv6 access", n), + n if n.starts_with("fe80:") => format!("{} - link-local IPv6 access", n), + n if n.starts_with("127.") => format!("{} - localhost IPv4 access", n), + n if n.starts_with("10.") => format!("{} - private IPv4 access", n), + n if private_regex.is_match(n) => format!("{} - private IPv4 access", n), + n if n.starts_with("192.168.") => format!("{} - private IPv4 access", n), + n if n.starts_with("169.254.") => format!("{} - link-local IPv4 access", n), + n if cgnat_regex.is_match(n) => format!("{} - CGNAT IPv4 access", n), + _ => { + is_special_ip = false; + ip.to_string() + } }; (processed_string, is_special_ip) } pub fn parse_location_string(location: String) -> Result { - let location_parts: Vec<&str> = location.split(",").collect::>(); + let location_parts = location.split(",").collect::>(); if location_parts.len() != 2 { return Err(format!("Unknown location format: {}", &location)); @@ -47,7 +43,7 @@ pub fn parse_location_string(location: String) -> Result { }) } -pub fn get_client_server_distance_string(client_location: String, units: Distance) -> String { +pub fn get_client_server_distance_string(client_location: String, units: Units) -> String { let client_location = parse_location_string(client_location).unwrap_or(Location { latitude: 0.0, longitude: 0.0, @@ -64,17 +60,7 @@ pub fn get_client_server_distance_string(client_location: String, units: Distanc .unwrap_or_default(), }; - let haversine_units = match units { - Distance::Km => Units::Kilometers, - Distance::Mi => Units::Miles, - Distance::Nm => Units::Kilometers, - }; + let distance = distance(client_location, server_location, &units); - let distance = distance(client_location, server_location, haversine_units); - let distance = match units { - Distance::Km => distance, - Distance::Mi => distance, - Distance::Nm => distance / 1.852, - }; - format!("{:.2} {}", &distance, units) + format!("{:.2} {}", distance, units) }