dominion_chat/
lib.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5#![warn(rust_2018_idioms, missing_debug_implementations)]
6
7use dominion::{DnsPacket, Name, QType, ServerService};
8use serde::Deserialize;
9use std::{collections::BTreeMap, net::SocketAddr};
10
11mod a;
12mod txt;
13
14#[derive(Debug)]
15pub struct Chat<'a> {
16    domain: Name<'a>,
17    xor: Option<Xor>,
18    files: Option<txt::TxtHandler>,
19}
20
21impl<'a> Chat<'a> {
22    pub fn new(name: Name<'a>, xor: Option<Xor>, files: Option<BTreeMap<String, String>>) -> Self {
23        let files = files.map(|f| txt::TxtHandler::new(f.into_iter()));
24        Chat {
25            domain: name,
26            files,
27            xor,
28        }
29    }
30}
31
32impl ServerService for Chat<'_> {
33    fn run<'a>(&self, client: SocketAddr, question: &'a DnsPacket<'a>) -> Option<DnsPacket<'a>> {
34        if question.header.questions > 0 {
35            match question.questions[0].qtype {
36                QType::A => Some(a::response(client, question, &self.domain, &self.xor)),
37                QType::Txt => {
38                    self.files.as_ref().map(|files| files.response(question, &self.domain, &self.xor))
39                }
40                _ => Some(refused(question.header.id)),
41            }
42        } else {
43            Some(refused(question.header.id))
44        }
45    }
46}
47
48#[derive(Debug, Deserialize)]
49/// Configuration from file
50pub struct Xor {
51    key: u8,
52    signal: String,
53}
54
55fn refused(id: u16) -> DnsPacket<'static> {
56    use dominion::*;
57
58    let flags = Flags {
59        qr: QueryResponse::Response,
60        opcode: OpCode::Query,
61        aa: AuthoritativeAnswer::Authoritative,
62        tc: TrunCation::NotTruncated,
63        rd: RecursionDesired::NotDesired,
64        ra: RecursionAvailable::NotAvailable,
65        z: Zero::Zero,
66        ad: AuthenticData::NotAuthentic,
67        cd: CheckingDisabled::Disabled,
68        rcode: ResponseCode::Refused,
69    };
70
71    let header = DnsHeader {
72        id,
73        flags,
74        questions: 0,
75        answers: 0,
76        authority: 0,
77        additional: 0,
78    };
79    DnsPacket {
80        header,
81        questions: vec![],
82        answers: vec![],
83        authority: vec![],
84        additional: vec![],
85    }
86}