From 8f607c6829c8282f52e8e4b7387f279c8c3560be Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 27 Nov 2024 18:27:15 +0100 Subject: [PATCH] feat(mdns): Add default and ffi build features --- .github/workflows/mdns__rust.yml | 3 + components/mdns/CMakeLists.txt | 1 + components/mdns/Cargo.toml | 6 + components/mdns/build.rs | 17 ++- components/mdns/examples/usage.rs | 25 ++-- components/mdns/mdns.c | 4 +- components/mdns/src/lib.rs | 170 ++++++++++------------ components/mdns/src/service/ffi.rs | 190 +++++++++++++++++++++++++ components/mdns/src/service/mod.rs | 9 ++ components/mdns/src/service/native.rs | 161 +++++++++++++++++++++ components/mdns/src/service/service.rs | 12 ++ 11 files changed, 494 insertions(+), 104 deletions(-) create mode 100644 components/mdns/src/service/ffi.rs create mode 100644 components/mdns/src/service/mod.rs create mode 100644 components/mdns/src/service/native.rs create mode 100644 components/mdns/src/service/service.rs diff --git a/.github/workflows/mdns__rust.yml b/.github/workflows/mdns__rust.yml index a32d0ab88c..3124c5c96a 100644 --- a/.github/workflows/mdns__rust.yml +++ b/.github/workflows/mdns__rust.yml @@ -31,4 +31,7 @@ jobs: cd components/mdns/examples/simple_query/ idf.py build cd ../.. + # FFI build COMPILE_COMMANDS_DIR=examples/simple_query/build/ cargo run --example usage + # Default build + cargo run --example usage diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 3a3b4c054b..60a13fd709 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -15,6 +15,7 @@ if(${target} STREQUAL "linux") set(dependencies esp_netif_linux esp_event) set(private_dependencies esp_timer console esp_system) set(srcs "mdns_stub.c" ${MDNS_NETWORKING} ${MDNS_CONSOLE}) + # set(srcs "mdns.c" ${MDNS_NETWORKING} ${MDNS_CONSOLE}) else() set(dependencies lwip console esp_netif) set(private_dependencies esp_timer esp_wifi) diff --git a/components/mdns/Cargo.toml b/components/mdns/Cargo.toml index 09a10e7458..420704dca5 100644 --- a/components/mdns/Cargo.toml +++ b/components/mdns/Cargo.toml @@ -6,8 +6,14 @@ edition = "2021" [dependencies] libc = "0.2" dns-parser = "0.8" +socket2 = "*" +nix = "0.26" +lazy_static = "*" [build-dependencies] cc = "1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" + +[features] +ffi = [] diff --git a/components/mdns/build.rs b/components/mdns/build.rs index 8647aa0c02..32c6e2893e 100644 --- a/components/mdns/build.rs +++ b/components/mdns/build.rs @@ -11,10 +11,23 @@ struct CompileCommand { } fn main() { + + println!("cargo:rerun-if-env-changed=COMPILE_COMMANDS_DIR"); // Get the directory for compile_commands.json from an environment variable - let compile_commands_dir = env::var("COMPILE_COMMANDS_DIR") - .unwrap_or_else(|_| ".".to_string()); // Default to current directory + let compile_commands_dir = match env::var("COMPILE_COMMANDS_DIR") { + Ok(dir) => dir, + Err(_) => { + // If the environment variable is not defined, return early + println!("COMPILE_COMMANDS_DIR not set, skipping custom build."); + // this is a native build + // println!("cargo:rustc-cfg=native"); + return; + } + }; + // building with FFI of mdns_networking + println!("COMPILE_COMMANDS_DIR set, enabling FFI feature."); + println!("cargo:rustc-cfg=feature=\"ffi\""); // Construct the path to the compile_commands.json file let compile_commands_path = Path::new(&compile_commands_dir).join("compile_commands.json"); diff --git a/components/mdns/examples/usage.rs b/components/mdns/examples/usage.rs index 68edcfd6c0..e82d998441 100644 --- a/components/mdns/examples/usage.rs +++ b/components/mdns/examples/usage.rs @@ -3,12 +3,16 @@ use mdns::*; use std::thread; use std::time::Duration; +use std::net::{UdpSocket, Ipv4Addr}; +use socket2::{Socket, Domain, Type, Protocol}; -pub fn test_mdns() { + + +fn test_mdns() { let ip4 = EspIpAddr { u_addr: EspIpUnion { ip4: EspIp4Addr { - addr: u32::from_le_bytes([224, 0, 0, 251]), // Convert 224.0.0.251 to big-endian + addr: u32::from_le_bytes([224, 0, 0, 251]), }, }, addr_type: ESP_IPADDR_TYPE_V4, @@ -25,11 +29,13 @@ pub fn test_mdns() { return; } - let query_packet = create_mdns_query(); - println!("{:?}", query_packet); + // let query_packet = create_mdns_query(); + // println!("{:?}", query_packet); + + - let len = mdns_udp_pcb_write_rust(MdnsIf::Netif0, MdnsIpProtocol::Ip4, ip4, 5353, &query_packet); - println!("Bytes sent: {}", len); + // let len = mdns_udp_pcb_write_rust(MdnsIf::Netif0, MdnsIpProtocol::Ip4, ip4, 5353, &query_packet); + // println!("Bytes sent: {}", len); thread::sleep(Duration::from_millis(500)); @@ -38,17 +44,20 @@ pub fn test_mdns() { } } + fn main() { // Initialize mDNS mdns::mdns_init(); // // Query for a specific host // mdns::mdns_query_host_rust("example.local"); - + mdns::mdns_query("david-work.local"); + thread::sleep(Duration::from_millis(500)); // Deinitialize mDNS mdns::mdns_deinit(); - test_mdns(); + + // test_mdns(); // let result = mdns::mdns_pcb_init_rust(mdns::MdnsIf::Netif0, mdns::MdnsIpProtocol::Ip4); // match result { diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index ca9d87ddbe..c59648ee76 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -176,7 +176,7 @@ static inline esp_netif_t *esp_netif_from_preset_if(mdns_predef_if_t predef_if) * @param tcpip_if Ordinal number of the interface * @return Pointer ot the esp_netif object if the interface is available, NULL otherwise */ -esp_netif_t *_mdns_get_esp_netif23(mdns_if_t tcpip_if) +esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) { if (tcpip_if < MDNS_MAX_INTERFACES) { 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) return true; } -esp_err_t _mdns_send_rx_action23(mdns_rx_packet_t *packet) +esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) { mdns_action_t *action = NULL; diff --git a/components/mdns/src/lib.rs b/components/mdns/src/lib.rs index 327cef0226..4e30c53ac6 100644 --- a/components/mdns/src/lib.rs +++ b/components/mdns/src/lib.rs @@ -1,4 +1,6 @@ // src/lib.rs +mod service; +use service::{Service, NativeService, CService}; extern crate libc; // extern crate trust_dns; @@ -13,6 +15,29 @@ use std::fmt::Write; // For formatting strings use std::net::Ipv4Addr; use dns_parser::{Builder, QueryClass, QueryType, Packet}; + + +#[cfg(not(feature = "ffi"))] +fn build_info() { + println!("Default build"); +} + +#[cfg(not(feature = "ffi"))] +fn create_service(cb: fn(&[u8])) -> Box { + NativeService::init(cb) +} + + +#[cfg(feature = "ffi")] +fn build_info() { + println!("FFI build"); +} + +#[cfg(feature = "ffi")] +fn create_service(cb: fn(&[u8])) -> Box { + CService::init(cb) +} + #[repr(C)] #[derive(Debug, Clone, Copy)] pub struct EspIp4Addr { @@ -64,26 +89,6 @@ impl Clone for EspIpUnion { // Manual implementation of Copy for the union impl Copy for EspIpUnion {} -// // Other structs remain the same -// #[repr(C)] -// #[derive(Debug, Clone, Copy)] -// pub struct EspIp4Addr { -// addr: u32, -// } -// -// #[repr(C)] -// #[derive(Debug, Clone, Copy)] -// pub struct EspIp6Addr { -// addr: [u32; 4], -// zone: u8, -// } -// -// #[repr(C)] -// #[derive(Debug, Clone, Copy)] -// pub struct EspIpAddr { -// u_addr: EspIpUnion, // Union containing IPv4 or IPv6 address -// addr_type: u8, -// } // Address type definitions pub const ESP_IPADDR_TYPE_V4: u8 = 0; pub const ESP_IPADDR_TYPE_V6: u8 = 6; @@ -117,8 +122,6 @@ extern "C" { ) -> usize; fn _mdns_pcb_deinit(tcpip_if: MdnsIf, ip_protocol: MdnsIpProtocol) -> EspErr; fn set_callback(callback: extern "C" fn(*const u8, usize)); - -// fn set_callback2(); } extern "C" fn rust_callback(data: *const u8, len: usize) @@ -127,92 +130,92 @@ extern "C" fn rust_callback(data: *const u8, len: usize) unsafe { // Ensure that the data pointer is valid if !data.is_null() { - // Create a Vec from the raw pointer and length - let data_vec = std::slice::from_raw_parts(data, len).to_vec(); + // Create a Vec from the raw pointer and length + let data_vec = std::slice::from_raw_parts(data, len).to_vec(); - // Now call the safe parser function with the Vec - parse_dns_response(&data_vec); } + // Now call the safe parser function with the Vec + parse_dns_response(&data_vec).unwrap(); + } } } -fn parse_dns_response(data: &[u8]) { - // Safe handling of the slice - println!("Parsing DNS response with length: {}", data.len()); - - parse_dns_response2(data); - // Process the data (this will be safe, as `data` is a slice) - // Example: You could convert the slice to a string, inspect it, or pass it to a DNS library -} - -fn parse_dns_response2(data: &[u8]) -> Result<(), String> { +fn parse_dns_response(data: &[u8]) -> Result<(), String> { println!("Parsing DNS response with length 2 : {}", data.len()); -// use dns_parser::Packet; let packet = Packet::parse(&data).unwrap(); for answer in packet.answers { println!("{:?}", answer); } -// match Message::from_vec(data) { -// Ok(msg) => { -// // Successful parsing -// println!("Parsed DNS message successfully."); -// } -// Err(e) => { -// // Detailed error message -// eprintln!("Error parsing DNS message: {}", e); -// } -// } - // Parse the response message -// let msg = Message::from_vec(data).map_err(|e| e.to_string())?; -// println!("Type: {}", msg.op_code().to_string()); -// // Check if the message is a response (opcode is Response) -// if msg.op_code() != trust_dns_client::op::OpCode::Status { -// return Err("Not a response message".to_string()); -// } -// -// // Display the answer section (which should contain A record) -// for answer in msg.answers() { -// println!("Non-IP answer: {:?}", answer); -// if let Some(ipv4_addr) = answer.rdata().to_ip_addr() { -// println!("Resolved IP address: {}", ipv4_addr); -// } else { -// println!("Non-IP answer: {:?}", answer); -// } -// } - + for question in packet.questions { + println!("{:?}", question); + } Ok(()) } use std::ffi::CString; +use std::thread; +use std::time::Duration; +use lazy_static::lazy_static; +use std::sync::{Arc, Mutex}; +lazy_static! { + static ref SERVICE: Arc>>> = Arc::new(Mutex::new(None)); +} + +fn read_cb(vec: &[u8]) { + println!("Received {:?}", vec); + parse_dns_response(vec).unwrap(); +} pub fn mdns_init() { + build_info(); + let mut service_guard = SERVICE.lock().unwrap(); + if service_guard.is_none() { + // Initialize the service only if it hasn't been initialized + *service_guard = Some(create_service(read_cb)); + } + // let service: Box = create_service(read_cb); + // service.action1(); + // let packet: [u8; 34] = [ + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x64, 0x61, + // 0x76, 0x69, 0x64, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, + // 0x00, 0x01, 0x00, 0x01, + // ]; + // service.send(packet.to_vec()); + // thread::sleep(Duration::from_millis(500)); + // service.deinit(); println!("mdns_init called"); } pub fn mdns_deinit() { + let mut service_guard = SERVICE.lock().unwrap(); + if let Some(service) = service_guard.take() { + service.deinit(); + } println!("mdns_deinit called"); } -pub fn create_mdns_query() -> Vec { - let query_name = "david-work.local"; // The domain you want to query +fn create_a_query(name: &str) -> Vec { let query_type = QueryType::A; // Type A query for IPv4 address let query_class = QueryClass::IN; // Class IN (Internet) // Create a new query with ID and recursion setting - let mut builder = Builder::new_query(12345, true); + let mut builder = Builder::new_query(0x5555, true); // Add the question for "david-work.local" - builder.add_question(query_name, false, query_type, query_class); + builder.add_question(name, false, query_type, query_class); // Build and return the query packet builder.build().unwrap_or_else(|x| x) } -pub fn mdns_query_host_rust(name: &str) { - let c_name = CString::new(name).expect("Failed to create CString"); -// unsafe { -// mdns_query_host(c_name.as_ptr()); -// } +pub fn mdns_query(name: &str) { + let service_guard = SERVICE.lock().unwrap(); + if let Some(service) = &*service_guard { + let packet = create_a_query(name); + service.send(packet); + } else { + println!("Service not initialized"); + } } 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 } } -pub fn mdns_udp_pcb_write_rust( - tcpip_if: MdnsIf, - ip_protocol: MdnsIpProtocol, - ip: EspIpAddr, - port: u16, - data: &[u8], -) -> usize { - unsafe { - _mdns_udp_pcb_write( - tcpip_if, - ip_protocol, - &ip as *const EspIpAddr, - port, - data.as_ptr(), - data.len(), - ) - } -} + pub fn mdns_pcb_deinit_rust(tcpip_if: MdnsIf, ip_protocol: MdnsIpProtocol) -> Result<(), EspErr> { let err = unsafe { _mdns_pcb_deinit(tcpip_if, ip_protocol) }; diff --git a/components/mdns/src/service/ffi.rs b/components/mdns/src/service/ffi.rs new file mode 100644 index 0000000000..d9f1390fbc --- /dev/null +++ b/components/mdns/src/service/ffi.rs @@ -0,0 +1,190 @@ +use libc::AT_NULL; + +use super::service::Service; +use std::fmt; + +pub struct CService +{ + callback: fn(&[u8]) +} + +impl CService { + fn new(cb: fn(&[u8])) -> Self { + CService { + callback: cb + } + } +} + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct EspIp4Addr { + pub addr: u32, // IPv4 address as a 32-bit integer +} + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct EspIp6Addr { + pub addr: [u32; 4], // IPv6 address as an array of 4 32-bit integers + pub zone: u8, // Zone ID +} + +#[repr(C)] +pub union EspIpUnion { + pub ip4: EspIp4Addr, + pub ip6: EspIp6Addr, +} + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct EspIpAddr { + pub u_addr: EspIpUnion, // Union containing IPv4 or IPv6 address + pub addr_type: u8, +} + +// Manual implementation of Debug for the union +impl fmt::Debug for EspIpUnion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Safely access and format the union's members for debugging + unsafe { + write!(f, "EspIpUnion {{ ip4: {:?}, ip6: {:?} }}", self.ip4, self.ip6) + } + } +} + +// Manual implementation of Clone for the union +impl Clone for EspIpUnion { + fn clone(&self) -> Self { + // Safety: Assuming the union contains valid data in either `ip4` or `ip6` + unsafe { + EspIpUnion { + ip4: self.ip4.clone(), + } + } + } +} + +// Manual implementation of Copy for the union +impl Copy for EspIpUnion {} + +// Address type definitions +pub const ESP_IPADDR_TYPE_V4: u8 = 0; +pub const ESP_IPADDR_TYPE_V6: u8 = 6; +pub const ESP_IPADDR_TYPE_ANY: u8 = 46; + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub enum MdnsIf { + Netif0 = 0, + // Add more as needed based on the actual C enum definition +} + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub enum MdnsIpProtocol { + Ip4 = 0, + Ip6 = 1, +} + +type EspErr = i32; + +extern "C" { + fn _mdns_pcb_init(tcpip_if: MdnsIf, ip_protocol: MdnsIpProtocol) -> EspErr; + fn _mdns_udp_pcb_write( + tcpip_if: MdnsIf, + ip_protocol: MdnsIpProtocol, + ip: *const EspIpAddr, + port: u16, + data: *const u8, + len: usize, + ) -> usize; + fn _mdns_pcb_deinit(tcpip_if: MdnsIf, ip_protocol: MdnsIpProtocol) -> EspErr; + fn set_callback(callback: extern "C" fn(*const u8, usize)); +} + +static mut CALLBACK: Option = None; + +extern "C" fn rust_callback(data: *const u8, len: usize) +{ + println!("Received len: {}", len); + unsafe { + // Ensure that the data pointer is valid + if !data.is_null() { + // Create a Vec from the raw pointer and length + let data_vec = std::slice::from_raw_parts(data, len).to_vec(); + if let Some(cb) = CALLBACK { + cb(&data_vec); + } + // Now call the safe parser function with the Vec + // parse_dns_response(&data_vec); + } + } +} + + +pub fn mdns_udp_pcb_write_rust( + tcpip_if: MdnsIf, + ip_protocol: MdnsIpProtocol, + ip: EspIpAddr, + port: u16, + data: &[u8], +) -> usize { + unsafe { + _mdns_udp_pcb_write( + tcpip_if, + ip_protocol, + &ip as *const EspIpAddr, + port, + data.as_ptr(), + data.len(), + ) + } +} + +impl Service for CService { + + + fn init(cb:fn(&[u8])) -> Box { + println!("FfiHousekeeper: Initializing."); + unsafe { + set_callback(rust_callback); + CALLBACK = Some(cb); + } + let _ = unsafe { _mdns_pcb_init(MdnsIf::Netif0, MdnsIpProtocol::Ip4) }; + + + Box::new(CService::new(cb)) + } + + fn send(&self, packet: Vec) { + let ip4 = EspIpAddr { + u_addr: EspIpUnion { + ip4: EspIp4Addr { + addr: u32::from_le_bytes([224, 0, 0, 251]), + }, + }, + addr_type: ESP_IPADDR_TYPE_V4, + }; + println!("FfiHousekeeper: Sending"); + let len = mdns_udp_pcb_write_rust(MdnsIf::Netif0, MdnsIpProtocol::Ip4, ip4, 5353, &packet); + println!("Bytes sent: {}", len); + } + + fn action1(&self) { + println!("FfiHousekeeper: Performing Action1."); + } + + fn action2(&self) { + println!("FfiHousekeeper: Performing Action2."); + } + + fn action3(&self) { + println!("FfiHousekeeper: Performing Action3."); + } + + fn deinit(self: Box) { + let _ = unsafe { _mdns_pcb_deinit(MdnsIf::Netif0, MdnsIpProtocol::Ip4) }; + println!("FfiHousekeeper: Deinitializing."); + } + +} diff --git a/components/mdns/src/service/mod.rs b/components/mdns/src/service/mod.rs new file mode 100644 index 0000000000..9d64845a64 --- /dev/null +++ b/components/mdns/src/service/mod.rs @@ -0,0 +1,9 @@ +mod service; // Import the trait definition +mod native; // Thread-based implementation +mod ffi; // FFI-based implementation + +pub use service::Service; // Expose the trait +pub use native::NativeService; +pub use ffi::CService; +// pub use thread::ThreadHousekeeper; // Expose the thread-based implementation +// pub use ffi::FfiHousekeeper; // Expose the FFI-based implementation diff --git a/components/mdns/src/service/native.rs b/components/mdns/src/service/native.rs new file mode 100644 index 0000000000..04c9ebfb24 --- /dev/null +++ b/components/mdns/src/service/native.rs @@ -0,0 +1,161 @@ +use super::service::Service; +use std::thread; + +use std::net::{UdpSocket, Ipv4Addr}; +use dns_parser::rdata::null; +use socket2::{Socket, Domain, Type, Protocol}; +use nix::unistd::{pipe, read, write, close}; +use nix::sys::select::{select, FdSet}; +use nix::sys::time::TimeVal; +use std::os::fd::{AsRawFd, FromRawFd}; +use std::mem::MaybeUninit; + +enum Action { + Action1, + Action2, + Action3, +} + +pub struct NativeService +{ + handle: Option>, + socket: UdpSocket, + write_fd: i32, + callback: fn(&[u8]), +} + +fn create_multicast_socket() -> UdpSocket { + let addr: std::net::SocketAddr = "0.0.0.0:5353".parse().unwrap(); + + let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP)).unwrap(); + socket.set_reuse_address(true).unwrap(); + socket.bind(&addr.into()).unwrap(); + + let multicast_addr = Ipv4Addr::new(224, 0, 0, 251); + let interface = Ipv4Addr::new(0, 0, 0, 0); + socket.join_multicast_v4(&multicast_addr, &interface).unwrap(); + + socket.into() +} + +impl NativeService +{ + fn new(cb: fn(&[u8])) -> Self { + let socket = create_multicast_socket(); + let (read_fd, w_fd) = pipe().expect("Failed to create pipe"); + let local_cb = cb; + let local_socket = socket.try_clone().unwrap(); + + let handle = thread::spawn(move || { + + loop { + let socket_fd = local_socket.as_raw_fd(); + let mut read_fds = FdSet::new(); + read_fds.insert(socket_fd); + read_fds.insert(read_fd); + + + let mut timeout = TimeVal::new(0, 100_000); + + match select(read_fd.max(socket_fd) + 1, Some(&mut read_fds), None, None, Some(&mut timeout)) { + Ok(0) => println!("ThreadHousekeeper: Performing housekeeping tasks"), + Ok(_) => { + if read_fds.contains(socket_fd) { + // let mut buf: [MaybeUninit; 1500] = unsafe { MaybeUninit::uninit().assume_init() }; + // let mut buf: [u8; 1500]; + let mut buf = vec![0u8; 1500]; // Create a buffer using a vector + // let sock = unsafe { Socket::from_raw_fd(socket_fd) }; + match local_socket.recv_from(&mut buf) { + Ok((size, addr)) => { + // Convert the buffer from MaybeUninit to a regular slice of u8 + // let buf = unsafe { + // std::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, size) + // }; + // println!("Received {} bytes from {:?}: {:?}", size, addr, buf); + local_cb(&buf[..size]); + } + Err(e) => println!("Error reading from socket: {:?}", e), + } + } + + if read_fds.contains(read_fd) { + let mut buf = [0u8; 10]; + match read(read_fd, &mut buf) { + Ok(size) => { + println!("{}", size); + if size == 0 { + break; + } + } + Err(e) => println!("Error reading from socket: {:?}", e), + } + } + } + Err(e) => { + println!("Error in select(): {:?}", e); + break; + } + } + } + + // close(read_fd).expect("Failed to close read end of pipe"); + }); + + NativeService { + handle: Some(handle), + socket, + write_fd: w_fd, + callback: cb + } + } +} + +impl Service for NativeService { + + fn init(cb: fn(&[u8])) -> Box { + println!("Native: Initializing."); + Box::new(NativeService::new(cb)) + } + + fn send(&self, packet: Vec) { + let destination: std::net::SocketAddr = "224.0.0.251:5353".parse().unwrap(); + self.socket.send_to(&packet, &destination) + .expect("Failed to send mDNS query"); + } + + fn action1(&self) { + let buf: [u8; 1] = [0x01]; + // self.socket.send(&buf).unwrap(); + write(self.write_fd, &buf).unwrap(); + // if let Some(tx) = &self.tx { + // tx.send(Action::Action1).unwrap(); + // } + } + + fn action2(&self) { + // if let Some(tx) = &self.tx { + // tx.send(Action::Action2).unwrap(); + // } + } + + fn action3(&self) { + // if let Some(tx) = &self.tx { + // tx.send(Action::Action3).unwrap(); + // } + } + + fn deinit(self: Box) { + println!("DEINIT called"); + // if let Some(tx) = self.tx { + // drop(tx); + // } + close(self.write_fd).unwrap(); + + if let Some(handle) = self.handle { + handle.join().unwrap(); + println!("NativeService: Deinitialized"); + } + println!("DEINIT done..."); + + } +} diff --git a/components/mdns/src/service/service.rs b/components/mdns/src/service/service.rs new file mode 100644 index 0000000000..8653611a1c --- /dev/null +++ b/components/mdns/src/service/service.rs @@ -0,0 +1,12 @@ +pub trait Service: Send + Sync { + fn init(cb: fn(&[u8])) -> Box + where + Self: Sized; + + fn send(&self, packet: Vec); + fn action1(&self); + fn action2(&self); + fn action3(&self); + + fn deinit(self: Box); +}