113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin/* 213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * Copyright (C) 2016 The Android Open Source Project 313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * 413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * Licensed under the Apache License, Version 2.0 (the "License"); 513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * you may not use this file except in compliance with the License. 613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * You may obtain a copy of the License at 713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * 813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * http://www.apache.org/licenses/LICENSE-2.0 913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * 1013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * Unless required by applicable law or agreed to in writing, software 1113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * distributed under the License is distributed on an "AS IS" BASIS, 1213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * See the License for the specific language governing permissions and 1413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin * limitations under the License. 1513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin */ 1613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 1713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin#define TRACE_TAG TRANSPORT 1813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 1913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin#include "transport.h" 2013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 212fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin#ifdef _WIN32 222fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin#include <winsock2.h> 232fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin#else 2413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin#include <arpa/inet.h> 252fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin#endif 2613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 276f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao#include <thread> 286f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao 2913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin#include <android-base/stringprintf.h> 3013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin#include <dns_sd.h> 3113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 3213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin#include "adb_mdns.h" 3313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin#include "adb_trace.h" 3413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin#include "fdevent.h" 3513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin#include "sysdeps.h" 3613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 3713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlinstatic DNSServiceRef service_ref; 3813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlinstatic fdevent service_ref_fde; 3913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 402fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin// Use adb_DNSServiceRefSockFD() instead of calling DNSServiceRefSockFD() 412fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin// directly so that the socket is put through the appropriate compatibility 422fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin// layers to work with the rest of ADB's internal APIs. 432fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlinstatic inline int adb_DNSServiceRefSockFD(DNSServiceRef ref) { 442fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin return adb_register_socket(DNSServiceRefSockFD(ref)); 452fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin} 462fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin#define DNSServiceRefSockFD ___xxx_DNSServiceRefSockFD 472fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin 482fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlinstatic void DNSSD_API register_service_ip(DNSServiceRef sdRef, 492fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin DNSServiceFlags flags, 502fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin uint32_t interfaceIndex, 512fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin DNSServiceErrorType errorCode, 522fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const char* hostname, 532fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const sockaddr* address, 542fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin uint32_t ttl, 552fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin void* context); 5613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 5713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlinstatic void pump_service_ref(int /*fd*/, unsigned ev, void* data) { 5813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin DNSServiceRef* ref = reinterpret_cast<DNSServiceRef*>(data); 5913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 6013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin if (ev & FDE_READ) 6113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin DNSServiceProcessResult(*ref); 6213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin} 6313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 6413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlinclass AsyncServiceRef { 6513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin public: 6613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin bool Initialized() { 6713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin return initialized_; 6813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 6913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 7013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin virtual ~AsyncServiceRef() { 7113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin if (! initialized_) { 7213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin return; 7313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 7413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 7513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin DNSServiceRefDeallocate(sdRef_); 7613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin fdevent_remove(&fde_); 7713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 7813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 7913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin protected: 8013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin DNSServiceRef sdRef_; 8113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 8213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin void Initialize() { 832fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin fdevent_install(&fde_, adb_DNSServiceRefSockFD(sdRef_), 8413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin pump_service_ref, &sdRef_); 8513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin fdevent_set(&fde_, FDE_READ); 8613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin initialized_ = true; 8713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 8813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 8913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin private: 9013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin bool initialized_; 9113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin fdevent fde_; 9213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin}; 9313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 9413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlinclass ResolvedService : public AsyncServiceRef { 9513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin public: 9613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin virtual ~ResolvedService() = default; 9713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 9813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin ResolvedService(std::string name, uint32_t interfaceIndex, 9913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin const char* hosttarget, uint16_t port) : 10013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin name_(name), 10113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin port_(port) { 102304150a521b95654a0568536d2f8c7696dbbb333Casey Dahlin 103304150a521b95654a0568536d2f8c7696dbbb333Casey Dahlin /* TODO: We should be able to get IPv6 support by adding 104304150a521b95654a0568536d2f8c7696dbbb333Casey Dahlin * kDNSServiceProtocol_IPv6 to the flags below. However, when we do 105304150a521b95654a0568536d2f8c7696dbbb333Casey Dahlin * this, we get served link-local addresses that are usually useless to 106304150a521b95654a0568536d2f8c7696dbbb333Casey Dahlin * connect to. What's more, we seem to /only/ get those and nothing else. 107304150a521b95654a0568536d2f8c7696dbbb333Casey Dahlin * If we want IPv6 in the future we'll have to figure out why. 108304150a521b95654a0568536d2f8c7696dbbb333Casey Dahlin */ 10913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin DNSServiceErrorType ret = 11013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin DNSServiceGetAddrInfo( 11113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin &sdRef_, 0, interfaceIndex, 112304150a521b95654a0568536d2f8c7696dbbb333Casey Dahlin kDNSServiceProtocol_IPv4, hosttarget, 11313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin register_service_ip, reinterpret_cast<void*>(this)); 11413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 11513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin if (ret != kDNSServiceErr_NoError) { 11613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin D("Got %d from DNSServiceGetAddrInfo.", ret); 11713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } else { 11813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin Initialize(); 11913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 12013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 12113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 12213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin void Connect(const sockaddr* address) { 12313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin char ip_addr[INET6_ADDRSTRLEN]; 12413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin const void* ip_addr_data; 12513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin const char* addr_format; 12613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 12713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin if (address->sa_family == AF_INET) { 12813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin ip_addr_data = 12913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin &reinterpret_cast<const sockaddr_in*>(address)->sin_addr; 13013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin addr_format = "%s:%hu"; 13113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } else if (address->sa_family == AF_INET6) { 13213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin ip_addr_data = 13313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin &reinterpret_cast<const sockaddr_in6*>(address)->sin6_addr; 13413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin addr_format = "[%s]:%hu"; 13513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } else { // Should be impossible 13613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin D("mDNS resolved non-IP address."); 13713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin return; 13813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 13913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 1402fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin // Winsock version requires the const cast Because Microsoft. 1412fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin if (!inet_ntop(address->sa_family, const_cast<void*>(ip_addr_data), 1422fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin ip_addr, INET6_ADDRSTRLEN)) { 14313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin D("Could not convert IP address to string."); 14413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin return; 14513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 14613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 14713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin std::string response; 14813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin connect_device(android::base::StringPrintf(addr_format, ip_addr, port_), 14913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin &response); 15013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin D("Connect to %s (%s:%hu) : %s", name_.c_str(), ip_addr, port_, 15113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin response.c_str()); 15213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 15313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 15413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin private: 15513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin std::string name_; 15613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin const uint16_t port_; 15713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin}; 15813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 1592fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlinstatic void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/, 1602fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin DNSServiceFlags /*flags*/, 1612fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin uint32_t /*interfaceIndex*/, 1622fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin DNSServiceErrorType /*errorCode*/, 1632fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const char* /*hostname*/, 1642fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const sockaddr* address, 1652fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin uint32_t /*ttl*/, 1662fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin void* context) { 1672fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin D("Got IP for service."); 16813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin std::unique_ptr<ResolvedService> data( 16913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin reinterpret_cast<ResolvedService*>(context)); 17013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin data->Connect(address); 17113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin} 17213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 1732fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlinstatic void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, 1742fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin DNSServiceFlags flags, 1752fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin uint32_t interfaceIndex, 1762fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin DNSServiceErrorType errorCode, 1772fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const char* fullname, 1782fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const char* hosttarget, 1792fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin uint16_t port, 1802fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin uint16_t txtLen, 1812fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const unsigned char* txtRecord, 1822fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin void* context); 18313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 18413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlinclass DiscoveredService : public AsyncServiceRef { 18513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin public: 18613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin DiscoveredService(uint32_t interfaceIndex, const char* serviceName, 18713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin const char* regtype, const char* domain) 18813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin : serviceName_(serviceName) { 18913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 19013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin DNSServiceErrorType ret = 19113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin DNSServiceResolve(&sdRef_, 0, interfaceIndex, serviceName, regtype, 19213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin domain, register_resolved_mdns_service, 19313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin reinterpret_cast<void*>(this)); 19413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 19513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin if (ret != kDNSServiceErr_NoError) { 19613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin D("Got %d from DNSServiceResolve.", ret); 19713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } else { 19813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin Initialize(); 19913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 20013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 20113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 20213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin const char* ServiceName() { 20313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin return serviceName_.c_str(); 20413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 20513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 20613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin private: 20713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin std::string serviceName_; 20813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin}; 20913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 2102fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlinstatic void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef, 2112fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin DNSServiceFlags flags, 2122fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin uint32_t interfaceIndex, 2132fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin DNSServiceErrorType errorCode, 2142fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const char* fullname, 2152fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const char* hosttarget, 2162fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin uint16_t port, 2172fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin uint16_t /*txtLen*/, 2182fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const unsigned char* /*txtRecord*/, 2192fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin void* context) { 2202fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin D("Resolved a service."); 22113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin std::unique_ptr<DiscoveredService> discovered( 22213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin reinterpret_cast<DiscoveredService*>(context)); 22313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 22413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin if (errorCode != kDNSServiceErr_NoError) { 22513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin D("Got error %d resolving service.", errorCode); 22613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin return; 22713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 22813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 22913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 23013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin auto resolved = 23113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin new ResolvedService(discovered->ServiceName(), 23213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin interfaceIndex, hosttarget, ntohs(port)); 23313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 23413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin if (! resolved->Initialized()) { 23513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin delete resolved; 23613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 23713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 23813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin if (flags) { /* Only ever equals MoreComing or 0 */ 23913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin discovered.release(); 24013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 24113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin} 24213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 2432fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlinstatic void DNSSD_API register_mdns_transport(DNSServiceRef sdRef, 2442fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin DNSServiceFlags flags, 2452fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin uint32_t interfaceIndex, 2462fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin DNSServiceErrorType errorCode, 2472fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const char* serviceName, 2482fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const char* regtype, 2492fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin const char* domain, 2502fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin void* /*context*/) { 2512fe9b6047536e1dbb3e6253bd6c2b3400d6f5903Casey Dahlin D("Registering a transport."); 25213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin if (errorCode != kDNSServiceErr_NoError) { 25313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin D("Got error %d during mDNS browse.", errorCode); 25413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin DNSServiceRefDeallocate(sdRef); 25513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin fdevent_remove(&service_ref_fde); 25613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin return; 25713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 25813a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 25913a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin auto discovered = new DiscoveredService(interfaceIndex, serviceName, 26013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin regtype, domain); 26113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 26213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin if (! discovered->Initialized()) { 26313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin delete discovered; 26413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 26513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin} 26613a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 2676f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gaovoid init_mdns_transport_discovery_thread(void) { 2686f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao DNSServiceErrorType errorCode = DNSServiceBrowse(&service_ref, 0, 0, kADBServiceType, nullptr, 2696f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao register_mdns_transport, nullptr); 27013a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 27113a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin if (errorCode != kDNSServiceErr_NoError) { 27213a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin D("Got %d initiating mDNS browse.", errorCode); 27313a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin return; 27413a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin } 27513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin 2766f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao fdevent_run_on_main_thread([]() { 2776f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao fdevent_install(&service_ref_fde, adb_DNSServiceRefSockFD(service_ref), pump_service_ref, 2786f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao &service_ref); 2796f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao fdevent_set(&service_ref_fde, FDE_READ); 2806f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao }); 2816f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao} 2826f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao 2836f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gaovoid init_mdns_transport_discovery(void) { 2846f46e6b912b2cd30a699757c3f4bbf9b679e2b79Josh Gao std::thread(init_mdns_transport_discovery_thread).detach(); 28513a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin} 286