From b8f9cda28728d3e51c49ec15382a0ae7b96792ba Mon Sep 17 00:00:00 2001 From: LuK1337 Date: Sat, 1 Aug 2026 20:01:59 +0200 Subject: [PATCH] Add option to enable new Rust based mDNS backend Fixes: https://github.com/nmeum/android-tools/issues/181 --- .gitmodules | 4 +++ CMakeLists.txt | 18 +++++++++++++ vendor/CMakeLists.adb.txt | 25 +++++++++++++++++++ vendor/adb/adb.cpp | 23 +++++++++++++---- vendor/adb/adb_mdns.cpp | 1 + vendor/adb/client/adb_wifi.cpp | 15 +++++++++-- vendor/adb/client/adbmdns/Cargo.toml | 9 ++++--- vendor/adb/client/adbmdns/adbmdns.cpp | 8 +++--- vendor/adb/client/adbmdns/adbmdns_bridge.rs | 2 +- .../client/adbmdns/netwatch/netwatch_linux.rs | 1 + vendor/adb/client/commandline.cpp | 2 ++ vendor/adb/client/main.cpp | 6 +++++ vendor/adb/client/mdns_utils.cpp | 10 -------- vendor/adb/client/mdns_utils.h | 2 -- vendor/adb/client/transport_mdns.cpp | 10 +------- vendor/adb/socket_spec.cpp | 25 +++++++++++++++++++ 16 files changed, 125 insertions(+), 36 deletions(-) diff --git a/.gitmodules b/.gitmodules index d840901..2ec06a2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -62,3 +62,7 @@ shallow = true path = vendor/fs_mgr url = https://android.googlesource.com/platform/system/fs/fs_mgr.git +[submodule "vendor/corrosion"] + shallow = true + path = vendor/corrosion + url = https://github.com/corrosion-rs/corrosion.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 27664cc..5c5bec0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,8 +9,10 @@ include(GNUInstallDirs) # This helps to build vendor projects with or without any patching. Also if any # files are changed in vendor projects those can be retained with this option. option(ANDROID_TOOLS_PATCH_VENDOR "Patch vendor projects using patches directory" ON) +option(ANDROID_TOOLS_USE_BUNDLED_CORROSION "Use bundled corrosion instead of system provided one" OFF) option(ANDROID_TOOLS_USE_BUNDLED_FMT "Use bundled fmt library instead of system provided one" OFF) option(ANDROID_TOOLS_USE_BUNDLED_LIBUSB "Use bundled libusb library instead of system provided one" OFF) +option(ANDROID_TOOLS_ADB_ENABLE_MDNS "Enable ADB mDNS support" OFF) option(ANDROID_TOOLS_LIBUSB_ENABLE_UDEV "Enable udev for device enumeration and hotplug support" OFF) # Install bash/zsh completion files. @@ -47,6 +49,7 @@ set(CPACK_SOURCE_GENERATOR "TXZ") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${ANDROID_VERSION}") set(CPACK_SOURCE_IGNORE_FILES "/patches/" "/build/" "/.git/" "/.github/" "/tests/" "/test/" "/testdata/" "/extras/simpleperf/scripts/" "/extras/simpleperf/demo/" + "/adb/client/adbmdns/.cargo" "/adb/client/adbmdns/vendor" "aes_128_gcm.txt" "aes_256_gcm.txt" "/fuzz/" "/wycheproof_testvectors/" @@ -56,6 +59,7 @@ set(CPACK_SOURCE_IGNORE_FILES "/patches/" "/build/" "/.git/" "/.github/" "/tests "\\\\.data$" "\\\\.git$" "\\\\.html$" + "\\\\.lock$" "\\\\.orig$" "\\\\.pdf$" "\\\\.pem$" @@ -68,3 +72,17 @@ set(CPACK_SOURCE_IGNORE_FILES "/patches/" "/build/" "/.git/" "/.github/" "/tests "\\\\.zip$" ) include(CPack) + +# Create a custom target to for vendor source tarball. +add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/${ANDROID_VENDOR}-${ANDROID_VERSION}-vendor.tar.xz + COMMAND ${CMAKE_COMMAND} -E tar + cJf ${CMAKE_BINARY_DIR}/${ANDROID_VENDOR}-${ANDROID_VERSION}-vendor.tar.xz + vendor/adb/client/adbmdns/.cargo + vendor/adb/client/adbmdns/vendor + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} +) + +add_custom_target(vendor_source + DEPENDS ${CMAKE_BINARY_DIR}/${ANDROID_VENDOR}-${ANDROID_VERSION}-vendor.tar.xz +) diff --git a/vendor/CMakeLists.adb.txt b/vendor/CMakeLists.adb.txt index b2afaba..8f766fc 100644 --- a/vendor/CMakeLists.adb.txt +++ b/vendor/CMakeLists.adb.txt @@ -9,6 +9,20 @@ protobuf_generate_cpp(ADB_KNOWN_HOSTS_PROTO_SRCS ADB_KNOWN_HOSTS_PROTO_HDRS protobuf_generate_cpp(ADB_PAIRING_PROTO_SRCS ADB_PAIRING_PROTO_HDRS adb/proto/pairing.proto) +if(ANDROID_TOOLS_ADB_ENABLE_MDNS) + if(ANDROID_TOOLS_USE_BUNDLED_CORROSION) + add_subdirectory(corrosion) + else() + find_package(Corrosion CONFIG REQUIRED) + message(STATUS "Found Corrosion: ${Corrosion_DIR} (version ${Corrosion_VERSION})") + endif() + + corrosion_import_crate( + MANIFEST_PATH adb/client/adbmdns/Cargo.toml + PROFILE release + ) +endif() + # No fastdeploy because it requires deployagent.inc set(libadb_SOURCES adb/client/adb_client.cpp @@ -60,6 +74,12 @@ else() adb/client/usb_linux_netlink.cpp) endif() +if(ANDROID_TOOLS_ADB_ENABLE_MDNS) + list(APPEND libadb_SOURCES + adb/client/adbmdns/adbmdns.cpp + adb/adb_mdns.cpp) +endif() + add_library(libadb STATIC ${libadb_SOURCES}) target_compile_definitions(libadb PRIVATE -D_GNU_SOURCE) target_compile_definitions(libadb PUBLIC -DADB_HOST=1) @@ -81,6 +101,11 @@ if(ANDROID_TOOLS_USE_BUNDLED_LIBUSB) target_include_directories(libadb PUBLIC libusb) endif() +if(ANDROID_TOOLS_ADB_ENABLE_MDNS) + target_compile_definitions(libadb PUBLIC -DADB_MDNS=1) + target_link_libraries(libadb PUBLIC adbmdns_bridge) +endif() + target_link_libraries(libadb PUBLIC fmt::fmt) add_library(libadb_crypto_defaults STATIC diff --git a/vendor/adb/adb.cpp b/vendor/adb/adb.cpp index f134288..1197bdd 100644 --- a/vendor/adb/adb.cpp +++ b/vendor/adb/adb.cpp @@ -1257,6 +1257,23 @@ bool is_usb_enabled() { } static bool handle_mdns_request(std::string_view service, int reply_fd) { +#if ADB_MDNS + if (!android::base::ConsumePrefix(&service, "mdns:")) { + return false; + } + + if (service == "check") { + std::string check = mdns_check(); + SendOkay(reply_fd, check); + return true; + } + if (service == "services") { + std::string services_list = mdns_list_discovered_services(); + SendOkay(reply_fd, services_list); + return true; + } +#endif + return false; } @@ -1354,11 +1371,7 @@ HostRequestResult handle_host_request(std::string_view service, TransportType ty status.set_usb_backend_forced(getenv("ADB_LIBUSB") != nullptr); if (mdns::is_enabled()) { - if (mdns::should_use_openscreen()) { - status.set_mdns_backend(adb::proto::AdbServerStatus::OPENSCREEN); - } else { - status.set_mdns_backend(adb::proto::AdbServerStatus::LIBADBMDNS); - } + status.set_mdns_backend(adb::proto::AdbServerStatus::LIBADBMDNS); } else { status.set_mdns_backend(adb::proto::AdbServerStatus::MDNS_DISABLED); } diff --git a/vendor/adb/adb_mdns.cpp b/vendor/adb/adb_mdns.cpp index dde08d7..312ea3c 100644 --- a/vendor/adb/adb_mdns.cpp +++ b/vendor/adb/adb_mdns.cpp @@ -19,6 +19,7 @@ #include "adb_mdns.h" #include +#include #include #include diff --git a/vendor/adb/client/adb_wifi.cpp b/vendor/adb/client/adb_wifi.cpp index 33762f3..8a00f8d 100644 --- a/vendor/adb/client/adb_wifi.cpp +++ b/vendor/adb/client/adb_wifi.cpp @@ -177,7 +177,13 @@ bool KnownWifiHostsFile::IsKnownHost(const std::string& host) { void adb_wifi_pair_device(const std::string& host, const std::string& password, std::string& response) { - if (true) { +#if ADB_MDNS + auto mdns_info = mdns_get_pairing_service_info(host); +#else + auto mdns_info = std::optional{}; +#endif + + if (!mdns_info.has_value()) { // Check the address for a valid address and port. std::string parsed_host; std::string err; @@ -221,7 +227,9 @@ void adb_wifi_pair_device(const std::string& host, const std::string& password, PairingResultWaiter waiter; std::unique_lock lock(waiter.mutex_); - if (!client->Start(host, + if (!client->Start(mdns_info.has_value() ? fmt::format("{}:{}", mdns_info->v4_address_string(), + mdns_info->port) + : host, waiter.OnResult, &waiter)) { response = "Failed: Unable to start pairing client."; return; @@ -245,4 +253,7 @@ void adb_wifi_pair_device(const std::string& host, const std::string& password, known_wifi_hosts_file.AddKnownHost(device_guid); // Try to auto-connect. +#if ADB_MDNS + adb_secure_connect_by_service_name(device_guid); +#endif } diff --git a/vendor/adb/client/adbmdns/Cargo.toml b/vendor/adb/client/adbmdns/Cargo.toml index 63e08e6..80fe13a 100644 --- a/vendor/adb/client/adbmdns/Cargo.toml +++ b/vendor/adb/client/adbmdns/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "adb_mdns" version = "0.1.0" -edition = "2024" +edition = "2021" [lib] -name = "zeroconf" +name = "adbmdns_bridge" path = "adbmdns_bridge.rs" +crate-type = ["staticlib"] [dependencies] socket2 = { version = "0.4.0", features = ["all"] } @@ -14,11 +15,11 @@ simple-dns = "0.11.0" zerocopy = { version = "0.8.26", features = ["derive"] } libc = "0.2.174" anyhow = "1.0.99" -nix = { version = "0.29.0", features = ["socket", "uio"] } +nix = { version = "0.29.0", features = ["net", "socket", "uio"] } if-addrs = "0.14.0" mio = { version = "1.1.0", features = ["net", "os-poll"] } -[dependencies.windows-sys] +[target.'cfg(windows)'.dependencies.windows-sys] version = "0.61.1" features = [ "Win32_Foundation", diff --git a/vendor/adb/client/adbmdns/adbmdns.cpp b/vendor/adb/client/adbmdns/adbmdns.cpp index dd88283..ee0005e 100644 --- a/vendor/adb/client/adbmdns/adbmdns.cpp +++ b/vendor/adb/client/adbmdns/adbmdns.cpp @@ -17,6 +17,8 @@ #include "adbmdns.h" #include "adbmdns_bridge.h" +#include + #include #include "adb_trace.h" @@ -25,9 +27,9 @@ template requires std::is_enum_v -struct std::formatter : std::formatter { +struct fmt::formatter : fmt::formatter { constexpr auto format(const E& e, auto& ctx) const { - using Base = std::formatter; + using Base = fmt::formatter; return Base::format("Enum(" + std::to_string(e) + ")", ctx); } }; @@ -78,7 +80,7 @@ static std::vector> parseTxt(const uint32_t num_txt_kv, for (uint32_t kv_index = 0; kv_index < num_txt_kv; kv_index++) { std::string key(txt_kvs[kv_index].key, txt_kvs[kv_index].key_size); std::string value(txt_kvs[kv_index].value, txt_kvs[kv_index].value_size); - std::string entry = std::format("{}={}", key, value); + std::string entry = fmt::format("{}={}", key, value); // Convert string into vector std::vector u8_vec; diff --git a/vendor/adb/client/adbmdns/adbmdns_bridge.rs b/vendor/adb/client/adbmdns/adbmdns_bridge.rs index 507b94a..52514fb 100644 --- a/vendor/adb/client/adbmdns/adbmdns_bridge.rs +++ b/vendor/adb/client/adbmdns/adbmdns_bridge.rs @@ -297,7 +297,7 @@ impl log::Log for AdbLogger { /// 3. Accept NUL-terminated strings for all const char* parameters /// 4. Accept a buffer of `num_ipv4s` 32-bit values in `ipv4s` (expected to be network order octets) /// 5. Accept a buffer of bytes in `ipv6s` which is the size of `num_ipv6s` * 16 (expected to be a sequence of sequences of octets, flattened). -#[unsafe(no_mangle)] +#[no_mangle] pub unsafe extern "C" fn adbmdns_start( log_callback: AdbLoggerCallback, event_callback: EventCallback, diff --git a/vendor/adb/client/adbmdns/netwatch/netwatch_linux.rs b/vendor/adb/client/adbmdns/netwatch/netwatch_linux.rs index 18e1bdb..05ab96c 100644 --- a/vendor/adb/client/adbmdns/netwatch/netwatch_linux.rs +++ b/vendor/adb/client/adbmdns/netwatch/netwatch_linux.rs @@ -37,6 +37,7 @@ use nix::sys::socket::SockProtocol; use nix::sys::socket::SockType; use std::collections::HashMap; use std::fmt; +use std::mem::size_of; use std::os::fd::AsRawFd; use std::path::PathBuf; use std::thread; diff --git a/vendor/adb/client/commandline.cpp b/vendor/adb/client/commandline.cpp index abe38dc..0e77793 100644 --- a/vendor/adb/client/commandline.cpp +++ b/vendor/adb/client/commandline.cpp @@ -1950,7 +1950,9 @@ int adb_commandline(int argc, const char** argv) { ReadOrderlyShutdown(fd); return 0; } else if (!strcmp(argv[0], "mdns")) { +#if !ADB_MDNS error_exit("mdns is not supported by this version of adb."); +#endif --argc; if (argc < 1) error_exit("mdns requires an argument"); diff --git a/vendor/adb/client/main.cpp b/vendor/adb/client/main.cpp index 50a53b0..efde06c 100644 --- a/vendor/adb/client/main.cpp +++ b/vendor/adb/client/main.cpp @@ -133,6 +133,12 @@ int adb_server_main(int is_daemon, const std::string& socket_spec, const char* o init_reconnect_handler(); +#if ADB_MDNS + if (mdns::is_enabled()) { + init_mdns_transport_discovery(); + } +#endif + if (is_usb_enabled()) { if (is_libusb_enabled()) { libusb::usb_init(); diff --git a/vendor/adb/client/mdns_utils.cpp b/vendor/adb/client/mdns_utils.cpp index e578c1a..74a9036 100644 --- a/vendor/adb/client/mdns_utils.cpp +++ b/vendor/adb/client/mdns_utils.cpp @@ -78,14 +78,4 @@ bool is_enabled() { return !getenv("ADB_MDNS") || strcmp(getenv("ADB_MDNS"), "0") != 0; } -// Historically, this env variable was a boolean used to disable openscreen. -// It has evolved into an enum to select the mdns backend -// 0 = Bonjour (deprecated) -// 1 = Openscreen -// 2 = Adbmdns -bool should_use_openscreen() { - const char* mdns_osp = getenv("ADB_MDNS_OPENSCREEN"); - return mdns_osp != nullptr && strcmp(mdns_osp, "1") == 0; -} - } // namespace mdns diff --git a/vendor/adb/client/mdns_utils.h b/vendor/adb/client/mdns_utils.h index d106133..86b8fe9 100644 --- a/vendor/adb/client/mdns_utils.h +++ b/vendor/adb/client/mdns_utils.h @@ -53,6 +53,4 @@ std::optional mdns_parse_instance_name(std::string_view name); // Return true if mdns backend is enabled bool is_enabled(); - -bool should_use_openscreen(); } // namespace mdns diff --git a/vendor/adb/client/transport_mdns.cpp b/vendor/adb/client/transport_mdns.cpp index 930c695..809f156 100644 --- a/vendor/adb/client/transport_mdns.cpp +++ b/vendor/adb/client/transport_mdns.cpp @@ -132,11 +132,7 @@ void OnServiceReceiverResult(const ServiceInfo& info, ServiceInfoState state) { ///////////////////////////////////////////////////////////////////////////////// void init_mdns_transport_discovery() { - if (mdns::should_use_openscreen()) { - StartOpenScreenDiscovery(); - } else { - StartAdbMdnsDiscovery(); - } + StartAdbMdnsDiscovery(); } bool adb_secure_connect_by_service_name(const std::string& instance_name) { @@ -152,10 +148,6 @@ std::string mdns_check() { return "ERROR: mdns discovery disabled"; } - if (mdns::should_use_openscreen()) { - return "mdns daemon version [Openscreen discovery 0.0.0]"; - } - return "mdns daemon version [adb discovery 0.0.0]"; } diff --git a/vendor/adb/socket_spec.cpp b/vendor/adb/socket_spec.cpp index 3c0e2d0..e298dc3 100644 --- a/vendor/adb/socket_spec.cpp +++ b/vendor/adb/socket_spec.cpp @@ -228,7 +228,32 @@ bool socket_spec_connect(unique_fd* fd, std::string_view address, int* port, if (tcp_host_is_local(hostname)) { fd->reset(network_loopback_client(port_value, SOCK_STREAM, error)); } else { +#if !ADB_MDNS fd->reset(network_connect(hostname, port_value, SOCK_STREAM, 0, error)); +#elif ADB_HOST + // Check if the address is an mdns service we can connect to. + if (auto mdns_info = mdns_get_connect_service_info(std::string(address.substr(4))); + mdns_info != std::nullopt) { + fd->reset(network_connect(mdns_info->v4_address_string(), mdns_info->port, + SOCK_STREAM, 0, error)); + if (fd->get() != -1) { + // TODO(joshuaduong): We still show the ip address for the serial. Change it to + // use the mdns instance name, so we can adjust to address changes on + // reconnects. + port_value = mdns_info->port; + if (transport_name) { + *transport_name = + fmt::format("{}.{}", mdns_info->instance, mdns_info->service); + } + } + } else { + fd->reset(network_connect(hostname, port_value, SOCK_STREAM, 0, error)); + } +#else + // Disallow arbitrary connections in adbd. + *error = "adbd does not support arbitrary tcp connections"; + return false; +#endif } if (fd->get() > 0) { -- 2.55.0