commit c03e1814d55e85e21010928d397d7e2517068091
parent 9dc22f2a86a8d58b2f5db1607932b92e519c8d87
Author: Daniel Barlow <dan@telent.net>
Date: Mon, 29 Dec 2025 12:27:53 +0000
move all mdns stuff to MdnsResponder
Diffstat:
| M | ecu-esp32/src/wifi.rs | | | 252 | +++++++++++++++++++++++++++++++++++-------------------------------------------- |
1 file changed, 112 insertions(+), 140 deletions(-)
diff --git a/ecu-esp32/src/wifi.rs b/ecu-esp32/src/wifi.rs
@@ -44,7 +44,6 @@ const DISCOVERY_NAME : &str = "_services._dns-sd._udp.local";
use dns_protocol::{Message, Question,
MessageType,
- Label,
ResourceRecord, ResourceType, Flags};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
@@ -101,15 +100,123 @@ impl<'a> MdnsResponder<'a> {
async fn advertise(&self) {
let db = &self.database;
- send_response(&self.sock, 0, MDNS_ENDPOINT, db, None, db.advertised()).await;
+ self.send_response(0, MDNS_ENDPOINT, None, db.advertised()).await;
}
fn may_recv(&self) -> bool {
self.sock.may_recv()
}
- fn sock(&self) -> &UdpSocket<'a> {
- &self.sock
+ async fn send_response(&self,
+ id: u16,
+ endpoint: IpEndpoint,
+ question: Option<&Question<'_>>,
+ answers: Vec<&DnsResource>) {
+
+ let questions = match question {
+ Some(q) =>&mut [*q][..],
+ None => &mut [][..]
+ };
+
+ let db = &self.database;
+ let mut flags = Flags::new();
+
+
+ flags.set_qr(MessageType::Reply);
+ flags.set_authoritative(true);
+
+ let mut additional : BTreeSet<ResourceRecord> = BTreeSet::new();
+ let mut answers : Vec<ResourceRecord> = {
+ let mut rrs = Vec::new();
+ for a in answers {
+ rrs.push(a.to_resource_record());
+ for r in db.all_additional(a).into_iter() {
+ additional.insert(r.to_resource_record());
+ };
+ }
+ rrs
+ };
+
+ // don't send anything in "additional" that's already in the answers
+ for rr in &answers {
+ additional.remove(&rr);
+ }
+
+ let mut additional : Vec<ResourceRecord> = additional.into_iter().collect();
+ let message = Message::new(
+ id,
+ flags,
+ questions,
+ &mut answers,
+ &mut [],
+ &mut additional);
+
+ let mut data_buf = [0; 4096];
+ // Serialize the message into the buffer
+ assert!(message.space_needed() <= data_buf.len());
+
+ info!("ready to send to {:?}", endpoint);
+
+ match message.write(&mut data_buf) {
+ Result::Ok(len) => {
+ if let Result::Err(x) = self.sock.send_to(&data_buf[..len], endpoint).await {
+ info!("sock.send failed: {:?}", x);
+ }
+ },
+ Result::Err(err) => {
+ error!("message.write {:?}", err);
+ }
+ }
+ }
+
+ async fn send_responses(&self,
+ message: &Message<'_,'_>,
+ meta: &UdpMetadata) {
+
+ let q_id = message.id();
+
+ for q in message.questions() {
+ let relevant = self.database.find(q.name().to_string(), q.ty());
+ if relevant.len() > 0 {
+ log::info!("question {:?} {:?} {:?} flags {:?} from {:?}",
+ q.name(), q.ty(), q.class(),
+ message.flags().raw(),
+ meta.endpoint);
+
+ self.send_response(q_id, MDNS_ENDPOINT, None, relevant).await
+ }
+ }
+ }
+
+ async fn process_packet(&self) {
+ let mut questions = [Question::default(); 64];
+ let mut answers = [ResourceRecord::default(); 64];
+ let mut authorities = [ResourceRecord::default(); 64];
+ let mut addl = [ResourceRecord::default(); 64];
+
+ let mut data_buf = [0; 4096];
+
+ let res = self.sock.recv_from(&mut data_buf).await;
+ if let Ok((n, meta)) = res {
+ let message = Message::read(
+ &data_buf[..n],
+ &mut questions,
+ &mut answers,
+ &mut authorities,
+ &mut addl,
+ );
+
+ match message {
+ Result::Ok(message) => {
+ self.send_responses(&message, &meta).await;
+ },
+ Result::Err(err) => {
+ log::error!("parsing dns message from {:?} : {:?}",
+ meta.endpoint,
+ err);
+ }
+ }
+ }
}
}
@@ -289,110 +396,6 @@ impl DnsDatabase {
}
}
-// RFC: "Multicast DNS responses MUST NOT contain any questions in the
-// Question Section. ". However, responses to "legacy" queries (port != 5353)
-// should have a question section just like traditional DNS
-
-async fn send_response(sock: &UdpSocket<'_>,
- id: u16,
- endpoint: IpEndpoint,
- db: &DnsDatabase,
- question: Option<&Question<'_>>,
- answers: Vec<&DnsResource>) {
-
- let questions = match question {
- Some(q) =>&mut [*q][..],
- None => &mut [][..]
- };
-
-
-
- let mut flags = Flags::new();
-
- flags.set_qr(MessageType::Reply);
- flags.set_authoritative(true);
-
- let mut additional : BTreeSet<ResourceRecord> = BTreeSet::new();
- let mut answers : Vec<ResourceRecord> = {
- let mut rrs = Vec::new();
- for a in answers {
- rrs.push(a.to_resource_record());
- for r in db.all_additional(a).into_iter() {
- additional.insert(r.to_resource_record());
- };
- }
- rrs
- };
-
- // don't send anything in "additional" that's already in the answers
- for rr in &answers {
- additional.remove(&rr);
- }
-
- let mut additional : Vec<ResourceRecord> = additional.into_iter().collect();
- let message = Message::new(
- id,
- flags,
- questions,
- &mut answers,
- &mut [],
- &mut additional);
-
- let mut data_buf = [0; 4096];
- // Serialize the message into the buffer
- assert!(message.space_needed() <= data_buf.len());
-
- info!("ready to send to {:?}", endpoint);
-
- match message.write(&mut data_buf) {
- Result::Ok(len) => {
- if let Result::Err(x) = sock.send_to(&data_buf[..len], endpoint).await {
- info!("sock.send failed: {:?}", x);
- }
- },
- Result::Err(err) => {
- error!("message.write {:?}", err);
- }
- }
-}
-
-async fn send_responses(sock: &UdpSocket<'_>,
- db: &DnsDatabase,
- message: &Message<'_,'_>,
- meta: &UdpMetadata) {
-
- let q_id = message.id();
-
- // for each relevant question we want to add RRs (as answers
- // or additional) to the reply packet. I'm uncertain whether
- // it's ok to do this for legacy queries but they probably
- // don't have multiple questions anyway
- for q in message.questions() {
- let relevant = db.find(q.name().to_string(), q.ty());
- if relevant.len() > 0 {
- log::info!("question {:?} {:?} {:?} flags {:?} from {:?}",
- q.name(), q.ty(), q.class(),
- message.flags().raw(),
- meta.endpoint);
-
- send_response(&sock, q_id, MDNS_ENDPOINT, &db, None, relevant).await
- }
-
-
- if q.name().eq(&Label::from("&my_hostname")) {
- // if meta.endpoint.port == 5353 {
- // send_advert(&sock, q_id, MDNS_ENDPOINT, None, &my_address).await;
- // } else if (q.class() & 0x8000) != 0 {
- // log::info!("unicast");
- // send_advert(&sock, q_id, meta.endpoint, None, &my_address).await;
- // } else {
- // // legacy unicast, send questions
- // send_advert(&sock, q_id, meta.endpoint, Some(q), &my_address).await;
- // }
- // log::info!("IT ME");
- }
- }
-}
pub async fn start_wifi(spawner: &Spawner,
wifi_peripheral: esp_hal::peripherals::WIFI<'static>) -> ! {
@@ -453,42 +456,11 @@ pub async fn start_wifi(spawner: &Spawner,
&mut tx_buffer,
my_address);
- let mut data_buf = [0; 4096];
-
- let dns_db = &mdns_responder.database;
- let sock = mdns_responder.sock();
-
mdns_responder.advertise().await;
loop {
if mdns_responder.may_recv() {
- let mut questions = [Question::default(); 64];
- let mut answers = [ResourceRecord::default(); 64];
- let mut authorities = [ResourceRecord::default(); 64];
- let mut addl = [ResourceRecord::default(); 64];
-
- let res = sock.recv_from(&mut data_buf).await;
- if let Ok((n, meta)) = res {
- // log::info!("received packet len {n}");
- let message = Message::read(
- &data_buf[..n],
- &mut questions,
- &mut answers,
- &mut authorities,
- &mut addl,
- );
-
- match message {
- Result::Ok(message) => {
- send_responses(&sock, &dns_db, &message, &meta).await;
- },
- Result::Err(err) => {
- log::error!("parsing dns message from {:?} : {:?}",
- meta.endpoint,
- err);
- }
- }
- }
+ mdns_responder.process_packet().await;
}
Timer::after(Duration::from_millis(80)).await;