2019-10-22 12:44:08 -07:00
|
|
|
use std::{
|
2019-12-13 14:25:14 -08:00
|
|
|
future::Future,
|
2019-10-22 12:44:08 -07:00
|
|
|
net::SocketAddr,
|
|
|
|
pin::Pin,
|
|
|
|
task::{Context, Poll},
|
|
|
|
};
|
|
|
|
|
2019-12-13 14:25:14 -08:00
|
|
|
use futures::prelude::*;
|
|
|
|
use tokio::net::TcpStream;
|
2019-10-22 12:44:08 -07:00
|
|
|
use tower::{discover::Change, Service, ServiceExt};
|
2021-05-17 13:49:16 -07:00
|
|
|
use tracing_futures::Instrument;
|
2019-10-22 12:44:08 -07:00
|
|
|
|
2021-08-26 18:34:33 -07:00
|
|
|
use zebra_chain::chain_tip::{ChainTip, NoChainTip};
|
|
|
|
|
2021-10-21 14:36:42 -07:00
|
|
|
use crate::{
|
|
|
|
peer::{Client, ConnectedAddr, Handshake, HandshakeRequest},
|
|
|
|
peer_set::ConnectionTracker,
|
|
|
|
BoxError, Request, Response,
|
|
|
|
};
|
2019-10-22 12:44:08 -07:00
|
|
|
|
2019-11-27 11:42:59 -08:00
|
|
|
/// A wrapper around [`peer::Handshake`] that opens a TCP connection before
|
2019-10-22 12:44:08 -07:00
|
|
|
/// forwarding to the inner handshake service. Writing this as its own
|
|
|
|
/// [`tower::Service`] lets us apply unified timeout policies, etc.
|
2021-08-26 18:34:33 -07:00
|
|
|
pub struct Connector<S, C = NoChainTip> {
|
|
|
|
handshaker: Handshake<S, C>,
|
2019-10-22 12:44:08 -07:00
|
|
|
}
|
|
|
|
|
2021-08-26 18:34:33 -07:00
|
|
|
impl<S: Clone, C: Clone> Clone for Connector<S, C> {
|
2019-10-22 12:44:08 -07:00
|
|
|
fn clone(&self) -> Self {
|
2019-11-27 11:43:59 -08:00
|
|
|
Connector {
|
2019-10-22 12:44:08 -07:00
|
|
|
handshaker: self.handshaker.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-26 18:34:33 -07:00
|
|
|
impl<S, C> Connector<S, C> {
|
|
|
|
pub fn new(handshaker: Handshake<S, C>) -> Self {
|
2019-11-27 11:43:59 -08:00
|
|
|
Connector { handshaker }
|
2019-10-22 12:44:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-21 14:36:42 -07:00
|
|
|
/// A connector request.
|
|
|
|
/// Contains the information needed to make an outbound connection to the peer.
|
|
|
|
pub struct OutboundConnectorRequest {
|
|
|
|
/// The Zcash listener address of the peer.
|
|
|
|
pub addr: SocketAddr,
|
|
|
|
|
|
|
|
/// A connection tracker that reduces the open connection count when dropped.
|
|
|
|
///
|
|
|
|
/// Used to limit the number of open connections in Zebra.
|
|
|
|
pub connection_tracker: ConnectionTracker,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S, C> Service<OutboundConnectorRequest> for Connector<S, C>
|
2019-10-22 12:44:08 -07:00
|
|
|
where
|
2020-09-18 11:20:55 -07:00
|
|
|
S: Service<Request, Response = Response, Error = BoxError> + Clone + Send + 'static,
|
2019-10-22 12:44:08 -07:00
|
|
|
S::Future: Send,
|
2021-08-26 18:34:33 -07:00
|
|
|
C: ChainTip + Clone + Send + 'static,
|
2019-10-22 12:44:08 -07:00
|
|
|
{
|
2019-11-27 11:27:17 -08:00
|
|
|
type Response = Change<SocketAddr, Client>;
|
2020-09-18 11:20:55 -07:00
|
|
|
type Error = BoxError;
|
2019-10-22 12:44:08 -07:00
|
|
|
type Future =
|
|
|
|
Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>;
|
|
|
|
|
|
|
|
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
|
|
Poll::Ready(Ok(()))
|
|
|
|
}
|
|
|
|
|
2021-10-21 14:36:42 -07:00
|
|
|
fn call(&mut self, req: OutboundConnectorRequest) -> Self::Future {
|
|
|
|
let OutboundConnectorRequest {
|
|
|
|
addr,
|
|
|
|
connection_tracker,
|
|
|
|
}: OutboundConnectorRequest = req;
|
|
|
|
|
2019-10-22 12:44:08 -07:00
|
|
|
let mut hs = self.handshaker.clone();
|
2021-05-17 13:49:16 -07:00
|
|
|
let connected_addr = ConnectedAddr::new_outbound_direct(addr);
|
|
|
|
let connector_span = info_span!("connector", peer = ?connected_addr);
|
2021-10-21 14:36:42 -07:00
|
|
|
|
2019-10-22 12:44:08 -07:00
|
|
|
async move {
|
|
|
|
let stream = TcpStream::connect(addr).await?;
|
2020-05-26 18:00:58 -07:00
|
|
|
hs.ready_and().await?;
|
2021-10-21 14:36:42 -07:00
|
|
|
let client = hs
|
|
|
|
.call(HandshakeRequest {
|
|
|
|
tcp_stream: stream,
|
|
|
|
connected_addr,
|
|
|
|
connection_tracker,
|
|
|
|
})
|
|
|
|
.await?;
|
2019-10-22 12:44:08 -07:00
|
|
|
Ok(Change::Insert(addr, client))
|
|
|
|
}
|
2021-05-17 13:49:16 -07:00
|
|
|
.instrument(connector_span)
|
2019-11-26 22:42:42 -08:00
|
|
|
.boxed()
|
2019-10-22 12:44:08 -07:00
|
|
|
}
|
|
|
|
}
|