|
|
|
@ -62,7 +62,6 @@ pub struct Stream<'a, IO, C> { |
|
|
|
|
pub io: &'a mut IO, |
|
|
|
|
pub session: &'a mut C, |
|
|
|
|
pub eof: bool, |
|
|
|
|
pub unexpected_eof: bool, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<'a, IO: AsyncRead + AsyncWrite + Unpin, C, SD> Stream<'a, IO, C> |
|
|
|
@ -77,7 +76,6 @@ where |
|
|
|
|
// The state so far is only used to detect EOF, so either Stream
|
|
|
|
|
// or EarlyData state should both be all right.
|
|
|
|
|
eof: false, |
|
|
|
|
unexpected_eof: false, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -238,70 +236,53 @@ where |
|
|
|
|
cx: &mut Context<'_>, |
|
|
|
|
buf: &mut ReadBuf<'_>, |
|
|
|
|
) -> Poll<io::Result<()>> { |
|
|
|
|
let prev = buf.remaining(); |
|
|
|
|
let mut io_pending = false; |
|
|
|
|
|
|
|
|
|
while buf.remaining() != 0 { |
|
|
|
|
let mut io_pending = false; |
|
|
|
|
|
|
|
|
|
// read a packet
|
|
|
|
|
while !self.eof && self.session.wants_read() { |
|
|
|
|
match self.read_io(cx) { |
|
|
|
|
Poll::Ready(Ok(0)) => { |
|
|
|
|
self.eof = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
Poll::Ready(Ok(_)) => (), |
|
|
|
|
Poll::Pending => { |
|
|
|
|
io_pending = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err)), |
|
|
|
|
// read a packet
|
|
|
|
|
while !self.eof && self.session.wants_read() { |
|
|
|
|
match self.read_io(cx) { |
|
|
|
|
Poll::Ready(Ok(0)) => { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
Poll::Ready(Ok(_)) => (), |
|
|
|
|
Poll::Pending => { |
|
|
|
|
io_pending = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err)), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return match self.session.reader().read(buf.initialize_unfilled()) { |
|
|
|
|
// If Rustls returns `Ok(0)` (while `buf` is non-empty), the peer closed the
|
|
|
|
|
// connection with a `CloseNotify` message and no more data will be forthcoming.
|
|
|
|
|
Ok(0) => break, |
|
|
|
|
|
|
|
|
|
// Rustls yielded more data: advance the buffer, then see if more data is coming.
|
|
|
|
|
Ok(n) => { |
|
|
|
|
buf.advance(n); |
|
|
|
|
|
|
|
|
|
if self.eof || io_pending { |
|
|
|
|
break; |
|
|
|
|
} else { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
match self.session.reader().read(buf.initialize_unfilled()) { |
|
|
|
|
// If Rustls returns `Ok(0)` (while `buf` is non-empty), the peer closed the
|
|
|
|
|
// connection with a `CloseNotify` message and no more data will be forthcoming.
|
|
|
|
|
//
|
|
|
|
|
// Rustls yielded more data: advance the buffer, then see if more data is coming.
|
|
|
|
|
//
|
|
|
|
|
// We don't need to modify `self.eof` here, because it is only a temporary mark.
|
|
|
|
|
// rustls will only return 0 if is has received `CloseNotify`,
|
|
|
|
|
// in which case no additional processing is required.
|
|
|
|
|
Ok(n) => { |
|
|
|
|
buf.advance(n); |
|
|
|
|
Poll::Ready(Ok(())) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Rustls doesn't have more data to yield, but it believes the connection is open.
|
|
|
|
|
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => { |
|
|
|
|
if prev == buf.remaining() && io_pending { |
|
|
|
|
Poll::Pending |
|
|
|
|
} else if self.eof || io_pending { |
|
|
|
|
break; |
|
|
|
|
} else { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
// Rustls doesn't have more data to yield, but it believes the connection is open.
|
|
|
|
|
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => { |
|
|
|
|
if !io_pending { |
|
|
|
|
// If `wants_read()` is satisfied, rustls will not return `WouldBlock`.
|
|
|
|
|
// but if it does, we can try again.
|
|
|
|
|
//
|
|
|
|
|
// If the rustls state is abnormal, it may cause a cyclic wakeup.
|
|
|
|
|
// but tokio's cooperative budget will prevent infinite wakeup.
|
|
|
|
|
cx.waker().wake_by_ref(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Err(err) if err.kind() == io::ErrorKind::UnexpectedEof => { |
|
|
|
|
self.eof = true; |
|
|
|
|
self.unexpected_eof = true; |
|
|
|
|
if prev == buf.remaining() { |
|
|
|
|
Poll::Ready(Err(err)) |
|
|
|
|
} else { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Poll::Pending |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This should be unreachable.
|
|
|
|
|
Err(err) => Poll::Ready(Err(err)), |
|
|
|
|
}; |
|
|
|
|
Err(err) => Poll::Ready(Err(err)), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Poll::Ready(Ok(())) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|