From b402a4c3ff1ff122abafaa7ea065ffa9a1338e24 Mon Sep 17 00:00:00 2001 From: Kenneth Knudsen Date: Wed, 16 Aug 2023 08:59:02 +0200 Subject: [PATCH] Changed linarmap to deque. Dnsstate inside DNStable --- ublox-short-range/src/client.rs | 74 ++++++++++++++++++------- ublox-short-range/src/wifi/dns.rs | 25 +++++---- ublox-short-range/src/wifi/tcp_stack.rs | 19 +++---- 3 files changed, 75 insertions(+), 43 deletions(-) diff --git a/ublox-short-range/src/client.rs b/ublox-short-range/src/client.rs index 4e65fdd..68467e7 100644 --- a/ublox-short-range/src/client.rs +++ b/ublox-short-range/src/client.rs @@ -39,7 +39,7 @@ use ublox_sockets::{ UdpSocket, UdpState, }; -#[derive(PartialEq, Copy, Clone)] +#[derive(PartialEq, Eq, Copy, Clone)] pub enum SerialMode { Cmd, ExtendedData, @@ -53,26 +53,68 @@ pub enum DNSState { Error(PingError), } +/// From u-connectXpress AT commands manual: +/// depends on the . For internet domain names, the maximum +/// length is 64 characters. +/// Domain name length is 128 for NINA-W13 and NINA-W15 software version 4.0 +/// .0 or later. + +#[cfg(not(feature = "nina_w1xx"))] +pub const MAX_DOMAIN_NAME_LENGTH: usize = 64; + +#[cfg(feature = "nina_w1xx")] +pub const MAX_DOMAIN_NAME_LENGTH: usize = 128; + +pub struct DNSTableEntry{ + domain_name: heapless::String, + state: DNSState +} + +impl DNSTableEntry { + pub fn new(state: DNSState, domain_name: heapless::String) -> Self{ + Self {domain_name, state } + } +} + pub struct DNSTable { - pub table: heapless::LinearMap, 16>, + pub table: heapless::Deque, } impl DNSTable { - fn new() -> Self { + const fn new() -> Self { Self { - table: heapless::LinearMap::new(), + table: heapless::Deque::new(), } } - pub fn insert(&mut self, ip: IpAddr, hostname: heapless::String<256>) -> Result<(), ()> { - self.table.insert(ip, hostname).ok(); - Ok(()) + pub fn upsert(&mut self, new_entry: DNSTableEntry){ + if let Some(entry) = self.table.iter_mut().find(|e| e.domain_name == new_entry.domain_name){ + entry.state = new_entry.state; + return; + } + + if self.table.is_full(){ + self.table.pop_front(); + } + unsafe{ + self.table.push_back_unchecked(new_entry); + } } - pub fn get_hostname_by_ip(&self, ip: &IpAddr) -> Option<&heapless::String<256>> { - self.table.get(ip) + + pub fn get_state(&self, domain_name: heapless::String) -> Option { + match self.table.iter().find(|e| e.domain_name == domain_name){ + Some(entry) => Some(entry.state), + None => None + } + } + pub fn reverse_lookup(&self, ip: IpAddr) -> Option<&heapless::String>{ + match self.table.iter().find(|e| e.state == DNSState::Resolved(ip)) { + Some(entry) => {Some(&entry.domain_name)}, + None => None, + } } } -#[derive(PartialEq, Clone, Default)] +#[derive(PartialEq, Eq, Clone, Default)] pub struct SecurityCredentials { pub ca_cert_name: Option>, pub c_cert_name: Option>, // TODO: Make &str with lifetime @@ -109,7 +151,6 @@ where pub(crate) client: C, pub(crate) config: Config, pub(crate) sockets: Option<&'static mut SocketSet>, - pub(crate) dns_state: DNSState, pub(crate) urc_attempts: u8, pub(crate) security_credentials: SecurityCredentials, pub(crate) timer: CLK, @@ -135,7 +176,6 @@ where client, config, sockets: None, - dns_state: DNSState::NotResolving, urc_attempts: 0, security_credentials: SecurityCredentials::default(), timer, @@ -290,7 +330,6 @@ where self.module_started = false; self.wifi_connection = None; self.wifi_config_active_on_startup = None; - self.dns_state = DNSState::NotResolving; self.urc_attempts = 0; self.security_credentials = SecurityCredentials::default(); self.socket_map = SocketMap::default(); @@ -329,7 +368,6 @@ where self.module_started = false; self.wifi_connection = None; self.wifi_config_active_on_startup = None; - self.dns_state = DNSState::NotResolving; self.urc_attempts = 0; self.security_credentials = SecurityCredentials::default(); self.socket_map = SocketMap::default(); @@ -410,7 +448,6 @@ where fn handle_urc(&mut self) -> Result { let mut ran = false; let socket_set = self.sockets.as_deref_mut(); - let dns_state = &mut self.dns_state; let socket_map = &mut self.socket_map; let udp_listener = &mut self.udp_listener; let wifi_connection = &mut self.wifi_connection; @@ -661,16 +698,11 @@ where } Urc::PingResponse(resp) => { debug!("[URC] PingResponse"); - if *dns_state == DNSState::Resolving { - *dns_state = DNSState::Resolved(resp.ip) - } + self.dns_table.upsert(DNSTableEntry { domain_name: resp.hostname, state: DNSState::Resolved(resp.ip) }); true } Urc::PingErrorResponse(resp) => { debug!("[URC] PingErrorResponse: {:?}", resp.error); - if *dns_state == DNSState::Resolving { - *dns_state = DNSState::Error(resp.error) - } true } } diff --git a/ublox-short-range/src/wifi/dns.rs b/ublox-short-range/src/wifi/dns.rs index 102085b..6a5f731 100644 --- a/ublox-short-range/src/wifi/dns.rs +++ b/ublox-short-range/src/wifi/dns.rs @@ -1,4 +1,4 @@ -use crate::client::DNSState; +use crate::client::{DNSState, DNSTableEntry}; use embedded_hal::digital::OutputPin; use embedded_nal::{nb, AddrType, Dns, IpAddr}; use fugit::ExtU32; @@ -31,27 +31,30 @@ where retry_num: 1, }) .map_err(|_| nb::Error::Other(Error::Unaddressable))?; - self.dns_state = DNSState::Resolving; + + self.dns_table.upsert(DNSTableEntry::new(DNSState::Resolving, String::from(hostname))); let expiration = self.timer.now() + 8.secs(); - while self.dns_state == DNSState::Resolving { + while let Some(DNSState::Resolving) = self.dns_table.get_state(String::from(hostname)){ self.spin().map_err(|_| nb::Error::Other(Error::Illegal))?; if self.timer.now() >= expiration { - return Err(nb::Error::Other(Error::Timeout)); + break; } } - match self.dns_state { - DNSState::Resolved(ip) => { - //Insert hostname and ip into dns table - self.dns_table - .insert(ip, heapless::String::from(hostname)) - .ok(); + match self.dns_table.get_state(String::from(hostname)) { + Some(DNSState::Resolved(ip)) => { Ok(ip) } - _ => Err(nb::Error::Other(Error::Illegal)), + Some(DNSState::Resolving) => { + self.dns_table.upsert(DNSTableEntry::new(DNSState::Error(types::PingError::Timeout), String::from(hostname))); + Err(nb::Error::Other(Error::Timeout)) + } + _ => Err(nb::Error::Other(Error::Illegal)) } } } + + diff --git a/ublox-short-range/src/wifi/tcp_stack.rs b/ublox-short-range/src/wifi/tcp_stack.rs index 2dfebe1..aa65d92 100644 --- a/ublox-short-range/src/wifi/tcp_stack.rs +++ b/ublox-short-range/src/wifi/tcp_stack.rs @@ -65,19 +65,16 @@ where defmt::debug!("[TCP] Connect socket"); self.connected_to_network().map_err(|_| Error::Illegal)?; - let mut url = PeerUrlBuilder::new(); - - //Connect with hostname if seen before - if let Some(hostname) = self.dns_table.get_hostname_by_ip(&remote.ip()) { - url.hostname(hostname).port(remote.port()); + let url = if let Some(hostname) = self.dns_table.reverse_lookup(remote.ip()){ + PeerUrlBuilder::new().hostname(hostname.as_str()).port(remote.port()).creds(self.security_credentials.clone()) + .tcp() + .map_err(|_| Error::Unaddressable)? } else { - url.address(&remote); - } - - let url = url - .creds(self.security_credentials.clone()) + PeerUrlBuilder::new().ip_addr(remote.ip()).port(remote.port()).creds(self.security_credentials.clone()) .tcp() - .map_err(|_| Error::Unaddressable)?; + .map_err(|_| Error::Unaddressable)? + }; + defmt::debug!("[TCP] Connecting socket: {:?} to url: {=str}", socket, url); // If no socket is found we stop here