Add implementations of prepare_uninitialized_buffer and read_buf where relevant (#1107)

* Fix #1080

* Fix browser WebSockets
This commit is contained in:
Pierre Krieger
2019-05-10 11:26:18 +02:00
committed by GitHub
parent 089e349671
commit c2398adf67
19 changed files with 121 additions and 8 deletions

View File

@ -68,13 +68,19 @@ where
A: AsyncRead,
B: AsyncRead,
{
#[inline]
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
match self {
EitherOutput::First(a) => a.prepare_uninitialized_buffer(buf),
EitherOutput::Second(b) => b.prepare_uninitialized_buffer(buf),
}
}
fn read_buf<Bu: bytes::BufMut>(&mut self, buf: &mut Bu) -> Poll<usize, IoError> {
match self {
EitherOutput::First(a) => a.read_buf(buf),
EitherOutput::Second(b) => b.read_buf(buf),
}
}
}
impl<A, B> Read for EitherOutput<A, B>
@ -179,6 +185,13 @@ where
}
}
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
match self {
EitherOutput::First(ref inner) => inner.prepare_uninitialized_buffer(buf),
EitherOutput::Second(ref inner) => inner.prepare_uninitialized_buffer(buf),
}
}
fn read_substream(&self, sub: &mut Self::Substream, buf: &mut [u8]) -> Poll<usize, Self::Error> {
match (self, sub) {
(EitherOutput::First(ref inner), EitherOutput::First(ref mut sub)) => {

View File

@ -132,6 +132,20 @@ pub trait StreamMuxer {
/// happened.
fn read_substream(&self, s: &mut Self::Substream, buf: &mut [u8]) -> Poll<usize, Self::Error>;
/// Mimics the `prepare_uninitialized_buffer` method of the `AsyncRead` trait.
///
/// This function isn't actually unsafe to call but unsafe to implement. The implementer must
/// ensure that either the whole buf has been zeroed or that `read_substream` overwrites the
/// buffer without reading it and returns correct value.
///
/// If this function returns true, then the memory has been zeroed out. This allows
/// implementations of `AsyncRead` which are composed of multiple subimplementations to
/// efficiently implement `prepare_uninitialized_buffer`.
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
for b in buf.iter_mut() { *b = 0; }
true
}
/// Write data to a substream. The behaviour is the same as `tokio_io::AsyncWrite::poll_write`.
///
/// If `NotReady` is returned, then the current task will be notified once the substream
@ -369,7 +383,10 @@ where
P: Deref,
P::Target: StreamMuxer,
{
#[inline]
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
self.muxer.prepare_uninitialized_buffer(buf)
}
fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, io::Error> {
let s = self.substream.as_mut().expect("substream was empty");
self.muxer.read_substream(s, buf).map_err(|e| e.into())
@ -488,6 +505,10 @@ impl StreamMuxer for StreamMuxerBox {
self.inner.destroy_outbound(substream)
}
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
self.inner.prepare_uninitialized_buffer(buf)
}
#[inline]
fn read_substream(&self, s: &mut Self::Substream, buf: &mut [u8]) -> Poll<usize, Self::Error> {
self.inner.read_substream(s, buf)
@ -579,6 +600,10 @@ where
self.inner.destroy_outbound(list.remove(&substream).unwrap())
}
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
self.inner.prepare_uninitialized_buffer(buf)
}
#[inline]
fn read_substream(&self, s: &mut Self::Substream, buf: &mut [u8]) -> Poll<usize, Self::Error> {
let mut list = self.substreams.lock();

View File

@ -101,6 +101,10 @@ where
fn destroy_outbound(&self, _: Self::OutboundSubstream) {
}
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
self.inner.lock().prepare_uninitialized_buffer(buf)
}
fn read_substream(&self, _: &mut Self::Substream, buf: &mut [u8]) -> Poll<usize, io::Error> {
let res = self.inner.lock().poll_read(buf);
if let Ok(Async::Ready(_)) = res {

View File

@ -94,6 +94,9 @@ impl io::Write for DummyStream {
}
impl tokio_io::AsyncRead for DummyStream {
unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool {
false
}
}
impl tokio_io::AsyncWrite for DummyStream {