Skip to content

Commit

Permalink
Post-split work
Browse files Browse the repository at this point in the history
  • Loading branch information
ivmarkov committed Dec 5, 2023
1 parent 4a80e47 commit fce1e9a
Show file tree
Hide file tree
Showing 44 changed files with 2,706 additions and 4,362 deletions.
82 changes: 30 additions & 52 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "edge-net"
version = "0.5.0"
version = "0.6.0"
authors = ["Ivan Markov <ivan.markov@gmail.com>"]
edition = "2021"
categories = ["embedded", "hardware-support"]
Expand All @@ -12,46 +12,19 @@ readme = "README.md"
rust-version = "1.71"

[features]
std = [
"alloc",
"embassy-sync/std",
"embedded-svc?/std",
"edge-http?/std",
"edge-captive?/std",
"dep:edge-tcp",

"futures-lite/std",
"dep:async-io",
"dep:embedded-io-async",
"dep:embedded-nal-async",
"dep:libc"
]
alloc = ["edge-http?/alloc", "embedded-svc?/alloc"]
nightly = ["dep:edge-http", "embedded-svc?/nightly"]
std = ["edge-http/std", "edge-captive/std", "edge-mqtt/std", "edge-std-nal-async/std"]
nightly = ["edge-dhcp/nightly", "edge-http/nightly", "edge-mqtt/nightly", "edge-raw/nightly", "edge-ws/nightly", "edge-std-nal-async/nightly"]
# TODO: embedded-svc

[dependencies]
embedded-svc = { version = "0.26", default-features = false, optional = true, features = ["embedded-io-async"] }

futures-lite = { version = "1", default-features = false, optional = true }
async-io = { version = "2", default-features = false, optional = true }
embedded-io-async = { workspace = true, optional = true }
embedded-nal-async = { workspace = true, optional = true }
libc = { version = "0.2", default-features = false, optional = true }

embassy-sync.workspace = true
log.workspace = true
heapless.workspace = true
no-std-net.workspace = true

edge-captive = { workspace = true, optional = true }
edge-dhcp = { workspace = true, optional = true }
edge-http = { workspace = true, optional = true }
edge-mdns = { workspace = true, optional = true }
edge-mqtt = { workspace = true, optional = true }
edge-ws = { workspace = true, optional = true }

# edge-tcp is an exception that only contains trait definitions
edge-tcp = { workspace = true, optional = true }
edge-captive = { workspace = true }
edge-dhcp = { workspace = true }
edge-http = { workspace = true }
edge-mdns = { workspace = true }
edge-mqtt = { workspace = true }
edge-raw = { workspace = true }
edge-ws = { workspace = true }
edge-std-nal-async = { workspace = true }

[dev-dependencies]
anyhow = "1"
Expand Down Expand Up @@ -81,24 +54,29 @@ members = [
"edge-http",
"edge-mdns",
"edge-mqtt",
"edge-tcp",
"edge-ws"
"edge-raw",
"edge-ws",
"edge-std-nal-async",
"embedded-nal-async-xtra"
]

[workspace.dependencies]
embassy-futures = "0.1"
embassy-sync = "0.3"
embedded-io = { version = "0.6", default-features = false }
embassy-futures = { version = "0.1", default-features = false }
embassy-sync = { version = "0.3", default-features = false }
embassy-time = { version = "0.1", default-features = false }
embedded-io-async = { version = "0.6", default-features = false }
embedded-nal-async = "0.6"
embedded-nal-async = { version = "0.6", default-features = false }
embedded-svc = { version = "0.26", default-features = false, features = ["embedded-io-async"] }
log = { version = "0.4", default-features = false }
heapless = { version = "0.7", default-features = false }
no-std-net = { version = "0.6", default-features = false }

edge-captive = { version = "0.1.0", path = "edge-captive" }
edge-dhcp = { version = "0.1.0", path = "edge-dhcp" }
edge-http = { version = "0.1.0", path = "edge-http" }
edge-mdns = { version = "0.1.0", path = "edge-mdns" }
edge-mqtt = { version = "0.1.0", path = "edge-mqtt" }
edge-tcp = { version = "0.1.0", path = "edge-tcp" }
edge-ws = { version = "0.1.0", path = "edge-ws" }
edge-captive = { version = "0.1.0", path = "edge-captive", default-features = false }
edge-dhcp = { version = "0.1.0", path = "edge-dhcp", default-features = false }
edge-http = { version = "0.1.0", path = "edge-http", default-features = false }
edge-mdns = { version = "0.1.0", path = "edge-mdns", default-features = false }
edge-mqtt = { version = "0.1.0", path = "edge-mqtt", default-features = false }
edge-raw = { version = "0.1.0", path = "edge-raw", default-features = false }
edge-ws = { version = "0.1.0", path = "edge-ws", default-features = false }
edge-std-nal-async = { version = "0.1.0", path = "edge-std-nal-async", default-features = false }
embedded-nal-async-xtra = { version = "0.1.0", path = "embedded-nal-async-xtra", default-features = false }
5 changes: 1 addition & 4 deletions edge-captive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ name = "edge-captive"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
std = ["domain/std"]

