use crate::{
cert::{Certificate, Identity},
dns::DnsResolver,
response::DeboaResponse,
Result,
};
use http::{Request, Version};
use hyper_body_utils::HttpBody;
use std::time::Duration;
use std::{future::Future, net::IpAddr};
pub struct ConnectionConfigBuilder<'a, I, C> {
scheme: &'a str,
host: &'a str,
port: u16,
protocol_version: Version,
connection_timeout: Duration,
identity: Option<&'a I>,
certificate: Option<&'a C>,
skip_cert_verification: bool,
client_bind_addr: IpAddr,
}
impl<'a, I, C> ConnectionConfigBuilder<'a, I, C>
where
I: Identity,
C: Certificate,
{
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self {
scheme: "http",
host: "",
port: 80,
protocol_version: Version::HTTP_2,
connection_timeout: Duration::from_secs(30),
identity: None,
certificate: None,
skip_cert_verification: false,
client_bind_addr: "0.0.0.0"
.parse()
.unwrap(),
}
}
pub fn scheme(mut self, scheme: &'a str) -> Self {
self.scheme = scheme;
self
}
pub fn host(mut self, host: &'a str) -> Self {
self.host = host;
self
}
pub fn port(mut self, port: u16) -> Self {
self.port = port;
self
}
pub fn protocol_version(mut self, protocol_version: Version) -> Self {
self.protocol_version = protocol_version;
self
}
pub fn connection_timeout(mut self, connection_timeout: Duration) -> Self {
self.connection_timeout = connection_timeout;
self
}
pub fn identity(mut self, identity: Option<&'a I>) -> Self {
self.identity = identity;
self
}
pub fn certificate(mut self, certificate: Option<&'a C>) -> Self {
self.certificate = certificate;
self
}
pub fn skip_cert_verification(mut self, skip_cert_verification: bool) -> Self {
self.skip_cert_verification = skip_cert_verification;
self
}
pub fn client_bind_addr(mut self, client_bind_addr: IpAddr) -> Self {
self.client_bind_addr = client_bind_addr;
self
}
pub fn build(self) -> ConnectionConfig<'a, I, C> {
ConnectionConfig {
scheme: self.scheme,
host: self.host,
port: self.port,
protocol_version: self.protocol_version,
connection_timeout: self.connection_timeout,
identity: self.identity,
certificate: self.certificate,
skip_cert_verification: self.skip_cert_verification,
client_bind_addr: self.client_bind_addr,
}
}
}
pub struct ConnectionConfig<'a, I, C> {
scheme: &'a str,
host: &'a str,
port: u16,
protocol_version: Version,
connection_timeout: Duration,
identity: Option<&'a I>,
certificate: Option<&'a C>,
skip_cert_verification: bool,
client_bind_addr: IpAddr,
}
impl<'a, I, C> ConnectionConfig<'a, I, C>
where
I: Identity,
C: Certificate,
{
pub fn builder() -> ConnectionConfigBuilder<'a, I, C> {
ConnectionConfigBuilder::new()
}
pub fn scheme(&self) -> &str {
self.scheme
}
pub fn host(&self) -> &str {
self.host
}
pub fn port(&self) -> u16 {
self.port
}
pub fn protocol_version(&self) -> &Version {
&self.protocol_version
}
pub fn connection_timeout(&self) -> Duration {
self.connection_timeout
}
pub fn identity(&self) -> Option<&I> {
self.identity
}
pub fn certificate(&self) -> Option<&C> {
self.certificate
}
pub fn skip_cert_verification(&self) -> bool {
self.skip_cert_verification
}
pub fn client_bind_addr(&self) -> &IpAddr {
&self.client_bind_addr
}
}
pub trait HttpConnection {
type Sender;
fn sender(&mut self) -> &mut Self::Sender;
}
pub trait HttpConnectionPool {
type Identity: crate::cert::Identity;
type Certificate: crate::cert::Certificate;
type ConnectionDispather: HttpConnectionDispatcher;
type ConnectionCache;
fn new(max_idle_connections: u32, keep_alive_duration: Duration) -> Self;
fn connections(&self) -> &Self::ConnectionCache;
fn connection_count(&self) -> u32;
fn create_connection<D>(
&mut self,
config: &ConnectionConfig<Self::Identity, Self::Certificate>,
dns_resolver: &D,
) -> impl Future<Output = Result<&mut Self::ConnectionDispather>>
where
D: DnsResolver;
}
pub trait HttpConnectionDispatcher {
fn send_request(
&mut self,
request: Request<HttpBody>,
timeout: Duration,
) -> impl Future<Output = Result<DeboaResponse>>;
}
pub trait ProtoConnection {
type Connection: HttpConnection;
type RuntimeStream;
fn connect(stream: Self::RuntimeStream) -> impl Future<Output = Result<Self::Connection>>;
fn protocol_version(&self) -> Version;
}