Skip to content

Commit

Permalink
Openscreen discovery integration for adb client.
Browse files Browse the repository at this point in the history
The openscreen discovery library will allow adb client on all three
platforms to discover mdns services without relying on having Bonjour on
the host machine.

If the host does have bonjour running, we will fallback to using the
MdnsResponder client.

The openscreen discovery code path will be disabled by default for now.
You can enable it by setting ADB_MDNS_OPENSCREEN=1. Check `adb
host-features` string for 'openscreen_mdns' feature.

Test: test_adb.py

Bug: 152884934
Change-Id: Ief153afe7f080cb21134897d8eaf00d90c6983d8
  • Loading branch information
jdd510 committed Mar 17, 2021
1 parent 8df5407 commit f4ba8d7
Show file tree
Hide file tree
Showing 23 changed files with 2,532 additions and 695 deletions.
19 changes: 18 additions & 1 deletion Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
tidy_errors = [
"-*",
"bugprone-inaccurate-erase",
"bugprone-use-after-move",
]

cc_defaults {
Expand Down Expand Up @@ -76,6 +77,7 @@ cc_defaults {
"-lws2_32",
"-lgdi32",
"-luserenv",
"-liphlpapi",
],
},
},
Expand Down Expand Up @@ -181,6 +183,7 @@ libadb_srcs = [
"adb.cpp",
"adb_io.cpp",
"adb_listeners.cpp",
"adb_mdns.cpp",
"adb_trace.cpp",
"adb_unique_fd.cpp",
"adb_utils.cpp",
Expand Down Expand Up @@ -233,13 +236,19 @@ cc_library_host_static {
defaults: ["adb_defaults"],

srcs: libadb_srcs + [
"client/openscreen/mdns_service_info.cpp",
"client/openscreen/mdns_service_watcher.cpp",
"client/openscreen/platform/logging.cpp",
"client/openscreen/platform/task_runner.cpp",
"client/openscreen/platform/udp_socket.cpp",
"client/auth.cpp",
"client/adb_wifi.cpp",
"client/usb_libusb.cpp",
"client/usb_dispatch.cpp",
"client/transport_local.cpp",
"client/transport_mdns.cpp",
"client/mdnsresponder_client.cpp",
"client/mdns_utils.cpp",
"client/transport_mdns.cpp",
"client/transport_usb.cpp",
"client/pairing/pairing_client.cpp",
],
Expand Down Expand Up @@ -279,6 +288,8 @@ cc_library_host_static {
"libutils",
"liblog",
"libcutils",
"libopenscreen-discovery",
"libopenscreen-platform-impl",
"libprotobuf-cpp-lite",
],
}
Expand Down Expand Up @@ -344,6 +355,8 @@ cc_test_host {
"liblog",
"libmdnssd",
"libdiagnose_usb",
"libopenscreen-discovery",
"libopenscreen-platform-impl",
"libprotobuf-cpp-lite",
"libssl",
"libusb",
Expand Down Expand Up @@ -406,6 +419,8 @@ cc_binary_host {
"liblog",
"liblz4",
"libmdnssd",
"libopenscreen-discovery",
"libopenscreen-platform-impl",
"libprotobuf-cpp-full",
"libssl",
"libusb",
Expand Down Expand Up @@ -907,6 +922,8 @@ cc_test_host {
"libfastdeploy_host",
"liblog",
"libmdnssd",
"libopenscreen-discovery",
"libopenscreen-platform-impl",
"libprotobuf-cpp-lite",
"libssl",
"libusb",
Expand Down
8 changes: 8 additions & 0 deletions PREUPLOAD.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[Builtin Hooks]
clang_format = true

[Builtin Hooks Options]
clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp

[Hook Scripts]
aosp_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "."
2 changes: 1 addition & 1 deletion adb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@
#include "adb_auth.h"
#include "adb_io.h"
#include "adb_listeners.h"
#include "adb_mdns.h"
#include "adb_unique_fd.h"
#include "adb_utils.h"
#include "adb_wifi.h"
#include "sysdeps/chrono.h"
#include "transport.h"

Expand Down
138 changes: 138 additions & 0 deletions adb_mdns.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Copyright (C) 2020 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 "adb_mdns.h"

#include <set>

#include <android-base/stringprintf.h>
#include <android-base/strings.h>

#include "adb_trace.h"

#define ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ver) ("v=" #ver)

const char* kADBSecurePairingServiceTxtRecord =
ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ADB_SECURE_SERVICE_VERSION);
const char* kADBSecureConnectServiceTxtRecord =
ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ADB_SECURE_SERVICE_VERSION);

#define ADB_FULL_MDNS_SERVICE_TYPE(atype) ("_" atype "._tcp")
const char* kADBDNSServices[] = {ADB_FULL_MDNS_SERVICE_TYPE(ADB_MDNS_SERVICE_TYPE),
ADB_FULL_MDNS_SERVICE_TYPE(ADB_MDNS_TLS_PAIRING_TYPE),
ADB_FULL_MDNS_SERVICE_TYPE(ADB_MDNS_TLS_CONNECT_TYPE)};

const char* kADBDNSServiceTxtRecords[] = {
nullptr,
kADBSecurePairingServiceTxtRecord,
kADBSecureConnectServiceTxtRecord,
};

#if ADB_HOST
namespace {

std::atomic<bool> g_allowedlist_configured{false};
[[clang::no_destroy]] std::set<int> g_autoconn_allowedlist;

void config_auto_connect_services() {
bool expected = false;
if (!g_allowedlist_configured.compare_exchange_strong(expected, true)) {
return;
}

// ADB_MDNS_AUTO_CONNECT is a comma-delimited list of mdns services
// that are allowed to auto-connect. By default, only allow "adb-tls-connect"
// to auto-connect, since this is filtered down to auto-connect only to paired
// devices.
g_autoconn_allowedlist.insert(kADBSecureConnectServiceRefIndex);
const char* srvs = getenv("ADB_MDNS_AUTO_CONNECT");
if (!srvs) {
return;
}

if (strcmp(srvs, "0") == 0) {
D("Disabling all auto-connecting");
g_autoconn_allowedlist.clear();
return;
}

if (strcmp(srvs, "all") == 0) {
D("Allow all auto-connecting");
g_autoconn_allowedlist.insert(kADBTransportServiceRefIndex);
return;
}

// Selectively choose which services to allow auto-connect.
// E.g. ADB_MDNS_AUTO_CONNECT=adb,adb-tls-connect would allow
// _adb._tcp and _adb-tls-connnect._tcp services to auto-connect.
auto srvs_list = android::base::Split(srvs, ",");
std::set<int> new_allowedlist;
for (const auto& item : srvs_list) {
auto full_srv = android::base::StringPrintf("_%s._tcp", item.data());
std::optional<int> idx = adb_DNSServiceIndexByName(full_srv);
if (idx.has_value()) {
new_allowedlist.insert(*idx);
}
}

if (!new_allowedlist.empty()) {
g_autoconn_allowedlist = std::move(new_allowedlist);
}

std::string res;
std::for_each(g_autoconn_allowedlist.begin(), g_autoconn_allowedlist.end(), [&](const int& i) {
res += kADBDNSServices[i];
res += ",";
});
D("mdns auto-connect allowedlist: [%s]", res.data());
}

} // namespace

std::optional<int> adb_DNSServiceIndexByName(std::string_view reg_type) {
for (int i = 0; i < kNumADBDNSServices; ++i) {
if (!strncmp(reg_type.data(), kADBDNSServices[i], strlen(kADBDNSServices[i]))) {
return i;
}
}
return std::nullopt;
}

bool adb_DNSServiceShouldAutoConnect(std::string_view reg_type, std::string_view service_name) {
config_auto_connect_services();

// Try to auto-connect to any "_adb" or "_adb-tls-connect" services excluding emulator services.
std::optional<int> index = adb_DNSServiceIndexByName(reg_type);
if (!index ||
(index != kADBTransportServiceRefIndex && index != kADBSecureConnectServiceRefIndex)) {
return false;
}
if (g_autoconn_allowedlist.find(*index) == g_autoconn_allowedlist.end()) {
D("Auto-connect for reg_type '%s' disabled", reg_type.data());
return false;
}
// Ignore adb-EMULATOR* service names, as it interferes with the
// emulator ports that are already connected.
if (android::base::StartsWith(service_name, "adb-EMULATOR")) {
LOG(INFO) << "Ignoring emulator transport service [" << service_name << "]";
return false;
}
return true;
}

#endif // ADB_HOST
114 changes: 60 additions & 54 deletions adb_mdns.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
* limitations under the License.
*/

#ifndef _ADB_MDNS_H_
#define _ADB_MDNS_H_
#pragma once

#include <android-base/macros.h>
#include <optional>
#include <string>
#include <string_view>

// The rules for Service Names [RFC6335] state that they may be no more
// than fifteen characters long (not counting the mandatory underscore),
Expand All @@ -28,65 +29,70 @@
#define ADB_MDNS_TLS_PAIRING_TYPE "adb-tls-pairing"
#define ADB_MDNS_TLS_CONNECT_TYPE "adb-tls-connect"

const int kADBTransportServiceRefIndex = 0;
const int kADBSecurePairingServiceRefIndex = 1;
const int kADBSecureConnectServiceRefIndex = 2;

// Each ADB Secure service advertises with a TXT record indicating the version
// using a key/value pair per RFC 6763 (https://tools.ietf.org/html/rfc6763).
//
// The first key/value pair is always the version of the protocol.
// There may be more key/value pairs added after.
//
// The version is purposely represented as the single letter "v" due to the
// need to minimize DNS traffic. The version starts at 1. With each breaking
// protocol change, the version is incremented by 1.
//
// Newer adb clients/daemons need to recognize and either reject
// or be backward-compatible with older verseions if there is a mismatch.
//
// Relevant sections:
//
// """
// 6.4. Rules for Keys in DNS-SD Key/Value Pairs
//
// The key MUST be at least one character. DNS-SD TXT record strings
// beginning with an '=' character (i.e., the key is missing) MUST be
// silently ignored.
//
// ...
//
// 6.5. Rules for Values in DNS-SD Key/Value Pairs
//
// If there is an '=' in a DNS-SD TXT record string, then everything
// after the first '=' to the end of the string is the value. The value
// can contain any eight-bit values including '='.
// """

#define ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ver) ("v=" #ver)

// Client/service versions are initially defined to be matching,
// but may go out of sync as different clients and services
// try to talk to each other.
#define ADB_SECURE_SERVICE_VERSION 1
#define ADB_SECURE_CLIENT_VERSION ADB_SECURE_SERVICE_VERSION

const char* kADBSecurePairingServiceTxtRecord =
ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ADB_SECURE_SERVICE_VERSION);
const char* kADBSecureConnectServiceTxtRecord =
ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ADB_SECURE_SERVICE_VERSION);
constexpr int kADBTransportServiceRefIndex = 0;
constexpr int kADBSecurePairingServiceRefIndex = 1;
constexpr int kADBSecureConnectServiceRefIndex = 2;
constexpr int kNumADBDNSServices = 3;

