Skip to main content

sidedns_core/
state.rs

1use std::collections::HashSet;
2use std::sync::Arc;
3
4use crate::{DnsRule, RuleStore};
5use serde::{Deserialize, Serialize};
6use tokio::sync::broadcast;
7use tokio_util::sync::CancellationToken;
8
9use crate::ipc::DnsEvent;
10
11/// The daemon's central state.
12#[derive(Debug)]
13pub struct AppState {
14    pub store: RuleStore,
15    pub events: broadcast::Sender<DnsEvent>,
16    pub token: CancellationToken,
17}
18
19pub type SharedState = Arc<AppState>;
20
21#[derive(Serialize, Deserialize, Default)]
22pub struct DnsConfig {
23    pub rules: Vec<DnsRule>,
24}
25
26impl AppState {
27    pub(crate) fn new(token: CancellationToken) -> Self {
28        let (events, _) = broadcast::channel(64);
29        Self {
30            store: RuleStore::new(),
31            events,
32            token,
33        }
34    }
35}
36
37impl AppState {
38    pub fn dispatch(&self, event: DnsEvent) -> bool {
39        self.events.send(event).is_ok()
40    }
41
42    pub fn snapshot_permanent(&self) -> Vec<DnsRule> {
43        self.store.snapshot_persistent()
44    }
45
46    pub fn snapshot_all_domains(&self) -> Vec<String> {
47        self.store
48            .snapshot_all()
49            .into_iter()
50            .map(|r| r.domain)
51            .collect::<HashSet<_>>()
52            .into_iter()
53            .collect()
54    }
55
56    pub fn save(&self) {
57        let config = DnsConfig {
58            rules: self.snapshot_permanent(),
59        };
60        if let Err(e) = confy::store("sidedns", "rules", &config) {
61            tracing::warn!("Failed to save rules: {e}");
62        } else {
63            tracing::info!("Rules saved");
64        }
65    }
66
67    pub fn load_rules(&self) -> Vec<DnsRule> {
68        let rules = match confy::load::<DnsConfig>("sidedns", "rules") {
69            Ok(c) => c.rules,
70            Err(e) => {
71                tracing::warn!("Failed to load saved rules: {e}");
72                vec![]
73            },
74        };
75        let size = self.store.add_all(rules.clone());
76        tracing::info!("Loaded {} saved rule(s)", size);
77        rules
78    }
79}