1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-12-02 19:32:24 +01:00

fix back pressure for h1 import stream

This commit is contained in:
Nikolay Kim 2018-02-09 16:20:10 -08:00
parent 728377a447
commit 74377ef73d
3 changed files with 71 additions and 52 deletions

View File

@ -260,6 +260,7 @@ impl PayloadWriter for PayloadSender {
} }
} }
#[inline]
fn capacity(&self) -> usize { fn capacity(&self) -> usize {
if let Some(shared) = self.inner.upgrade() { if let Some(shared) = self.inner.upgrade() {
shared.borrow().capacity() shared.borrow().capacity()
@ -327,10 +328,10 @@ impl Inner {
if let Some(data) = self.items.pop_front() { if let Some(data) = self.items.pop_front() {
self.len -= data.len(); self.len -= data.len();
Ok(Async::Ready(Some(PayloadItem(data)))) Ok(Async::Ready(Some(PayloadItem(data))))
} else if self.eof {
Ok(Async::Ready(None))
} else if let Some(err) = self.err.take() { } else if let Some(err) = self.err.take() {
Err(err) Err(err)
} else if self.eof {
Ok(Async::Ready(None))
} else { } else {
self.task = Some(current_task()); self.task = Some(current_task());
Ok(Async::NotReady) Ok(Async::NotReady)
@ -439,6 +440,7 @@ impl Inner {
self.items.push_front(data); self.items.push_front(data);
} }
#[inline]
fn capacity(&self) -> usize { fn capacity(&self) -> usize {
if self.len > self.buf_size { if self.len > self.buf_size {
0 0

View File

@ -94,6 +94,7 @@ impl PayloadType {
} }
impl PayloadWriter for PayloadType { impl PayloadWriter for PayloadType {
#[inline]
fn set_error(&mut self, err: PayloadError) { fn set_error(&mut self, err: PayloadError) {
match *self { match *self {
PayloadType::Sender(ref mut sender) => sender.set_error(err), PayloadType::Sender(ref mut sender) => sender.set_error(err),
@ -101,6 +102,7 @@ impl PayloadWriter for PayloadType {
} }
} }
#[inline]
fn feed_eof(&mut self) { fn feed_eof(&mut self) {
match *self { match *self {
PayloadType::Sender(ref mut sender) => sender.feed_eof(), PayloadType::Sender(ref mut sender) => sender.feed_eof(),
@ -108,6 +110,7 @@ impl PayloadWriter for PayloadType {
} }
} }
#[inline]
fn feed_data(&mut self, data: Bytes) { fn feed_data(&mut self, data: Bytes) {
match *self { match *self {
PayloadType::Sender(ref mut sender) => sender.feed_data(data), PayloadType::Sender(ref mut sender) => sender.feed_data(data),
@ -115,6 +118,7 @@ impl PayloadWriter for PayloadType {
} }
} }
#[inline]
fn capacity(&self) -> usize { fn capacity(&self) -> usize {
match *self { match *self {
PayloadType::Sender(ref sender) => sender.capacity(), PayloadType::Sender(ref sender) => sender.capacity(),

View File

@ -16,7 +16,7 @@ use pipeline::Pipeline;
use httpcodes::HTTPNotFound; use httpcodes::HTTPNotFound;
use httprequest::HttpRequest; use httprequest::HttpRequest;
use error::{ParseError, PayloadError, ResponseError}; use error::{ParseError, PayloadError, ResponseError};
use payload::{Payload, PayloadWriter, DEFAULT_BUFFER_SIZE}; use payload::{Payload, PayloadWriter};
use super::{utils, Writer}; use super::{utils, Writer};
use super::h1writer::H1Writer; use super::h1writer::H1Writer;
@ -319,7 +319,6 @@ struct Reader {
} }
enum Decoding { enum Decoding {
Paused,
Ready, Ready,
NotReady, NotReady,
} }
@ -343,29 +342,25 @@ impl Reader {
} }
} }
fn decode(&mut self, buf: &mut BytesMut) -> std::result::Result<Decoding, ReaderError> { #[inline]
if let Some(ref mut payload) = self.payload { fn decode(&mut self, buf: &mut BytesMut, payload: &mut PayloadInfo)
if payload.tx.capacity() > DEFAULT_BUFFER_SIZE { -> std::result::Result<Decoding, ReaderError>
return Ok(Decoding::Paused) {
} loop {
loop { match payload.decoder.decode(buf) {
match payload.decoder.decode(buf) { Ok(Async::Ready(Some(bytes))) => {
Ok(Async::Ready(Some(bytes))) => { payload.tx.feed_data(bytes)
payload.tx.feed_data(bytes) },
}, Ok(Async::Ready(None)) => {
Ok(Async::Ready(None)) => { payload.tx.feed_eof();
payload.tx.feed_eof(); return Ok(Decoding::Ready)
return Ok(Decoding::Ready) },
}, Ok(Async::NotReady) => return Ok(Decoding::NotReady),
Ok(Async::NotReady) => return Ok(Decoding::NotReady), Err(err) => {
Err(err) => { payload.tx.set_error(err.into());
payload.tx.set_error(err.into()); return Err(ReaderError::Payload)
return Err(ReaderError::Payload)
}
} }
} }
} else {
return Ok(Decoding::Ready)
} }
} }
@ -375,29 +370,48 @@ impl Reader {
where T: IoStream where T: IoStream
{ {
// read payload // read payload
if self.payload.is_some() { let done = {
match utils::read_from_io(io, buf) { if let Some(ref mut payload) = self.payload {
Ok(Async::Ready(0)) => { if payload.tx.capacity() == 0 {
if let Some(ref mut payload) = self.payload { return Ok(Async::NotReady)
payload.tx.set_error(PayloadError::Incomplete);
}
// http channel should not deal with payload errors
return Err(ReaderError::Payload)
},
Err(err) => {
if let Some(ref mut payload) = self.payload {
payload.tx.set_error(err.into());
}
// http channel should not deal with payload errors
return Err(ReaderError::Payload)
} }
_ => (), match utils::read_from_io(io, buf) {
Ok(Async::Ready(0)) => {
payload.tx.set_error(PayloadError::Incomplete);
// http channel should not deal with payload errors
return Err(ReaderError::Payload)
},
Err(err) => {
payload.tx.set_error(err.into());
// http channel should not deal with payload errors
return Err(ReaderError::Payload)
}
_ => (),
}
loop {
match payload.decoder.decode(buf) {
Ok(Async::Ready(Some(bytes))) => {
payload.tx.feed_data(bytes)
},
Ok(Async::Ready(None)) => {
payload.tx.feed_eof();
break true
},
Ok(Async::NotReady) =>
break false,
Err(err) => {
payload.tx.set_error(err.into());
return Err(ReaderError::Payload)
}
}
}
} else {
false
} }
match self.decode(buf)? { };
Decoding::Ready => self.payload = None, if done { self.payload = None }
Decoding::Paused | Decoding::NotReady => return Ok(Async::NotReady),
}
}
// if buf is empty parse_message will always return NotReady, let's avoid that // if buf is empty parse_message will always return NotReady, let's avoid that
let read = if buf.is_empty() { let read = if buf.is_empty() {
@ -421,11 +435,10 @@ impl Reader {
match Reader::parse_message(buf, settings).map_err(ReaderError::Error)? { match Reader::parse_message(buf, settings).map_err(ReaderError::Error)? {
Async::Ready((msg, decoder)) => { Async::Ready((msg, decoder)) => {
// process payload // process payload
if let Some(payload) = decoder { if let Some(mut payload) = decoder {
self.payload = Some(payload); match self.decode(buf, &mut payload)? {
match self.decode(buf)? { Decoding::Ready => (),
Decoding::Paused | Decoding::NotReady => (), Decoding::NotReady => self.payload = Some(payload),
Decoding::Ready => self.payload = None,
} }
} }
return Ok(Async::Ready(msg)); return Ok(Async::Ready(msg));