Skip to content

Commit 8f607c6

Browse files
committed
feat(mdns): Add default and ffi build features
1 parent b983fe4 commit 8f607c6

File tree

11 files changed

+494
-104
lines changed

11 files changed

+494
-104
lines changed

.github/workflows/mdns__rust.yml

+3
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,7 @@ jobs:
3131
cd components/mdns/examples/simple_query/
3232
idf.py build
3333
cd ../..
34+
# FFI build
3435
COMPILE_COMMANDS_DIR=examples/simple_query/build/ cargo run --example usage
36+
# Default build
37+
cargo run --example usage

components/mdns/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ if(${target} STREQUAL "linux")
1515
set(dependencies esp_netif_linux esp_event)
1616
set(private_dependencies esp_timer console esp_system)
1717
set(srcs "mdns_stub.c" ${MDNS_NETWORKING} ${MDNS_CONSOLE})
18+
# set(srcs "mdns.c" ${MDNS_NETWORKING} ${MDNS_CONSOLE})
1819
else()
1920
set(dependencies lwip console esp_netif)
2021
set(private_dependencies esp_timer esp_wifi)

components/mdns/Cargo.toml

+6
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,14 @@ edition = "2021"
66
[dependencies]
77
libc = "0.2"
88
dns-parser = "0.8"
9+
socket2 = "*"
10+
nix = "0.26"
11+
lazy_static = "*"
912

1013
[build-dependencies]
1114
cc = "1.0"
1215
serde = { version = "1.0", features = ["derive"] }
1316
serde_json = "1.0"
17+
18+
[features]
19+
ffi = []

components/mdns/build.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,23 @@ struct CompileCommand {
1111
}
1212

