1use std::sync::Arc;
2
3use tokio::time::{Duration, MissedTickBehavior};
4
5use tc_error::*;
6use tc_transact::TxnId;
7use tc_value::Host;
8use tcgeneric::{NetworkTime, PathSegment};
9
10use crate::kernel::Kernel;
11use crate::txn::{Txn, TxnServer};
12use crate::Endpoint;
13
14const GC_INTERVAL: Duration = Duration::from_millis(100);
15
16pub struct Server {
17 kernel: Arc<Kernel>,
18 txn_server: TxnServer,
19}
20
21impl Server {
22 pub(crate) fn new(kernel: Arc<Kernel>, txn_server: TxnServer) -> mdns_sd::Result<Self> {
23 spawn_cleanup_thread(kernel.clone(), txn_server.clone());
24
25 Ok(Self { kernel, txn_server })
26 }
27
28 pub(crate) fn kernel(&self) -> Arc<Kernel> {
29 self.kernel.clone()
30 }
31
32 pub(crate) fn txn_server(&self) -> TxnServer {
33 self.txn_server.clone()
34 }
35
36 pub fn address(&self) -> &Host {
37 self.txn_server.address()
38 }
39
40 pub fn create_txn(&self) -> TCResult<Txn> {
41 self.txn_server.create_txn(NetworkTime::now())
42 }
43
44 pub async fn verify_txn(&self, txn_id: TxnId, token: String) -> TCResult<Txn> {
45 self.txn_server
46 .verify_txn(txn_id, NetworkTime::now(), token)
47 .await
48 }
49
50 pub async fn get_txn(&self, txn_id: TxnId, token: Option<String>) -> TCResult<Txn> {
51 if let Some(token) = token {
52 let now = NetworkTime::now();
53 self.txn_server.verify_txn(txn_id, now, token).await
54 } else {
55 self.txn_server.get_txn(txn_id)
56 }
57 }
58}
59
60impl Server {
61 pub async fn authorize_claim_and_route<'a>(
62 &'a self,
63 path: &'a [PathSegment],
64 txn: &'a Txn,
65 ) -> TCResult<Endpoint<'a>> {
66 self.kernel.route(path, txn).await
67 }
68}
69
70fn spawn_cleanup_thread(kernel: Arc<Kernel>, txn_server: TxnServer) {
71 let mut interval = tokio::time::interval(GC_INTERVAL);
72 interval.set_missed_tick_behavior(MissedTickBehavior::Skip);
73
74 tokio::spawn(async move {
75 loop {
76 interval.tick().await;
77 txn_server.finalize(&kernel, NetworkTime::now()).await;
78 }
79 });
80}