extern const char* _Nonnull kADBSecurePairingServiceTxtRecord;
extern const char* _Nonnull kADBSecureConnectServiceTxtRecord;

extern const char* _Nonnull kADBDNSServices[kNumADBDNSServices];
extern const char* _Nonnull kADBDNSServiceTxtRecords[kNumADBDNSServices];

#if ADB_HOST
// ADB Secure DNS service interface. Used to query what ADB Secure DNS services have been
// resolved, and to run some kind of callback for each one.
using adb_secure_foreach_service_callback =
std::function<void(const std::string& service_name, const std::string& reg_type,
const std::string& ip_address, uint16_t port)>;

#define ADB_FULL_MDNS_SERVICE_TYPE(atype) ("_" atype "._tcp")
const char* kADBDNSServices[] = {ADB_FULL_MDNS_SERVICE_TYPE(ADB_MDNS_SERVICE_TYPE),
ADB_FULL_MDNS_SERVICE_TYPE(ADB_MDNS_TLS_PAIRING_TYPE),
ADB_FULL_MDNS_SERVICE_TYPE(ADB_MDNS_TLS_CONNECT_TYPE)};
// Tries to connect to a |service_name| if found. Returns true if found and
// connected, false otherwise.
bool adb_secure_connect_by_service_name(const std::string& instance_name);