1313
fn main() {
14+
15+
println!("cargo:rerun-if-env-changed=COMPILE_COMMANDS_DIR");
1416
// Get the directory for compile_commands.json from an environment variable
15-
let compile_commands_dir = env::var("COMPILE_COMMANDS_DIR")
16-
.unwrap_or_else(|_| ".".to_string()); // Default to current directory
17+
let compile_commands_dir = match env::var("COMPILE_COMMANDS_DIR") {
18+
Ok(dir) => dir,
19+
Err(_) => {
20+
// If the environment variable is not defined, return early
21+
println!("COMPILE_COMMANDS_DIR not set, skipping custom build.");
22+
// this is a native build
23+
// println!("cargo:rustc-cfg=native");
24+
return;
25+
}
26+
};
1727

28+
// building with FFI of mdns_networking
29+
println!("COMPILE_COMMANDS_DIR set, enabling FFI feature.");
30+
println!("cargo:rustc-cfg=feature=\"ffi\"");
1831
// Construct the path to the compile_commands.json file
1932
let compile_commands_path = Path::new(&compile_commands_dir).join("compile_commands.json");
2033

components/mdns/examples/usage.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
use mdns::*;
44
use std::thread;
55
use std::time::Duration;
6+
use std::net::{UdpSocket, Ipv4Addr};
7+
use socket2::{Socket, Domain, Type, Protocol};
68

7-
pub fn test_mdns() {
9+
10+
11+
fn test_mdns() {
812
let ip4 = EspIpAddr {
913
u_addr: EspIpUnion {
1014
ip4: EspIp4Addr {
11-
addr: u32::from_le_bytes([224, 0, 0, 251]), // Convert 224.0.0.251 to big-endian
15+
addr: u32::from_le_bytes([224, 0, 0, 251]),
1216
},
1317
},
1418
addr_type: ESP_IPADDR_TYPE_V4,
@@ -25,11 +29,13 @@ pub fn test_mdns() {
2529
return;
2630
}
2731

28-
let query_packet = create_mdns_query();
29-
println!("{:?}", query_packet);
32+
// let query_packet = create_mdns_query();
33+
// println!("{:?}", query_packet);
34+
35+
3036

31-
let len = mdns_udp_pcb_write_rust(MdnsIf::Netif0, MdnsIpProtocol::Ip4, ip4, 5353, &query_packet);
32-
println!("Bytes sent: {}", len);
37+
// let len = mdns_udp_pcb_write_rust(MdnsIf::Netif0, MdnsIpProtocol::Ip4, ip4, 5353, &query_packet);
38+
// println!("Bytes sent: {}", len);
3339

3440
thread::sleep(Duration::from_millis(500));
3541

@@ -38,17 +44,20 @@ pub fn test_mdns() {
3844
}
3945
}
4046

47+
4148
fn main() {
4249
// Initialize mDNS
4350
mdns::mdns_init();
4451

4552
// // Query for a specific host
4653
// mdns::mdns_query_host_rust("example.local");
47-
54+
mdns::mdns_query("david-work.local");
55+
thread::sleep(Duration::from_millis(500));
4856
// Deinitialize mDNS
4957
mdns::mdns_deinit();
5058

51-
test_mdns();
59+
60+
// test_mdns();
5261

5362
// let result = mdns::mdns_pcb_init_rust(mdns::MdnsIf::Netif0, mdns::MdnsIpProtocol::Ip4);
5463
// match result {

components/mdns/mdns.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ static inline esp_netif_t *esp_netif_from_preset_if(mdns_predef_if_t predef_if)
176176
* @param tcpip_if Ordinal number of the interface
177177
* @return Pointer ot the esp_netif object if the interface is available, NULL otherwise
178178
*/
179-
esp_netif_t *_mdns_get_esp_netif23(mdns_if_t tcpip_if)
179+
esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if)
180180
{
181181
if (tcpip_if < MDNS_MAX_INTERFACES) {
182182
if (s_esp_netifs[tcpip_if].netif == NULL && s_esp_netifs[tcpip_if].predefined) {
@@ -347,7 +347,7 @@ static bool _mdns_can_add_more_services(void)
347347
return true;
348348
}
349349

350-
esp_err_t _mdns_send_rx_action23(mdns_rx_packet_t *packet)
350+
esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet)
351351
{
352352
mdns_action_t *action = NULL;
353353

components/mdns/src/lib.rs

+78-92
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// src/lib.rs
2+
mod service;
3+
use service::{Service, NativeService, CService};
24

35
extern crate libc;
46
// extern crate trust_dns;
@@ -13,6 +15,29 @@ use std::fmt::Write; // For formatting strings
1315
use std::net::Ipv4Addr;
1416
use dns_parser::{Builder, QueryClass, QueryType, Packet};
1517

18+
19+
20+
#[cfg(not(feature = "ffi"))]
21+
fn build_info() {
22+
println!("Default build");
23+
}
24+
25+
#[cfg(not(feature = "ffi"))]
26+
fn create_service(cb: fn(&[u8])) -> Box<dyn Service> {
27+
NativeService::init(cb)
28+
}
29+
30+
31+
#[cfg(feature = "ffi")]
32+
fn build_info() {
33+
println!("FFI build");
34+
}
35+
36+
#[cfg(feature = "ffi")]
37+
fn create_service(cb: fn(&[u8])) -> Box<dyn Service> {
38+
CService::init(cb)
39+
}
40+
1641
#[repr(C)]
1742
#[derive(Debug, Clone, Copy)]
1843
pub struct EspIp4Addr {
@@ -64,26 +89,6 @@ impl Clone for EspIpUnion {
6489
// Manual implementation of Copy for the union
6590
impl Copy for EspIpUnion {}
6691

67-
// // Other structs remain the same
68-
// #[repr(C)]
69-
// #[derive(Debug, Clone, Copy)]
70-
// pub struct EspIp4Addr {
71-
// addr: u32,
72-
// }
73-
//
74-
// #[repr(C)]
75-
// #[derive(Debug, Clone, Copy)]
76-
// pub struct EspIp6Addr {
77-
// addr: [u32; 4],
78-
// zone: u8,
79-
// }
80-
//
81-
// #[repr(C)]
82-
// #[derive(Debug, Clone, Copy)]
83-
// pub struct EspIpAddr {
84-
// u_addr: EspIpUnion, // Union containing IPv4 or IPv6 address
85-
// addr_type: u8,
86-
// }
8792
// Address type definitions
8893
pub const ESP_IPADDR_TYPE_V4: u8 = 0;
8994
pub const ESP_IPADDR_TYPE_V6: u8 = 6;
@@ -117,8 +122,6 @@ extern "C" {
117122
) -> usize;
118123
fn _mdns_pcb_deinit(tcpip_if: MdnsIf, ip_protocol: MdnsIpProtocol) -> EspErr;
119124
fn set_callback(callback: extern "C" fn(*const u8, usize));
120-
121-
// fn set_callback2();
122125
}
123126

124127
extern "C" fn rust_callback(data: *const u8, len: usize)
@@ -127,92 +130,92 @@ extern "C" fn rust_callback(data: *const u8, len: usize)
127130
unsafe {
128131
// Ensure that the data pointer is valid
129132
if !data.is_null() {
130-
// Create a Vec<u8> from the raw pointer and length
131-
let data_vec = std::slice::from_raw_parts(data, len).to_vec();
133+
// Create a Vec<u8> from the raw pointer and length
134+
let data_vec = std::slice::from_raw_parts(data, len).to_vec();
132135

133-
// Now call the safe parser function with the Vec<u8>
134-
parse_dns_response(&data_vec); }
136+
// Now call the safe parser function with the Vec<u8>
137+
parse_dns_response(&data_vec).unwrap();
138+
}
135139
}
136140
}
137141

138-
fn parse_dns_response(data: &[u8]) {
139-
// Safe handling of the slice
140-
println!("Parsing DNS response with length: {}", data.len());
141-
142-
parse_dns_response2(data);
143-
// Process the data (this will be safe, as `data` is a slice)
144-
// Example: You could convert the slice to a string, inspect it, or pass it to a DNS library
145-
}
146-
147-
fn parse_dns_response2(data: &[u8]) -> Result<(), String> {
142+
fn parse_dns_response(data: &[u8]) -> Result<(), String> {
148143
println!("Parsing DNS response with length 2 : {}", data.len());
149-
// use dns_parser::Packet;
150144
let packet = Packet::parse(&data).unwrap();
151145
for answer in packet.answers {
152146
println!("{:?}", answer);
153147
}
154-
// match Message::from_vec(data) {
155-
// Ok(msg) => {
156-
// // Successful parsing
157-
// println!("Parsed DNS message successfully.");
158-
// }
159-
// Err(e) => {
160-
// // Detailed error message
161-
// eprintln!("Error parsing DNS message: {}", e);
162-
// }
163-
// }
164-
// Parse the response message
165-
// let msg = Message::from_vec(data).map_err(|e| e.to_string())?;
166-
// println!("Type: {}", msg.op_code().to_string());
167-
// // Check if the message is a response (opcode is Response)
168-
// if msg.op_code() != trust_dns_client::op::OpCode::Status {
169-
// return Err("Not a response message".to_string());
170-
// }
171-
//
172-
// // Display the answer section (which should contain A record)
173-
// for answer in msg.answers() {
174-
// println!("Non-IP answer: {:?}", answer);
175-
// if let Some(ipv4_addr) = answer.rdata().to_ip_addr() {
176-
// println!("Resolved IP address: {}", ipv4_addr);
177-
// } else {
178-
// println!("Non-IP answer: {:?}", answer);
179-
// }
180-
// }
181-
148+
for question in packet.questions {
149+
println!("{:?}", question);
150+
}
182151
Ok(())
183152
}
184153

185154
use std::ffi::CString;
155+
use std::thread;
156+
use std::time::Duration;
157+
use lazy_static::lazy_static;
158+
use std::sync::{Arc, Mutex};
186159

160+
lazy_static! {
161+
static ref SERVICE: Arc<Mutex<Option<Box<dyn Service>>>> = Arc::new(Mutex::new(None));
162+
}
163+
164+
fn read_cb(vec: &[u8]) {
165+
println!("Received {:?}", vec);
166+
parse_dns_response(vec).unwrap();
167+
}
187168

188169
pub fn mdns_init() {
170+
build_info();
171+
let mut service_guard = SERVICE.lock().unwrap();
172+
if service_guard.is_none() {
173+
// Initialize the service only if it hasn't been initialized
174+
*service_guard = Some(create_service(read_cb));
175+
}
176+
// let service: Box<dyn Service> = create_service(read_cb);
177+
// service.action1();
178+
// let packet: [u8; 34] = [
179+
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x64, 0x61,
180+
// 0x76, 0x69, 0x64, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00,
181+
// 0x00, 0x01, 0x00, 0x01,
182+
// ];
183+
// service.send(packet.to_vec());
184+
// thread::sleep(Duration::from_millis(500));
185+
// service.deinit();
189186
println!("mdns_init called");
190187
}
191188

192189
pub fn mdns_deinit() {
190+
let mut service_guard = SERVICE.lock().unwrap();
191+
if let Some(service) = service_guard.take() {
192+
service.deinit();
193+
}
193194
println!("mdns_deinit called");
194195
}
195196

196-
pub fn create_mdns_query() -> Vec<u8> {
197-
let query_name = "david-work.local"; // The domain you want to query
197+
fn create_a_query(name: &str) -> Vec<u8> {
198198
let query_type = QueryType::A; // Type A query for IPv4 address
199199
let query_class = QueryClass::IN; // Class IN (Internet)
200200

201201
// Create a new query with ID and recursion setting
202-
let mut builder = Builder::new_query(12345, true);
202+
let mut builder = Builder::new_query(0x5555, true);
203203

204204
// Add the question for "david-work.local"
205-
builder.add_question(query_name, false, query_type, query_class);
205+
builder.add_question(name, false, query_type, query_class);
206206

207207
// Build and return the query packet
208208
builder.build().unwrap_or_else(|x| x)
209209
}
210210

211-
pub fn mdns_query_host_rust(name: &str) {
212-
let c_name = CString::new(name).expect("Failed to create CString");
213-
// unsafe {
214-
// mdns_query_host(c_name.as_ptr());
215-
// }
211+
pub fn mdns_query(name: &str) {
212+
let service_guard = SERVICE.lock().unwrap();
213+
if let Some(service) = &*service_guard {
214+
let packet = create_a_query(name);
215+
service.send(packet);
216+
} else {
217+
println!("Service not initialized");
218+
}
216219
}
217220

218221
pub fn mdns_pcb_init_rust(tcpip_if: MdnsIf, ip_protocol: MdnsIpProtocol) -> Result<(), EspErr> {
@@ -229,24 +232,7 @@ pub fn mdns_pcb_init_rust(tcpip_if: MdnsIf, ip_protocol: MdnsIpProtocol) -> Resu
229232
}
230233
}
231234

232-
pub fn mdns_udp_pcb_write_rust(
233-
tcpip_if: MdnsIf,
234-
ip_protocol: MdnsIpProtocol,
235-
ip: EspIpAddr,
236-
port: u16,
237-
data: &[u8],
238-
) -> usize {
239-
unsafe {
240-
_mdns_udp_pcb_write(
241-
tcpip_if,
242-
ip_protocol,
243-
&ip as *const EspIpAddr,
244-
port,
245-
data.as_ptr(),
246-
data.len(),
247-
)
248-
}
249-
}
235+
250236

251237
pub fn mdns_pcb_deinit_rust(tcpip_if: MdnsIf, ip_protocol: MdnsIpProtocol) -> Result<(), EspErr> {
252238
let err = unsafe { _mdns_pcb_deinit(tcpip_if, ip_protocol) };

0 commit comments

Comments
 (0)