Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion sep2_client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use tokio::sync::Mutex;

use crate::{
time::{current_time_with_offset, SEPTime},
tls::{create_client, create_client_tls_cfg, create_http_client, ClientInner},
tls::{create_client, create_client_tls_cfg, create_http_client, ClientInner, HttpRequester},
};

#[cfg(feature = "event")]
Expand Down Expand Up @@ -294,6 +294,26 @@ impl Client {
Ok(out)
}

/// Construct an IEEE 2030.5 Client instance that uses a custom [`HttpRequester`] implementation.
///
/// This is useful for testing or mocking HTTP interactions.
pub fn new_custom(
server_addr: &str,
requester: impl HttpRequester + 'static,
tickrate: Option<Duration>,
) -> Self {
let out = Client {
addr: server_addr.to_owned().into(),
inner: ClientInner::Custom(Arc::new(requester)),
polls: Arc::new(Mutex::new(BinaryHeap::new())),
};
tokio::spawn(
out.clone()
.poll_task(tickrate.unwrap_or(Self::DEFAULT_TICKRATE)),
);
out
}

async fn poll_task(self, tickrate: Duration) {
loop {
tokio::time::sleep(tickrate).await;
Expand Down
31 changes: 26 additions & 5 deletions sep2_client/src/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
//! Provides an interface for parsing & verifying 2030.5 certificates, as per IEEE 2030.5 section 6.11
//!

use std::future::Future;
use std::path::Path;
use std::pin::Pin;
use std::sync::Arc;
use std::time::Duration;

use anyhow::{bail, Result};
use hyper::client::{HttpConnector, ResponseFuture};
use hyper::client::HttpConnector;
use hyper::{Body, Client, Request};
use hyper_openssl::HttpsConnector;
use openssl::ssl::{SslConnector, SslConnectorBuilder, SslFiletype, SslMethod, SslVerifyMode};
Expand All @@ -21,17 +24,35 @@ pub(crate) type HTTPSClient = Client<HTTPSConnector, Body>;
pub(crate) type HTTPClient = Client<HttpConnector, Body>;
pub(crate) type TlsClientConfig = SslConnectorBuilder;

#[derive(Clone, Debug)]
/// A trait for custom HTTP request handling, useful for mocking.
pub trait HttpRequester: Send + Sync {
fn request(
&self,
req: Request<Body>,
) -> Pin<
Box<
dyn Future<Output = std::result::Result<hyper::Response<Body>, hyper::Error>> + Send,
>,
>;
}

#[derive(Clone)]
pub(crate) enum ClientInner {
Https(HTTPSClient),
Http(HTTPClient),
Custom(Arc<dyn HttpRequester>),
}

impl ClientInner {
pub(crate) fn request(&self, req: Request<Body>) -> ResponseFuture {
pub(crate) fn request(
&self,
req: Request<Body>,
) -> Pin<Box<dyn Future<Output = std::result::Result<hyper::Response<Body>, hyper::Error>> + Send>>
{
match self {
ClientInner::Https(c) => c.request(req),
ClientInner::Http(c) => c.request(req),
ClientInner::Https(c) => Box::pin(c.request(req)),
ClientInner::Http(c) => Box::pin(c.request(req)),
ClientInner::Custom(c) => c.request(req),
}
}
}
Expand Down