diff --git a/Cargo.toml b/Cargo.toml index fda4d28..275ad48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "roughenough" -version = "1.2.0-draft5" +version = "1.2.1-draft5" repository = "https://github.com/int08h/roughenough" authors = ["Stuart Stock ", "Aaron Hill "] license = "Apache-2.0" diff --git a/src/lib.rs b/src/lib.rs index c84840f..11f512f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,7 +79,7 @@ pub mod stats; pub mod version; /// Version of Roughenough -pub const VERSION: &str = "1.2.0-draft5"; +pub const VERSION: &str = "1.2.1-draft5"; /// Roughenough version string enriched with any compile-time optional features pub fn roughenough_version() -> String { diff --git a/src/responder.rs b/src/responder.rs index e010c6f..b51876f 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -112,11 +112,14 @@ impl Responder { Version::Rfc => resp_msg.encode_framed().unwrap(), }; - let bytes_sent = socket - .send_to(&resp_bytes, &src_addr) - .expect("send_to failed"); + let mut bytes_sent: usize = 0; + let mut successful_send: bool = true; + match socket.send_to(&resp_bytes, &src_addr) { + Ok(n_bytes) => bytes_sent = n_bytes, + Err(_) => successful_send = false, + } - info!( + debug!( "Responded {} {} bytes to {} for '{}..' (#{} in batch)", self.version, bytes_sent, @@ -125,9 +128,13 @@ impl Responder { idx + 1, ); - match self.version { - Version::Classic => stats.add_classic_response(&src_addr.ip(), bytes_sent), - Version::Rfc => stats.add_rfc_response(&src_addr.ip(), bytes_sent), + if successful_send { + match self.version { + Version::Classic => stats.add_classic_response(&src_addr.ip(), bytes_sent), + Version::Rfc => stats.add_rfc_response(&src_addr.ip(), bytes_sent), + } + } else { + stats.add_failed_send_attempt(&src_addr.ip()); } } } diff --git a/src/server.rs b/src/server.rs index bdd1263..d2a3009 100644 --- a/src/server.rs +++ b/src/server.rs @@ -275,19 +275,20 @@ impl Server { for (addr, counts) in vec { info!( - "{:16}: {} classic req, {} rfc req; {} invalid requests; {} classic resp, {} rfc resp ({} sent)", + "{:16}: {} classic req, {} rfc req; {} invalid requests; {} classic resp, {} rfc resp ({} sent); {} failed sends", format!("{}", addr), counts.classic_requests, counts.rfc_requests, counts.invalid_requests, counts.classic_responses_sent, counts.rfc_responses_sent, - counts.bytes_sent.file_size(fsopts::BINARY).unwrap() + counts.bytes_sent.file_size(fsopts::BINARY).unwrap(), + counts.failed_send_attempts ); } info!( - "Totals: {} unique clients; {} total req ({} classic req, {} rfc req); {} invalid requests; {} total resp ({} classic resp, {} rfc resp); {} sent", + "Totals: {} unique clients; {} total req ({} classic req, {} rfc req); {} invalid requests; {} total resp ({} classic resp, {} rfc resp); {} sent; {} failed sends", self.stats.total_unique_clients(), self.stats.total_valid_requests(), self.stats.num_classic_requests(), @@ -296,7 +297,8 @@ impl Server { self.stats.total_responses_sent(), self.stats.num_classic_responses_sent(), self.stats.num_rfc_responses_sent(), - self.stats.total_bytes_sent().file_size(fsopts::BINARY) .unwrap() + self.stats.total_bytes_sent().file_size(fsopts::BINARY).unwrap(), + self.stats.total_failed_send_attempts() ); self.timer.set_timeout(self.status_interval, ()); diff --git a/src/stats/aggregated.rs b/src/stats/aggregated.rs index a6ab110..3d28136 100644 --- a/src/stats/aggregated.rs +++ b/src/stats/aggregated.rs @@ -32,6 +32,7 @@ pub struct AggregatedStats { rfc_responses_sent: u64, classic_responses_sent: u64, bytes_sent: usize, + failed_send_attempts: u64, empty_map: HashMap, } @@ -52,6 +53,7 @@ impl AggregatedStats { rfc_responses_sent: 0, classic_responses_sent: 0, bytes_sent: 0, + failed_send_attempts: 0, empty_map: HashMap::new(), } } @@ -70,6 +72,10 @@ impl ServerStats for AggregatedStats { self.invalid_requests += 1 } + fn add_failed_send_attempt(&mut self, _: &IpAddr) { + self.failed_send_attempts += 1; + } + fn add_health_check(&mut self, _: &IpAddr) { self.health_checks += 1 } @@ -104,6 +110,10 @@ impl ServerStats for AggregatedStats { self.health_checks } + fn total_failed_send_attempts(&self) -> u64 { + self.failed_send_attempts + } + fn total_responses_sent(&self) -> u64 { self.rfc_responses_sent + self.classic_responses_sent } diff --git a/src/stats/mod.rs b/src/stats/mod.rs index 35f6832..bc89ff3 100644 --- a/src/stats/mod.rs +++ b/src/stats/mod.rs @@ -37,6 +37,7 @@ pub struct ClientStatEntry { pub rfc_responses_sent: u64, pub classic_responses_sent: u64, pub bytes_sent: usize, + pub failed_send_attempts: u64, } impl ClientStatEntry { @@ -49,6 +50,7 @@ impl ClientStatEntry { rfc_responses_sent: 0, classic_responses_sent: 0, bytes_sent: 0, + failed_send_attempts: 0, } } } @@ -63,6 +65,8 @@ pub trait ServerStats { fn add_invalid_request(&mut self, addr: &IpAddr); + fn add_failed_send_attempt(&mut self, addr: &IpAddr); + fn add_health_check(&mut self, addr: &IpAddr); fn add_rfc_response(&mut self, addr: &IpAddr, bytes_sent: usize); @@ -79,6 +83,8 @@ pub trait ServerStats { fn total_health_checks(&self) -> u64; + fn total_failed_send_attempts(&self) -> u64; + fn total_responses_sent(&self) -> u64; fn num_rfc_responses_sent(&self) -> u64; @@ -112,6 +118,7 @@ mod test { assert_eq!(stats.total_responses_sent(), 0); assert_eq!(stats.total_bytes_sent(), 0); assert_eq!(stats.total_unique_clients(), 0); + assert_eq!(stats.total_failed_send_attempts(), 0); assert_eq!(stats.num_overflows(), 0); } @@ -146,6 +153,7 @@ mod test { stats.add_rfc_response(&ip, 2048); stats.add_classic_response(&ip, 1024); stats.add_classic_response(&ip, 1024); + stats.add_failed_send_attempt(&ip); let entry = stats.stats_for_client(&ip).unwrap(); assert_eq!(entry.classic_requests, 1); @@ -153,6 +161,7 @@ mod test { assert_eq!(entry.rfc_responses_sent, 1); assert_eq!(entry.classic_responses_sent, 2); assert_eq!(entry.bytes_sent, 4096); + assert_eq!(entry.failed_send_attempts, 1); } #[test] diff --git a/src/stats/per_client.rs b/src/stats/per_client.rs index cf5652a..a63fa5f 100644 --- a/src/stats/per_client.rs +++ b/src/stats/per_client.rs @@ -109,6 +109,16 @@ impl ServerStats for PerClientStats { .invalid_requests += 1; } + fn add_failed_send_attempt(&mut self, addr: &IpAddr) { + if self.too_many_entries() { + return; + } + self.clients + .entry(*addr) + .or_insert_with(ClientStatEntry::new) + .failed_send_attempts += 1; + } + fn add_health_check(&mut self, addr: &IpAddr) { if self.too_many_entries() { return; @@ -168,6 +178,10 @@ impl ServerStats for PerClientStats { self.clients.values().map(|&v| v.health_checks).sum() } + fn total_failed_send_attempts(&self) -> u64 { + self.clients.values().map(|&v| v.failed_send_attempts).sum() + } + fn total_responses_sent(&self) -> u64 { self.clients .values()