Repo of no-std crates for my personal embedded projects
at main 3.2 kB view raw
1use alloc::vec::Vec; 2use sachy_fmt::{error, info}; 3 4use crate::{ 5 dns::{ 6 flags::Flags, 7 query::{QClass, Query}, 8 records::QType, 9 reqres::{Request, Response}, 10 traits::DnsParse, 11 }, 12 encoder::Encoder, 13 service::Service, 14}; 15 16pub(crate) enum ResponseKind { 17 Announcement, 18 QueryResponse(Vec<(QType, QClass)>), 19} 20 21#[derive(Debug)] 22#[cfg_attr(feature = "defmt", derive(defmt::Format))] 23pub(crate) struct Server { 24 service: Service, 25} 26 27impl Server { 28 pub(crate) fn new(service: Service) -> Self { 29 Self { service } 30 } 31 32 pub(crate) fn broadcast<'a, 'b>( 33 &self, 34 response_kind: ResponseKind, 35 flags: Flags, 36 id: u16, 37 queries: Vec<Query<'b>>, 38 outgoing: &'a mut [u8], 39 ) -> Option<&'a [u8]> { 40 let answers: Vec<_> = match response_kind { 41 ResponseKind::Announcement => self.service.as_answers(QClass::Multicast).collect(), 42 ResponseKind::QueryResponse(valid) => valid 43 .iter() 44 .flat_map(|&(qtype, qclass)| match qtype { 45 QType::A | QType::AAAA => self.service.ip_answer(qclass), 46 QType::PTR => self.service.ptr_answer(qclass), 47 QType::TXT => self.service.txt_answer(qclass), 48 QType::SRV => self.service.srv_answer(qclass), 49 QType::Any | QType::Unknown(_) => None, 50 }) 51 .collect(), 52 }; 53 54 if !answers.is_empty() { 55 let res = Response { 56 flags, 57 id, 58 queries, 59 answers, 60 }; 61 62 info!("MDNS RESPONSE: {}", res); 63 64 return Encoder::new(outgoing) 65 .encode(res) 66 .inspect_err(|err| error!("Encoder errored: {}", err)) 67 .ok(); 68 } 69 70 None 71 } 72 73 pub(crate) fn respond<'a>(&self, incoming: &[u8], outgoing: &'a mut [u8]) -> Option<&'a [u8]> { 74 Request::parse(&mut &incoming[..], incoming) 75 .ok() 76 .and_then(|req| { 77 let valid_queries = 78 req.queries 79 .iter() 80 .filter_map(|q| match q.qtype { 81 QType::A | QType::AAAA | QType::TXT | QType::SRV => { 82 (q.name == self.service.hostname()).then_some((q.qtype, q.qclass)) 83 } 84 QType::PTR => (q.name == self.service.service_type()) 85 .then_some((q.qtype, q.qclass)), 86 QType::Any | QType::Unknown(_) => None, 87 }) 88 .collect::<Vec<_>>(); 89 90 if !valid_queries.is_empty() { 91 self.broadcast( 92 ResponseKind::QueryResponse(valid_queries), 93 req.flags, 94 req.id, 95 req.queries, 96 outgoing, 97 ) 98 } else { 99 None 100 } 101 }) 102 } 103}