const char* kADBDNSServiceTxtRecords[] = {
nullptr,
kADBSecurePairingServiceTxtRecord,
kADBSecureConnectServiceTxtRecord,
// Returns the index in kADBDNSServices array if |reg_type| matches a service name, otherwise
// std::nullopt.
std::optional<int> adb_DNSServiceIndexByName(std::string_view reg_type);
// Returns true if auto-connect is allowed for |service_name| and |instance_name|.
// See ADB_MDNS_AUTO_CONNECT environment variable for more info.
bool adb_DNSServiceShouldAutoConnect(std::string_view service_name, std::string_view instance_name);

void mdns_cleanup(void);
std::string mdns_check();
std::string mdns_list_discovered_services();

struct MdnsInfo {
std::string service_name;
std::string service_type;
std::string addr;
uint16_t port = 0;

MdnsInfo(std::string_view name, std::string_view type, std::string_view addr, uint16_t port)
: service_name(name), service_type(type), addr(addr), port(port) {}
};

const int kNumADBDNSServices = arraysize(kADBDNSServices);
std::optional<MdnsInfo> mdns_get_connect_service_info(const std::string& name);
std::optional<MdnsInfo> mdns_get_pairing_service_info(const std::string& name);

// TODO: Remove once openscreen has support for bonjour client APIs.
struct AdbMdnsResponderFuncs {
std::string (*_Nonnull mdns_check)(void);
std::string (*_Nonnull mdns_list_discovered_services)(void);
std::optional<MdnsInfo> (*_Nonnull mdns_get_connect_service_info)(const std::string&);
std::optional<MdnsInfo> (*_Nonnull mdns_get_pairing_service_info)(const std::string&);
void (*_Nonnull mdns_cleanup)(void);
bool (*_Nonnull adb_secure_connect_by_service_name)(const std::string&);
}; // AdbBonjourCallbacks

#endif
// TODO: Remove once openscreen has support for bonjour client APIs.
// Start mdns discovery using MdnsResponder backend. Fills in AdbMdnsResponderFuncs for adb mdns
// related functions.
AdbMdnsResponderFuncs StartMdnsResponderDiscovery();
#endif // ADB_HOST
16 changes: 0 additions & 16 deletions adb_wifi.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,6 @@ void adb_wifi_pair_device(const std::string& host, const std::string& password,
std::string& response);
bool adb_wifi_is_known_host(const std::string& host);

std::string mdns_check();
std::string mdns_list_discovered_services();

struct MdnsInfo {
std::string service_name;
std::string service_type;
std::string addr;
uint16_t port = 0;

MdnsInfo(std::string_view name, std::string_view type, std::string_view addr, uint16_t port)
: service_name(name), service_type(type), addr(addr), port(port) {}
};

std::optional<MdnsInfo> mdns_get_connect_service_info(std::string_view name);
std::optional<MdnsInfo> mdns_get_pairing_service_info(std::string_view name);

#else // !ADB_HOST

struct AdbdAuthContext;
Expand Down
Loading

0 comments on commit f4ba8d7

Please sign in to comment.