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; 1094833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt char *quotedServiceName = SocketClient::quoteArg(serviceName); 110745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (flags & kDNSServiceFlagsAdd) { 111745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 112745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Discover found new serviceName %s, regType %s and domain %s for %d", 113745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceName, regType, replyDomain, refNumber); 114745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 115745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt respCode = ResponseCode::ServiceDiscoveryServiceAdded; 116745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 117745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 118745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Discover lost serviceName %s, regType %s and domain %s for %d", 119745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceName, regType, replyDomain, refNumber); 120745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 121745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt respCode = ResponseCode::ServiceDiscoveryServiceRemoved; 122745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 1234833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt asprintf(&msg, "%d %s %s %s", refNumber, quotedServiceName, regType, replyDomain); 1244833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt free(quotedServiceName); 125745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(respCode, msg, false); 126745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 127745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 128745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 129745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 130745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::stop(SocketClient *cli, int argc, char **argv, const char *str) { 131745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 3) { 132745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 133745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "Invalid number of arguments to %s", str); 134745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, msg, false); 135745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 136745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 137745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 138745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 139745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->lookupServiceRef(requestId); 140745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 141745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("%s stop used unknown requestId %d", str, requestId); 142745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, "Unknown requestId", false); 143745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 144745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 145745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("Stopping %s with ref %p", str, ref); 146745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRefDeallocate(*ref); 147745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 148745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 149745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%s stopped", str); 150745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, msg, false); 151745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 152745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 153745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 154745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::serviceRegister(SocketClient *cli, int requestId, 155745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *interfaceName, const char *serviceName, const char *serviceType, 156745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *domain, const char *host, int port, int txtLen, void *txtRecord) { 157745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 158745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("serviceRegister(%d, %s, %s, %s, %s, %s, %d, %d, <binary>)", requestId, 159745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt interfaceName, serviceName, serviceType, domain, host, port, txtLen); 160745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 161745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Context *context = new Context(requestId, mListener); 162745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context); 163745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt port = htons(port); 164745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 165745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("requestId %d already in use during register call", requestId); 166745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 167745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "RequestId already in use during register call", false); 168745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 169745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 170745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceFlags nativeFlags = 0; 171745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int interfaceInt = ifaceNameToI(interfaceName); 172745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType result = DNSServiceRegister(ref, interfaceInt, nativeFlags, serviceName, 173745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceType, domain, host, port, txtLen, txtRecord, &MDnsSdListenerRegisterCallback, 174745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context); 175745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (result != kDNSServiceErr_NoError) { 176745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("service register request %d got an error from DNSServiceRegister %d", requestId, 177745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result); 178745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 179745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 180745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "serviceRegister request got an error from DNSServiceRegister", false); 181745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 182745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 183745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->startMonitoring(requestId); 184745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("serviceRegister successful"); 185745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "serviceRegister started", false); 186745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 187745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 188745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 189745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerRegisterCallback(DNSServiceRef sdRef, DNSServiceFlags flags, 190745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType errorCode, const char *serviceName, const char *regType, 191745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *domain, void *inContext) { 192745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 193745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 194745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 195745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 196745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 197745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceRegistrationFailed, msg, false); 198745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("register failure for %d, error= %d", refNumber, errorCode); 199745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 2004833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt char *quotedServiceName = SocketClient::quoteArg(serviceName); 2014833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt asprintf(&msg, "%d %s", refNumber, quotedServiceName); 2024833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt free(quotedServiceName); 203745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceRegistrationSucceeded, msg, false); 204745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("register succeeded for %d as %s", refNumber, serviceName); 205745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 206745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 207745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 208745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 209745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 210745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::resolveService(SocketClient *cli, int requestId, 211745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *interfaceName, const char *serviceName, const char *regType, 212745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *domain) { 213745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 214745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("resolveService(%d, %s, %s, %s, %s)", requestId, interfaceName, 215745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceName, regType, domain); 216745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 217745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Context *context = new Context(requestId, mListener); 218745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context); 219745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 220745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("request Id %d already in use during resolve call", requestId); 221745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 222745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "RequestId already in use during resolve call", false); 223745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 224745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 225745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceFlags nativeFlags = 0; 226745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int interfaceInt = ifaceNameToI(interfaceName); 227745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType result = DNSServiceResolve(ref, nativeFlags, interfaceInt, serviceName, 228745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt regType, domain, &MDnsSdListenerResolveCallback, context); 229745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (result != kDNSServiceErr_NoError) { 230745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("service resolve request %d got an error from DNSServiceResolve %d", requestId, 231745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result); 232745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 233745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 234745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "resolveService got an error from DNSServiceResolve", false); 235745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 236745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 237745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->startMonitoring(requestId); 238745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("resolveService successful"); 239745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "resolveService started", false); 240745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 241745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 242745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 243745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerResolveCallback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interface, 244745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, 245745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt uint16_t txtLen, const unsigned char *txtRecord, void *inContext) { 246745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 247745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 248745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 249745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt port = ntohs(port); 250745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 251745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 252745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceResolveFailed, msg, false); 253745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("resolve failure for %d, error= %d", refNumber, errorCode); 254745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 2554833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt char *quotedFullName = SocketClient::quoteArg(fullname); 2564833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt char *quotedHostTarget = SocketClient::quoteArg(hosttarget); 2574833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt asprintf(&msg, "%d %s %s %d %d", refNumber, quotedFullName, quotedHostTarget, port, txtLen); 2584833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt free(quotedFullName); 2594833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt free(quotedHostTarget); 260745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceResolveSuccess, msg, false); 261745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 262745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("resolve succeeded for %d finding %s at %s:%d with txtLen %d", 263745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt refNumber, fullname, hosttarget, port, txtLen); 264745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 265745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 266745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 267745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 268745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 269745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::getAddrInfo(SocketClient *cli, int requestId, 270745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *interfaceName, uint32_t protocol, const char *hostname) { 271745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("getAddrInfo(%d, %s %d, %s)", requestId, interfaceName, protocol, hostname); 272745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Context *context = new Context(requestId, mListener); 273745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context); 274745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 275745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("request ID %d already in use during getAddrInfo call", requestId); 276745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 277745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "RequestId already in use during getAddrInfo call", false); 278745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 279745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 280745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceFlags nativeFlags = 0; 281745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int interfaceInt = ifaceNameToI(interfaceName); 282745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType result = DNSServiceGetAddrInfo(ref, nativeFlags, interfaceInt, protocol, 283745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt hostname, &MDnsSdListenerGetAddrInfoCallback, context); 284745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (result != kDNSServiceErr_NoError) { 285745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("getAddrInfo request %d got an error from DNSServiceGetAddrInfo %d", requestId, 286745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result); 287745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 288745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 289745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "getAddrInfo request got an error from DNSServiceGetAddrInfo", false); 290745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 291745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 292745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->startMonitoring(requestId); 293745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("getAddrInfo successful"); 294745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "getAddrInfo started", false); 295745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 296745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 297745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 298745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerGetAddrInfoCallback(DNSServiceRef sdRef, DNSServiceFlags flags, 299745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt uint32_t interface, DNSServiceErrorType errorCode, const char *hostname, 300745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const struct sockaddr *const sa, uint32_t ttl, void *inContext) { 301745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 302745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 303745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 304745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 305745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 306745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 307745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceGetAddrInfoFailed, msg, false); 308745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("getAddrInfo failure for %d, error= %d", refNumber, errorCode); 309745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 310745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 311745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char addr[INET6_ADDRSTRLEN]; 312745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 3134833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt char *quotedHostname = SocketClient::quoteArg(hostname); 314745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (sa->sa_family == AF_INET) { 315745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt inet_ntop(sa->sa_family, &(((struct sockaddr_in *)sa)->sin_addr), addr, sizeof(addr)); 316745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 317745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt inet_ntop(sa->sa_family, &(((struct sockaddr_in6 *)sa)->sin6_addr), addr, sizeof(addr)); 318745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 3194833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt asprintf(&msg, "%d %s %d %s", refNumber, quotedHostname, ttl, addr); 3204833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt free(quotedHostname); 321745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceGetAddrInfoSuccess, msg, false); 322745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 323745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("getAddrInfo succeeded for %d: %s", refNumber, msg); 324745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 325745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 326745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 327745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 328745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 329745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::setHostname(SocketClient *cli, int requestId, 330745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *hostname) { 331745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("setHostname(%d, %s)", requestId, hostname); 332745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Context *context = new Context(requestId, mListener); 333745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context); 334745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 335745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("request Id %d already in use during setHostname call", requestId); 336745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 337745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "RequestId already in use during setHostname call", false); 338745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 339745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 340745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceFlags nativeFlags = 0; 341745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType result = DNSSetHostname(ref, nativeFlags, hostname, 342745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt &MDnsSdListenerSetHostnameCallback, context); 343745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (result != kDNSServiceErr_NoError) { 344745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("setHostname request %d got an error from DNSSetHostname %d", requestId, result); 345745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 346745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 347745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "setHostname got an error from DNSSetHostname", false); 348745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 349745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 350745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->startMonitoring(requestId); 351745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("setHostname successful"); 352745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "setHostname started", false); 353745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 354745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 355745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 356745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerSetHostnameCallback(DNSServiceRef sdRef, DNSServiceFlags flags, 357745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType errorCode, const char *hostname, void *inContext) { 358745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 359745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 360745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 361745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 362745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 363745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceSetHostnameFailed, msg, false); 364745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("setHostname failure for %d, error= %d", refNumber, errorCode); 365745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 3664833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt char *quotedHostname = SocketClient::quoteArg(hostname); 3674833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt asprintf(&msg, "%d %s", refNumber, quotedHostname); 3684833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt free(quotedHostname); 369745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceSetHostnameSuccess, msg, false); 370745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("setHostname succeeded for %d. Set to %s", refNumber, hostname); 371745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 372745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 373745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 374745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 375745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 376745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Handler::ifaceNameToI(const char *iface) { 377745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 378745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 379745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 380745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltconst char *MDnsSdListener::Handler::iToIfaceName(int i) { 381745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 382745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 383745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 384745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltDNSServiceFlags MDnsSdListener::Handler::iToFlags(int i) { 385745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 386745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 387745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 388745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Handler::flagsToI(DNSServiceFlags flags) { 389745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 390745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 391745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 392745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Handler::runCommand(SocketClient *cli, 393745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int argc, char **argv) { 394745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc < 2) { 395745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char* msg = NULL; 396745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf( &msg, "Invalid number of arguments to mdnssd: %i", argc); 397745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGW("%s", msg); 398745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, msg, false); 399745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 400745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return -1; 401745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 402745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 403745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char* cmd = argv[1]; 404745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 405745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (strcmp(cmd, "discover") == 0) { 406745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 4) { 407745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 408745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd discover", false); 409745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 410745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 411745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 412745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceType = argv[3]; 413745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 414745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt discover(cli, NULL, serviceType, NULL, requestId, 0); 415745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-discover") == 0) { 416745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "discover"); 417745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "register") == 0) { 418745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 6) { 419745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 420745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd register", false); 421745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 422745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 423745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 424745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceName = argv[3]; 425745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceType = argv[4]; 426745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int port = atoi(argv[5]); 427745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *interfaceName = NULL; // will use all 428745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *domain = NULL; // will use default 429745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *host = NULL; // will use default hostname 430745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int textLen = 0; 431745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt void *textRecord = NULL; 432745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 433745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceRegister(cli, requestId, interfaceName, serviceName, 434745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceType, domain, host, port, textLen, textRecord); 435745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-register") == 0) { 436745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "register"); 437745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "resolve") == 0) { 438745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 6) { 439745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 440745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd resolve", false); 441745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 442745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 443745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 444745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *interfaceName = NULL; // will use all 445745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceName = argv[3]; 446745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *regType = argv[4]; 447745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *domain = argv[5]; 448745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt resolveService(cli, requestId, interfaceName, serviceName, regType, domain); 449745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-resolve") == 0) { 450745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "resolve"); 451745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "start-service") == 0) { 452745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mMonitor->startService()) { 453745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "Service Started", false); 454745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 455745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::ServiceStartFailed, "Service already running", false); 456745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 457745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-service") == 0) { 458745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mMonitor->stopService()) { 459745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "Service Stopped", false); 460745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 461745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::ServiceStopFailed, "Service still in use", false); 462745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 463745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "sethostname") == 0) { 464745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 4) { 465745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 466745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd sethostname", false); 467745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 468745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 469745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 470745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *hostname = argv[3]; 471745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt setHostname(cli, requestId, hostname); 472745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-sethostname") == 0) { 473745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "sethostname"); 474745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "getaddrinfo") == 0) { 475745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 4) { 476745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 477745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd getaddrinfo", false); 478745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 479745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 480745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 481745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *hostname = argv[3]; 482745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *interfaceName = NULL; // default 483745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int protocol = 0; // intelligient heuristic (both v4 + v6) 484745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt getAddrInfo(cli, requestId, interfaceName, protocol, hostname); 485745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-getaddrinfo") == 0) { 486745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "getaddrinfo"); 487745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 488745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGE("Unknown cmd %s", cmd); 489745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown mdnssd cmd", false); 490745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 491745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 492745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 493745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 494745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 495745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltMDnsSdListener::Monitor::Monitor() { 496745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mHead = NULL; 497745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_init(&mHeadMutex, NULL); 498745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt socketpair(AF_LOCAL, SOCK_STREAM, 0, mCtrlSocketPair); 499745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_create(&mThread, NULL, MDnsSdListener::Monitor::threadStart, this); 500745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 501745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 502745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid *MDnsSdListener::Monitor::threadStart(void *obj) { 503745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Monitor *monitor = reinterpret_cast<Monitor *>(obj); 504745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 505745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt monitor->run(); 506745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete monitor; 507745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_exit(NULL); 508745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 509745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 510745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 511745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Monitor::startService() { 512745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int result = 0; 513745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char property_value[PROPERTY_VALUE_MAX]; 514745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 515745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt property_get(MDNS_SERVICE_STATUS, property_value, ""); 516745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (strcmp("running", property_value) != 0) { 517745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Starting MDNSD"); 518745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt property_set("ctl.start", MDNS_SERVICE_NAME); 519745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt wait_for_property(MDNS_SERVICE_STATUS, "running", 5); 520745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = -1; 521745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 522745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = 0; 523745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 524745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 525745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return result; 526745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 527745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 528745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Monitor::stopService() { 529745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int result = 0; 530745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 531745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mHead == NULL) { 532745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Stopping MDNSD"); 533745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt property_set("ctl.stop", MDNS_SERVICE_NAME); 534745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt wait_for_property(MDNS_SERVICE_STATUS, "stopped", 5); 535745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = -1; 536745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 537745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = 0; 538745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 539745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 540745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return result; 541745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 542745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 543745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Monitor::run() { 544745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int pollCount = 1; 545745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollSize = 10; 546745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 547745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize); 548745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize); 549745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 550745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].fd = mCtrlSocketPair[0]; 551745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].events = POLLIN; 552745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 553745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("MDnsSdListener starting to monitor"); 554745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (1) { 555745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("Going to poll with pollCount %d", pollCount); 556745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int pollResults = poll(mPollFds, pollCount, 10000000); 557745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (pollResults < 0) { 558745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("Error in poll - got %d", errno); 559745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (pollResults > 0) { 560745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("Monitor poll got data pollCount = %d, %d", pollCount, pollResults); 561745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt for(int i = 1; i < pollCount; i++) { 562745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mPollFds[i].revents != 0) { 563745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 564745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Monitor found [%d].revents = %d - calling ProcessResults", 565745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt i, mPollFds[i].revents); 566745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 567745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceProcessResult(*(mPollRefs[i])); 568745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[i].revents = 0; 569745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 570745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 571745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("controlSocket shows revent= %d", mPollFds[0].revents); 572745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt switch (mPollFds[0].revents) { 573745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt case POLLIN: { 574745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char readBuf[2]; 575745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt read(mCtrlSocketPair[0], &readBuf, 1); 576745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGD("MDnsSdListener::Monitor got %c", readBuf[0]); 577745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (memcmp(RESCAN, readBuf, 1) == 0) { 578745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pollCount = rescan(); 579745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 580745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 581745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 582745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].revents = 0; 583745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 584745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("MDnsSdListener::Monitor poll timed out"); 585745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 586745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 587745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollFds); 588745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollRefs); 589745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 590745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 591745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define DBG_RESCAN 0 592745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 593745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Monitor::rescan() { 594745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt// rescan the list from mHead and make new pollfds and serviceRefs 595745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 596745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("MDnsSdListener::Monitor poll rescanning - size=%d, live=%d", mPollSize, mLiveCount); 597745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 598745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int count = 0; 599745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 600745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element **prevPtr = &mHead; 601745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int i = 1; 602745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mPollSize <= mLiveCount) { 603745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollSize = mLiveCount + 5; 604745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollFds); 605745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollRefs); 606745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize); 607745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize); 608745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 609745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt memset(mPollFds, sizeof(struct pollfd) * mPollSize, 0); 610745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt memset(mPollRefs, sizeof(DNSServiceRef *) * mPollSize, 0); 611745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 612745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].fd = mCtrlSocketPair[0]; 613745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].events = POLLIN; 614745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("mHead = %p", mHead); 615745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (*prevPtr != NULL) { 616745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("checking %p, mReady = %d", *prevPtr, (*prevPtr)->mReady); 617745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if ((*prevPtr)->mReady == 1) { 618745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int fd = DNSServiceRefSockFD((*prevPtr)->mRef); 619745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (fd != -1) { 620745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD(" adding FD %d", fd); 621745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[i].fd = fd; 622745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[i].events = POLLIN; 623745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollRefs[i] = &((*prevPtr)->mRef); 624745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt i++; 625745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 626745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("Error retreving socket FD for live ServiceRef"); 627745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 628745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt prevPtr = &((*prevPtr)->mNext); // advance to the next element 629745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if ((*prevPtr)->mReady == -1) { 630745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD(" removing %p from play", *prevPtr); 631745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur = *prevPtr; 632745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt *prevPtr = (cur)->mNext; // change our notion of this element and don't advance 633745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete cur; 634745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 635745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 636745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 637745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return i; 638745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 639745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 640745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltDNSServiceRef *MDnsSdListener::Monitor::allocateServiceRef(int id, Context *context) { 641745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (lookupServiceRef(id) != NULL) { 642745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete(context); 643745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 644745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 645745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *e = new Element(id, context); 646745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 647745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt e->mNext = mHead; 648745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mHead = e; 649745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 650745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return &(e->mRef); 651745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 652745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 653745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltDNSServiceRef *MDnsSdListener::Monitor::lookupServiceRef(int id) { 654745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 655745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur = mHead; 656745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (cur != NULL) { 657745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mId == id) { 658745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *result = &(cur->mRef); 659745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 660745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return result; 661745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 662745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur = cur->mNext; 663745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 664745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 665745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 666745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 667745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 668745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Monitor::startMonitoring(int id) { 669745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("startMonitoring %d", id); 670745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 671745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur = mHead; 672745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (cur != NULL) { 673745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mId == id) { 674745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("marking %p as ready to be added", cur); 675745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mLiveCount++; 676745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur->mReady = 1; 677745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 678745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt write(mCtrlSocketPair[1], RESCAN, 1); // trigger a rescan for a fresh poll 679745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("triggering rescan"); 680745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 681745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 682745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur = cur->mNext; 683745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 684745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 685745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 686745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 687745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define NAP_TIME 200 // 200 ms between polls 688745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltstatic int wait_for_property(const char *name, const char *desired_value, int maxwait) 689745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt{ 690745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char value[PROPERTY_VALUE_MAX] = {'\0'}; 691745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int maxnaps = (maxwait * 1000) / NAP_TIME; 692745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 693745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (maxnaps < 1) { 694745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt maxnaps = 1; 695745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 696745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 697745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (maxnaps-- > 0) { 698745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt usleep(NAP_TIME * 1000); 699745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (property_get(name, value, NULL)) { 700745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (desired_value == NULL || strcmp(value, desired_value) == 0) { 701745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 702745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 703745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 704745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 705745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return -1; /* failure */ 706745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 707745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 708745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Monitor::freeServiceRef(int id) { 709745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("freeServiceRef %d", id); 710745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 711745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element **prevPtr = &mHead; 712745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur; 713745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (*prevPtr != NULL) { 714745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur = *prevPtr; 715745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mId == id) { 716745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("marking %p as ready to be removed", cur); 717745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mLiveCount--; 718745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mReady == 1) { 719745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur->mReady = -1; // tell poll thread to delete 720745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt write(mCtrlSocketPair[1], RESCAN, 1); // trigger a rescan for a fresh poll 721745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("triggering rescan"); 722745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 723745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt *prevPtr = cur->mNext; 724745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete cur; 725745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 726745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 727745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 728745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 729745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt prevPtr = &(cur->mNext); 730745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 731745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 732745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 733