feat(client): add ALPN h2 support for client connectors

- Adds `Connected::negotiated_h2()` method to signal the connection must
  use HTTP2. `Connect` implementations should set this if using ALPN.

If a connection to a host is detected to have been upgraded via ALPN,
any other oustanding connect futures will be canceled, and the waiting
requests will make use of the single HTTP2 connection.

The `http2_only` builder configuration still works the same, not
requiring ALPN at all, and always using only a single connection.
This commit is contained in:
Sean McArthur
2018-10-26 18:55:03 -07:00
parent bf188b28fe
commit 976a77a673
7 changed files with 200 additions and 95 deletions

View File

@@ -358,11 +358,12 @@ impl Read for Duplex {
impl Write for Duplex {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut inner = self.inner.lock().unwrap();
let ret = inner.write.write(buf);
if let Some(task) = inner.handle_read_task.take() {
trace!("waking DuplexHandle read");
task.notify();
}
inner.write.write(buf)
ret
}
fn flush(&mut self) -> io::Result<()> {
@@ -404,8 +405,7 @@ impl DuplexHandle {
inner.handle_read_task = Some(task::current());
return Ok(Async::NotReady);
}
inner.write.inner.vec.truncate(0);
Ok(Async::Ready(inner.write.inner.len()))
inner.write.read(buf).map(Async::Ready)
}
pub fn write(&self, bytes: &[u8]) -> Poll<usize, io::Error> {
@@ -456,6 +456,13 @@ impl MockConnector {
}
pub fn mock_fut<F>(&mut self, key: &str, fut: F) -> DuplexHandle
where
F: Future + Send + 'static,
{
self.mock_opts(key, Connected::new(), fut)
}
pub fn mock_opts<F>(&mut self, key: &str, connected: Connected, fut: F) -> DuplexHandle
where
F: Future + Send + 'static,
{
@@ -465,7 +472,7 @@ impl MockConnector {
let fut = Box::new(fut.then(move |_| {
trace!("MockConnector mocked fut ready");
Ok((duplex, Connected::new()))
Ok((duplex, connected))
}));
self.mocks.lock().unwrap().entry(key)
.or_insert(Vec::new())