use std::{future::Future, pin::Pin, task::{self, Poll}}; use http::Uri; use hyper_util::{client::legacy::Client, rt::{TokioExecutor, TokioIo}}; use rustls::RootCertStore; use tower_service::Service; use sparse_actions::payload_types::Parameters; use crate::{adapter, error, tcp::{self, setup_network}}; #[derive(Clone)] pub struct ServerConnector where T: adapter::BeaconAdapter + Clone + Send + 'static { adapter: T, parameters: Parameters } impl Service for ServerConnector where T: adapter::BeaconAdapter + Clone + Send + Sync + 'static { type Response = TokioIo; type Error = error::BeaconError; type Future = Pin> + Send >>; fn poll_ready(&mut self, _: &mut task::Context<'_>) -> Poll> { Poll::Ready(Ok(())) } fn call(&mut self, _: Uri) -> Self::Future { Box::pin({ let adapter = self.adapter.clone(); let params = self.parameters.clone(); async move { setup_network(adapter, params) .await .map(TokioIo::new) } }) } } pub async fn obtain_https_client( adapter: &T, parameters: &Parameters, ) -> Result>, B>, error::BeaconError> where T: adapter::BeaconAdapter + Clone + Send + Sync + 'static, B: hyper::body::Body + Send, ::Data: Send { let server_cert = rustls::pki_types::CertificateDer::from( parameters.pubkey_cert[..parameters.pubkey_cert_size as usize].to_owned() ); let client_cert = rustls::pki_types::CertificateDer::from( parameters.client_cert[..parameters.client_cert_length as usize].to_owned() ); let client_key = rustls::pki_types::PrivateKeyDer::try_from( parameters.client_key[..parameters.client_key_length as usize].to_owned() ) .map_err(|_| rustls::Error::InvalidCertificate( rustls::CertificateError::BadEncoding ))?; let mut root_store = RootCertStore::empty(); root_store.add(server_cert.clone())?; let tls_config = rustls::ClientConfig::builder() .with_root_certificates(root_store) .with_client_auth_cert( vec![client_cert, server_cert], client_key )?; let https = hyper_rustls::HttpsConnectorBuilder::new() .with_tls_config(tls_config) .https_only() .enable_http1() .enable_http2() .wrap_connector(ServerConnector { adapter: adapter.clone(), parameters: parameters.clone() }); let client = Client::builder(TokioExecutor::new()) .build(https); Ok(client) }