1#![forbid(unsafe_code)]
4
5use crate::log::{ScannerLog, builder::LogImpls};
6use chrono::{DateTime, Utc};
7use futures::future::try_join_all;
8use luct_client::Client;
9use luct_core::{CtLog, Fingerprint, LogId, store::SearchableStore, v1::SignedTreeHead};
10use std::collections::BTreeMap;
11pub use {
12 config::{ScannerConfig, ScannerConfigBuilder},
13 error::ScannerError,
14 report::{Report, SctReport, SthReport},
15 utils::Validated,
16};
17
18type HashOutput = [u8; 32];
19
20mod config;
21mod error;
22mod log;
23mod report;
24mod sth;
25mod utils;
26
27pub trait ScannerImpl {
31 type Client: Client + Clone;
33 type ReportStore: SearchableStore<Key = Fingerprint, Value = Report>;
35 type SthStore: SearchableStore<Key = u64, Value = Validated<SignedTreeHead>>;
37}
38
39pub struct Scanner<S: ScannerImpl> {
44 config: ScannerConfig,
45 logs: BTreeMap<LogId, ScannerLog<S>>,
46 report_store: S::ReportStore,
47 client: S::Client,
48 time_source: Box<dyn Fn() -> DateTime<Utc>>,
49}
50
51#[allow(clippy::type_complexity)]
52impl<S: ScannerImpl> Scanner<S> {
53 pub fn logs<'a>(&'a self) -> Box<dyn Iterator<Item = &'a CtLog> + 'a> {
54 Box::new(self.logs.values().map(|val| val.client().log()))
55 }
56
57 pub fn new<F: Fn() -> DateTime<Utc> + 'static>(
58 config: ScannerConfig,
59 report_store: S::ReportStore,
60 client: S::Client,
61 time_source: F,
62 ) -> Self {
63 Self {
64 config,
65 logs: BTreeMap::new(),
66 report_store,
67 client,
68 time_source: Box::new(time_source) as _,
69 }
70 }
71
72 pub fn add_log(&mut self, log: &CtLog, sth_store: S::SthStore) -> &mut Self {
73 let impls = LogImpls {
74 client: self.client.clone(),
75 sth_store,
76 };
77 let scanner_log = ScannerLog::new(log, impls);
78 let log_id = scanner_log.client().log().log_id().clone();
79
80 self.logs.insert(log_id, scanner_log);
81 self
82 }
83
84 pub async fn refresh_all_logs(&self) -> Result<(), ScannerError> {
86 let updates = self
87 .logs
88 .values()
89 .map(|log| log.update_sth())
90 .collect::<Vec<_>>();
91
92 try_join_all(updates).await?;
93
94 Ok(())
95 }
96}