commit 604e227bba685c7a51cafaf881adcc01d79cbee6
parent 68d65ebf2faa018388e10fa7d63eb307bbc436c2
Author: Daniel Barlow <dan@telent.net>
Date: Sun, 7 Dec 2025 18:02:10 +0000
use mdns to publish our hostname
this is not spec-compliant, but it works
Diffstat:
3 files changed, 133 insertions(+), 43 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -272,6 +272,15 @@ dependencies = [
]
[[package]]
+name = "dns-protocol"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96e95919581371ae96cbf05b0aeec65cdc20bd3a2dca282ab6af808fbddaddb4"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "document-features"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -286,6 +295,7 @@ version = "0.1.0"
dependencies = [
"bleps",
"bt-hci",
+ "dns-protocol",
"embassy-executor",
"embassy-futures",
"embassy-net",
diff --git a/Cargo.toml b/Cargo.toml
@@ -62,9 +62,15 @@ trouble-host = { version = "0.5.0", features = [
"derive", "scan",
] }
embassy-net = { version = "0.7.1", features = [
-"medium-ethernet", "proto-ipv4", "tcp", "dhcpv4",
+ "medium-ethernet", "proto-ipv4", "tcp", "dhcpv4", "udp",
+ "dns", "mdns", "multicast"
] }
+dns-protocol = { version = "0.1.2", default-features = false, features = [
+ # no "std" feature
+] }
+
+
[profile.dev]
# Rust debug is too slow.
diff --git a/src/wifi.rs b/src/wifi.rs
@@ -1,22 +1,22 @@
//! Set SSID and PASSWORD env variable before running this example.
//!
-//! This gets an ip address via DHCP then performs an HTTP get request to some
-//! "random" server
+//! This gets an ip address via DHCP and advertises it with mdns
-use core::net::Ipv4Addr;
-
use embassy_executor::Spawner;
-use embassy_net::{Runner, StackResources, tcp::TcpSocket};
+use embassy_net::{
+ Runner,
+ StackResources,
+ udp::{PacketMetadata, UdpSocket},
+ IpAddress,
+ IpEndpoint
+};
+
use embassy_time::{Duration, Timer};
use esp_alloc as _;
use esp_backtrace as _;
use esp_hal::{
- // clock::CpuClock,
- // interrupt::software::SoftwareInterruptControl,
- // ram,
rng::Rng,
- // timer::timg::TimerGroup,
};
use esp_println::println;
use esp_radio::{
@@ -32,6 +32,11 @@ use esp_radio::{
},
};
+
+use dns_protocol::{Message, Question,
+ MessageType,
+ 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
macro_rules! mk_static {
($t:ty,$val:expr) => {{
@@ -45,6 +50,11 @@ macro_rules! mk_static {
const SSID: &str = env!("SSID");
const PASSWORD: &str = env!("PASSWORD");
+const MDNS_IP: IpAddress = IpAddress::v4(224, 0, 0, 251);
+const MDNS_PORT: u16 = 5353;
+const MDNS_ENDPOINT: IpEndpoint = IpEndpoint::new(MDNS_IP, MDNS_PORT);
+
+
pub async fn start_wifi(spawner: &Spawner,
wifi_peripheral: esp_hal::peripherals::WIFI<'static>) -> ! {
@@ -74,6 +84,7 @@ pub async fn start_wifi(spawner: &Spawner,
let mut rx_buffer = [0; 4096];
let mut tx_buffer = [0; 4096];
+ let my_address;
loop {
if stack.is_link_up() {
@@ -86,51 +97,114 @@ pub async fn start_wifi(spawner: &Spawner,
loop {
if let Some(config) = stack.config_v4() {
println!("Got IP: {}", config.address);
+ my_address = config.address.address().octets();
break;
}
Timer::after(Duration::from_millis(500)).await;
}
+ let mut rx_meta = [PacketMetadata::EMPTY; 512];
+ let mut tx_meta = [PacketMetadata::EMPTY; 512];
+ let mut sock = UdpSocket::new(
+ stack,
+ &mut rx_meta,
+ &mut rx_buffer,
+ &mut tx_meta,
+ &mut tx_buffer,
+ );
+
+ log::info!("sock.bind(5353) res: {:?}", sock.bind(MDNS_PORT));
+ log::info!(
+ "multicast_res: {:?}",
+ stack.join_multicast_group(MDNS_IP)
+ );
+
+ let mut answer = [
+ ResourceRecord::new(
+ "eculogical.local",
+ ResourceType::A,
+ 1, // class
+ 60, // ttl
+ &my_address
+ )
+ ];
+
+ let mut flags = Flags::new();
+ flags.set_qr(MessageType::Reply);
+ flags.set_authoritative(true);
+
+ // RFC: Multicast DNS responses MUST NOT contain any questions in the
+ // RFC: Question Section.
+
+ let message = Message::new((rng.random() as u16),
+ flags,
+ &mut [],
+ &mut answer,
+ &mut [],
+ &mut []);
+
+
+ let mut data_buf = [0; 4096];
+ // Serialize the message into the buffer
+ assert!(message.space_needed() <= data_buf.len());
+
loop {
- Timer::after(Duration::from_millis(1_000)).await;
+ match message.write(&mut data_buf) {
+ Result::Ok(len) => {
+ log::info!("sock.send: {:?}", sock.send_to(&data_buf[..len], MDNS_ENDPOINT).await);
+ },
+ Result::Err(err) => {
+ log::error!("message.write {:?}", err);
+ }
+ }
- let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
+ if sock.may_recv() {
- socket.set_timeout(Some(embassy_time::Duration::from_secs(10)));
+ let mut questions = [Question::default(); 16];
+ let mut answers = [ResourceRecord::default(); 16];
+ let mut authorities = [ResourceRecord::default(); 16];
+ let mut addl = [ResourceRecord::default(); 16];
- let remote_endpoint = (Ipv4Addr::new(142, 250, 185, 115), 80);
- println!("connecting...");
- let r = socket.connect(remote_endpoint).await;
- if let Err(e) = r {
- println!("connect error: {:?}", e);
- continue;
- }
- println!("connected!");
- let mut buf = [0; 1024];
- loop {
- use embedded_io_async::Write;
- let r = socket
- .write(b"GET / HTTP/1.0\r\nHost: www.mobile-j.de\r\n\r\n")
- .await;
- if let Err(e) = r {
- println!("write error: {:?}", e);
- break;
+ let res = sock.recv_from(&mut data_buf).await;
+ if let Ok((n, _endpoint)) = 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) => {
+ log::info!("message receivefd");
+ for q in message.questions() {
+ log::info!("question {:?}", q.name());
+ }
+
+ for q in message.answers() {
+ log::info!("answer {:?}", q.data());
+ }
+ },
+ Result::Err(err) => {
+ log::error!("parsing dns message: {:?}", err);
+ }
+ }
}
- let n = match socket.read(&mut buf).await {
- Ok(0) => {
- println!("read EOF");
- break;
- }
- Ok(n) => n,
- Err(e) => {
- println!("read error: {:?}", e);
- break;
- }
- };
- println!("{}", core::str::from_utf8(&buf[..n]).unwrap());
}
- Timer::after(Duration::from_millis(3000)).await;
+
+ Timer::after(Duration::from_millis(30 * 1000)).await;
}
+
+ // _ = stack.leave_multicast_group(MDNS_IP);
+ // sock.close();
+ // drop(sock);
+
+ // loop {
+ // Timer::after(Duration::from_millis(1_000)).await;
+ // log::info!("bump");
+ // }
+
}
#[embassy_executor::task]