pharos_plugins/
minimal.rs1use pharos_proto::{Message, NameRef, NameWirePart, ResponseType, typify_response};
4use pharos_server::{Context, Next, Outcome, Plugin};
5use std::time::{SystemTime, UNIX_EPOCH};
6
7#[derive(Debug)]
8pub struct Minimal;
9
10fn references_counts(name: NameRef<'_>) -> bool {
11 name.wire_parts().any(|part| match part {
12 NameWirePart::Label { offset, len } => offset < 12 && offset + len > 8,
13 NameWirePart::Root { offset } | NameWirePart::Pointer { offset, .. } => {
14 (8..12).contains(&offset)
15 }
16 })
17}
18
19impl Plugin for Minimal {
20 async fn serve<N: Next + Send>(&self, cx: &mut Context<'_>, next: N) -> Outcome {
21 let outcome = next.run(cx).await;
22 if outcome != Outcome::Response {
23 return outcome;
24 }
25 let Ok(message) = Message::parse(cx.response) else {
26 return outcome;
27 };
28 let now = SystemTime::now()
29 .duration_since(UNIX_EPOCH)
30 .map_or(0, |time| time.as_secs() as i64);
31 if typify_response(Some(&message), now) != ResponseType::Positive {
32 return outcome;
33 }
34 if message
37 .questions()
38 .any(|question| references_counts(question.name))
39 || message.answers().any(|record| {
40 references_counts(record.name)
41 || record.compressible_names().map_or(true, |names| {
42 names.into_iter().flatten().any(references_counts)
43 })
44 })
45 {
46 return outcome;
47 }
48 let end = message
50 .authorities()
51 .next()
52 .or_else(|| message.additionals().next())
53 .map_or(cx.response.len(), |record| record.name.offset());
54 cx.response.truncate(end);
55 cx.response[8..12].fill(0);
56 outcome
57 }
58}