16cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin/*
26cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin * Copyright (C) 2016 The Android Open Source Project
36cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin *
46cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin * Licensed under the Apache License, Version 2.0 (the "License");
56cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin * you may not use this file except in compliance with the License.
66cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin * You may obtain a copy of the License at
76cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin *
86cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin *      http://www.apache.org/licenses/LICENSE-2.0
96cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin *
106cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin * Unless required by applicable law or agreed to in writing, software
116cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin * distributed under the License is distributed on an "AS IS" BASIS,
126cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin * See the License for the specific language governing permissions and
146cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin * limitations under the License.
156cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin */
166cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
1713a269ea24a98111d2e84a7ffa3c05ab8a4e73a9Casey Dahlin#include "adb_mdns.h"
186cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin#include "sysdeps.h"
196cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
206cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin#include <dns_sd.h>
216cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin#include <endian.h>
226cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin#include <unistd.h>
236cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
24e1dacfc1b65b04958924d1f982263d4aa71b0b94Josh Gao#include <chrono>
25e1dacfc1b65b04958924d1f982263d4aa71b0b94Josh Gao#include <mutex>
26e1dacfc1b65b04958924d1f982263d4aa71b0b94Josh Gao#include <thread>
27e1dacfc1b65b04958924d1f982263d4aa71b0b94Josh Gao
286cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin#include <android-base/logging.h>
296cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin#include <android-base/properties.h>
306cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
316cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlinusing namespace std::chrono_literals;
326cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
336cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlinstatic std::mutex& mdns_lock = *new std::mutex();
346cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlinstatic int port;
356cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlinstatic DNSServiceRef mdns_ref;
366cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlinstatic bool mdns_registered = false;
376cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
386cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlinstatic void start_mdns() {
396cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    if (android::base::GetProperty("init.svc.mdnsd", "") == "running") {
406cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin        return;
416cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    }
426cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
436cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    android::base::SetProperty("ctl.start", "mdnsd");
446cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
456cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    if (! android::base::WaitForProperty("init.svc.mdnsd", "running", 5s)) {
466cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin        LOG(ERROR) << "Could not start mdnsd.";
476cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    }
486cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin}
496cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
506cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlinstatic void mdns_callback(DNSServiceRef /*ref*/,
516cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin                          DNSServiceFlags /*flags*/,
526cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin                          DNSServiceErrorType errorCode,
536cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin                          const char* /*name*/,
546cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin                          const char* /*regtype*/,
556cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin                          const char* /*domain*/,
566cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin                          void* /*context*/) {
576cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    if (errorCode != kDNSServiceErr_NoError) {
586cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin        LOG(ERROR) << "Encountered mDNS registration error ("
596cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin            << errorCode << ").";
606cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    }
616cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin}
626cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
63e1dacfc1b65b04958924d1f982263d4aa71b0b94Josh Gaostatic void setup_mdns_thread() {
646cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    start_mdns();
656cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    std::lock_guard<std::mutex> lock(mdns_lock);
666cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
671fe3cae67ecc20f346aa38bb0ed4500f8e2885bfCasey Dahlin    std::string hostname = "adb-";
681fe3cae67ecc20f346aa38bb0ed4500f8e2885bfCasey Dahlin    hostname += android::base::GetProperty("ro.serialno", "unidentified");
691fe3cae67ecc20f346aa38bb0ed4500f8e2885bfCasey Dahlin
701fe3cae67ecc20f346aa38bb0ed4500f8e2885bfCasey Dahlin    auto error = DNSServiceRegister(&mdns_ref, 0, 0, hostname.c_str(),
711fe3cae67ecc20f346aa38bb0ed4500f8e2885bfCasey Dahlin                                    kADBServiceType, nullptr, nullptr,
721fe3cae67ecc20f346aa38bb0ed4500f8e2885bfCasey Dahlin                                    htobe16((uint16_t)port), 0, nullptr,
731fe3cae67ecc20f346aa38bb0ed4500f8e2885bfCasey Dahlin                                    mdns_callback, nullptr);
746cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
756cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    if (error != kDNSServiceErr_NoError) {
766cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin        LOG(ERROR) << "Could not register mDNS service (" << error << ").";
776cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin        mdns_registered = false;
786cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    }
796cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
806cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    mdns_registered = true;
816cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin}
826cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
836cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlinstatic void teardown_mdns() {
846cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    std::lock_guard<std::mutex> lock(mdns_lock);
856cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
866cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    if (mdns_registered) {
876cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin        DNSServiceRefDeallocate(mdns_ref);
886cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    }
896cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin}
906cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
916cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlinvoid setup_mdns(int port_in) {
926cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    port = port_in;
93e1dacfc1b65b04958924d1f982263d4aa71b0b94Josh Gao    std::thread(setup_mdns_thread).detach();
946cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin
956cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    // TODO: Make this more robust against a hard kill.
966cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin    atexit(teardown_mdns);
976cd5e0b4efded6b86c27de7d97dd910190436867Casey Dahlin}
98