start migrate to futures 0.3 (again)
This commit is contained in:
parent
00f1022f88
commit
017b1b64d1
@ -9,14 +9,15 @@ documentation = "https://docs.rs/tokio-rustls"
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
description = "Asynchronous TLS/SSL streams for Tokio using Rustls."
|
description = "Asynchronous TLS/SSL streams for Tokio using Rustls."
|
||||||
categories = ["asynchronous", "cryptography", "network-programming"]
|
categories = ["asynchronous", "cryptography", "network-programming"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "quininer/tokio-rustls" }
|
travis-ci = { repository = "quininer/tokio-rustls" }
|
||||||
appveyor = { repository = "quininer/tokio-rustls" }
|
appveyor = { repository = "quininer/tokio-rustls" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "0.1"
|
smallvec = "*"
|
||||||
tokio-io = "0.1.6"
|
futures = { package = "futures-preview", version = "0.3.0-alpha.15" }
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
iovec = "0.1"
|
iovec = "0.1"
|
||||||
rustls = "0.15"
|
rustls = "0.15"
|
||||||
|
@ -1,18 +1,23 @@
|
|||||||
mod vecbuf;
|
// mod vecbuf;
|
||||||
|
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::Poll;
|
||||||
|
use std::marker::Unpin;
|
||||||
use std::io::{ self, Read, Write };
|
use std::io::{ self, Read, Write };
|
||||||
use rustls::Session;
|
use rustls::Session;
|
||||||
use rustls::WriteV;
|
use rustls::WriteV;
|
||||||
use tokio_io::{ AsyncRead, AsyncWrite };
|
use futures::task::Context;
|
||||||
|
use futures::io::{ AsyncRead, AsyncWrite, IoVec };
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
|
||||||
pub struct Stream<'a, IO: 'a, S: 'a> {
|
pub struct Stream<'a, IO, S> {
|
||||||
pub io: &'a mut IO,
|
pub io: &'a mut IO,
|
||||||
pub session: &'a mut S
|
pub session: &'a mut S,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WriteTls<'a, IO: AsyncRead + AsyncWrite, S: Session>: Read + Write {
|
pub trait WriteTls<IO: AsyncWrite, S: Session> {
|
||||||
fn write_tls(&mut self) -> io::Result<usize>;
|
fn write_tls(&mut self, cx: &mut Context) -> io::Result<usize>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -22,36 +27,59 @@ enum Focus {
|
|||||||
Writable
|
Writable
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, IO: AsyncRead + AsyncWrite, S: Session> Stream<'a, IO, S> {
|
impl<'a, IO: AsyncRead + AsyncWrite + Unpin, S: Session> Stream<'a, IO, S> {
|
||||||
pub fn new(io: &'a mut IO, session: &'a mut S) -> Self {
|
pub fn new(io: &'a mut IO, session: &'a mut S) -> Self {
|
||||||
Stream { io, session }
|
Stream { io, session }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn complete_io(&mut self) -> io::Result<(usize, usize)> {
|
pub fn complete_io(&mut self, cx: &mut Context) -> Poll<io::Result<(usize, usize)>> {
|
||||||
self.complete_inner_io(Focus::Empty)
|
self.complete_inner_io(cx, Focus::Empty)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_read_io(&mut self) -> io::Result<usize> {
|
fn complete_read_io(&mut self, cx: &mut Context) -> Poll<io::Result<usize>> {
|
||||||
let n = self.session.read_tls(self.io)?;
|
struct Reader<'a, 'b, T> {
|
||||||
|
io: &'a mut T,
|
||||||
|
cx: &'a mut Context<'b>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, T: AsyncRead + Unpin> Read for Reader<'a, 'b, T> {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
match Pin::new(&mut self.io).poll_read(self.cx, buf) {
|
||||||
|
Poll::Ready(result) => result,
|
||||||
|
Poll::Pending => Err(io::ErrorKind::WouldBlock.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut reader = Reader { io: self.io, cx };
|
||||||
|
|
||||||
|
let n = match self.session.read_tls(&mut reader) {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => return Poll::Pending,
|
||||||
|
Err(err) => return Poll::Ready(Err(err))
|
||||||
|
};
|
||||||
|
|
||||||
self.session.process_new_packets()
|
self.session.process_new_packets()
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
// In case we have an alert to send describing this error,
|
// In case we have an alert to send describing this error,
|
||||||
// try a last-gasp write -- but don't predate the primary
|
// try a last-gasp write -- but don't predate the primary
|
||||||
// error.
|
// error.
|
||||||
let _ = self.write_tls();
|
let _ = self.write_tls(cx);
|
||||||
|
|
||||||
io::Error::new(io::ErrorKind::InvalidData, err)
|
io::Error::new(io::ErrorKind::InvalidData, err)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(n)
|
Poll::Ready(Ok(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_write_io(&mut self) -> io::Result<usize> {
|
fn complete_write_io(&mut self, cx: &mut Context) -> Poll<io::Result<usize>> {
|
||||||
self.write_tls()
|
match self.write_tls(cx) {
|
||||||
|
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Poll::Pending,
|
||||||
|
result => Poll::Ready(result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_inner_io(&mut self, focus: Focus) -> io::Result<(usize, usize)> {
|
fn complete_inner_io(&mut self, cx: &mut Context, focus: Focus) -> Poll<io::Result<(usize, usize)>> {
|
||||||
let mut wrlen = 0;
|
let mut wrlen = 0;
|
||||||
let mut rdlen = 0;
|
let mut rdlen = 0;
|
||||||
let mut eof = false;
|
let mut eof = false;
|
||||||
@ -61,22 +89,22 @@ impl<'a, IO: AsyncRead + AsyncWrite, S: Session> Stream<'a, IO, S> {
|
|||||||
let mut read_would_block = false;
|
let mut read_would_block = false;
|
||||||
|
|
||||||
while self.session.wants_write() {
|
while self.session.wants_write() {
|
||||||
match self.complete_write_io() {
|
match self.complete_write_io(cx) {
|
||||||
Ok(n) => wrlen += n,
|
Poll::Ready(Ok(n)) => wrlen += n,
|
||||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
|
Poll::Pending => {
|
||||||
write_would_block = true;
|
write_would_block = true;
|
||||||
break
|
break
|
||||||
},
|
},
|
||||||
Err(err) => return Err(err)
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !eof && self.session.wants_read() {
|
if !eof && self.session.wants_read() {
|
||||||
match self.complete_read_io() {
|
match self.complete_read_io(cx) {
|
||||||
Ok(0) => eof = true,
|
Poll::Ready(Ok(0)) => eof = true,
|
||||||
Ok(n) => rdlen += n,
|
Poll::Ready(Ok(n)) => rdlen += n,
|
||||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => read_would_block = true,
|
Poll::Pending => read_would_block = true,
|
||||||
Err(err) => return Err(err)
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +115,7 @@ impl<'a, IO: AsyncRead + AsyncWrite, S: Session> Stream<'a, IO, S> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match (eof, self.session.is_handshaking(), would_block) {
|
match (eof, self.session.is_handshaking(), would_block) {
|
||||||
(true, true, _) => return Err(io::ErrorKind::UnexpectedEof.into()),
|
(true, true, _) => return Poll::Pending,
|
||||||
(_, false, true) => {
|
(_, false, true) => {
|
||||||
let would_block = match focus {
|
let would_block = match focus {
|
||||||
Focus::Empty => rdlen == 0 && wrlen == 0,
|
Focus::Empty => rdlen == 0 && wrlen == 0,
|
||||||
@ -96,83 +124,96 @@ impl<'a, IO: AsyncRead + AsyncWrite, S: Session> Stream<'a, IO, S> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return if would_block {
|
return if would_block {
|
||||||
Err(io::ErrorKind::WouldBlock.into())
|
Poll::Pending
|
||||||
} else {
|
} else {
|
||||||
Ok((rdlen, wrlen))
|
Poll::Ready(Ok((rdlen, wrlen)))
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
(_, false, _) => return Ok((rdlen, wrlen)),
|
(_, false, _) => return Poll::Ready(Ok((rdlen, wrlen))),
|
||||||
(_, true, true) => return Err(io::ErrorKind::WouldBlock.into()),
|
(_, true, true) => return Poll::Pending,
|
||||||
(..) => ()
|
(..) => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, IO: AsyncRead + AsyncWrite, S: Session> WriteTls<'a, IO, S> for Stream<'a, IO, S> {
|
impl<'a, IO: AsyncRead + AsyncWrite + Unpin, S: Session> WriteTls<IO, S> for Stream<'a, IO, S> {
|
||||||
fn write_tls(&mut self) -> io::Result<usize> {
|
fn write_tls(&mut self, cx: &mut Context) -> io::Result<usize> {
|
||||||
use futures::Async;
|
struct Writer<'a, 'b, IO> {
|
||||||
use self::vecbuf::VecBuf;
|
io: &'a mut IO,
|
||||||
|
cx: &'a mut Context<'b>
|
||||||
|
}
|
||||||
|
|
||||||
struct V<'a, IO: 'a>(&'a mut IO);
|
impl<'a, 'b, IO: AsyncWrite + Unpin> WriteV for Writer<'a, 'b, IO> {
|
||||||
|
|
||||||
impl<'a, IO: AsyncWrite> WriteV for V<'a, IO> {
|
|
||||||
fn writev(&mut self, vbytes: &[&[u8]]) -> io::Result<usize> {
|
fn writev(&mut self, vbytes: &[&[u8]]) -> io::Result<usize> {
|
||||||
let mut vbytes = VecBuf::new(vbytes);
|
let vbytes = vbytes
|
||||||
match self.0.write_buf(&mut vbytes) {
|
.into_iter()
|
||||||
Ok(Async::Ready(n)) => Ok(n),
|
.try_fold(SmallVec::<[&'_ IoVec; 16]>::new(), |mut sum, next| {
|
||||||
Ok(Async::NotReady) => Err(io::ErrorKind::WouldBlock.into()),
|
sum.push(IoVec::from_bytes(next)?);
|
||||||
Err(err) => Err(err)
|
Some(sum)
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
match Pin::new(&mut self.io).poll_vectored_write(self.cx, &vbytes) {
|
||||||
|
Poll::Ready(result) => result,
|
||||||
|
Poll::Pending => Err(io::ErrorKind::WouldBlock.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut vecio = V(self.io);
|
let mut vecio = Writer { io: self.io, cx };
|
||||||
self.session.writev_tls(&mut vecio)
|
self.session.writev_tls(&mut vecio)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, IO: AsyncRead + AsyncWrite, S: Session> Read for Stream<'a, IO, S> {
|
impl<'a, IO: AsyncRead + AsyncWrite + Unpin, S: Session> Stream<'a, IO, S> {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn poll_read(&mut self, cx: &mut Context, buf: &mut [u8]) -> Poll<io::Result<usize>> {
|
||||||
while self.session.wants_read() {
|
while self.session.wants_read() {
|
||||||
if let (0, _) = self.complete_inner_io(Focus::Readable)? {
|
match self.complete_inner_io(cx, Focus::Readable) {
|
||||||
break
|
Poll::Ready(Ok((0, _))) => break,
|
||||||
|
Poll::Ready(Ok(_)) => (),
|
||||||
|
Poll::Pending => return Poll::Pending,
|
||||||
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.session.read(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, IO: AsyncRead + AsyncWrite, S: Session> Write for Stream<'a, IO, S> {
|
// FIXME rustls always ready ?
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
Poll::Ready(self.session.read(buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_write(&mut self, cx: &mut Context, buf: &[u8]) -> Poll<io::Result<usize>> {
|
||||||
let len = self.session.write(buf)?;
|
let len = self.session.write(buf)?;
|
||||||
while self.session.wants_write() {
|
while self.session.wants_write() {
|
||||||
match self.complete_inner_io(Focus::Writable) {
|
match self.complete_inner_io(cx, Focus::Writable) {
|
||||||
Ok(_) => (),
|
Poll::Ready(Ok(_)) => (),
|
||||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock && len != 0 => break,
|
Poll::Pending if len != 0 => break,
|
||||||
Err(err) => return Err(err)
|
Poll::Pending => return Poll::Pending,
|
||||||
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len != 0 || buf.is_empty() {
|
if len != 0 || buf.is_empty() {
|
||||||
Ok(len)
|
Poll::Ready(Ok(len))
|
||||||
} else {
|
} else {
|
||||||
// not write zero
|
// not write zero
|
||||||
self.session.write(buf)
|
match self.session.write(buf) {
|
||||||
.and_then(|len| if len != 0 {
|
Ok(0) => Poll::Pending,
|
||||||
Ok(len)
|
Ok(n) => Poll::Ready(Ok(n)),
|
||||||
} else {
|
Err(err) => Poll::Ready(Err(err))
|
||||||
Err(io::ErrorKind::WouldBlock.into())
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
fn poll_flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
|
||||||
self.session.flush()?;
|
self.session.flush()?;
|
||||||
while self.session.wants_write() {
|
while self.session.wants_write() {
|
||||||
self.complete_inner_io(Focus::Writable)?;
|
match self.complete_inner_io(cx, Focus::Writable) {
|
||||||
|
Poll::Ready(Ok(_)) => (),
|
||||||
|
Poll::Pending => return Poll::Pending,
|
||||||
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
src/lib.rs
14
src/lib.rs
@ -1,17 +1,10 @@
|
|||||||
//! Asynchronous TLS/SSL streams for Tokio using [Rustls](https://github.com/ctz/rustls).
|
//! Asynchronous TLS/SSL streams for Tokio using [Rustls](https://github.com/ctz/rustls).
|
||||||
|
|
||||||
pub extern crate rustls;
|
// pub mod client;
|
||||||
pub extern crate webpki;
|
|
||||||
|
|
||||||
extern crate bytes;
|
|
||||||
extern crate futures;
|
|
||||||
extern crate iovec;
|
|
||||||
extern crate tokio_io;
|
|
||||||
|
|
||||||
pub mod client;
|
|
||||||
mod common;
|
mod common;
|
||||||
pub mod server;
|
// pub mod server;
|
||||||
|
|
||||||
|
/*
|
||||||
use common::Stream;
|
use common::Stream;
|
||||||
use futures::{Async, Future, Poll};
|
use futures::{Async, Future, Poll};
|
||||||
use rustls::{ClientConfig, ClientSession, ServerConfig, ServerSession};
|
use rustls::{ClientConfig, ClientSession, ServerConfig, ServerSession};
|
||||||
@ -194,3 +187,4 @@ impl<IO: AsyncRead + AsyncWrite> Future for Accept<IO> {
|
|||||||
#[cfg(feature = "early-data")]
|
#[cfg(feature = "early-data")]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_0rtt;
|
mod test_0rtt;
|
||||||
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user