2018-11-12 08:12:54 +01:00
|
|
|
use std::cell::RefCell;
|
2019-01-27 20:40:26 +01:00
|
|
|
use std::collections::VecDeque;
|
2019-11-15 10:54:11 +01:00
|
|
|
use std::future::Future;
|
2018-11-12 08:12:54 +01:00
|
|
|
use std::io;
|
2019-11-15 10:54:11 +01:00
|
|
|
use std::pin::Pin;
|
2018-11-12 08:12:54 +01:00
|
|
|
use std::rc::Rc;
|
2019-11-15 10:54:11 +01:00
|
|
|
use std::task::{Context, Poll};
|
2018-11-12 08:12:54 +01:00
|
|
|
use std::time::{Duration, Instant};
|
|
|
|
|
2018-12-11 03:08:33 +01:00
|
|
|
use actix_codec::{AsyncRead, AsyncWrite};
|
|
|
|
use actix_service::Service;
|
2019-11-18 13:42:27 +01:00
|
|
|
use actix_utils::{oneshot, task::LocalWaker};
|
2019-01-29 05:41:09 +01:00
|
|
|
use bytes::Bytes;
|
2019-11-18 13:42:27 +01:00
|
|
|
use futures::future::{err, ok, poll_fn, Either, FutureExt, LocalBoxFuture, Ready};
|
|
|
|
use h2::client::{handshake, Connection, SendRequest};
|
2019-01-27 20:40:26 +01:00
|
|
|
use hashbrown::HashMap;
|
2019-04-20 03:03:44 +02:00
|
|
|
use http::uri::Authority;
|
2018-11-12 08:12:54 +01:00
|
|
|
use indexmap::IndexSet;
|
|
|
|
use slab::Slab;
|
2019-11-15 10:54:11 +01:00
|
|
|
use tokio_timer::{delay_for, Delay};
|
2018-11-12 08:12:54 +01:00
|
|
|
|
2019-01-29 05:41:09 +01:00
|
|
|
use super::connection::{ConnectionType, IoConnection};
|
2019-03-13 22:41:40 +01:00
|
|
|
use super::error::ConnectError;
|
2019-04-20 03:03:44 +02:00
|
|
|
use super::Connect;
|
2018-11-12 08:12:54 +01:00
|
|
|
|
2019-01-29 05:41:09 +01:00
|
|
|
#[derive(Clone, Copy, PartialEq)]
|
2019-04-08 20:09:57 +02:00
|
|
|
/// Protocol version
|
2019-01-29 05:41:09 +01:00
|
|
|
pub enum Protocol {
|
|
|
|
Http1,
|
|
|
|
Http2,
|
|
|
|
}
|
|
|
|
|
2018-11-12 08:12:54 +01:00
|
|
|
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
|
|
|
|
pub(crate) struct Key {
|
|
|
|
authority: Authority,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Authority> for Key {
|
|
|
|
fn from(authority: Authority) -> Key {
|
|
|
|
Key { authority }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Connections pool
|
2019-11-18 13:42:27 +01:00
|
|
|
pub(crate) struct ConnectionPool<T, Io: 'static>(Rc<RefCell<T>>, Rc<RefCell<Inner<Io>>>);
|
2018-11-12 08:12:54 +01:00
|
|
|
|
|
|
|
impl<T, Io> ConnectionPool<T, Io>
|
|
|
|
where
|
|
|
|
Io: AsyncRead + AsyncWrite + 'static,
|
2019-04-23 23:57:03 +02:00
|
|
|
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError>
|
2019-11-18 13:42:27 +01:00
|
|
|
+ Unpin
|
2019-04-23 23:57:03 +02:00
|
|
|
+ 'static,
|
2019-11-18 13:42:27 +01:00
|
|
|
T::Future: Unpin,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
|
|
|
pub(crate) fn new(
|
|
|
|
connector: T,
|
|
|
|
conn_lifetime: Duration,
|
|
|
|
conn_keep_alive: Duration,
|
|
|
|
disconnect_timeout: Option<Duration>,
|
|
|
|
limit: usize,
|
|
|
|
) -> Self {
|
|
|
|
ConnectionPool(
|
2019-11-18 13:42:27 +01:00
|
|
|
Rc::new(RefCell::new(connector)),
|
2018-11-12 08:12:54 +01:00
|
|
|
Rc::new(RefCell::new(Inner {
|
|
|
|
conn_lifetime,
|
|
|
|
conn_keep_alive,
|
|
|
|
disconnect_timeout,
|
|
|
|
limit,
|
|
|
|
acquired: 0,
|
|
|
|
waiters: Slab::new(),
|
|
|
|
waiters_queue: IndexSet::new(),
|
|
|
|
available: HashMap::new(),
|
2019-11-18 13:42:27 +01:00
|
|
|
waker: LocalWaker::new(),
|
2018-11-12 08:12:54 +01:00
|
|
|
})),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T, Io> Clone for ConnectionPool<T, Io>
|
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: 'static,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
ConnectionPool(self.0.clone(), self.1.clone())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-09 16:37:23 +01:00
|
|
|
impl<T, Io> Service for ConnectionPool<T, Io>
|
2018-11-12 08:12:54 +01:00
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
2019-04-23 23:57:03 +02:00
|
|
|
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError>
|
2019-11-18 13:42:27 +01:00
|
|
|
+ Unpin
|
2019-04-23 23:57:03 +02:00
|
|
|
+ 'static,
|
2019-11-18 13:42:27 +01:00
|
|
|
T::Future: Unpin,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
2019-04-20 03:03:44 +02:00
|
|
|
type Request = Connect;
|
2018-11-15 20:10:23 +01:00
|
|
|
type Response = IoConnection<Io>;
|
2019-03-13 22:41:40 +01:00
|
|
|
type Error = ConnectError;
|
2019-11-18 13:42:27 +01:00
|
|
|
type Future = LocalBoxFuture<'static, Result<IoConnection<Io>, ConnectError>>;
|
2018-11-12 08:12:54 +01:00
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
self.0.poll_ready(cx)
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
|
2019-04-20 03:03:44 +02:00
|
|
|
fn call(&mut self, req: Connect) -> Self::Future {
|
2019-11-18 13:42:27 +01:00
|
|
|
// start support future
|
|
|
|
tokio_executor::current_thread::spawn(ConnectorPoolSupport {
|
|
|
|
connector: self.0.clone(),
|
|
|
|
inner: self.1.clone(),
|
|
|
|
});
|
|
|
|
|
|
|
|
let mut connector = self.0.clone();
|
|
|
|
let inner = self.1.clone();
|
|
|
|
|
|
|
|
let fut = async move {
|
|
|
|
let key = if let Some(authority) = req.uri.authority_part() {
|
|
|
|
authority.clone().into()
|
|
|
|
} else {
|
|
|
|
return Err(ConnectError::Unresolverd);
|
|
|
|
};
|
2018-11-12 08:12:54 +01:00
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
// acquire connection
|
|
|
|
match poll_fn(|cx| Poll::Ready(inner.borrow_mut().acquire(&key, cx))).await {
|
|
|
|
Acquire::Acquired(io, created) => {
|
|
|
|
// use existing connection
|
|
|
|
return Ok(IoConnection::new(
|
|
|
|
io,
|
|
|
|
created,
|
|
|
|
Some(Acquired(key, Some(inner))),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
Acquire::Available => {
|
|
|
|
// open tcp connection
|
|
|
|
let (io, proto) = connector.call(req).await?;
|
|
|
|
|
|
|
|
let guard = OpenGuard::new(key, inner);
|
|
|
|
|
|
|
|
if proto == Protocol::Http1 {
|
|
|
|
Ok(IoConnection::new(
|
|
|
|
ConnectionType::H1(io),
|
|
|
|
Instant::now(),
|
|
|
|
Some(guard.consume()),
|
|
|
|
))
|
|
|
|
} else {
|
|
|
|
let (snd, connection) = handshake(io).await?;
|
|
|
|
tokio_executor::current_thread::spawn(connection.map(|_| ()));
|
|
|
|
Ok(IoConnection::new(
|
|
|
|
ConnectionType::H2(snd),
|
|
|
|
Instant::now(),
|
|
|
|
Some(guard.consume()),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
// connection is not available, wait
|
|
|
|
let (rx, token) = inner.borrow_mut().wait_for(req);
|
|
|
|
|
|
|
|
let guard = WaiterGuard::new(key, token, inner);
|
|
|
|
let res = match rx.await {
|
|
|
|
Err(_) => Err(ConnectError::Disconnected),
|
|
|
|
Ok(res) => res,
|
|
|
|
};
|
|
|
|
guard.consume();
|
|
|
|
res
|
|
|
|
}
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
2019-11-18 13:42:27 +01:00
|
|
|
};
|
2019-04-23 23:57:03 +02:00
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
fut.boxed_local()
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
struct WaiterGuard<Io>
|
2018-11-12 08:12:54 +01:00
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
|
|
|
key: Key,
|
|
|
|
token: usize,
|
|
|
|
inner: Option<Rc<RefCell<Inner<Io>>>>,
|
|
|
|
}
|
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
impl<Io> WaiterGuard<Io>
|
2018-11-12 08:12:54 +01:00
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
2019-11-18 13:42:27 +01:00
|
|
|
fn new(key: Key, token: usize, inner: Rc<RefCell<Inner<Io>>>) -> Self {
|
|
|
|
Self {
|
|
|
|
key,
|
|
|
|
token,
|
|
|
|
inner: Some(inner),
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
}
|
2019-11-18 13:42:27 +01:00
|
|
|
|
|
|
|
fn consume(mut self) {
|
|
|
|
let _ = self.inner.take();
|
|
|
|
}
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
impl<Io> Drop for WaiterGuard<Io>
|
2018-11-12 08:12:54 +01:00
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
2019-11-18 13:42:27 +01:00
|
|
|
fn drop(&mut self) {
|
|
|
|
if let Some(i) = self.inner.take() {
|
|
|
|
let mut inner = i.as_ref().borrow_mut();
|
|
|
|
inner.release_waiter(&self.key, self.token);
|
|
|
|
inner.check_availibility();
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
struct OpenGuard<Io>
|
2018-11-12 08:12:54 +01:00
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
|
|
|
key: Key,
|
|
|
|
inner: Option<Rc<RefCell<Inner<Io>>>>,
|
|
|
|
}
|
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
impl<Io> OpenGuard<Io>
|
2018-11-12 08:12:54 +01:00
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
2019-11-18 13:42:27 +01:00
|
|
|
fn new(key: Key, inner: Rc<RefCell<Inner<Io>>>) -> Self {
|
|
|
|
Self {
|
2018-11-12 08:12:54 +01:00
|
|
|
key,
|
|
|
|
inner: Some(inner),
|
|
|
|
}
|
|
|
|
}
|
2019-11-18 13:42:27 +01:00
|
|
|
|
|
|
|
fn consume(mut self) -> Acquired<Io> {
|
|
|
|
Acquired(self.key.clone(), self.inner.take())
|
|
|
|
}
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
impl<Io> Drop for OpenGuard<Io>
|
2018-11-12 08:12:54 +01:00
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
|
|
|
fn drop(&mut self) {
|
2019-11-18 13:42:27 +01:00
|
|
|
if let Some(i) = self.inner.take() {
|
|
|
|
let mut inner = i.as_ref().borrow_mut();
|
2018-11-12 08:12:54 +01:00
|
|
|
inner.release();
|
|
|
|
inner.check_availibility();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
enum Acquire<T> {
|
2019-01-29 05:41:09 +01:00
|
|
|
Acquired(ConnectionType<T>, Instant),
|
2018-11-12 08:12:54 +01:00
|
|
|
Available,
|
|
|
|
NotAvailable,
|
|
|
|
}
|
|
|
|
|
2019-01-29 05:41:09 +01:00
|
|
|
struct AvailableConnection<Io> {
|
|
|
|
io: ConnectionType<Io>,
|
|
|
|
used: Instant,
|
|
|
|
created: Instant,
|
|
|
|
}
|
|
|
|
|
2018-11-14 07:53:30 +01:00
|
|
|
pub(crate) struct Inner<Io> {
|
2018-11-12 08:12:54 +01:00
|
|
|
conn_lifetime: Duration,
|
|
|
|
conn_keep_alive: Duration,
|
|
|
|
disconnect_timeout: Option<Duration>,
|
|
|
|
limit: usize,
|
|
|
|
acquired: usize,
|
|
|
|
available: HashMap<Key, VecDeque<AvailableConnection<Io>>>,
|
2019-07-30 17:00:46 +02:00
|
|
|
waiters: Slab<
|
|
|
|
Option<(
|
|
|
|
Connect,
|
|
|
|
oneshot::Sender<Result<IoConnection<Io>, ConnectError>>,
|
|
|
|
)>,
|
|
|
|
>,
|
2018-11-12 08:12:54 +01:00
|
|
|
waiters_queue: IndexSet<(Key, usize)>,
|
2019-11-18 13:42:27 +01:00
|
|
|
waker: LocalWaker,
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
|
2018-11-14 07:53:30 +01:00
|
|
|
impl<Io> Inner<Io> {
|
|
|
|
fn reserve(&mut self) {
|
|
|
|
self.acquired += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn release(&mut self) {
|
|
|
|
self.acquired -= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn release_waiter(&mut self, key: &Key, token: usize) {
|
|
|
|
self.waiters.remove(token);
|
2019-09-12 17:52:46 +02:00
|
|
|
let _ = self.waiters_queue.shift_remove(&(key.clone(), token));
|
2018-11-14 07:53:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-12 08:12:54 +01:00
|
|
|
impl<Io> Inner<Io>
|
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
|
|
|
/// connection is not available, wait
|
|
|
|
fn wait_for(
|
|
|
|
&mut self,
|
2019-04-20 03:03:44 +02:00
|
|
|
connect: Connect,
|
2018-11-12 08:12:54 +01:00
|
|
|
) -> (
|
2019-03-13 22:41:40 +01:00
|
|
|
oneshot::Receiver<Result<IoConnection<Io>, ConnectError>>,
|
2018-11-12 08:12:54 +01:00
|
|
|
usize,
|
|
|
|
) {
|
|
|
|
let (tx, rx) = oneshot::channel();
|
|
|
|
|
2019-04-20 03:03:44 +02:00
|
|
|
let key: Key = connect.uri.authority_part().unwrap().clone().into();
|
2018-11-12 08:12:54 +01:00
|
|
|
let entry = self.waiters.vacant_entry();
|
|
|
|
let token = entry.key();
|
2019-07-30 17:00:46 +02:00
|
|
|
entry.insert(Some((connect, tx)));
|
2019-04-23 23:57:03 +02:00
|
|
|
assert!(self.waiters_queue.insert((key, token)));
|
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
(rx, token)
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
fn acquire(&mut self, key: &Key, cx: &mut Context) -> Acquire<Io> {
|
2018-11-12 08:12:54 +01:00
|
|
|
// check limits
|
|
|
|
if self.limit > 0 && self.acquired >= self.limit {
|
|
|
|
return Acquire::NotAvailable;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.reserve();
|
|
|
|
|
|
|
|
// check if open connection is available
|
|
|
|
// cleanup stale connections at the same time
|
|
|
|
if let Some(ref mut connections) = self.available.get_mut(key) {
|
|
|
|
let now = Instant::now();
|
|
|
|
while let Some(conn) = connections.pop_back() {
|
|
|
|
// check if it still usable
|
|
|
|
if (now - conn.used) > self.conn_keep_alive
|
|
|
|
|| (now - conn.created) > self.conn_lifetime
|
|
|
|
{
|
|
|
|
if let Some(timeout) = self.disconnect_timeout {
|
2019-01-29 05:41:09 +01:00
|
|
|
if let ConnectionType::H1(io) = conn.io {
|
2019-11-15 10:54:11 +01:00
|
|
|
tokio_executor::current_thread::spawn(CloseConnection::new(
|
2019-01-29 05:41:09 +01:00
|
|
|
io, timeout,
|
|
|
|
))
|
|
|
|
}
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
let mut io = conn.io;
|
|
|
|
let mut buf = [0; 2];
|
2019-01-29 05:41:09 +01:00
|
|
|
if let ConnectionType::H1(ref mut s) = io {
|
2019-11-18 13:42:27 +01:00
|
|
|
match Pin::new(s).poll_read(cx, &mut buf) {
|
|
|
|
Poll::Pending => (),
|
|
|
|
Poll::Ready(Ok(n)) if n > 0 => {
|
2019-01-29 05:41:09 +01:00
|
|
|
if let Some(timeout) = self.disconnect_timeout {
|
|
|
|
if let ConnectionType::H1(io) = io {
|
2019-11-15 10:54:11 +01:00
|
|
|
tokio_executor::current_thread::spawn(
|
2019-01-29 05:41:09 +01:00
|
|
|
CloseConnection::new(io, timeout),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
2019-11-18 13:42:27 +01:00
|
|
|
_ => continue,
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Acquire::Acquired(io, conn.created);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Acquire::Available
|
|
|
|
}
|
|
|
|
|
2019-04-23 23:57:03 +02:00
|
|
|
fn release_conn(&mut self, key: &Key, io: ConnectionType<Io>, created: Instant) {
|
|
|
|
self.acquired -= 1;
|
|
|
|
self.available
|
|
|
|
.entry(key.clone())
|
|
|
|
.or_insert_with(VecDeque::new)
|
|
|
|
.push_back(AvailableConnection {
|
|
|
|
io,
|
|
|
|
created,
|
|
|
|
used: Instant::now(),
|
|
|
|
});
|
|
|
|
self.check_availibility();
|
|
|
|
}
|
|
|
|
|
2019-01-29 05:41:09 +01:00
|
|
|
fn release_close(&mut self, io: ConnectionType<Io>) {
|
2018-11-12 08:12:54 +01:00
|
|
|
self.acquired -= 1;
|
|
|
|
if let Some(timeout) = self.disconnect_timeout {
|
2019-01-29 05:41:09 +01:00
|
|
|
if let ConnectionType::H1(io) = io {
|
2019-11-15 10:54:11 +01:00
|
|
|
tokio_executor::current_thread::spawn(CloseConnection::new(io, timeout))
|
2019-01-29 05:41:09 +01:00
|
|
|
}
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
2019-04-23 23:57:03 +02:00
|
|
|
self.check_availibility();
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn check_availibility(&self) {
|
|
|
|
if !self.waiters_queue.is_empty() && self.acquired < self.limit {
|
2019-11-18 13:42:27 +01:00
|
|
|
self.waker.wake();
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CloseConnection<T> {
|
|
|
|
io: T,
|
|
|
|
timeout: Delay,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> CloseConnection<T>
|
|
|
|
where
|
|
|
|
T: AsyncWrite,
|
|
|
|
{
|
|
|
|
fn new(io: T, timeout: Duration) -> Self {
|
|
|
|
CloseConnection {
|
|
|
|
io,
|
2019-11-15 10:54:11 +01:00
|
|
|
timeout: delay_for(timeout),
|
2018-11-12 08:12:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Future for CloseConnection<T>
|
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
T: AsyncWrite + Unpin,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
2019-11-18 13:42:27 +01:00
|
|
|
type Output = ();
|
|
|
|
|
|
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> {
|
|
|
|
match Pin::new(&mut self.timeout).poll(cx) {
|
|
|
|
Poll::Ready(_) => Poll::Ready(()),
|
|
|
|
Poll::Pending => match Pin::new(&mut self.io).poll_shutdown(cx) {
|
|
|
|
Poll::Ready(_) => Poll::Ready(()),
|
|
|
|
Poll::Pending => Poll::Pending,
|
2018-11-12 08:12:54 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-23 23:57:03 +02:00
|
|
|
struct ConnectorPoolSupport<T, Io>
|
|
|
|
where
|
|
|
|
Io: AsyncRead + AsyncWrite + 'static,
|
|
|
|
{
|
|
|
|
connector: T,
|
|
|
|
inner: Rc<RefCell<Inner<Io>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T, Io> Future for ConnectorPoolSupport<T, Io>
|
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
|
|
|
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError>
|
|
|
|
+ Unpin,
|
|
|
|
T::Future: Unpin + 'static,
|
2019-04-23 23:57:03 +02:00
|
|
|
{
|
2019-11-18 13:42:27 +01:00
|
|
|
type Output = ();
|
|
|
|
|
|
|
|
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
|
|
|
let this = self.get_mut();
|
2019-04-23 23:57:03 +02:00
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
let mut inner = this.inner.as_ref().borrow_mut();
|
|
|
|
inner.waker.register(cx.waker());
|
2019-04-23 23:57:03 +02:00
|
|
|
|
|
|
|
// check waiters
|
|
|
|
loop {
|
|
|
|
let (key, token) = {
|
|
|
|
if let Some((key, token)) = inner.waiters_queue.get_index(0) {
|
|
|
|
(key.clone(), *token)
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
2019-07-30 17:00:46 +02:00
|
|
|
if inner.waiters.get(token).unwrap().is_none() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
match inner.acquire(&key, cx) {
|
2019-04-23 23:57:03 +02:00
|
|
|
Acquire::NotAvailable => break,
|
|
|
|
Acquire::Acquired(io, created) => {
|
2019-07-30 17:00:46 +02:00
|
|
|
let tx = inner.waiters.get_mut(token).unwrap().take().unwrap().1;
|
2019-04-23 23:57:03 +02:00
|
|
|
if let Err(conn) = tx.send(Ok(IoConnection::new(
|
|
|
|
io,
|
|
|
|
created,
|
2019-11-18 13:42:27 +01:00
|
|
|
Some(Acquired(key.clone(), Some(this.inner.clone()))),
|
2019-04-23 23:57:03 +02:00
|
|
|
))) {
|
|
|
|
let (io, created) = conn.unwrap().into_inner();
|
|
|
|
inner.release_conn(&key, io, created);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Acquire::Available => {
|
2019-07-30 17:00:46 +02:00
|
|
|
let (connect, tx) =
|
|
|
|
inner.waiters.get_mut(token).unwrap().take().unwrap();
|
2019-04-23 23:57:03 +02:00
|
|
|
OpenWaitingConnection::spawn(
|
|
|
|
key.clone(),
|
|
|
|
tx,
|
2019-11-18 13:42:27 +01:00
|
|
|
this.inner.clone(),
|
|
|
|
this.connector.call(connect),
|
2019-04-23 23:57:03 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let _ = inner.waiters_queue.swap_remove_index(0);
|
|
|
|
}
|
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
Poll::Pending
|
2019-04-23 23:57:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct OpenWaitingConnection<F, Io>
|
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
2019-04-23 23:57:03 +02:00
|
|
|
{
|
|
|
|
fut: F,
|
|
|
|
key: Key,
|
2019-11-18 13:42:27 +01:00
|
|
|
h2: Option<
|
|
|
|
LocalBoxFuture<
|
|
|
|
'static,
|
|
|
|
Result<(SendRequest<Bytes>, Connection<Io, Bytes>), h2::Error>,
|
|
|
|
>,
|
|
|
|
>,
|
2019-04-23 23:57:03 +02:00
|
|
|
rx: Option<oneshot::Sender<Result<IoConnection<Io>, ConnectError>>>,
|
|
|
|
inner: Option<Rc<RefCell<Inner<Io>>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F, Io> OpenWaitingConnection<F, Io>
|
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
F: Future<Output = Result<(Io, Protocol), ConnectError>> + Unpin + 'static,
|
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
2019-04-23 23:57:03 +02:00
|
|
|
{
|
|
|
|
fn spawn(
|
|
|
|
key: Key,
|
|
|
|
rx: oneshot::Sender<Result<IoConnection<Io>, ConnectError>>,
|
|
|
|
inner: Rc<RefCell<Inner<Io>>>,
|
|
|
|
fut: F,
|
|
|
|
) {
|
2019-11-15 10:54:11 +01:00
|
|
|
tokio_executor::current_thread::spawn(OpenWaitingConnection {
|
2019-04-23 23:57:03 +02:00
|
|
|
key,
|
|
|
|
fut,
|
|
|
|
h2: None,
|
|
|
|
rx: Some(rx),
|
|
|
|
inner: Some(inner),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F, Io> Drop for OpenWaitingConnection<F, Io>
|
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
Io: AsyncRead + AsyncWrite + Unpin + 'static,
|
2019-04-23 23:57:03 +02:00
|
|
|
{
|
|
|
|
fn drop(&mut self) {
|
|
|
|
if let Some(inner) = self.inner.take() {
|
|
|
|
let mut inner = inner.as_ref().borrow_mut();
|
|
|
|
inner.release();
|
|
|
|
inner.check_availibility();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F, Io> Future for OpenWaitingConnection<F, Io>
|
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
F: Future<Output = Result<(Io, Protocol), ConnectError>> + Unpin,
|
|
|
|
Io: AsyncRead + AsyncWrite + Unpin,
|
2019-04-23 23:57:03 +02:00
|
|
|
{
|
2019-11-18 13:42:27 +01:00
|
|
|
type Output = ();
|
|
|
|
|
|
|
|
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
|
|
|
let this = self.get_mut();
|
|
|
|
|
|
|
|
if let Some(ref mut h2) = this.h2 {
|
|
|
|
return match Pin::new(h2).poll(cx) {
|
|
|
|
Poll::Ready(Ok((snd, connection))) => {
|
|
|
|
tokio_executor::current_thread::spawn(connection.map(|_| ()));
|
|
|
|
let rx = this.rx.take().unwrap();
|
2019-08-13 14:55:04 +02:00
|
|
|
let _ = rx.send(Ok(IoConnection::new(
|
|
|
|
ConnectionType::H2(snd),
|
|
|
|
Instant::now(),
|
2019-11-18 13:42:27 +01:00
|
|
|
Some(Acquired(this.key.clone(), this.inner.take())),
|
2019-08-13 14:55:04 +02:00
|
|
|
)));
|
2019-11-18 13:42:27 +01:00
|
|
|
Poll::Ready(())
|
2019-08-13 14:55:04 +02:00
|
|
|
}
|
2019-11-18 13:42:27 +01:00
|
|
|
Poll::Pending => Poll::Pending,
|
|
|
|
Poll::Ready(Err(err)) => {
|
|
|
|
let _ = this.inner.take();
|
|
|
|
if let Some(rx) = this.rx.take() {
|
2019-08-13 14:55:04 +02:00
|
|
|
let _ = rx.send(Err(ConnectError::H2(err)));
|
|
|
|
}
|
2019-11-18 13:42:27 +01:00
|
|
|
Poll::Ready(())
|
2019-08-13 14:55:04 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-11-18 13:42:27 +01:00
|
|
|
match Pin::new(&mut this.fut).poll(cx) {
|
|
|
|
Poll::Ready(Err(err)) => {
|
|
|
|
let _ = this.inner.take();
|
|
|
|
if let Some(rx) = this.rx.take() {
|
2019-04-23 23:57:03 +02:00
|
|
|
let _ = rx.send(Err(err));
|
|
|
|
}
|
2019-11-18 13:42:27 +01:00
|
|
|
Poll::Ready(())
|
2019-04-23 23:57:03 +02:00
|
|
|
}
|
2019-11-18 13:42:27 +01:00
|
|
|
Poll::Ready(Ok((io, proto))) => {
|
2019-04-23 23:57:03 +02:00
|
|
|
if proto == Protocol::Http1 {
|
2019-11-18 13:42:27 +01:00
|
|
|
let rx = this.rx.take().unwrap();
|
2019-04-23 23:57:03 +02:00
|
|
|
let _ = rx.send(Ok(IoConnection::new(
|
|
|
|
ConnectionType::H1(io),
|
|
|
|
Instant::now(),
|
2019-11-18 13:42:27 +01:00
|
|
|
Some(Acquired(this.key.clone(), this.inner.take())),
|
2019-04-23 23:57:03 +02:00
|
|
|
)));
|
2019-11-18 13:42:27 +01:00
|
|
|
Poll::Ready(())
|
2019-04-23 23:57:03 +02:00
|
|
|
} else {
|
2019-11-18 13:42:27 +01:00
|
|
|
this.h2 = Some(handshake(io).boxed_local());
|
|
|
|
Pin::new(this).poll(cx)
|
2019-04-23 23:57:03 +02:00
|
|
|
}
|
|
|
|
}
|
2019-11-18 13:42:27 +01:00
|
|
|
Poll::Pending => Poll::Pending,
|
2019-04-23 23:57:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-14 07:53:30 +01:00
|
|
|
pub(crate) struct Acquired<T>(Key, Option<Rc<RefCell<Inner<T>>>>);
|
2018-11-12 08:12:54 +01:00
|
|
|
|
|
|
|
impl<T> Acquired<T>
|
|
|
|
where
|
2019-11-18 13:42:27 +01:00
|
|
|
T: AsyncRead + AsyncWrite + Unpin + 'static,
|
2018-11-12 08:12:54 +01:00
|
|
|
{
|
2018-11-15 20:10:23 +01:00
|
|
|
pub(crate) fn close(&mut self, conn: IoConnection<T>) {
|
2018-11-12 08:12:54 +01:00
|
|
|
if let Some(inner) = self.1.take() {
|
|
|
|
let (io, _) = conn.into_inner();
|
|
|
|
inner.as_ref().borrow_mut().release_close(io);
|
|
|
|
}
|
|
|
|
}
|
2018-11-15 20:10:23 +01:00
|
|
|
pub(crate) fn release(&mut self, conn: IoConnection<T>) {
|
2018-11-12 08:12:54 +01:00
|
|
|
if let Some(inner) = self.1.take() {
|
|
|
|
let (io, created) = conn.into_inner();
|
|
|
|
inner
|
|
|
|
.as_ref()
|
|
|
|
.borrow_mut()
|
|
|
|
.release_conn(&self.0, io, created);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-14 07:53:30 +01:00
|
|
|
impl<T> Drop for Acquired<T> {
|
2018-11-12 08:12:54 +01:00
|
|
|
fn drop(&mut self) {
|
|
|
|
if let Some(inner) = self.1.take() {
|
|
|
|
inner.as_ref().borrow_mut().release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|