From 6cd5e0b4efded6b86c27de7d97dd910190436867 Mon Sep 17 00:00:00 2001 From: Casey Dahlin Date: Fri, 6 May 2016 16:19:13 -0700 Subject: [PATCH 1/6] Make ADBD announce its presence over mDNS We now request mdnsd from adb and register a service of type _adb._tcp for clients to connect to. Test: Verified service appears in avahi-browse Bug: 28074466 (cherry picked from 379ac414e4d9f53388d903913022a55695292775) Change-Id: Ie871b9c8b40e86063cc1e68e8f3e4290ead2d279 --- adb/Android.mk | 2 + adb/daemon/main.cpp | 11 +++++- adb/daemon/mdns.cpp | 90 +++++++++++++++++++++++++++++++++++++++++++++ adb/daemon/mdns.h | 22 +++++++++++ 4 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 adb/daemon/mdns.cpp create mode 100644 adb/daemon/mdns.h diff --git a/adb/Android.mk b/adb/Android.mk index a2ea699bc..d5b8ddb24 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -325,6 +325,7 @@ LOCAL_CLANG := true LOCAL_SRC_FILES := \ daemon/main.cpp \ + daemon/mdns.cpp \ services.cpp \ file_sync_service.cpp \ framebuffer_service.cpp \ @@ -372,6 +373,7 @@ LOCAL_STATIC_LIBRARIES := \ libcrypto_utils \ libcrypto \ libminijail \ + libmdnssd \ libdebuggerd_handler \ include $(BUILD_EXECUTABLE) diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp index 6382b6789..7da94ce10 100644 --- a/adb/daemon/main.cpp +++ b/adb/daemon/main.cpp @@ -45,6 +45,8 @@ #include "adb_utils.h" #include "transport.h" +#include "mdns.h" + static const char* root_seclabel = nullptr; static void drop_capabilities_bounding_set_if_needed(struct minijail *j) { @@ -140,6 +142,11 @@ static void drop_privileges(int server_port) { } } +static void setup_port(int port) { + local_init(port); + setup_mdns(port); +} + int adbd_main(int server_port) { umask(0); @@ -188,10 +195,10 @@ int adbd_main(int server_port) { if (sscanf(prop_port.c_str(), "%d", &port) == 1 && port > 0) { D("using port=%d", port); // Listen on TCP port specified by service.adb.tcp.port property. - local_init(port); + setup_port(port); } else if (!is_usb) { // Listen on default port. - local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); + setup_port(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); } D("adbd_main(): pre init_jdwp()"); diff --git a/adb/daemon/mdns.cpp b/adb/daemon/mdns.cpp new file mode 100644 index 000000000..85c5a07d4 --- /dev/null +++ b/adb/daemon/mdns.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sysdeps.h" + +#include +#include +#include +#include +#include + +#include +#include + +using namespace std::chrono_literals; + +static std::mutex& mdns_lock = *new std::mutex(); +static int port; +static DNSServiceRef mdns_ref; +static bool mdns_registered = false; + +static void start_mdns() { + if (android::base::GetProperty("init.svc.mdnsd", "") == "running") { + return; + } + + android::base::SetProperty("ctl.start", "mdnsd"); + + if (! android::base::WaitForProperty("init.svc.mdnsd", "running", 5s)) { + LOG(ERROR) << "Could not start mdnsd."; + } +} + +static void mdns_callback(DNSServiceRef /*ref*/, + DNSServiceFlags /*flags*/, + DNSServiceErrorType errorCode, + const char* /*name*/, + const char* /*regtype*/, + const char* /*domain*/, + void* /*context*/) { + if (errorCode != kDNSServiceErr_NoError) { + LOG(ERROR) << "Encountered mDNS registration error (" + << errorCode << ")."; + } +} + +static void setup_mdns_thread(void* /* unused */) { + start_mdns(); + std::lock_guard lock(mdns_lock); + + auto error = DNSServiceRegister(&mdns_ref, 0, 0, nullptr, "_adb._tcp", + nullptr, nullptr, htobe16((uint16_t)port), + 0, nullptr, mdns_callback, nullptr); + + if (error != kDNSServiceErr_NoError) { + LOG(ERROR) << "Could not register mDNS service (" << error << ")."; + mdns_registered = false; + } + + mdns_registered = true; +} + +static void teardown_mdns() { + std::lock_guard lock(mdns_lock); + + if (mdns_registered) { + DNSServiceRefDeallocate(mdns_ref); + } +} + +void setup_mdns(int port_in) { + port = port_in; + adb_thread_create(setup_mdns_thread, nullptr, nullptr); + + // TODO: Make this more robust against a hard kill. + atexit(teardown_mdns); +} diff --git a/adb/daemon/mdns.h b/adb/daemon/mdns.h new file mode 100644 index 000000000..4c6b1ca02 --- /dev/null +++ b/adb/daemon/mdns.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DAEMON_MDNS_H_ +#define _DAEMON_MDNS_H_ + +void setup_mdns(int port); + +#endif // _DAEMON_MDNS_H_ From 1fe3cae67ecc20f346aa38bb0ed4500f8e2885bf Mon Sep 17 00:00:00 2001 From: Casey Dahlin Date: Fri, 20 May 2016 16:34:51 -0700 Subject: [PATCH 2/6] adb: Set a hostname for mDNS Now all devices won't appear as "Android." Should make it easier to multiplex. Test: Verified locally on a raspberry pi 3 Bug: 28887278 (cherry picked from 815b23319635d264ae0ce2c8c29a5776a57b8051) Change-Id: Icfd0116477543af6a3049c14d818c1cff7fc3b93 --- adb/daemon/mdns.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/adb/daemon/mdns.cpp b/adb/daemon/mdns.cpp index 85c5a07d4..a8622ae08 100644 --- a/adb/daemon/mdns.cpp +++ b/adb/daemon/mdns.cpp @@ -61,9 +61,13 @@ static void setup_mdns_thread(void* /* unused */) { start_mdns(); std::lock_guard lock(mdns_lock); - auto error = DNSServiceRegister(&mdns_ref, 0, 0, nullptr, "_adb._tcp", - nullptr, nullptr, htobe16((uint16_t)port), - 0, nullptr, mdns_callback, nullptr); + std::string hostname = "adb-"; + hostname += android::base::GetProperty("ro.serialno", "unidentified"); + + auto error = DNSServiceRegister(&mdns_ref, 0, 0, hostname.c_str(), + kADBServiceType, nullptr, nullptr, + htobe16((uint16_t)port), 0, nullptr, + mdns_callback, nullptr); if (error != kDNSServiceErr_NoError) { LOG(ERROR) << "Could not register mDNS service (" << error << ")."; From 13a269ea24a98111d2e84a7ffa3c05ab8a4e73a9 Mon Sep 17 00:00:00 2001 From: Casey Dahlin Date: Thu, 23 Jun 2016 14:19:37 -0700 Subject: [PATCH 3/6] Add mDNS device discovery for adb client Test: Was able to discover a raspberry pi. Bug: 28074466 (cherry picked from e292cd16760321fccc99c8c261cb92fa4b6462ab) Change-Id: Id9571576457a4a0a078e48a274a4e8eac78bfe2b --- adb/Android.mk | 5 +- adb/adb_mdns.h | 22 ++++ adb/client/main.cpp | 2 + adb/daemon/mdns.cpp | 1 + adb/services.cpp | 39 ------ adb/transport.h | 4 + adb/transport_local.cpp | 41 +++++++ adb/transport_mdns.cpp | 257 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 331 insertions(+), 40 deletions(-) create mode 100644 adb/adb_mdns.h create mode 100644 adb/transport_mdns.cpp diff --git a/adb/Android.mk b/adb/Android.mk index d5b8ddb24..ef29695b0 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -145,6 +145,7 @@ LOCAL_CFLAGS_darwin := $(LIBADB_darwin_CFLAGS) LOCAL_SRC_FILES := \ $(LIBADB_SRC_FILES) \ adb_auth_host.cpp \ + transport_mdns.cpp LOCAL_SRC_FILES_darwin := $(LIBADB_darwin_SRC_FILES) LOCAL_SRC_FILES_linux := $(LIBADB_linux_SRC_FILES) @@ -154,7 +155,7 @@ LOCAL_SANITIZE := $(adb_host_sanitize) # Even though we're building a static library (and thus there's no link step for # this to take effect), this adds the includes to our path. -LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase +LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase libmdnssd LOCAL_STATIC_LIBRARIES_linux := libusb LOCAL_STATIC_LIBRARIES_darwin := libusb @@ -225,6 +226,7 @@ LOCAL_STATIC_LIBRARIES := \ libcutils \ libdiagnose_usb \ libgmock_host \ + libmdnssd \ LOCAL_STATIC_LIBRARIES_linux := libusb LOCAL_STATIC_LIBRARIES_darwin := libusb @@ -292,6 +294,7 @@ LOCAL_STATIC_LIBRARIES := \ libcrypto \ libdiagnose_usb \ liblog \ + libmdnssd \ # Don't use libcutils on Windows. LOCAL_STATIC_LIBRARIES_darwin := libcutils diff --git a/adb/adb_mdns.h b/adb/adb_mdns.h new file mode 100644 index 000000000..2e544d7fe --- /dev/null +++ b/adb/adb_mdns.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ADB_MDNS_H_ +#define _ADB_MDNS_H_ + +const char* kADBServiceType = "_adb._tcp"; + +#endif diff --git a/adb/client/main.cpp b/adb/client/main.cpp index 97a54fd6c..606203cb4 100644 --- a/adb/client/main.cpp +++ b/adb/client/main.cpp @@ -117,6 +117,8 @@ int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply init_transport_registration(); + init_mdns_transport_discovery(); + usb_init(); local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); diff --git a/adb/daemon/mdns.cpp b/adb/daemon/mdns.cpp index a8622ae08..781114351 100644 --- a/adb/daemon/mdns.cpp +++ b/adb/daemon/mdns.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "adb_mdns.h" #include "sysdeps.h" #include diff --git a/adb/services.cpp b/adb/services.cpp index a48d85512..47f0a03d7 100644 --- a/adb/services.cpp +++ b/adb/services.cpp @@ -377,45 +377,6 @@ static void wait_for_state(int fd, void* data) { D("wait_for_state is done"); } -static void connect_device(const std::string& address, std::string* response) { - if (address.empty()) { - *response = "empty address"; - return; - } - - std::string serial; - std::string host; - int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; - if (!android::base::ParseNetAddress(address, &host, &port, &serial, response)) { - return; - } - - std::string error; - int fd = network_connect(host.c_str(), port, SOCK_STREAM, 10, &error); - if (fd == -1) { - *response = android::base::StringPrintf("unable to connect to %s: %s", - serial.c_str(), error.c_str()); - return; - } - - D("client: connected %s remote on fd %d", serial.c_str(), fd); - close_on_exec(fd); - disable_tcp_nagle(fd); - - // Send a TCP keepalive ping to the device every second so we can detect disconnects. - if (!set_tcp_keepalive(fd, 1)) { - D("warning: failed to configure TCP keepalives (%s)", strerror(errno)); - } - - int ret = register_socket_transport(fd, serial.c_str(), port, 0); - if (ret < 0) { - adb_close(fd); - *response = android::base::StringPrintf("already connected to %s", serial.c_str()); - } else { - *response = android::base::StringPrintf("connected to %s", serial.c_str()); - } -} - void connect_emulator(const std::string& port_spec, std::string* response) { std::vector pieces = android::base::Split(port_spec, ","); if (pieces.size() != 2) { diff --git a/adb/transport.h b/adb/transport.h index 490e51329..4d97fc78b 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -187,6 +187,7 @@ void kick_transport(atransport* t); void update_transports(void); void init_transport_registration(void); +void init_mdns_transport_discovery(void); std::string list_transports(bool long_listing); atransport* find_transport(const char* serial); void kick_all_tcp_devices(); @@ -194,6 +195,9 @@ void kick_all_tcp_devices(); void register_usb_transport(usb_handle* h, const char* serial, const char* devpath, unsigned writeable); +/* Connect to a network address and register it as a device */ +void connect_device(const std::string& address, std::string* response); + /* cause new transports to be init'd and added to the list */ int register_socket_transport(int s, const char* serial, int port, int local); diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp index b5d0ef070..12b98ba3b 100644 --- a/adb/transport_local.cpp +++ b/adb/transport_local.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -101,6 +102,46 @@ bool local_connect(int port) { return local_connect_arbitrary_ports(port-1, port, &dummy) == 0; } +void connect_device(const std::string& address, std::string* response) { + if (address.empty()) { + *response = "empty address"; + return; + } + + std::string serial; + std::string host; + int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; + if (!android::base::ParseNetAddress(address, &host, &port, &serial, response)) { + return; + } + + std::string error; + int fd = network_connect(host.c_str(), port, SOCK_STREAM, 10, &error); + if (fd == -1) { + *response = android::base::StringPrintf("unable to connect to %s: %s", + serial.c_str(), error.c_str()); + return; + } + + D("client: connected %s remote on fd %d", serial.c_str(), fd); + close_on_exec(fd); + disable_tcp_nagle(fd); + + // Send a TCP keepalive ping to the device every second so we can detect disconnects. + if (!set_tcp_keepalive(fd, 1)) { + D("warning: failed to configure TCP keepalives (%s)", strerror(errno)); + } + + int ret = register_socket_transport(fd, serial.c_str(), port, 0); + if (ret < 0) { + adb_close(fd); + *response = android::base::StringPrintf("already connected to %s", serial.c_str()); + } else { + *response = android::base::StringPrintf("connected to %s", serial.c_str()); + } +} + + int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error) { int fd = -1; diff --git a/adb/transport_mdns.cpp b/adb/transport_mdns.cpp new file mode 100644 index 000000000..b63fc83b4 --- /dev/null +++ b/adb/transport_mdns.cpp @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define TRACE_TAG TRANSPORT + +#include "transport.h" + +#include + +#include +#include + +#include "adb_mdns.h" +#include "adb_trace.h" +#include "fdevent.h" +#include "sysdeps.h" + +static DNSServiceRef service_ref; +static fdevent service_ref_fde; + +static void register_service_ip(DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char* hostname, + const sockaddr* address, + uint32_t ttl, + void* context); + +static void pump_service_ref(int /*fd*/, unsigned ev, void* data) { + DNSServiceRef* ref = reinterpret_cast(data); + + if (ev & FDE_READ) + DNSServiceProcessResult(*ref); +} + +class AsyncServiceRef { + public: + bool Initialized() { + return initialized_; + } + + virtual ~AsyncServiceRef() { + if (! initialized_) { + return; + } + + DNSServiceRefDeallocate(sdRef_); + fdevent_remove(&fde_); + } + + protected: + DNSServiceRef sdRef_; + + void Initialize() { + fdevent_install(&fde_, DNSServiceRefSockFD(sdRef_), + pump_service_ref, &sdRef_); + fdevent_set(&fde_, FDE_READ); + initialized_ = true; + } + + private: + bool initialized_; + fdevent fde_; +}; + +class ResolvedService : public AsyncServiceRef { + public: + virtual ~ResolvedService() = default; + + ResolvedService(std::string name, uint32_t interfaceIndex, + const char* hosttarget, uint16_t port) : + name_(name), + port_(port) { + DNSServiceErrorType ret = + DNSServiceGetAddrInfo( + &sdRef_, 0, interfaceIndex, + kDNSServiceProtocol_IPv6|kDNSServiceProtocol_IPv4, hosttarget, + register_service_ip, reinterpret_cast(this)); + + if (ret != kDNSServiceErr_NoError) { + D("Got %d from DNSServiceGetAddrInfo.", ret); + } else { + Initialize(); + } + } + + void Connect(const sockaddr* address) { + char ip_addr[INET6_ADDRSTRLEN]; + const void* ip_addr_data; + const char* addr_format; + + if (address->sa_family == AF_INET) { + ip_addr_data = + &reinterpret_cast(address)->sin_addr; + addr_format = "%s:%hu"; + } else if (address->sa_family == AF_INET6) { + ip_addr_data = + &reinterpret_cast(address)->sin6_addr; + addr_format = "[%s]:%hu"; + } else { // Should be impossible + D("mDNS resolved non-IP address."); + return; + } + + if (!inet_ntop(address->sa_family, ip_addr_data, ip_addr, + INET6_ADDRSTRLEN)) { + D("Could not convert IP address to string."); + return; + } + + std::string response; + connect_device(android::base::StringPrintf(addr_format, ip_addr, port_), + &response); + D("Connect to %s (%s:%hu) : %s", name_.c_str(), ip_addr, port_, + response.c_str()); + } + + private: + std::string name_; + const uint16_t port_; +}; + +static void register_service_ip(DNSServiceRef /*sdRef*/, + DNSServiceFlags /*flags*/, + uint32_t /*interfaceIndex*/, + DNSServiceErrorType /*errorCode*/, + const char* /*hostname*/, + const sockaddr* address, + uint32_t /*ttl*/, + void* context) { + std::unique_ptr data( + reinterpret_cast(context)); + data->Connect(address); +} + +static void register_resolved_mdns_service(DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char* fullname, + const char* hosttarget, + uint16_t port, + uint16_t txtLen, + const unsigned char* txtRecord, + void* context); + +class DiscoveredService : public AsyncServiceRef { + public: + DiscoveredService(uint32_t interfaceIndex, const char* serviceName, + const char* regtype, const char* domain) + : serviceName_(serviceName) { + + DNSServiceErrorType ret = + DNSServiceResolve(&sdRef_, 0, interfaceIndex, serviceName, regtype, + domain, register_resolved_mdns_service, + reinterpret_cast(this)); + + if (ret != kDNSServiceErr_NoError) { + D("Got %d from DNSServiceResolve.", ret); + } else { + Initialize(); + } + } + + const char* ServiceName() { + return serviceName_.c_str(); + } + + private: + std::string serviceName_; +}; + +static void register_resolved_mdns_service(DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char* fullname, + const char* hosttarget, + uint16_t port, + uint16_t /*txtLen*/, + const unsigned char* /*txtRecord*/, + void* context) { + std::unique_ptr discovered( + reinterpret_cast(context)); + + if (errorCode != kDNSServiceErr_NoError) { + D("Got error %d resolving service.", errorCode); + return; + } + + + auto resolved = + new ResolvedService(discovered->ServiceName(), + interfaceIndex, hosttarget, ntohs(port)); + + if (! resolved->Initialized()) { + delete resolved; + } + + if (flags) { /* Only ever equals MoreComing or 0 */ + discovered.release(); + } +} + +static void register_mdns_transport(DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char* serviceName, + const char* regtype, + const char* domain, + void* /*context*/) { + if (errorCode != kDNSServiceErr_NoError) { + D("Got error %d during mDNS browse.", errorCode); + DNSServiceRefDeallocate(sdRef); + fdevent_remove(&service_ref_fde); + return; + } + + auto discovered = new DiscoveredService(interfaceIndex, serviceName, + regtype, domain); + + if (! discovered->Initialized()) { + delete discovered; + } +} + +void init_mdns_transport_discovery(void) { + DNSServiceErrorType errorCode = + DNSServiceBrowse(&service_ref, 0, 0, kADBServiceType, nullptr, + register_mdns_transport, nullptr); + + if (errorCode != kDNSServiceErr_NoError) { + D("Got %d initiating mDNS browse.", errorCode); + return; + } + + fdevent_install(&service_ref_fde, + DNSServiceRefSockFD(service_ref), + pump_service_ref, + &service_ref); + fdevent_set(&service_ref_fde, FDE_READ); +} From d6c8091e9f5cc31e6face99253c3805d9cc7058b Mon Sep 17 00:00:00 2001 From: Casey Dahlin Date: Tue, 19 Jul 2016 14:18:54 -0700 Subject: [PATCH 4/6] Don't include mDNS support on platforms other than Linux Test: Shamu build now passes Bug: None (cherry picked from 122a7738606d854d6dc10fa361c1d7296cc9670a) Change-Id: I650adf0bca96fb655163f5e9b27d9995ae448ec2 --- adb/Android.mk | 21 +++++++++++---------- adb/transport_mdns_unsupported.cpp | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 adb/transport_mdns_unsupported.cpp diff --git a/adb/Android.mk b/adb/Android.mk index ef29695b0..233a21f23 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -144,19 +144,22 @@ LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS) LOCAL_CFLAGS_darwin := $(LIBADB_darwin_CFLAGS) LOCAL_SRC_FILES := \ $(LIBADB_SRC_FILES) \ - adb_auth_host.cpp \ - transport_mdns.cpp + adb_auth_host.cpp LOCAL_SRC_FILES_darwin := $(LIBADB_darwin_SRC_FILES) LOCAL_SRC_FILES_linux := $(LIBADB_linux_SRC_FILES) LOCAL_SRC_FILES_windows := $(LIBADB_windows_SRC_FILES) +LOCAL_SRC_FILES_linux += transport_mdns.cpp +LOCAL_SRC_FILES_darwin += transport_mdns_unsupported.cpp +LOCAL_SRC_FILES_windows += transport_mdns_unsupported.cpp + LOCAL_SANITIZE := $(adb_host_sanitize) # Even though we're building a static library (and thus there's no link step for # this to take effect), this adds the includes to our path. -LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase libmdnssd -LOCAL_STATIC_LIBRARIES_linux := libusb +LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase +LOCAL_STATIC_LIBRARIES_linux := libusb libmdnssd LOCAL_STATIC_LIBRARIES_darwin := libusb LOCAL_C_INCLUDES_windows := development/host/windows/usb/api/ @@ -225,10 +228,9 @@ LOCAL_STATIC_LIBRARIES := \ libcrypto \ libcutils \ libdiagnose_usb \ - libgmock_host \ - libmdnssd \ + libgmock_host -LOCAL_STATIC_LIBRARIES_linux := libusb +LOCAL_STATIC_LIBRARIES_linux := libusb libmdnssd LOCAL_STATIC_LIBRARIES_darwin := libusb # Set entrypoint to wmain from sysdeps_win32.cpp instead of main @@ -293,12 +295,11 @@ LOCAL_STATIC_LIBRARIES := \ libcrypto_utils \ libcrypto \ libdiagnose_usb \ - liblog \ - libmdnssd \ + liblog # Don't use libcutils on Windows. LOCAL_STATIC_LIBRARIES_darwin := libcutils -LOCAL_STATIC_LIBRARIES_linux := libcutils +LOCAL_STATIC_LIBRARIES_linux := libcutils libmdnssd LOCAL_STATIC_LIBRARIES_darwin += libusb LOCAL_STATIC_LIBRARIES_linux += libusb diff --git a/adb/transport_mdns_unsupported.cpp b/adb/transport_mdns_unsupported.cpp new file mode 100644 index 000000000..387d34132 --- /dev/null +++ b/adb/transport_mdns_unsupported.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* For when mDNS discovery is unsupported */ +void init_mdns_transport_discovery(void) {} From 304150a521b95654a0568536d2f8c7696dbbb333 Mon Sep 17 00:00:00 2001 From: Casey Dahlin Date: Tue, 23 Aug 2016 14:48:28 -0700 Subject: [PATCH 5/6] Enable mDNS on Darwin We have to disable IPv6 to get this going, but nobody was yet using IPv6, so that should be fine for now. Test: Verified mDNS discovery on a MacBook Bug: 31042497 (cherry picked from 9ae65de087171072f3890a81b074ae27db319508) Change-Id: I628f0a1e9c4784db42fa56f5faf2904b6e1cf548 --- adb/Android.mk | 2 +- adb/transport_mdns.cpp | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/adb/Android.mk b/adb/Android.mk index 233a21f23..b12a9f8a7 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -151,7 +151,7 @@ LOCAL_SRC_FILES_linux := $(LIBADB_linux_SRC_FILES) LOCAL_SRC_FILES_windows := $(LIBADB_windows_SRC_FILES) LOCAL_SRC_FILES_linux += transport_mdns.cpp -LOCAL_SRC_FILES_darwin += transport_mdns_unsupported.cpp +LOCAL_SRC_FILES_darwin += transport_mdns.cpp LOCAL_SRC_FILES_windows += transport_mdns_unsupported.cpp LOCAL_SANITIZE := $(adb_host_sanitize) diff --git a/adb/transport_mdns.cpp b/adb/transport_mdns.cpp index b63fc83b4..384845252 100644 --- a/adb/transport_mdns.cpp +++ b/adb/transport_mdns.cpp @@ -85,10 +85,17 @@ class ResolvedService : public AsyncServiceRef { const char* hosttarget, uint16_t port) : name_(name), port_(port) { + + /* TODO: We should be able to get IPv6 support by adding + * kDNSServiceProtocol_IPv6 to the flags below. However, when we do + * this, we get served link-local addresses that are usually useless to + * connect to. What's more, we seem to /only/ get those and nothing else. + * If we want IPv6 in the future we'll have to figure out why. + */ DNSServiceErrorType ret = DNSServiceGetAddrInfo( &sdRef_, 0, interfaceIndex, - kDNSServiceProtocol_IPv6|kDNSServiceProtocol_IPv4, hosttarget, + kDNSServiceProtocol_IPv4, hosttarget, register_service_ip, reinterpret_cast(this)); if (ret != kDNSServiceErr_NoError) { From 2fe9b6047536e1dbb3e6253bd6c2b3400d6f5903 Mon Sep 17 00:00:00 2001 From: Casey Dahlin Date: Wed, 21 Sep 2016 14:03:39 -0700 Subject: [PATCH 6/6] Make ADB over mDNS work on Windows Test: Verified ADB over mDNS on a Windows machine Bug: 30482671 (cherry picked from 9fdd77101f49d03ff29342e12e23edf241f68522) Change-Id: If955ca304db71a5b08c5a9654f1e27ab74af9af8 --- adb/Android.mk | 21 ++++---- adb/sysdeps.h | 7 +++ adb/sysdeps_win32.cpp | 17 ++++--- adb/transport_mdns.cpp | 112 +++++++++++++++++++++++------------------ 4 files changed, 92 insertions(+), 65 deletions(-) diff --git a/adb/Android.mk b/adb/Android.mk index b12a9f8a7..8a43e37bc 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -144,22 +144,19 @@ LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS) LOCAL_CFLAGS_darwin := $(LIBADB_darwin_CFLAGS) LOCAL_SRC_FILES := \ $(LIBADB_SRC_FILES) \ - adb_auth_host.cpp + adb_auth_host.cpp \ + transport_mdns.cpp \ LOCAL_SRC_FILES_darwin := $(LIBADB_darwin_SRC_FILES) LOCAL_SRC_FILES_linux := $(LIBADB_linux_SRC_FILES) LOCAL_SRC_FILES_windows := $(LIBADB_windows_SRC_FILES) -LOCAL_SRC_FILES_linux += transport_mdns.cpp -LOCAL_SRC_FILES_darwin += transport_mdns.cpp -LOCAL_SRC_FILES_windows += transport_mdns_unsupported.cpp - LOCAL_SANITIZE := $(adb_host_sanitize) # Even though we're building a static library (and thus there's no link step for # this to take effect), this adds the includes to our path. -LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase -LOCAL_STATIC_LIBRARIES_linux := libusb libmdnssd +LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase libmdnssd +LOCAL_STATIC_LIBRARIES_linux := libusb LOCAL_STATIC_LIBRARIES_darwin := libusb LOCAL_C_INCLUDES_windows := development/host/windows/usb/api/ @@ -180,7 +177,7 @@ LOCAL_SRC_FILES := \ shell_service_test.cpp \ LOCAL_SANITIZE := $(adb_target_sanitize) -LOCAL_STATIC_LIBRARIES := libadbd libcrypto_utils libcrypto libusb +LOCAL_STATIC_LIBRARIES := libadbd libcrypto_utils libcrypto libusb libmdnssd LOCAL_SHARED_LIBRARIES := liblog libbase libcutils include $(BUILD_NATIVE_TEST) @@ -228,9 +225,10 @@ LOCAL_STATIC_LIBRARIES := \ libcrypto \ libcutils \ libdiagnose_usb \ + libmdnssd \ libgmock_host -LOCAL_STATIC_LIBRARIES_linux := libusb libmdnssd +LOCAL_STATIC_LIBRARIES_linux := libusb LOCAL_STATIC_LIBRARIES_darwin := libusb # Set entrypoint to wmain from sysdeps_win32.cpp instead of main @@ -295,11 +293,12 @@ LOCAL_STATIC_LIBRARIES := \ libcrypto_utils \ libcrypto \ libdiagnose_usb \ - liblog + liblog \ + libmdnssd # Don't use libcutils on Windows. LOCAL_STATIC_LIBRARIES_darwin := libcutils -LOCAL_STATIC_LIBRARIES_linux := libcutils libmdnssd +LOCAL_STATIC_LIBRARIES_linux := libcutils LOCAL_STATIC_LIBRARIES_darwin += libusb LOCAL_STATIC_LIBRARIES_linux += libusb diff --git a/adb/sysdeps.h b/adb/sysdeps.h index 654072c35..f195b4eb4 100644 --- a/adb/sysdeps.h +++ b/adb/sysdeps.h @@ -197,6 +197,7 @@ extern int adb_write(int fd, const void* buf, int len); extern int adb_lseek(int fd, int pos, int where); extern int adb_shutdown(int fd); extern int adb_close(int fd); +extern int adb_register_socket(SOCKET s); // See the comments for the !defined(_WIN32) version of unix_close(). static __inline__ int unix_close(int fd) @@ -523,6 +524,12 @@ __inline__ int adb_close(int fd) { #undef close #define close ____xxx_close +// On Windows, ADB has an indirection layer for file descriptors. If we get a +// Win32 SOCKET object from an external library, we have to map it in to that +// indirection layer, which this does. +__inline__ int adb_register_socket(int s) { + return s; +} static __inline__ int adb_read(int fd, void* buf, size_t len) { diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp index a4b5e6978..f997e6b84 100644 --- a/adb/sysdeps_win32.cpp +++ b/adb/sysdeps_win32.cpp @@ -126,10 +126,7 @@ typedef struct FHRec_ SOCKET socket; } u; - int mask; - char name[32]; - } FHRec; #define fh_handle u.handle @@ -577,7 +574,6 @@ extern int adb_poll(adb_pollfd* fds, size_t nfds, int timeout) { static void _fh_socket_init(FH f) { f->fh_socket = INVALID_SOCKET; - f->mask = 0; } static int _fh_socket_close( FH f ) { @@ -598,7 +594,6 @@ static int _fh_socket_close( FH f ) { } f->fh_socket = INVALID_SOCKET; } - f->mask = 0; return 0; } @@ -913,6 +908,12 @@ int network_connect(const std::string& host, int port, int type, int timeout, st return fd; } +int adb_register_socket(SOCKET s) { + FH f = _fh_alloc( &_fh_socket_class ); + f->fh_socket = s; + return _fh_to_int(f); +} + #undef accept int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen) { @@ -1113,18 +1114,22 @@ bool set_file_block_mode(int fd, bool block) { if (!fh || !fh->used) { errno = EBADF; + D("Setting nonblocking on bad file descriptor %d", fd); return false; } if (fh->clazz == &_fh_socket_class) { u_long x = !block; if (ioctlsocket(fh->u.socket, FIONBIO, &x) != 0) { - _socket_set_errno(WSAGetLastError()); + int error = WSAGetLastError(); + _socket_set_errno(error); + D("Setting %d nonblocking failed (%d)", fd, error); return false; } return true; } else { errno = ENOTSOCK; + D("Setting nonblocking on non-socket %d", fd); return false; } } diff --git a/adb/transport_mdns.cpp b/adb/transport_mdns.cpp index 384845252..e49b1c668 100644 --- a/adb/transport_mdns.cpp +++ b/adb/transport_mdns.cpp @@ -18,7 +18,11 @@ #include "transport.h" +#ifdef _WIN32 +#include +#else #include +#endif #include #include @@ -31,14 +35,22 @@ static DNSServiceRef service_ref; static fdevent service_ref_fde; -static void register_service_ip(DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char* hostname, - const sockaddr* address, - uint32_t ttl, - void* context); +// Use adb_DNSServiceRefSockFD() instead of calling DNSServiceRefSockFD() +// directly so that the socket is put through the appropriate compatibility +// layers to work with the rest of ADB's internal APIs. +static inline int adb_DNSServiceRefSockFD(DNSServiceRef ref) { + return adb_register_socket(DNSServiceRefSockFD(ref)); +} +#define DNSServiceRefSockFD ___xxx_DNSServiceRefSockFD + +static void DNSSD_API register_service_ip(DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char* hostname, + const sockaddr* address, + uint32_t ttl, + void* context); static void pump_service_ref(int /*fd*/, unsigned ev, void* data) { DNSServiceRef* ref = reinterpret_cast(data); @@ -66,7 +78,7 @@ class AsyncServiceRef { DNSServiceRef sdRef_; void Initialize() { - fdevent_install(&fde_, DNSServiceRefSockFD(sdRef_), + fdevent_install(&fde_, adb_DNSServiceRefSockFD(sdRef_), pump_service_ref, &sdRef_); fdevent_set(&fde_, FDE_READ); initialized_ = true; @@ -123,8 +135,9 @@ class ResolvedService : public AsyncServiceRef { return; } - if (!inet_ntop(address->sa_family, ip_addr_data, ip_addr, - INET6_ADDRSTRLEN)) { + // Winsock version requires the const cast Because Microsoft. + if (!inet_ntop(address->sa_family, const_cast(ip_addr_data), + ip_addr, INET6_ADDRSTRLEN)) { D("Could not convert IP address to string."); return; } @@ -141,29 +154,30 @@ class ResolvedService : public AsyncServiceRef { const uint16_t port_; }; -static void register_service_ip(DNSServiceRef /*sdRef*/, - DNSServiceFlags /*flags*/, - uint32_t /*interfaceIndex*/, - DNSServiceErrorType /*errorCode*/, - const char* /*hostname*/, - const sockaddr* address, - uint32_t /*ttl*/, - void* context) { +static void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/, + DNSServiceFlags /*flags*/, + uint32_t /*interfaceIndex*/, + DNSServiceErrorType /*errorCode*/, + const char* /*hostname*/, + const sockaddr* address, + uint32_t /*ttl*/, + void* context) { + D("Got IP for service."); std::unique_ptr data( reinterpret_cast(context)); data->Connect(address); } -static void register_resolved_mdns_service(DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char* fullname, - const char* hosttarget, - uint16_t port, - uint16_t txtLen, - const unsigned char* txtRecord, - void* context); +static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char* fullname, + const char* hosttarget, + uint16_t port, + uint16_t txtLen, + const unsigned char* txtRecord, + void* context); class DiscoveredService : public AsyncServiceRef { public: @@ -191,16 +205,17 @@ class DiscoveredService : public AsyncServiceRef { std::string serviceName_; }; -static void register_resolved_mdns_service(DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char* fullname, - const char* hosttarget, - uint16_t port, - uint16_t /*txtLen*/, - const unsigned char* /*txtRecord*/, - void* context) { +static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char* fullname, + const char* hosttarget, + uint16_t port, + uint16_t /*txtLen*/, + const unsigned char* /*txtRecord*/, + void* context) { + D("Resolved a service."); std::unique_ptr discovered( reinterpret_cast(context)); @@ -223,14 +238,15 @@ static void register_resolved_mdns_service(DNSServiceRef sdRef, } } -static void register_mdns_transport(DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char* serviceName, - const char* regtype, - const char* domain, - void* /*context*/) { +static void DNSSD_API register_mdns_transport(DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char* serviceName, + const char* regtype, + const char* domain, + void* /*context*/) { + D("Registering a transport."); if (errorCode != kDNSServiceErr_NoError) { D("Got error %d during mDNS browse.", errorCode); DNSServiceRefDeallocate(sdRef); @@ -257,7 +273,7 @@ void init_mdns_transport_discovery(void) { } fdevent_install(&service_ref_fde, - DNSServiceRefSockFD(service_ref), + adb_DNSServiceRefSockFD(service_ref), pump_service_ref, &service_ref); fdevent_set(&service_ref_fde, FDE_READ);