Merge changes from topic "adbwifi-client-mdns" am: a71ba615ea
am: 73447676aa
Change-Id: Ifc9736f4ab3940ad48e16691d3d0cae33adea315
This commit is contained in:
commit
560b4a0c94
|
@ -17,6 +17,72 @@
|
|||
#ifndef _ADB_MDNS_H_
|
||||
#define _ADB_MDNS_H_
|
||||
|
||||
#include <android-base/macros.h>
|
||||
|
||||
const char* kADBServiceType = "_adb._tcp";
|
||||
const char* kADBSecurePairingServiceType = "_adb_secure_pairing._tcp";
|
||||
const char* kADBSecureConnectServiceType = "_adb_secure_connect._tcp";
|
||||
|
||||
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);
|
||||
|
||||
const char* kADBDNSServices[] = {
|
||||
kADBServiceType,
|
||||
kADBSecurePairingServiceType,
|
||||
kADBSecureConnectServiceType,
|
||||
};
|
||||
|
||||
const char* kADBDNSServiceTxtRecords[] = {
|
||||
nullptr,
|
||||
kADBSecurePairingServiceTxtRecord,
|
||||
kADBSecureConnectServiceTxtRecord,
|
||||
};
|
||||
|
||||
const int kNumADBDNSServices = arraysize(kADBDNSServices);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
|
@ -86,3 +87,16 @@ std::optional<std::string> adb_get_server_executable_path();
|
|||
// Globally acccesible argv/envp, for the purpose of re-execing adb.
|
||||
extern const char* _Nullable * _Nullable __adb_argv;
|
||||
extern const char* _Nullable * _Nullable __adb_envp;
|
||||
|
||||
// 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 char* _Nonnull host_name, const char* _Nonnull ip_address, uint16_t port)>;
|
||||
|
||||
// Queries pairing/connect services that have been discovered and resolved.
|
||||
// If |host_name| is not null, run |cb| only for services
|
||||
// matching |host_name|. Otherwise, run for all services.
|
||||
void adb_secure_foreach_pairing_service(const char* _Nullable host_name,
|
||||
adb_secure_foreach_service_callback cb);
|
||||
void adb_secure_foreach_connect_service(const char* _Nullable host_name,
|
||||
adb_secure_foreach_service_callback cb);
|
||||
|
|
|
@ -25,17 +25,33 @@
|
|||
#endif
|
||||
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <dns_sd.h>
|
||||
|
||||
#include "adb_client.h"
|
||||
#include "adb_mdns.h"
|
||||
#include "adb_trace.h"
|
||||
#include "fdevent/fdevent.h"
|
||||
#include "sysdeps.h"
|
||||
|
||||
static DNSServiceRef service_ref;
|
||||
static fdevent* service_ref_fde;
|
||||
static DNSServiceRef service_refs[kNumADBDNSServices];
|
||||
static fdevent* service_ref_fdes[kNumADBDNSServices];
|
||||
|
||||
static int adb_DNSServiceIndexByName(const char* regType) {
|
||||
for (int i = 0; i < kNumADBDNSServices; ++i) {
|
||||
if (!strncmp(regType, kADBDNSServices[i], strlen(kADBDNSServices[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool adb_DNSServiceShouldConnect(const char* regType) {
|
||||
int index = adb_DNSServiceIndexByName(regType);
|
||||
return index == kADBTransportServiceRefIndex;
|
||||
}
|
||||
|
||||
// Use adb_DNSServiceRefSockFD() instead of calling DNSServiceRefSockFD()
|
||||
// directly so that the socket is put through the appropriate compatibility
|
||||
|
@ -94,10 +110,16 @@ 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) {
|
||||
ResolvedService(std::string serviceName, std::string regType, uint32_t interfaceIndex,
|
||||
const char* hosttarget, uint16_t port, int version)
|
||||
: serviceName_(serviceName),
|
||||
regType_(regType),
|
||||
hosttarget_(hosttarget),
|
||||
port_(port),
|
||||
sa_family_(0),
|
||||
ip_addr_data_(NULL),
|
||||
serviceVersion_(version) {
|
||||
memset(ip_addr_, 0, sizeof(ip_addr_));
|
||||
|
||||
/* TODO: We should be able to get IPv6 support by adding
|
||||
* kDNSServiceProtocol_IPv6 to the flags below. However, when we do
|
||||
|
@ -116,45 +138,135 @@ class ResolvedService : public AsyncServiceRef {
|
|||
} else {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
D("Client version: %d Service version: %d\n", clientVersion_, serviceVersion_);
|
||||
}
|
||||
|
||||
void Connect(const sockaddr* address) {
|
||||
char ip_addr[INET6_ADDRSTRLEN];
|
||||
const void* ip_addr_data;
|
||||
sa_family_ = address->sa_family;
|
||||
const char* addr_format;
|
||||
|
||||
if (address->sa_family == AF_INET) {
|
||||
ip_addr_data =
|
||||
&reinterpret_cast<const sockaddr_in*>(address)->sin_addr;
|
||||
if (sa_family_ == AF_INET) {
|
||||
ip_addr_data_ = &reinterpret_cast<const sockaddr_in*>(address)->sin_addr;
|
||||
addr_format = "%s:%hu";
|
||||
} else if (address->sa_family == AF_INET6) {
|
||||
ip_addr_data =
|
||||
&reinterpret_cast<const sockaddr_in6*>(address)->sin6_addr;
|
||||
} else if (sa_family_ == AF_INET6) {
|
||||
ip_addr_data_ = &reinterpret_cast<const sockaddr_in6*>(address)->sin6_addr;
|
||||
addr_format = "[%s]:%hu";
|
||||
} else { // Should be impossible
|
||||
} else { // Should be impossible
|
||||
D("mDNS resolved non-IP address.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Winsock version requires the const cast Because Microsoft.
|
||||
if (!inet_ntop(address->sa_family, const_cast<void*>(ip_addr_data),
|
||||
ip_addr, INET6_ADDRSTRLEN)) {
|
||||
if (!inet_ntop(sa_family_, const_cast<void*>(ip_addr_data_), ip_addr_, sizeof(ip_addr_))) {
|
||||
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());
|
||||
// adb secure service needs to do something different from just
|
||||
// connecting here.
|
||||
if (adb_DNSServiceShouldConnect(regType_.c_str())) {
|
||||
std::string response;
|
||||
connect_device(android::base::StringPrintf(addr_format, ip_addr_, port_), &response);
|
||||
D("Connect to %s regtype %s (%s:%hu) : %s", serviceName_.c_str(), regType_.c_str(),
|
||||
ip_addr_, port_, response.c_str());
|
||||
} else {
|
||||
D("Not immediately connecting to serviceName=[%s], regtype=[%s] ipaddr=(%s:%hu)",
|
||||
serviceName_.c_str(), regType_.c_str(), ip_addr_, port_);
|
||||
}
|
||||
|
||||
int adbSecureServiceType = serviceIndex();
|
||||
switch (adbSecureServiceType) {
|
||||
case kADBSecurePairingServiceRefIndex:
|
||||
sAdbSecurePairingServices->push_back(this);
|
||||
break;
|
||||
case kADBSecureConnectServiceRefIndex:
|
||||
sAdbSecureConnectServices->push_back(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int serviceIndex() const { return adb_DNSServiceIndexByName(regType_.c_str()); }
|
||||
|
||||
std::string hostTarget() const { return hosttarget_; }
|
||||
|
||||
std::string ipAddress() const { return ip_addr_; }
|
||||
|
||||
uint16_t port() const { return port_; }
|
||||
|
||||
using ServiceRegistry = std::vector<ResolvedService*>;
|
||||
|
||||
static ServiceRegistry* sAdbSecurePairingServices;
|
||||
static ServiceRegistry* sAdbSecureConnectServices;
|
||||
|
||||
static void initAdbSecure();
|
||||
|
||||
static void forEachService(const ServiceRegistry& services, const std::string& hostname,
|
||||
adb_secure_foreach_service_callback cb);
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
int clientVersion_ = ADB_SECURE_CLIENT_VERSION;
|
||||
std::string serviceName_;
|
||||
std::string regType_;
|
||||
std::string hosttarget_;
|
||||
const uint16_t port_;
|
||||
int sa_family_;
|
||||
const void* ip_addr_data_;
|
||||
char ip_addr_[INET6_ADDRSTRLEN];
|
||||
int serviceVersion_;
|
||||
};
|
||||
|
||||
// static
|
||||
std::vector<ResolvedService*>* ResolvedService::sAdbSecurePairingServices = NULL;
|
||||
|
||||
// static
|
||||
std::vector<ResolvedService*>* ResolvedService::sAdbSecureConnectServices = NULL;
|
||||
|
||||
// static
|
||||
void ResolvedService::initAdbSecure() {
|
||||
if (!sAdbSecurePairingServices) {
|
||||
sAdbSecurePairingServices = new ServiceRegistry;
|
||||
}
|
||||
if (!sAdbSecureConnectServices) {
|
||||
sAdbSecureConnectServices = new ServiceRegistry;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void ResolvedService::forEachService(const ServiceRegistry& services,
|
||||
const std::string& wanted_host,
|
||||
adb_secure_foreach_service_callback cb) {
|
||||
initAdbSecure();
|
||||
|
||||
for (auto service : services) {
|
||||
auto hostname = service->hostTarget();
|
||||
auto ip = service->ipAddress();
|
||||
auto port = service->port();
|
||||
|
||||
if (wanted_host == "") {
|
||||
cb(hostname.c_str(), ip.c_str(), port);
|
||||
} else if (hostname == wanted_host) {
|
||||
cb(hostname.c_str(), ip.c_str(), port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void adb_secure_foreach_pairing_service(const char* host_name,
|
||||
adb_secure_foreach_service_callback cb) {
|
||||
ResolvedService::forEachService(*ResolvedService::sAdbSecurePairingServices,
|
||||
host_name ? host_name : "", cb);
|
||||
}
|
||||
|
||||
// static
|
||||
void adb_secure_foreach_connect_service(const char* host_name,
|
||||
adb_secure_foreach_service_callback cb) {
|
||||
ResolvedService::forEachService(*ResolvedService::sAdbSecureConnectServices,
|
||||
host_name ? host_name : "", cb);
|
||||
}
|
||||
|
||||
static void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/,
|
||||
DNSServiceFlags /*flags*/,
|
||||
uint32_t /*interfaceIndex*/,
|
||||
|
@ -167,6 +279,12 @@ static void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/,
|
|||
std::unique_ptr<ResolvedService> data(
|
||||
reinterpret_cast<ResolvedService*>(context));
|
||||
data->Connect(address);
|
||||
|
||||
// For ADB Secure services, keep those ResolvedService's around
|
||||
// for later processing with secure connection establishment.
|
||||
if (data->serviceIndex() != kADBTransportServiceRefIndex) {
|
||||
data.release();
|
||||
}
|
||||
}
|
||||
|
||||
static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef,
|
||||
|
@ -182,18 +300,23 @@ static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef,
|
|||
|
||||
class DiscoveredService : public AsyncServiceRef {
|
||||
public:
|
||||
DiscoveredService(uint32_t interfaceIndex, const char* serviceName,
|
||||
const char* regtype, const char* domain)
|
||||
: serviceName_(serviceName) {
|
||||
|
||||
DiscoveredService(uint32_t interfaceIndex, const char* serviceName, const char* regtype,
|
||||
const char* domain)
|
||||
: serviceName_(serviceName), regType_(regtype) {
|
||||
DNSServiceErrorType ret =
|
||||
DNSServiceResolve(&sdRef_, 0, interfaceIndex, serviceName, regtype,
|
||||
domain, register_resolved_mdns_service,
|
||||
reinterpret_cast<void*>(this));
|
||||
|
||||
if (ret != kDNSServiceErr_NoError) {
|
||||
D("Got %d from DNSServiceResolve.", ret);
|
||||
} else {
|
||||
D("DNSServiceResolve for "
|
||||
"interfaceIndex %u "
|
||||
"serviceName %s "
|
||||
"regtype %s "
|
||||
"domain %s "
|
||||
": %d",
|
||||
interfaceIndex, serviceName, regtype, domain, ret);
|
||||
|
||||
if (ret == kDNSServiceErr_NoError) {
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
@ -202,20 +325,62 @@ class DiscoveredService : public AsyncServiceRef {
|
|||
return serviceName_.c_str();
|
||||
}
|
||||
|
||||
const char* RegType() { return regType_.c_str(); }
|
||||
|
||||
private:
|
||||
std::string serviceName_;
|
||||
std::string regType_;
|
||||
};
|
||||
|
||||
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) {
|
||||
// Returns the version the device wanted to advertise,
|
||||
// or -1 if parsing fails.
|
||||
static int parse_version_from_txt_record(uint16_t txtLen, const unsigned char* txtRecord) {
|
||||
if (!txtLen) return -1;
|
||||
if (!txtRecord) return -1;
|
||||
|
||||
// https://tools.ietf.org/html/rfc6763
|
||||
// """
|
||||
// 6.1. General Format Rules for DNS TXT Records
|
||||
//
|
||||
// A DNS TXT record can be up to 65535 (0xFFFF) bytes long. The total
|
||||
// length is indicated by the length given in the resource record header
|
||||
// in the DNS message. There is no way to tell directly from the data
|
||||
// alone how long it is (e.g., there is no length count at the start, or
|
||||
// terminating NULL byte at the end).
|
||||
// """
|
||||
|
||||
// Let's trust the TXT record's length byte
|
||||
// Worst case, it wastes 255 bytes
|
||||
std::vector<char> recordAsString(txtLen + 1, '\0');
|
||||
char* str = recordAsString.data();
|
||||
|
||||
memcpy(str, txtRecord + 1 /* skip the length byte */, txtLen);
|
||||
|
||||
// Check if it's the version key
|
||||
static const char* versionKey = "v=";
|
||||
size_t versionKeyLen = strlen(versionKey);
|
||||
|
||||
if (strncmp(versionKey, str, versionKeyLen)) return -1;
|
||||
|
||||
auto valueStart = str + versionKeyLen;
|
||||
|
||||
long parsedNumber = strtol(valueStart, 0, 10);
|
||||
|
||||
// No valid conversion. Also, 0
|
||||
// is not a valid version.
|
||||
if (!parsedNumber) return -1;
|
||||
|
||||
// Outside bounds of long.
|
||||
if (parsedNumber == LONG_MIN || parsedNumber == LONG_MAX) return -1;
|
||||
|
||||
// Possibly valid version
|
||||
return static_cast<int>(parsedNumber);
|
||||
}
|
||||
|
||||
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<DiscoveredService> discovered(
|
||||
reinterpret_cast<DiscoveredService*>(context));
|
||||
|
@ -225,10 +390,14 @@ static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef,
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: Reject certain combinations of invalid or mismatched client and
|
||||
// service versions here before creating anything.
|
||||
// At the moment, there is nothing to reject, so accept everything
|
||||
// as an optimistic default.
|
||||
auto serviceVersion = parse_version_from_txt_record(txtLen, txtRecord);
|
||||
|
||||
auto resolved =
|
||||
new ResolvedService(discovered->ServiceName(),
|
||||
interfaceIndex, hosttarget, ntohs(port));
|
||||
auto resolved = new ResolvedService(discovered->ServiceName(), discovered->RegType(),
|
||||
interfaceIndex, hosttarget, ntohs(port), serviceVersion);
|
||||
|
||||
if (! resolved->Initialized()) {
|
||||
delete resolved;
|
||||
|
@ -239,19 +408,18 @@ static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef,
|
|||
}
|
||||
}
|
||||
|
||||
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*/) {
|
||||
static void DNSSD_API on_service_browsed(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);
|
||||
fdevent_destroy(service_ref_fde);
|
||||
int serviceIndex = adb_DNSServiceIndexByName(regtype);
|
||||
if (serviceIndex != -1) {
|
||||
fdevent_destroy(service_ref_fdes[serviceIndex]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -262,21 +430,27 @@ static void DNSSD_API register_mdns_transport(DNSServiceRef sdRef,
|
|||
}
|
||||
|
||||
void init_mdns_transport_discovery_thread(void) {
|
||||
DNSServiceErrorType errorCode = DNSServiceBrowse(&service_ref, 0, 0, kADBServiceType, nullptr,
|
||||
register_mdns_transport, nullptr);
|
||||
int errorCodes[kNumADBDNSServices];
|
||||
|
||||
if (errorCode != kDNSServiceErr_NoError) {
|
||||
D("Got %d initiating mDNS browse.", errorCode);
|
||||
return;
|
||||
for (int i = 0; i < kNumADBDNSServices; ++i) {
|
||||
errorCodes[i] = DNSServiceBrowse(&service_refs[i], 0, 0, kADBDNSServices[i], nullptr,
|
||||
on_service_browsed, nullptr);
|
||||
|
||||
if (errorCodes[i] != kDNSServiceErr_NoError) {
|
||||
D("Got %d browsing for mDNS service %s.", errorCodes[i], kADBDNSServices[i]);
|
||||
}
|
||||
|
||||
if (errorCodes[i] == kDNSServiceErr_NoError) {
|
||||
fdevent_run_on_main_thread([i]() {
|
||||
service_ref_fdes[i] = fdevent_create(adb_DNSServiceRefSockFD(service_refs[i]),
|
||||
pump_service_ref, &service_refs[i]);
|
||||
fdevent_set(service_ref_fdes[i], FDE_READ);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fdevent_run_on_main_thread([]() {
|
||||
service_ref_fde =
|
||||
fdevent_create(adb_DNSServiceRefSockFD(service_ref), pump_service_ref, &service_ref);
|
||||
fdevent_set(service_ref_fde, FDE_READ);
|
||||
});
|
||||
}
|
||||
|
||||
void init_mdns_transport_discovery(void) {
|
||||
ResolvedService::initAdbSecure();
|
||||
std::thread(init_mdns_transport_discovery_thread).detach();
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "mdns.h"
|
||||
#include "adb_mdns.h"
|
||||
#include "sysdeps.h"
|
||||
|
||||
|
@ -32,8 +33,8 @@ 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 DNSServiceRef mdns_refs[kNumADBDNSServices];
|
||||
static bool mdns_registered[kNumADBDNSServices];
|
||||
|
||||
static void start_mdns() {
|
||||
if (android::base::GetProperty("init.svc.mdnsd", "") == "running") {
|
||||
|
@ -60,34 +61,86 @@ static void mdns_callback(DNSServiceRef /*ref*/,
|
|||
}
|
||||
}
|
||||
|
||||
static void setup_mdns_thread() {
|
||||
start_mdns();
|
||||
static void register_mdns_service(int index, int port) {
|
||||
std::lock_guard<std::mutex> lock(mdns_lock);
|
||||
|
||||
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);
|
||||
// https://tools.ietf.org/html/rfc6763
|
||||
// """
|
||||
// The format of the data within a DNS TXT record is one or more
|
||||
// strings, packed together in memory without any intervening gaps or
|
||||
// padding bytes for word alignment.
|
||||
//
|
||||
// The format of each constituent string within the DNS TXT record is a
|
||||
// single length byte, followed by 0-255 bytes of text data.
|
||||
// """
|
||||
//
|
||||
// Therefore:
|
||||
// 1. Begin with the string length
|
||||
// 2. No null termination
|
||||
|
||||
std::vector<char> txtRecord;
|
||||
|
||||
if (kADBDNSServiceTxtRecords[index]) {
|
||||
size_t txtRecordStringLength = strlen(kADBDNSServiceTxtRecords[index]);
|
||||
|
||||
txtRecord.resize(1 + // length byte
|
||||
txtRecordStringLength // string bytes
|
||||
);
|
||||
|
||||
txtRecord[0] = (char)txtRecordStringLength;
|
||||
memcpy(txtRecord.data() + 1, kADBDNSServiceTxtRecords[index], txtRecordStringLength);
|
||||
}
|
||||
|
||||
auto error = DNSServiceRegister(
|
||||
&mdns_refs[index], 0, 0, hostname.c_str(), kADBDNSServices[index], nullptr, nullptr,
|
||||
htobe16((uint16_t)port), (uint16_t)txtRecord.size(),
|
||||
txtRecord.empty() ? nullptr : txtRecord.data(), mdns_callback, nullptr);
|
||||
|
||||
if (error != kDNSServiceErr_NoError) {
|
||||
LOG(ERROR) << "Could not register mDNS service (" << error << ").";
|
||||
return;
|
||||
LOG(ERROR) << "Could not register mDNS service " << kADBDNSServices[index] << ", error ("
|
||||
<< error << ").";
|
||||
mdns_registered[index] = false;
|
||||
}
|
||||
|
||||
mdns_registered = true;
|
||||
mdns_registered[index] = true;
|
||||
|
||||
LOG(INFO) << "adbd mDNS service " << kADBDNSServices[index]
|
||||
<< " registered: " << mdns_registered[index];
|
||||
}
|
||||
|
||||
static void teardown_mdns() {
|
||||
static void unregister_mdns_service(int index) {
|
||||
std::lock_guard<std::mutex> lock(mdns_lock);
|
||||
|
||||
if (mdns_registered) {
|
||||
DNSServiceRefDeallocate(mdns_ref);
|
||||
if (mdns_registered[index]) {
|
||||
DNSServiceRefDeallocate(mdns_refs[index]);
|
||||
}
|
||||
}
|
||||
|
||||
static void register_base_mdns_transport() {
|
||||
register_mdns_service(kADBTransportServiceRefIndex, port);
|
||||
}
|
||||
|
||||
static void setup_mdns_thread() {
|
||||
start_mdns();
|
||||
|
||||
// We will now only set up the normal transport mDNS service
|
||||
// instead of registering all the adb secure mDNS services
|
||||
// in the beginning. This is to provide more privacy/security.
|
||||
register_base_mdns_transport();
|
||||
}
|
||||
|
||||
// This also tears down any adb secure mDNS services, if they exist.
|
||||
static void teardown_mdns() {
|
||||
for (int i = 0; i < kNumADBDNSServices; ++i) {
|
||||
unregister_mdns_service(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Public interface/////////////////////////////////////////////////////////////
|
||||
|
||||
void setup_mdns(int port_in) {
|
||||
port = port_in;
|
||||
std::thread(setup_mdns_thread).detach();
|
||||
|
@ -95,3 +148,33 @@ void setup_mdns(int port_in) {
|
|||
// TODO: Make this more robust against a hard kill.
|
||||
atexit(teardown_mdns);
|
||||
}
|
||||
|
||||
void register_adb_secure_pairing_service(int port) {
|
||||
std::thread([port]() {
|
||||
register_mdns_service(kADBSecurePairingServiceRefIndex, port);
|
||||
}).detach();
|
||||
}
|
||||
|
||||
void unregister_adb_secure_pairing_service() {
|
||||
std::thread([]() { unregister_mdns_service(kADBSecurePairingServiceRefIndex); }).detach();
|
||||
}
|
||||
|
||||
bool is_adb_secure_pairing_service_registered() {
|
||||
std::lock_guard<std::mutex> lock(mdns_lock);
|
||||
return mdns_registered[kADBSecurePairingServiceRefIndex];
|
||||
}
|
||||
|
||||
void register_adb_secure_connect_service(int port) {
|
||||
std::thread([port]() {
|
||||
register_mdns_service(kADBSecureConnectServiceRefIndex, port);
|
||||
}).detach();
|
||||
}
|
||||
|
||||
void unregister_adb_secure_connect_service() {
|
||||
std::thread([]() { unregister_mdns_service(kADBSecureConnectServiceRefIndex); }).detach();
|
||||
}
|
||||
|
||||
bool is_adb_secure_connect_service_registered() {
|
||||
std::lock_guard<std::mutex> lock(mdns_lock);
|
||||
return mdns_registered[kADBSecureConnectServiceRefIndex];
|
||||
}
|
||||
|
|
|
@ -19,4 +19,12 @@
|
|||
|
||||
void setup_mdns(int port);
|
||||
|
||||
void register_adb_secure_pairing_service(int port);
|
||||
void unregister_adb_secure_pairing_service(int port);
|
||||
bool is_adb_secure_pairing_service_registered();
|
||||
|
||||
void register_adb_secure_connect_service(int port);
|
||||
void unregister_adb_secure_connect_service(int port);
|
||||
bool is_adb_secure_connect_service_registered();
|
||||
|
||||
#endif // _DAEMON_MDNS_H_
|
||||
|
|
Loading…
Reference in New Issue