MDnsSdListener.cpp revision 745e09fc5694e73920aaad18a626275597bdddb1
1745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt/* 2745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * Copyright (C) 2010 The Android Open Source Project 3745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * 4745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License"); 5745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * you may not use this file except in compliance with the License. 6745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * You may obtain a copy of the License at 7745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * 8745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * http://www.apache.org/licenses/LICENSE-2.0 9745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * 10745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * Unless required by applicable law or agreed to in writing, software 11745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS, 12745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * See the License for the specific language governing permissions and 14745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * limitations under the License. 15745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt */ 16745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 17745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <arpa/inet.h> 18745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <dirent.h> 19745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <errno.h> 20745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <linux/if.h> 21745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <netdb.h> 22745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <netinet/in.h> 23745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <pthread.h> 24745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <stdlib.h> 25745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <sys/poll.h> 26745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <sys/socket.h> 27745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <sys/types.h> 28745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <string.h> 29745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 30745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define LOG_TAG "MDnsDS" 31745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define DBG 1 32745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define VDBG 1 33745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 34745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <cutils/log.h> 35745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <cutils/properties.h> 36745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <sysutils/SocketClient.h> 37745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 38745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include "MDnsSdListener.h" 39745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include "ResponseCode.h" 40745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 41745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define MDNS_SERVICE_NAME "mdnsd" 42745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define MDNS_SERVICE_STATUS "init.svc.mdnsd" 43745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 44745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltMDnsSdListener::MDnsSdListener() : 45745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt FrameworkListener("mdns", true) { 46745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Monitor *m = new Monitor(); 47745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt registerCmd(new Handler(m, this)); 48745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 49745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 50745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltMDnsSdListener::Handler::Handler(Monitor *m, MDnsSdListener *listener) : 51745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt NetdCommand("mdnssd") { 52745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGD("MDnsSdListener::Hander starting up"); 53745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor = m; 54745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mListener = listener; 55745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 56745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 57745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltMDnsSdListener::Handler::~Handler() {} 58745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 59745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::discover(SocketClient *cli, 60745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *iface, 61745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *regType, 62745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *domain, 63745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const int requestId, 64745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const int requestFlags) { 65745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 66745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("discover(%s, %s, %s, %d, %d)", iface, regType, domain, requestId, 67745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt requestFlags); 68745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 69745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Context *context = new Context(requestId, mListener); 70745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context); 71745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 72745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("requestId %d already in use during discover call", requestId); 73745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 74745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "RequestId already in use during discover call", false); 75745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 76745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 77745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("using ref %p", ref); 78745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceFlags nativeFlags = iToFlags(requestFlags); 79745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int interfaceInt = ifaceNameToI(iface); 80745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 81745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType result = DNSServiceBrowse(ref, nativeFlags, interfaceInt, regType, 82745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt domain, &MDnsSdListenerDiscoverCallback, context); 83745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (result != kDNSServiceErr_NoError) { 84745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("Discover request %d got an error from DNSServiceBrowse %d", requestId, result); 85745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 86745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 87745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Discover request got an error from DNSServiceBrowse", false); 88745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 89745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 90745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->startMonitoring(requestId); 91745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("discover successful"); 92745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "Discover operation started", false); 93745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 94745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 95745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 96745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerDiscoverCallback(DNSServiceRef sdRef, DNSServiceFlags flags, 97745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, 98745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *regType, const char *replyDomain, void *inContext) { 99745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 100745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 101745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 102745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 103745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 104745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 105745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceDiscoveryFailed, msg, false); 106745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("discover failure for %d, error= %d", refNumber, errorCode); 107745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 108745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int respCode; 109745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (flags & kDNSServiceFlagsAdd) { 110745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 111745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Discover found new serviceName %s, regType %s and domain %s for %d", 112745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceName, regType, replyDomain, refNumber); 113745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 114745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt respCode = ResponseCode::ServiceDiscoveryServiceAdded; 115745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 116745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 117745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Discover lost serviceName %s, regType %s and domain %s for %d", 118745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceName, regType, replyDomain, refNumber); 119745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 120745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt respCode = ResponseCode::ServiceDiscoveryServiceRemoved; 121745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 122745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %s %s %s", refNumber, serviceName, regType, replyDomain); 123745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(respCode, msg, false); 124745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 125745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 126745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 127745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 128745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::stop(SocketClient *cli, int argc, char **argv, const char *str) { 129745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 3) { 130745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 131745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "Invalid number of arguments to %s", str); 132745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, msg, false); 133745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 134745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 135745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 136745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 137745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->lookupServiceRef(requestId); 138745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 139745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("%s stop used unknown requestId %d", str, requestId); 140745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, "Unknown requestId", false); 141745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 142745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 143745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("Stopping %s with ref %p", str, ref); 144745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRefDeallocate(*ref); 145745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 146745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 147745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%s stopped", str); 148745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, msg, false); 149745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 150745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 151745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 152745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::serviceRegister(SocketClient *cli, int requestId, 153745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *interfaceName, const char *serviceName, const char *serviceType, 154745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *domain, const char *host, int port, int txtLen, void *txtRecord) { 155745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 156745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("serviceRegister(%d, %s, %s, %s, %s, %s, %d, %d, <binary>)", requestId, 157745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt interfaceName, serviceName, serviceType, domain, host, port, txtLen); 158745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 159745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Context *context = new Context(requestId, mListener); 160745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context); 161745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt port = htons(port); 162745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 163745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("requestId %d already in use during register call", requestId); 164745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 165745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "RequestId already in use during register call", false); 166745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 167745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 168745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceFlags nativeFlags = 0; 169745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int interfaceInt = ifaceNameToI(interfaceName); 170745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType result = DNSServiceRegister(ref, interfaceInt, nativeFlags, serviceName, 171745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceType, domain, host, port, txtLen, txtRecord, &MDnsSdListenerRegisterCallback, 172745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context); 173745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (result != kDNSServiceErr_NoError) { 174745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("service register request %d got an error from DNSServiceRegister %d", requestId, 175745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result); 176745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 177745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 178745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "serviceRegister request got an error from DNSServiceRegister", false); 179745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 180745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 181745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->startMonitoring(requestId); 182745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("serviceRegister successful"); 183745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "serviceRegister started", false); 184745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 185745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 186745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 187745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerRegisterCallback(DNSServiceRef sdRef, DNSServiceFlags flags, 188745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType errorCode, const char *serviceName, const char *regType, 189745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *domain, void *inContext) { 190745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 191745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 192745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 193745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 194745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 195745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceRegistrationFailed, msg, false); 196745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("register failure for %d, error= %d", refNumber, errorCode); 197745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 198745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %s", refNumber, serviceName); 199745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceRegistrationSucceeded, msg, false); 200745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("register succeeded for %d as %s", refNumber, serviceName); 201745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 202745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 203745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 204745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 205745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 206745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::resolveService(SocketClient *cli, int requestId, 207745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *interfaceName, const char *serviceName, const char *regType, 208745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *domain) { 209745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 210745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("resolveService(%d, %s, %s, %s, %s)", requestId, interfaceName, 211745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceName, regType, domain); 212745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 213745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Context *context = new Context(requestId, mListener); 214745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context); 215745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 216745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("request Id %d already in use during resolve call", requestId); 217745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 218745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "RequestId already in use during resolve call", false); 219745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 220745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 221745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceFlags nativeFlags = 0; 222745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int interfaceInt = ifaceNameToI(interfaceName); 223745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType result = DNSServiceResolve(ref, nativeFlags, interfaceInt, serviceName, 224745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt regType, domain, &MDnsSdListenerResolveCallback, context); 225745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (result != kDNSServiceErr_NoError) { 226745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("service resolve request %d got an error from DNSServiceResolve %d", requestId, 227745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result); 228745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 229745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 230745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "resolveService got an error from DNSServiceResolve", false); 231745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 232745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 233745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->startMonitoring(requestId); 234745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("resolveService successful"); 235745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "resolveService started", false); 236745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 237745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 238745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 239745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerResolveCallback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interface, 240745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, 241745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt uint16_t txtLen, const unsigned char *txtRecord, void *inContext) { 242745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 243745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 244745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 245745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt port = ntohs(port); 246745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 247745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 248745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceResolveFailed, msg, false); 249745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("resolve failure for %d, error= %d", refNumber, errorCode); 250745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 251745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %s %s %d %d", refNumber, fullname, hosttarget, port, txtLen); 252745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceResolveSuccess, msg, false); 253745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 254745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("resolve succeeded for %d finding %s at %s:%d with txtLen %d", 255745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt refNumber, fullname, hosttarget, port, txtLen); 256745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 257745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 258745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 259745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 260745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 261745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::getAddrInfo(SocketClient *cli, int requestId, 262745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *interfaceName, uint32_t protocol, const char *hostname) { 263745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("getAddrInfo(%d, %s %d, %s)", requestId, interfaceName, protocol, hostname); 264745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Context *context = new Context(requestId, mListener); 265745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context); 266745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 267745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("request ID %d already in use during getAddrInfo call", requestId); 268745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 269745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "RequestId already in use during getAddrInfo call", false); 270745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 271745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 272745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceFlags nativeFlags = 0; 273745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int interfaceInt = ifaceNameToI(interfaceName); 274745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType result = DNSServiceGetAddrInfo(ref, nativeFlags, interfaceInt, protocol, 275745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt hostname, &MDnsSdListenerGetAddrInfoCallback, context); 276745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (result != kDNSServiceErr_NoError) { 277745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("getAddrInfo request %d got an error from DNSServiceGetAddrInfo %d", requestId, 278745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result); 279745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 280745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 281745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "getAddrInfo request got an error from DNSServiceGetAddrInfo", false); 282745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 283745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 284745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->startMonitoring(requestId); 285745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("getAddrInfo successful"); 286745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "getAddrInfo started", false); 287745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 288745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 289745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 290745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerGetAddrInfoCallback(DNSServiceRef sdRef, DNSServiceFlags flags, 291745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt uint32_t interface, DNSServiceErrorType errorCode, const char *hostname, 292745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const struct sockaddr *const sa, uint32_t ttl, void *inContext) { 293745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 294745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 295745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 296745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 297745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 298745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 299745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceGetAddrInfoFailed, msg, false); 300745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("getAddrInfo failure for %d, error= %d", refNumber, errorCode); 301745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 302745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 303745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char addr[INET6_ADDRSTRLEN]; 304745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 305745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (sa->sa_family == AF_INET) { 306745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt inet_ntop(sa->sa_family, &(((struct sockaddr_in *)sa)->sin_addr), addr, sizeof(addr)); 307745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 308745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt inet_ntop(sa->sa_family, &(((struct sockaddr_in6 *)sa)->sin6_addr), addr, sizeof(addr)); 309745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 310745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %s %d %s", refNumber, hostname, ttl, addr); 311745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceGetAddrInfoSuccess, msg, false); 312745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 313745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("getAddrInfo succeeded for %d: %s", refNumber, msg); 314745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 315745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 316745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 317745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 318745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 319745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::setHostname(SocketClient *cli, int requestId, 320745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *hostname) { 321745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("setHostname(%d, %s)", requestId, hostname); 322745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Context *context = new Context(requestId, mListener); 323745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context); 324745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 325745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("request Id %d already in use during setHostname call", requestId); 326745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 327745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "RequestId already in use during setHostname call", false); 328745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 329745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 330745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceFlags nativeFlags = 0; 331745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType result = DNSSetHostname(ref, nativeFlags, hostname, 332745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt &MDnsSdListenerSetHostnameCallback, context); 333745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (result != kDNSServiceErr_NoError) { 334745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("setHostname request %d got an error from DNSSetHostname %d", requestId, result); 335745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 336745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 337745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "setHostname got an error from DNSSetHostname", false); 338745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 339745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 340745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->startMonitoring(requestId); 341745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("setHostname successful"); 342745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "setHostname started", false); 343745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 344745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 345745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 346745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerSetHostnameCallback(DNSServiceRef sdRef, DNSServiceFlags flags, 347745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType errorCode, const char *hostname, void *inContext) { 348745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 349745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 350745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 351745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 352745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 353745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceSetHostnameFailed, msg, false); 354745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("setHostname failure for %d, error= %d", refNumber, errorCode); 355745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 356745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %s", refNumber, hostname); 357745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceSetHostnameSuccess, msg, false); 358745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("setHostname succeeded for %d. Set to %s", refNumber, hostname); 359745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 360745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 361745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 362745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 363745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 364745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Handler::ifaceNameToI(const char *iface) { 365745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 366745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 367745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 368745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltconst char *MDnsSdListener::Handler::iToIfaceName(int i) { 369745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 370745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 371745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 372745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltDNSServiceFlags MDnsSdListener::Handler::iToFlags(int i) { 373745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 374745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 375745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 376745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Handler::flagsToI(DNSServiceFlags flags) { 377745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 378745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 379745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 380745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Handler::runCommand(SocketClient *cli, 381745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int argc, char **argv) { 382745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc < 2) { 383745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char* msg = NULL; 384745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf( &msg, "Invalid number of arguments to mdnssd: %i", argc); 385745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGW("%s", msg); 386745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, msg, false); 387745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 388745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return -1; 389745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 390745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 391745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char* cmd = argv[1]; 392745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 393745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (strcmp(cmd, "discover") == 0) { 394745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 4) { 395745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 396745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd discover", false); 397745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 398745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 399745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 400745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceType = argv[3]; 401745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 402745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt discover(cli, NULL, serviceType, NULL, requestId, 0); 403745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-discover") == 0) { 404745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "discover"); 405745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "register") == 0) { 406745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 6) { 407745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 408745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd register", false); 409745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 410745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 411745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 412745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceName = argv[3]; 413745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceType = argv[4]; 414745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int port = atoi(argv[5]); 415745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *interfaceName = NULL; // will use all 416745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *domain = NULL; // will use default 417745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *host = NULL; // will use default hostname 418745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int textLen = 0; 419745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt void *textRecord = NULL; 420745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 421745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceRegister(cli, requestId, interfaceName, serviceName, 422745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceType, domain, host, port, textLen, textRecord); 423745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-register") == 0) { 424745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "register"); 425745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "resolve") == 0) { 426745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 6) { 427745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 428745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd resolve", false); 429745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 430745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 431745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 432745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *interfaceName = NULL; // will use all 433745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceName = argv[3]; 434745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *regType = argv[4]; 435745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *domain = argv[5]; 436745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt resolveService(cli, requestId, interfaceName, serviceName, regType, domain); 437745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-resolve") == 0) { 438745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "resolve"); 439745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "start-service") == 0) { 440745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mMonitor->startService()) { 441745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "Service Started", false); 442745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 443745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::ServiceStartFailed, "Service already running", false); 444745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 445745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-service") == 0) { 446745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mMonitor->stopService()) { 447745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "Service Stopped", false); 448745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 449745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::ServiceStopFailed, "Service still in use", false); 450745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 451745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "sethostname") == 0) { 452745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 4) { 453745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 454745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd sethostname", false); 455745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 456745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 457745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 458745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *hostname = argv[3]; 459745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt setHostname(cli, requestId, hostname); 460745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-sethostname") == 0) { 461745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "sethostname"); 462745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "getaddrinfo") == 0) { 463745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 4) { 464745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 465745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd getaddrinfo", false); 466745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 467745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 468745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 469745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *hostname = argv[3]; 470745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *interfaceName = NULL; // default 471745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int protocol = 0; // intelligient heuristic (both v4 + v6) 472745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt getAddrInfo(cli, requestId, interfaceName, protocol, hostname); 473745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-getaddrinfo") == 0) { 474745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "getaddrinfo"); 475745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 476745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGE("Unknown cmd %s", cmd); 477745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown mdnssd cmd", false); 478745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 479745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 480745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 481745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 482745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 483745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltMDnsSdListener::Monitor::Monitor() { 484745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mHead = NULL; 485745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_init(&mHeadMutex, NULL); 486745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt socketpair(AF_LOCAL, SOCK_STREAM, 0, mCtrlSocketPair); 487745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_create(&mThread, NULL, MDnsSdListener::Monitor::threadStart, this); 488745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 489745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 490745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid *MDnsSdListener::Monitor::threadStart(void *obj) { 491745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Monitor *monitor = reinterpret_cast<Monitor *>(obj); 492745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 493745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt monitor->run(); 494745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete monitor; 495745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_exit(NULL); 496745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 497745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 498745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 499745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Monitor::startService() { 500745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int result = 0; 501745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char property_value[PROPERTY_VALUE_MAX]; 502745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 503745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt property_get(MDNS_SERVICE_STATUS, property_value, ""); 504745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (strcmp("running", property_value) != 0) { 505745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Starting MDNSD"); 506745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt property_set("ctl.start", MDNS_SERVICE_NAME); 507745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt wait_for_property(MDNS_SERVICE_STATUS, "running", 5); 508745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = -1; 509745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 510745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = 0; 511745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 512745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 513745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return result; 514745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 515745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 516745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Monitor::stopService() { 517745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int result = 0; 518745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 519745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mHead == NULL) { 520745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Stopping MDNSD"); 521745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt property_set("ctl.stop", MDNS_SERVICE_NAME); 522745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt wait_for_property(MDNS_SERVICE_STATUS, "stopped", 5); 523745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = -1; 524745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 525745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = 0; 526745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 527745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 528745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return result; 529745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 530745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 531745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Monitor::run() { 532745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int pollCount = 1; 533745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollSize = 10; 534745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 535745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize); 536745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize); 537745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 538745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].fd = mCtrlSocketPair[0]; 539745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].events = POLLIN; 540745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 541745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("MDnsSdListener starting to monitor"); 542745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (1) { 543745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("Going to poll with pollCount %d", pollCount); 544745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int pollResults = poll(mPollFds, pollCount, 10000000); 545745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (pollResults < 0) { 546745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("Error in poll - got %d", errno); 547745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (pollResults > 0) { 548745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("Monitor poll got data pollCount = %d, %d", pollCount, pollResults); 549745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt for(int i = 1; i < pollCount; i++) { 550745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mPollFds[i].revents != 0) { 551745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 552745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Monitor found [%d].revents = %d - calling ProcessResults", 553745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt i, mPollFds[i].revents); 554745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 555745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceProcessResult(*(mPollRefs[i])); 556745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[i].revents = 0; 557745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 558745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 559745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("controlSocket shows revent= %d", mPollFds[0].revents); 560745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt switch (mPollFds[0].revents) { 561745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt case POLLIN: { 562745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char readBuf[2]; 563745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt read(mCtrlSocketPair[0], &readBuf, 1); 564745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGD("MDnsSdListener::Monitor got %c", readBuf[0]); 565745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (memcmp(RESCAN, readBuf, 1) == 0) { 566745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pollCount = rescan(); 567745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 568745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 569745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 570745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].revents = 0; 571745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 572745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("MDnsSdListener::Monitor poll timed out"); 573745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 574745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 575745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollFds); 576745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollRefs); 577745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 578745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 579745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define DBG_RESCAN 0 580745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 581745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Monitor::rescan() { 582745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt// rescan the list from mHead and make new pollfds and serviceRefs 583745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 584745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("MDnsSdListener::Monitor poll rescanning - size=%d, live=%d", mPollSize, mLiveCount); 585745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 586745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int count = 0; 587745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 588745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element **prevPtr = &mHead; 589745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int i = 1; 590745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mPollSize <= mLiveCount) { 591745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollSize = mLiveCount + 5; 592745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollFds); 593745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollRefs); 594745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize); 595745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize); 596745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 597745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt memset(mPollFds, sizeof(struct pollfd) * mPollSize, 0); 598745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt memset(mPollRefs, sizeof(DNSServiceRef *) * mPollSize, 0); 599745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 600745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].fd = mCtrlSocketPair[0]; 601745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].events = POLLIN; 602745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("mHead = %p", mHead); 603745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (*prevPtr != NULL) { 604745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("checking %p, mReady = %d", *prevPtr, (*prevPtr)->mReady); 605745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if ((*prevPtr)->mReady == 1) { 606745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int fd = DNSServiceRefSockFD((*prevPtr)->mRef); 607745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (fd != -1) { 608745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD(" adding FD %d", fd); 609745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[i].fd = fd; 610745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[i].events = POLLIN; 611745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollRefs[i] = &((*prevPtr)->mRef); 612745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt i++; 613745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 614745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("Error retreving socket FD for live ServiceRef"); 615745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 616745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt prevPtr = &((*prevPtr)->mNext); // advance to the next element 617745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if ((*prevPtr)->mReady == -1) { 618745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD(" removing %p from play", *prevPtr); 619745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur = *prevPtr; 620745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt *prevPtr = (cur)->mNext; // change our notion of this element and don't advance 621745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete cur; 622745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 623745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 624745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 625745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return i; 626745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 627745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 628745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltDNSServiceRef *MDnsSdListener::Monitor::allocateServiceRef(int id, Context *context) { 629745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (lookupServiceRef(id) != NULL) { 630745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete(context); 631745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 632745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 633745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *e = new Element(id, context); 634745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 635745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt e->mNext = mHead; 636745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mHead = e; 637745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 638745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return &(e->mRef); 639745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 640745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 641745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltDNSServiceRef *MDnsSdListener::Monitor::lookupServiceRef(int id) { 642745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 643745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur = mHead; 644745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (cur != NULL) { 645745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mId == id) { 646745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *result = &(cur->mRef); 647745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 648745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return result; 649745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 650745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur = cur->mNext; 651745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 652745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 653745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 654745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 655745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 656745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Monitor::startMonitoring(int id) { 657745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("startMonitoring %d", id); 658745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 659745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur = mHead; 660745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (cur != NULL) { 661745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mId == id) { 662745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("marking %p as ready to be added", cur); 663745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mLiveCount++; 664745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur->mReady = 1; 665745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 666745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt write(mCtrlSocketPair[1], RESCAN, 1); // trigger a rescan for a fresh poll 667745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("triggering rescan"); 668745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 669745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 670745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur = cur->mNext; 671745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 672745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 673745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 674745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 675745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define NAP_TIME 200 // 200 ms between polls 676745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltstatic int wait_for_property(const char *name, const char *desired_value, int maxwait) 677745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt{ 678745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char value[PROPERTY_VALUE_MAX] = {'\0'}; 679745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int maxnaps = (maxwait * 1000) / NAP_TIME; 680745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 681745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (maxnaps < 1) { 682745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt maxnaps = 1; 683745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 684745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 685745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (maxnaps-- > 0) { 686745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt usleep(NAP_TIME * 1000); 687745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (property_get(name, value, NULL)) { 688745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (desired_value == NULL || strcmp(value, desired_value) == 0) { 689745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 690745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 691745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 692745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 693745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return -1; /* failure */ 694745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 695745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 696745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Monitor::freeServiceRef(int id) { 697745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("freeServiceRef %d", id); 698745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 699745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element **prevPtr = &mHead; 700745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur; 701745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (*prevPtr != NULL) { 702745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur = *prevPtr; 703745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mId == id) { 704745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("marking %p as ready to be removed", cur); 705745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mLiveCount--; 706745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mReady == 1) { 707745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur->mReady = -1; // tell poll thread to delete 708745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt write(mCtrlSocketPair[1], RESCAN, 1); // trigger a rescan for a fresh poll 709745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("triggering rescan"); 710745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 711745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt *prevPtr = cur->mNext; 712745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete cur; 713745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 714745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 715745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 716745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 717745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt prevPtr = &(cur->mNext); 718745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 719745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 720745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 721