#![forbid(unsafe_code)]
use luct_core::{
CtLog, CtLogConfig, SignatureValidationError,
tiling::{ParseCheckpointError, TilingError},
tree::ProofValidationError,
};
use std::{error::Error, fmt::Debug, sync::Arc};
use thiserror::Error;
use url::Url;
pub use impls::*;
mod impls;
mod request;
mod util;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CtClient<C> {
log: CtLog,
client: C,
}
impl<C> CtClient<C> {
pub fn new(config: CtLogConfig, client: C) -> Self {
Self {
log: CtLog::new(config),
client,
}
}
pub fn log(&self) -> &CtLog {
&self.log
}
}
pub trait Client: Debug {
fn get(
&self,
url: &Url,
params: &[(&str, &str)],
) -> impl Future<Output = Result<(u16, Arc<String>), ClientError>>;
fn get_bin(
&self,
url: &Url,
params: &[(&str, &str)],
) -> impl Future<Output = Result<(u16, Arc<Vec<u8>>), ClientError>>;
}
#[derive(Debug, Clone, Error)]
pub enum ClientError {
#[error("The version of the log is not supported by this client")]
UnsupportedVersion,
#[error("Failed to parse JSON: line: {line}, column: {column}")]
JsonError { line: usize, column: usize },
#[error("Signature validation of {0} against the logs key failed: {1}")]
SignatureValidationFailed(&'static str, SignatureValidationError),
#[error("Failed to validate a consistency path: {0}")]
ConsistencyProofError(ProofValidationError),
#[error("Failed to validate an audit path: {0}")]
AuditProofError(ProofValidationError),
#[error("Failed to connect to host: {0}")]
ConnectionError(String),
#[error("Failed to connect to host: {0}")]
ConnectionErrorStd(Arc<dyn Error + Send + Sync>),
#[error("Request to {url} returned error: {code}: {msg}")]
ResponseError { url: String, code: u16, msg: String },
#[error("Failed parsing checkpoint: {0}")]
Checkpoint(#[from] ParseCheckpointError),
#[error("Tiling error: {0}")]
TilingError(#[from] TilingError),
#[error("The STH could not be parsed")]
SthError,
}
impl From<serde_json::Error> for ClientError {
fn from(value: serde_json::Error) -> Self {
ClientError::JsonError {
line: value.line(),
column: value.column(),
}
}
}