1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-24 00:21:08 +01:00

better deflate decoding

This commit is contained in:
Nikolay Kim 2017-11-06 09:24:19 -08:00
parent c2978a6eea
commit bddd8e9c2e

View File

@ -8,8 +8,8 @@ use bytes::{Bytes, BytesMut, BufMut, Writer};
use http2::Error as Http2Error; use http2::Error as Http2Error;
use futures::{Async, Poll, Stream}; use futures::{Async, Poll, Stream};
use futures::task::{Task, current as current_task}; use futures::task::{Task, current as current_task};
use flate2::{FlateReadExt, Flush, Decompress, Status as DecompressStatus}; use flate2::read::{GzDecoder};
use flate2::read::GzDecoder; use flate2::write::{DeflateDecoder};
use brotli2::write::BrotliDecoder; use brotli2::write::BrotliDecoder;
use actix::ResponseType; use actix::ResponseType;
@ -206,7 +206,7 @@ impl PayloadWriter for PayloadSender {
} }
enum Decoder { enum Decoder {
Zlib(Decompress), Zlib(DeflateDecoder<BytesWriter>),
Gzip(Option<GzDecoder<Wrapper>>), Gzip(Option<GzDecoder<Wrapper>>),
Br(Rc<RefCell<BytesMut>>, BrotliDecoder<WrapperRc>), Br(Rc<RefCell<BytesMut>>, BrotliDecoder<WrapperRc>),
Identity, Identity,
@ -226,6 +226,27 @@ impl io::Read for Wrapper {
} }
} }
struct BytesWriter {
buf: BytesMut,
}
impl Default for BytesWriter {
fn default() -> BytesWriter {
BytesWriter{buf: BytesMut::with_capacity(8192)}
}
}
impl io::Write for BytesWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.buf.extend(buf);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[derive(Debug)] #[derive(Debug)]
struct WrapperRc { struct WrapperRc {
buf: Rc<RefCell<BytesMut>>, buf: Rc<RefCell<BytesMut>>,
@ -245,14 +266,14 @@ pub(crate) struct EncodedPayload {
inner: PayloadSender, inner: PayloadSender,
decoder: Decoder, decoder: Decoder,
dst: Writer<BytesMut>, dst: Writer<BytesMut>,
buffer: BytesMut,
error: bool, error: bool,
} }
impl EncodedPayload { impl EncodedPayload {
pub fn new(inner: PayloadSender, enc: ContentEncoding) -> EncodedPayload { pub fn new(inner: PayloadSender, enc: ContentEncoding) -> EncodedPayload {
let dec = match enc { let dec = match enc {
ContentEncoding::Deflate => Decoder::Zlib(Decompress::new(false)), ContentEncoding::Deflate => Decoder::Zlib(
DeflateDecoder::new(BytesWriter::default())),
ContentEncoding::Gzip => Decoder::Gzip(None), ContentEncoding::Gzip => Decoder::Gzip(None),
ContentEncoding::Br => { ContentEncoding::Br => {
let buf = Rc::new(RefCell::new(BytesMut::new())); let buf = Rc::new(RefCell::new(BytesMut::new()));
@ -266,7 +287,6 @@ impl EncodedPayload {
decoder: dec, decoder: dec,
error: false, error: false,
dst: BytesMut::new().writer(), dst: BytesMut::new().writer(),
buffer: BytesMut::new(),
} }
} }
} }
@ -323,32 +343,16 @@ impl PayloadWriter for EncodedPayload {
} }
} }
Decoder::Zlib(ref mut decoder) => { Decoder::Zlib(ref mut decoder) => {
let len = self.dst.get_ref().len(); match decoder.flush() {
if len < self.buffer.len() * 2 { Ok(_) => {
self.dst.get_mut().reserve(self.buffer.len() * 2 - len); let b = decoder.get_mut().buf.take().freeze();
unsafe{self.dst.get_mut().set_len(self.buffer.len() * 2)}; if !b.is_empty() {
} self.inner.feed_data(b);
}
let len = self.dst.get_ref().len();
let before_in = decoder.total_in();
let before_out = decoder.total_out();
let ret = decoder.decompress(
self.buffer.as_ref(), &mut self.dst.get_mut()[..len], Flush::Finish);
let read = (decoder.total_out() - before_out) as usize;
let consumed = (decoder.total_in() - before_in) as usize;
let ch = self.dst.get_mut().split_to(read).freeze();
if !ch.is_empty() {
self.inner.feed_data(ch);
}
self.buffer.split_to(consumed);
match ret {
Ok(DecompressStatus::Ok) | Ok(DecompressStatus::StreamEnd) => {
self.inner.feed_eof(); self.inner.feed_eof();
return return
}, },
_ => None, Err(err) => Some(err),
} }
}, },
Decoder::Identity => { Decoder::Identity => {
@ -390,7 +394,7 @@ impl PayloadWriter for EncodedPayload {
if decoder.is_none() { if decoder.is_none() {
let mut buf = BytesMut::new(); let mut buf = BytesMut::new();
buf.extend(data); buf.extend(data);
*decoder = Some(Wrapper{buf: buf}.gz_decode().unwrap()); *decoder = Some(GzDecoder::new(Wrapper{buf: buf}).unwrap());
} else { } else {
decoder.as_mut().unwrap().get_mut().buf.extend(data); decoder.as_mut().unwrap().get_mut().buf.extend(data);
} }
@ -420,42 +424,17 @@ impl PayloadWriter for EncodedPayload {
} }
Decoder::Zlib(ref mut decoder) => { Decoder::Zlib(ref mut decoder) => {
self.buffer.extend(data); match decoder.write(&data) {
Ok(_) => {
loop { let b = decoder.get_mut().buf.take().freeze();
if self.buffer.is_empty() { if !b.is_empty() {
self.inner.feed_data(b);
}
return return
} },
Err(err) => {
let ret = { trace!("Error decoding deflate encoding: {}", err);
let len = self.dst.get_ref().len(); },
if len < self.buffer.len() * 2 {
self.dst.get_mut().reserve(self.buffer.len() * 2 - len);
unsafe{self.dst.get_mut().set_len(self.buffer.len() * 2)};
}
let before_out = decoder.total_out();
let before_in = decoder.total_in();
let len = self.dst.get_ref().len();
let ret = decoder.decompress(
self.buffer.as_ref(), &mut self.dst.get_mut()[..len], Flush::None);
let read = (decoder.total_out() - before_out) as usize;
let consumed = (decoder.total_in() - before_in) as usize;
let ch = self.dst.get_mut().split_to(read).freeze();
if !ch.is_empty() {
self.inner.feed_data(ch);
}
if self.buffer.len() > consumed {
self.buffer.split_to(consumed);
}
ret
};
match ret {
Ok(DecompressStatus::Ok) => continue,
_ => break,
}
} }
} }
Decoder::Identity => { Decoder::Identity => {