Resolve DNS A record

This commit is contained in:
Invariantspace 2024-10-14 00:41:59 -07:00
parent 95ad37bcaa
commit 97238b56f7
No known key found for this signature in database
GPG key ID: EBC4A20067373921
4 changed files with 128 additions and 9 deletions

16
Cargo.lock generated
View file

@ -902,6 +902,12 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]]
name = "no-std-net"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
[[package]]
name = "num-traits"
version = "0.2.19"
@ -1009,6 +1015,7 @@ dependencies = [
"rand",
"serde",
"serde_yaml",
"sntpc",
"static_cell",
]
@ -1341,6 +1348,15 @@ dependencies = [
"managed",
]
[[package]]
name = "sntpc"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de6292f240a2bf33ae7156cb354802bca8ecfacf96b820a6ec2f2e9f5c01f260"
dependencies = [
"no-std-net",
]
[[package]]
name = "ssmarshal"
version = "1.0.0"

View file

@ -21,6 +21,7 @@ log ="*"
panic-halt = "*"
portable-atomic = { version = "*", features = ["critical-section"] }
rand = { version = "*", default-features = false }
sntpc = { version = "*", default-features = false }
static_cell = "*"
[profile.release]

View file

@ -2,12 +2,17 @@
#![no_std]
#![no_main]
mod picow_time;
extern crate panic_halt;
use cyw43::JoinOptions;
use cyw43_pio::PioSpi;
use embassy_executor::Spawner;
use embassy_net::{Config, DhcpConfig, StackResources};
use embassy_net::{
dns::{DnsQueryType, DnsSocket},
Config, DhcpConfig, IpAddress, StackResources,
};
use embassy_rp::{
bind_interrupts,
clocks::RoscRng,
@ -18,15 +23,16 @@ use embassy_rp::{
};
use embassy_time::Timer;
use log::info;
use picow_time::PicowUDPBuffer;
use rand::RngCore;
use static_cell::StaticCell;
const HOSTNAME: &str = "picow";
const NTP_ENDPOINT: &str = "time.google.com";
const WAIT_SECOND: u64 = 7;
const WIRELESS_CREDENTIALS: &[(&str, &str)] =
&include!(concat!(env!("OUT_DIR"), "/wireless-credentials.rs"));
const WIRELESS_SCAN_PERIOD_SECOND: u64 = 7;
bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => pio::InterruptHandler<PIO0>;
USBCTRL_IRQ => usb::InterruptHandler<USB>;
@ -107,11 +113,11 @@ async fn main(spawner: Spawner) -> ! {
.set_power_management(cyw43::PowerManagementMode::PowerSave)
.await;
// set hostname
// hostname
let mut dhcpv4_config = DhcpConfig::default();
dhcpv4_config.hostname = HOSTNAME.try_into().ok();
// setup network stack
// network stack
static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
let (network_stack, network_runner) = embassy_net::new(
network_device,
@ -141,8 +147,8 @@ async fn main(spawner: Spawner) -> ! {
.0
{
info!("Unable to join any wireless network with provided credentials");
info!("Sleep for {WIRELESS_SCAN_PERIOD_SECOND} seconds before rescan");
Timer::after_secs(WIRELESS_SCAN_PERIOD_SECOND).await;
info!("Sleep for {WAIT_SECOND} seconds before rescan");
Timer::after_secs(WAIT_SECOND).await;
}
}
@ -156,8 +162,37 @@ async fn main(spawner: Spawner) -> ! {
// turn on led to indicate network connection
wireless_control.gpio_set(0, true).await;
// dns client
let dns_client = DnsSocket::new(network_stack);
// udp client
// let mut udp_buffer = PicowUDPBuffer::default();
// let udp_client = udp_buffer.socket(network_stack);
loop {
info!("System is idle");
Timer::after_secs(1).await;
let ntp_ipv4 = match dns_client.query(NTP_ENDPOINT, DnsQueryType::A).await {
Ok(address) => match address.first() {
Some(IpAddress::Ipv4(ipv4)) => ipv4.octets(),
None => {
info!(
"DNS A record lookup returned no IPv4 address: {}",
NTP_ENDPOINT
);
continue;
}
},
Err(error) => {
info!(
"DNS A record lookup returned error: {}, {:?}",
NTP_ENDPOINT, error
);
continue;
}
};
info!(
"Resolved IPv4 address for {}: {}.{}.{}.{}",
NTP_ENDPOINT, ntp_ipv4[0], ntp_ipv4[1], ntp_ipv4[1], ntp_ipv4[3]
);
Timer::after_secs(WAIT_SECOND).await;
}
}

67
src/picow_time.rs Normal file
View file

@ -0,0 +1,67 @@
use embassy_net::{
udp::{PacketMetadata, UdpSocket},
Stack,
};
use embassy_time::{Duration, Instant};
use sntpc::NtpTimestampGenerator;
const UDP_BUFFER_SIZE_BYTE: usize = 1 << 12;
const UDP_METADATA_SIZE: usize = 1 << 3;
#[derive(Copy, Clone)]
pub struct PicowTimestampGenerator {
duration: Duration,
}
impl Default for PicowTimestampGenerator {
fn default() -> Self {
Self {
duration: Instant::now().duration_since(Instant::MIN),
}
}
}
impl NtpTimestampGenerator for PicowTimestampGenerator {
fn init(&mut self) {
self.duration = Instant::now().duration_since(Instant::MIN);
}
fn timestamp_sec(&self) -> u64 {
self.duration.as_secs()
}
fn timestamp_subsec_micros(&self) -> u32 {
(self.duration.as_micros() % 1000000) as u32
}
}
#[derive(Debug)]
pub struct PicowUDPBuffer {
receive_buffer: [u8; UDP_BUFFER_SIZE_BYTE],
receive_metadata: [PacketMetadata; UDP_METADATA_SIZE],
transmit_buffer: [u8; UDP_BUFFER_SIZE_BYTE],
transmit_metadata: [PacketMetadata; UDP_METADATA_SIZE],
}
impl Default for PicowUDPBuffer {
fn default() -> Self {
Self {
receive_buffer: [0; UDP_BUFFER_SIZE_BYTE],
receive_metadata: [PacketMetadata::EMPTY; UDP_METADATA_SIZE],
transmit_buffer: [0; UDP_BUFFER_SIZE_BYTE],
transmit_metadata: [PacketMetadata::EMPTY; UDP_METADATA_SIZE],
}
}
}
impl PicowUDPBuffer {
pub fn socket<'me>(&'me mut self, network_stack: Stack<'me>) -> UdpSocket<'me> {
UdpSocket::new(
network_stack,
&mut self.receive_metadata,
&mut self.receive_buffer,
&mut self.transmit_metadata,
&mut self.transmit_buffer,
)
}
}