diff --git a/lib/build.rs b/lib/build.rs index e159803a..69125818 100644 --- a/lib/build.rs +++ b/lib/build.rs @@ -8,7 +8,7 @@ use ansi_term::Color::{Red, Yellow, Blue, White}; use version_check::{is_nightly, is_min_version}; // Specifies the minimum nightly version needed to compile Rocket. -const MIN_VERSION: &'static str = "1.16.0-nightly"; +const MIN_VERSION: &'static str = "1.19.0-nightly"; // Convenience macro for writing to stderr. macro_rules! printerr { diff --git a/lib/src/data/data.rs b/lib/src/data/data.rs index 24af63d9..31b71f8b 100644 --- a/lib/src/data/data.rs +++ b/lib/src/data/data.rs @@ -5,7 +5,7 @@ use std::time::Duration; #[cfg(feature = "tls")] use super::net_stream::HttpsStream; -use super::data_stream::DataStream; +use super::data_stream::{DataStream, kill_stream}; use super::net_stream::NetStream; use ext::ReadExt; @@ -17,7 +17,7 @@ use http::hyper::net::{HttpStream, NetworkStream}; pub type HyperBodyReader<'a, 'b> = self::HttpReader<&'a mut hyper::buffer::BufReader<&'b mut NetworkStream>>; -// |---- from hyper ----| +// |---- from hyper ----| pub type BodyReader = HttpReader>, NetStream>>; /// The number of bytes to read into the "peek" buffer. @@ -217,11 +217,8 @@ impl Data { } } -// impl Drop for Data { -// fn drop(&mut self) { -// // FIXME: Do a read; if > 1024, kill the stream. Need access to the -// // internals of `Chain` to do this efficiently/without crazy baggage. -// // https://github.com/rust-lang/rust/pull/41463 -// let _ = io::copy(&mut self.stream, &mut io::sink()); -// } -// } +impl Drop for Data { + fn drop(&mut self) { + kill_stream(&mut self.stream); + } +} diff --git a/lib/src/data/data_stream.rs b/lib/src/data/data_stream.rs index 6e6e8731..1fbb9337 100644 --- a/lib/src/data/data_stream.rs +++ b/lib/src/data/data_stream.rs @@ -1,6 +1,8 @@ use std::io::{self, Read, Cursor, Chain}; +use std::net::Shutdown; use super::data::BodyReader; +use http::hyper::net::NetworkStream; // It's very unfortunate that we have to wrap `BodyReader` in a `BufReader` // since it already contains another `BufReader`. The issue is that Hyper's @@ -38,11 +40,23 @@ impl Read for DataStream { // } // } -// impl Drop for DataStream { -// fn drop(&mut self) { -// // FIXME: Do a read; if > 1024, kill the stream. Need access to the -// // internals of `Chain` to do this efficiently/without crazy baggage. -// // https://github.com/rust-lang/rust/pull/41463 -// let _ = io::copy(&mut self.0, &mut io::sink()); -// } -// } +pub fn kill_stream(stream: &mut BodyReader) { + // Take <= 1k from the stream. If there might be more data, force close. + const FLUSH_LEN: u64 = 1024; + match io::copy(&mut stream.take(FLUSH_LEN), &mut io::sink()) { + Ok(FLUSH_LEN) | Err(_) => { + warn_!("Data left unread. Force closing network stream."); + let (_, network) = stream.get_mut().get_mut(); + if let Err(e) = network.close(Shutdown::Both) { + error_!("Failed to close network stream: {:?}", e); + } + } + Ok(n) => debug!("flushed {} unread bytes", n) + } +} + +impl Drop for DataStream { + fn drop(&mut self) { + kill_stream(&mut self.0.get_mut().1); + } +} diff --git a/lib/src/data/net_stream.rs b/lib/src/data/net_stream.rs index 340ed792..a53b037d 100644 --- a/lib/src/data/net_stream.rs +++ b/lib/src/data/net_stream.rs @@ -91,20 +91,3 @@ impl NetworkStream for NetStream { } } } - -// impl Drop for NetStream { -// fn drop(&mut self) { -// // Take <= 1k from the stream. If there might be more data, force close. -// trace_!("Dropping the network stream..."); -// // const FLUSH_LEN: u64 = 1024; -// // match io::copy(&mut self.take(FLUSH_LEN), &mut io::sink()) { -// // Ok(FLUSH_LEN) | Err(_) => { -// // warn_!("Data left unread. Force closing network stream."); -// // if let Err(e) = self.close(Shutdown::Both) { -// // error_!("Failed to close network stream: {:?}", e); -// // } -// // } -// // Ok(n) => debug!("flushed {} unread bytes", n) -// // } -// } -// } diff --git a/lib/src/http/uri.rs b/lib/src/http/uri.rs index d57557ca..20b990ec 100644 --- a/lib/src/http/uri.rs +++ b/lib/src/http/uri.rs @@ -339,6 +339,7 @@ pub struct Segments<'a>(pub &'a str); impl<'a> Iterator for Segments<'a> { type Item = &'a str; + #[inline] fn next(&mut self) -> Option { // Find the start of the next segment (first that's not '/'). let i = match self.0.find(|c| c != '/') { @@ -348,8 +349,7 @@ impl<'a> Iterator for Segments<'a> { // Get the index of the first character that _is_ a '/' after start. // j = index of first character after i (hence the i +) that's not a '/' - let rest = &self.0[i..]; - let j = rest.find('/').map_or(self.0.len(), |j| i + j); + let j = self.0[i..].find('/').map_or(self.0.len(), |j| i + j); // Save the result, update the iterator, and return! let result = Some(&self.0[i..j]); diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 9221c04e..6c9bd4b5 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -8,6 +8,7 @@ #![feature(plugin)] #![feature(never_type)] #![feature(concat_idents)] +#![feature(more_io_inner_methods)] #![plugin(pear_codegen)] diff --git a/lib/src/router/collider.rs b/lib/src/router/collider.rs index 63f17715..5e4ed1f2 100644 --- a/lib/src/router/collider.rs +++ b/lib/src/router/collider.rs @@ -13,10 +13,9 @@ pub trait Collider { #[inline(always)] fn index_match_until(break_c: char, - a: &str, - b: &str, - dir: bool) - -> Option<(isize, isize)> { + a: &str, + b: &str, + dir: bool) -> Option<(isize, isize)> { let (a_len, b_len) = (a.len() as isize, b.len() as isize); let (mut i, mut j, delta) = if dir { (0, 0, 1)