[dependencies]
log.workspace = true

log = { workspace = true }
domain = { version = "0.7", default-features = false }
153 changes: 153 additions & 0 deletions edge-captive/src/io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#[cfg(feature = "std")]
pub mod server {
use std::{
io, mem,
net::{Ipv4Addr, SocketAddrV4, UdpSocket},
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
thread::{self, JoinHandle},
time::Duration,
};

use log::*;

#[derive(Clone, Debug)]
pub struct DnsConf {
pub bind_ip: Ipv4Addr,
pub bind_port: u16,
pub ip: Ipv4Addr,
pub ttl: Duration,
}

impl DnsConf {
pub fn new(ip: Ipv4Addr) -> Self {
Self {
bind_ip: Ipv4Addr::new(0, 0, 0, 0),
bind_port: 53,
ip,
ttl: Duration::from_secs(60),
}
}
}

#[derive(Debug)]
pub enum Status {
Stopped,
Started,
Error(io::Error),
}

pub struct DnsServer {
conf: DnsConf,
status: Status,
running: Arc<AtomicBool>,
handle: Option<JoinHandle<Result<(), io::Error>>>,
}

impl DnsServer {
pub fn new(conf: DnsConf) -> Self {
Self {
conf,
status: Status::Stopped,
running: Arc::new(AtomicBool::new(false)),
handle: None,
}
}

pub fn get_status(&mut self) -> &Status {
self.cleanup();
&self.status
}

pub fn start(&mut self) -> Result<(), io::Error> {
if matches!(self.get_status(), Status::Started) {
return Ok(());
}
let socket_address = SocketAddrV4::new(self.conf.bind_ip, self.conf.bind_port);
let running = self.running.clone();
let ip = self.conf.ip;
let ttl = self.conf.ttl;

self.running.store(true, Ordering::Relaxed);
self.handle = Some(
thread::Builder::new()
// default stack size is not enough
// 9000 was found via trial and error
.stack_size(9000)
.spawn(move || {
// Socket is not movable across thread bounds
// Otherwise we run into an assertion error here: https://github.com/espressif/esp-idf/blob/master/components/lwip/port/esp32/freertos/sys_arch.c#L103
let socket = UdpSocket::bind(socket_address)?;
socket.set_read_timeout(Some(Duration::from_secs(1)))?;
let result = Self::run(&running, ip, ttl, socket);

running.store(false, Ordering::Relaxed);

result
})
.unwrap(),
);

Ok(())
}

pub fn stop(&mut self) -> Result<(), io::Error> {
if matches!(self.get_status(), Status::Stopped) {
return Ok(());
}

self.running.store(false, Ordering::Relaxed);
self.cleanup();

let mut status = Status::Stopped;
mem::swap(&mut self.status, &mut status);

match status {
Status::Error(e) => Err(e),
_ => Ok(()),
}
}

fn cleanup(&mut self) {
if !self.running.load(Ordering::Relaxed) && self.handle.is_some() {
self.status = match mem::take(&mut self.handle).unwrap().join().unwrap() {
Ok(_) => Status::Stopped,
Err(e) => Status::Error(e),
};
}
}

fn run(
running: &AtomicBool,
ip: Ipv4Addr,
ttl: Duration,
socket: UdpSocket,
) -> Result<(), io::Error> {
while running.load(Ordering::Relaxed) {
let mut request_arr = [0_u8; 512];
debug!("Waiting for data");
let (request_len, source_addr) = match socket.recv_from(&mut request_arr) {
Ok(value) => value,
Err(err) => match err.kind() {
std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut => continue,
_ => return Err(err),
},
};

let request = &request_arr[..request_len];

debug!("Received {} bytes from {}", request.len(), source_addr);
let response = crate::process_dns_request(request, &ip.octets(), ttl)
.map_err(|_| io::ErrorKind::Other)?;

socket.send_to(response.as_ref(), source_addr)?;

debug!("Sent {} bytes to {}", response.as_ref().len(), source_addr);
}

Ok(())
}
}
}
10 changes: 3 additions & 7 deletions edge-captive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ use domain::{
rdata::A,
};

#[cfg(feature = "std")]
mod server;

#[cfg(feature = "std")]
pub use server::*;
pub mod io;

#[derive(Debug)]
pub struct InnerError<T: fmt::Debug + fmt::Display>(T);
Expand Down Expand Up @@ -54,11 +50,10 @@ impl From<ParseError> for DnsError {
impl std::error::Error for DnsError {}

pub fn process_dns_request(
request: impl AsRef<[u8]>,
request: &[u8],
ip: &[u8; 4],
ttl: Duration,
) -> Result<impl AsRef<[u8]>, DnsError> {
let request = request.as_ref();
let response = Octets512::new();

let message = domain::base::Message::from_octets(request)?;
Expand Down Expand Up @@ -106,5 +101,6 @@ pub fn process_dns_request(

responseb.finish()
};

Ok(response)
}
Loading

0 comments on commit fce1e9a

Please sign in to comment.