fix(conn): always read till blocked when parsing

Closes #1111
This commit is contained in:
Sean McArthur
2017-04-05 15:21:24 -07:00
parent 6e55fbe75d
commit 633b37df11
3 changed files with 45 additions and 24 deletions

View File

@@ -55,31 +55,33 @@ impl<T: AsyncRead + AsyncWrite> Buffered<T> {
}
pub fn parse<S: Http1Transaction>(&mut self) -> ::Result<Option<MessageHead<S::Incoming>>> {
self.reserve_read_buf();
match self.read_from_io() {
Ok(0) => {
trace!("parse eof");
return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "parse eof").into());
loop {
match try!(parse::<S, _>(&mut self.read_buf)) {
Some(head) => {
//trace!("parsed {} bytes out of {}", len, self.read_buf.len());
return Ok(Some(head.0))
},
None => {
if self.read_buf.capacity() >= MAX_BUFFER_SIZE {
debug!("MAX_BUFFER_SIZE reached, closing");
return Err(::Error::TooLarge);
}
},
}
Ok(_) => {},
Err(e) => match e.kind() {
io::ErrorKind::WouldBlock => {},
_ => return Err(e.into())
}
}
match try!(parse::<S, _>(&mut self.read_buf)) {
Some(head) => {
//trace!("parsed {} bytes out of {}", len, self.read_buf.len());
Ok(Some(head.0))
},
None => {
if self.read_buf.capacity() >= MAX_BUFFER_SIZE {
debug!("MAX_BUFFER_SIZE reached, closing");
Err(::Error::TooLarge)
} else {
Ok(None)
self.reserve_read_buf();
match self.read_from_io() {
Ok(0) => {
trace!("parse eof");
return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "parse eof").into());
}
},
Ok(_) => {},
Err(e) => match e.kind() {
io::ErrorKind::WouldBlock => {
return Ok(None);
},
_ => return Err(e.into())
}
}
}
}
@@ -340,3 +342,15 @@ fn test_iobuf_write_empty_slice() {
// when there is nothing to flush
io_buf.flush().expect("should short-circuit flush");
}
#[test]
fn test_parse_reads_until_blocked() {
use mock::{AsyncIo, Buf as MockBuf};
// missing last line ending
let raw = "HTTP/1.1 200 OK\r\n";
let mock = AsyncIo::new(MockBuf::wrap(raw.into()), raw.len());
let mut buffered = Buffered::new(mock);
assert_eq!(buffered.parse::<super::ClientTransaction>().unwrap(), None);
assert!(buffered.io.blocked());
}