Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mdns]: Experimental rust crate #701

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 0 additions & 84 deletions .github/workflows/mdns__build-target-test.yml

This file was deleted.

64 changes: 0 additions & 64 deletions .github/workflows/mdns__host-tests.yml

This file was deleted.

37 changes: 37 additions & 0 deletions .github/workflows/mdns__rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: "mdns: rust-tests"

on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, labeled]

jobs:
host_test_mdns:
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
name: Host test build
runs-on: ubuntu-22.04
container: espressif/idf:latest

steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4

- name: Build and Test
shell: bash
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
# Add Rust to the current PATH
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
. "$HOME/.cargo/env"
rustc --version
cargo --version
. ${IDF_PATH}/export.sh
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
3 changes: 2 additions & 1 deletion components/mdns/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "linux")
set(dependencies esp_netif_linux esp_event)
set(private_dependencies esp_timer console esp_system)
set(srcs "mdns.c" ${MDNS_NETWORKING} ${MDNS_CONSOLE})
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)
Expand Down
19 changes: 19 additions & 0 deletions components/mdns/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "mdns"
version = "0.1.0"
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 = []
117 changes: 117 additions & 0 deletions components/mdns/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct CompileCommand {
directory: String,
command: String,
file: String,
}

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 = 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");

// Parse compile_commands.json
let compile_commands: Vec<CompileCommand> = {
let data = fs::read_to_string(&compile_commands_path)
.expect("Failed to read compile_commands.json");
serde_json::from_str(&data)
.expect("Failed to parse compile_commands.json")
};

// Directory of compile_commands.json, used to resolve relative paths
let base_dir = compile_commands_path
.parent()
.expect("Failed to get base directory of compile_commands.json");

// List of C files to compile (only base names)
let files_to_compile = vec![
"mdns_networking_socket.c",
"log_write.c",
"log_timestamp.c",
"esp_netif_linux.c",
"freertos_linux.c",
"tag_log_level.c",
"log_linked_list.c",
"log_lock.c",
"log_level.c",
"log_binary_heap.c",
"esp_system_linux2.c",
"heap_caps_linux.c",
"mdns_stub.c",
"log_buffers.c",
"util.c"
];

// Initialize the build
let mut build = cc::Build::new();

for file in &files_to_compile {
// Extract the base name from `file` for comparison
let target_base_name = Path::new(file)
.file_name()
.expect("Failed to extract base name from target file")
.to_str()
.expect("Target file name is not valid UTF-8");

// Find the entry in compile_commands.json by matching the base name
let cmd = compile_commands.iter()
.find(|entry| {
let full_path = Path::new(&entry.directory).join(&entry.file); // Resolve relative paths
if let Some(base_name) = full_path.file_name().and_then(|name| name.to_str()) {
// println!("Checking file: {} against {}", base_name, target_base_name); // Debug information
base_name == target_base_name
} else {
false
}
})
.unwrap_or_else(|| panic!("{} not found in compile_commands.json", target_base_name));

// Add the file to the build
build.file(&cmd.file);

// Parse flags and include paths from the command
for part in cmd.command.split_whitespace() {
if part.starts_with("-I") {
// Handle include directories
let include_path = &part[2..];
let full_include_path = if Path::new(include_path).is_relative() {
base_dir.join(include_path).canonicalize()
.expect("Failed to resolve relative include path")
} else {
PathBuf::from(include_path)
};
build.include(full_include_path);
} else if part.starts_with("-D") || part.starts_with("-std") {
// Add other compilation flags
build.flag(part);
}
}
}




// Compile with the gathered information
build.compile("mdns");
}
16 changes: 16 additions & 0 deletions components/mdns/examples/simple_query/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.5)


include($ENV{IDF_PATH}/tools/cmake/project.cmake)
if(${IDF_TARGET} STREQUAL "linux")
set(EXTRA_COMPONENT_DIRS "../../../../common_components/linux_compat" "../../tests/host_test/components/")
set(COMPONENTS main)
endif()

project(mdns_host)

# Enable sanitizers only without console (we'd see some leaks on argtable when console exits)
if(NOT CONFIG_TEST_CONSOLE AND CONFIG_IDF_TARGET_LINUX)
idf_component_get_property(mdns mdns COMPONENT_LIB)
target_link_options(${mdns} INTERFACE -fsanitize=address -fsanitize=undefined)
endif()
4 changes: 4 additions & 0 deletions components/mdns/examples/simple_query/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
idf_component_register(SRCS "main.c" "esp_system_linux2.c"
INCLUDE_DIRS
"."
REQUIRES mdns console nvs_flash)
21 changes: 21 additions & 0 deletions components/mdns/examples/simple_query/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
menu "Test Configuration"

config TEST_HOSTNAME
string "mDNS Hostname"
default "esp32-mdns"
help
mDNS Hostname for example to use

config TEST_NETIF_NAME
string "Network interface name"
default "eth2"
help
Name/ID if the network interface on which we run the mDNS host test

config TEST_CONSOLE
bool "Start console"
default n
help
Test uses esp_console for interactive testing.

endmenu
Loading
Loading