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 9656afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandranvoid MDnsSdListenerDiscoverCallback(DNSServiceRef /* sdRef */, DNSServiceFlags flags, 9756afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran 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 18956afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandranvoid MDnsSdListenerRegisterCallback(DNSServiceRef /* sdRef */, DNSServiceFlags /* flags */, 19056afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran DNSServiceErrorType errorCode, const char *serviceName, const char * /* regType */, 19156afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran 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 24356afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandranvoid MDnsSdListenerResolveCallback(DNSServiceRef /* sdRef */, DNSServiceFlags /* flags */, 24456afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran uint32_t /* interface */, DNSServiceErrorType errorCode, const char *fullname, 24556afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran const char *hosttarget, uint16_t port, uint16_t txtLen, 24656afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran const unsigned char * /* txtRecord */, void *inContext) { 247745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 248745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 249745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 250745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt port = ntohs(port); 251745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 252745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 253745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceResolveFailed, msg, false); 254745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("resolve failure for %d, error= %d", refNumber, errorCode); 255745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 2564833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt char *quotedFullName = SocketClient::quoteArg(fullname); 2574833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt char *quotedHostTarget = SocketClient::quoteArg(hosttarget); 2584833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt asprintf(&msg, "%d %s %s %d %d", refNumber, quotedFullName, quotedHostTarget, port, txtLen); 2594833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt free(quotedFullName); 2604833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt free(quotedHostTarget); 261745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceResolveSuccess, msg, false); 262745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 263745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("resolve succeeded for %d finding %s at %s:%d with txtLen %d", 264745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt refNumber, fullname, hosttarget, port, txtLen); 265745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 266745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 267745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 268745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 269745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 270745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::getAddrInfo(SocketClient *cli, int requestId, 271745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *interfaceName, uint32_t protocol, const char *hostname) { 272745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("getAddrInfo(%d, %s %d, %s)", requestId, interfaceName, protocol, hostname); 273745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Context *context = new Context(requestId, mListener); 274745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context); 275745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 276745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("request ID %d already in use during getAddrInfo call", requestId); 277745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 278745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "RequestId already in use during getAddrInfo call", false); 279745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 280745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 281745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceFlags nativeFlags = 0; 282745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int interfaceInt = ifaceNameToI(interfaceName); 283745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType result = DNSServiceGetAddrInfo(ref, nativeFlags, interfaceInt, protocol, 284745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt hostname, &MDnsSdListenerGetAddrInfoCallback, context); 285745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (result != kDNSServiceErr_NoError) { 286745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("getAddrInfo request %d got an error from DNSServiceGetAddrInfo %d", requestId, 287745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result); 288745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 289745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 290745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "getAddrInfo request got an error from DNSServiceGetAddrInfo", false); 291745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 292745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 293745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->startMonitoring(requestId); 294745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("getAddrInfo successful"); 295745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "getAddrInfo started", false); 296745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 297745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 298745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 29956afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandranvoid MDnsSdListenerGetAddrInfoCallback(DNSServiceRef /* sdRef */, DNSServiceFlags /* flags */, 30056afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran uint32_t /* interface */, DNSServiceErrorType errorCode, const char *hostname, 301745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const struct sockaddr *const sa, uint32_t ttl, void *inContext) { 302745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 303745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 304745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 305745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 306745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 307745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 308745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceGetAddrInfoFailed, msg, false); 309745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("getAddrInfo failure for %d, error= %d", refNumber, errorCode); 310745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 311745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 312745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char addr[INET6_ADDRSTRLEN]; 313745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 3144833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt char *quotedHostname = SocketClient::quoteArg(hostname); 315745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (sa->sa_family == AF_INET) { 316745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt inet_ntop(sa->sa_family, &(((struct sockaddr_in *)sa)->sin_addr), addr, sizeof(addr)); 317745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 318745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt inet_ntop(sa->sa_family, &(((struct sockaddr_in6 *)sa)->sin6_addr), addr, sizeof(addr)); 319745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 3204833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt asprintf(&msg, "%d %s %d %s", refNumber, quotedHostname, ttl, addr); 3214833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt free(quotedHostname); 322745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceGetAddrInfoSuccess, msg, false); 323745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 324745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("getAddrInfo succeeded for %d: %s", refNumber, msg); 325745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 326745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 327745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 328745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 329745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 330745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Handler::setHostname(SocketClient *cli, int requestId, 331745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt const char *hostname) { 332745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("setHostname(%d, %s)", requestId, hostname); 333745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Context *context = new Context(requestId, mListener); 334745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context); 335745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (ref == NULL) { 336745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("request Id %d already in use during setHostname call", requestId); 337745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 338745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "RequestId already in use during setHostname call", false); 339745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 340745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 341745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceFlags nativeFlags = 0; 342745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType result = DNSSetHostname(ref, nativeFlags, hostname, 343745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt &MDnsSdListenerSetHostnameCallback, context); 344745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (result != kDNSServiceErr_NoError) { 345745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("setHostname request %d got an error from DNSSetHostname %d", requestId, result); 346745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->freeServiceRef(requestId); 347745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 348745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "setHostname got an error from DNSSetHostname", false); 349745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 350745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 351745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mMonitor->startMonitoring(requestId); 352745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("setHostname successful"); 353745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "setHostname started", false); 354745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 355745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 356745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 35756afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandranvoid MDnsSdListenerSetHostnameCallback(DNSServiceRef /* sdRef */, DNSServiceFlags /* flags */, 358745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceErrorType errorCode, const char *hostname, void *inContext) { 359745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext); 360745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *msg; 361745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int refNumber = context->mRefNumber; 362745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (errorCode != kDNSServiceErr_NoError) { 363745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf(&msg, "%d %d", refNumber, errorCode); 364745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceSetHostnameFailed, msg, false); 365745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGE("setHostname failure for %d, error= %d", refNumber, errorCode); 366745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 3674833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt char *quotedHostname = SocketClient::quoteArg(hostname); 3684833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt asprintf(&msg, "%d %s", refNumber, quotedHostname); 3694833e47bb886db80cf4ec23a00cc4ba2a1f113e7Robert Greenwalt free(quotedHostname); 370745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt context->mListener->sendBroadcast(ResponseCode::ServiceSetHostnameSuccess, msg, false); 371745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("setHostname succeeded for %d. Set to %s", refNumber, hostname); 372745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 373745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 374745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 375745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 376745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 37756afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandranint MDnsSdListener::Handler::ifaceNameToI(const char * /* iface */) { 378745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 379745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 380745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 38156afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandranconst char *MDnsSdListener::Handler::iToIfaceName(int /* i */) { 382745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 383745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 384745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 38556afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram RamachandranDNSServiceFlags MDnsSdListener::Handler::iToFlags(int /* i */) { 386745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 387745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 388745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 38956afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandranint MDnsSdListener::Handler::flagsToI(DNSServiceFlags /* flags */) { 390745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 391745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 392745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 393745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Handler::runCommand(SocketClient *cli, 394745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int argc, char **argv) { 395745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc < 2) { 396745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char* msg = NULL; 397745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt asprintf( &msg, "Invalid number of arguments to mdnssd: %i", argc); 398745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGW("%s", msg); 399745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, msg, false); 400745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(msg); 401745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return -1; 402745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 403745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 404745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char* cmd = argv[1]; 405745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 406745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (strcmp(cmd, "discover") == 0) { 407745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 4) { 408745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 409745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd discover", false); 410745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 411745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 412745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 413745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceType = argv[3]; 414745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 415745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt discover(cli, NULL, serviceType, NULL, requestId, 0); 416745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-discover") == 0) { 417745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "discover"); 418745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "register") == 0) { 419c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane if (argc < 6) { 420745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 421745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd register", false); 422745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 423745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 424745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 425745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceName = argv[3]; 426745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceType = argv[4]; 427745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int port = atoi(argv[5]); 428745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *interfaceName = NULL; // will use all 429745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *domain = NULL; // will use default 430745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *host = NULL; // will use default hostname 431c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane unsigned char txtRecord[2048] = ""; 432c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane unsigned char *ptr = txtRecord; 433c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane for (int i = 6; i < argc; ++i) { 434c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane int dataLength = strlen(argv[i]); 435c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane if (dataLength < 1) { 436c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane continue; 437c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane } 438c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane if (dataLength > 255) { 439c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane cli->sendMsg(ResponseCode::CommandParameterError, 440c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane "TXT record fields must not be longer than 255 characters", false); 441c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane return 0; 442c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane } 443c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane if (ptr + dataLength + 1 > txtRecord + sizeof(txtRecord)) { 444c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane cli->sendMsg(ResponseCode::CommandParameterError, 445c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane "Total length of TXT record must be smaller than 2048 bytes", false); 446c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane return 0; 447c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane } 448c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane *ptr++ = dataLength; 449c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane strcpy( (char*) ptr, argv[i]); 450c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane ptr += dataLength; 451c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane } 452745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt serviceRegister(cli, requestId, interfaceName, serviceName, 453c0bc14a3c2f0efe1f368f2120de38e99ccb6d9f0Christopher Lane serviceType, domain, host, port, ptr - txtRecord, txtRecord); 454745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-register") == 0) { 455745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "register"); 456745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "resolve") == 0) { 457745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 6) { 458745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 459745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd resolve", false); 460745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 461745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 462745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 463745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *interfaceName = NULL; // will use all 464745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *serviceName = argv[3]; 465745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *regType = argv[4]; 466745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *domain = argv[5]; 467745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt resolveService(cli, requestId, interfaceName, serviceName, regType, domain); 468745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-resolve") == 0) { 469745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "resolve"); 470745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "start-service") == 0) { 471745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mMonitor->startService()) { 472745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "Service Started", false); 473745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 474745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::ServiceStartFailed, "Service already running", false); 475745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 476745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-service") == 0) { 477745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mMonitor->stopService()) { 478745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "Service Stopped", false); 479745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 480745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::ServiceStopFailed, "Service still in use", false); 481745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 482745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "sethostname") == 0) { 483745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 4) { 484745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 485745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd sethostname", false); 486745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 487745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 488745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 489745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *hostname = argv[3]; 490745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt setHostname(cli, requestId, hostname); 491745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-sethostname") == 0) { 492745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "sethostname"); 493745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "getaddrinfo") == 0) { 494745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (argc != 4) { 495745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandParameterError, 496745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt "Invalid number of arguments to mdnssd getaddrinfo", false); 497745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 498745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 499745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int requestId = atoi(argv[2]); 500745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *hostname = argv[3]; 501745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char *interfaceName = NULL; // default 502745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int protocol = 0; // intelligient heuristic (both v4 + v6) 503745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt getAddrInfo(cli, requestId, interfaceName, protocol, hostname); 504745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (strcmp(cmd, "stop-getaddrinfo") == 0) { 505745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt stop(cli, argc, argv, "getaddrinfo"); 506745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 507745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGE("Unknown cmd %s", cmd); 508745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown mdnssd cmd", false); 509745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 510745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 511745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return 0; 512745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 513745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 514745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltMDnsSdListener::Monitor::Monitor() { 515745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mHead = NULL; 51630ffdfa62cb6bd8807b3d8eb529e2e8abaa80386Narayan Kamath mLiveCount = 0; 51730ffdfa62cb6bd8807b3d8eb529e2e8abaa80386Narayan Kamath mPollFds = NULL; 51830ffdfa62cb6bd8807b3d8eb529e2e8abaa80386Narayan Kamath mPollRefs = NULL; 51930ffdfa62cb6bd8807b3d8eb529e2e8abaa80386Narayan Kamath mPollSize = 10; 520745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt socketpair(AF_LOCAL, SOCK_STREAM, 0, mCtrlSocketPair); 52130ffdfa62cb6bd8807b3d8eb529e2e8abaa80386Narayan Kamath pthread_mutex_init(&mHeadMutex, NULL); 52230ffdfa62cb6bd8807b3d8eb529e2e8abaa80386Narayan Kamath 523745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_create(&mThread, NULL, MDnsSdListener::Monitor::threadStart, this); 5242d4610ec34cc78799a3353638fa05ee53276892aMattias Falk pthread_detach(mThread); 525745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 526745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 527745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid *MDnsSdListener::Monitor::threadStart(void *obj) { 528745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Monitor *monitor = reinterpret_cast<Monitor *>(obj); 529745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 530745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt monitor->run(); 531745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete monitor; 532745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_exit(NULL); 533745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 534745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 535745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 53656afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran#define NAP_TIME 200 // 200 ms between polls 53756afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandranstatic int wait_for_property(const char *name, const char *desired_value, int maxwait) 53856afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran{ 53956afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran char value[PROPERTY_VALUE_MAX] = {'\0'}; 54056afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran int maxnaps = (maxwait * 1000) / NAP_TIME; 54156afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran 54256afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran if (maxnaps < 1) { 54356afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran maxnaps = 1; 54456afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran } 54556afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran 54656afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran while (maxnaps-- > 0) { 54756afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran usleep(NAP_TIME * 1000); 54856afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran if (property_get(name, value, NULL)) { 54956afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran if (desired_value == NULL || strcmp(value, desired_value) == 0) { 55056afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran return 0; 55156afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran } 55256afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran } 55356afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran } 55456afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran return -1; /* failure */ 55556afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran} 55656afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran 557745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Monitor::startService() { 558745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int result = 0; 559745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char property_value[PROPERTY_VALUE_MAX]; 560745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 561745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt property_get(MDNS_SERVICE_STATUS, property_value, ""); 562745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (strcmp("running", property_value) != 0) { 563745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Starting MDNSD"); 564745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt property_set("ctl.start", MDNS_SERVICE_NAME); 565745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt wait_for_property(MDNS_SERVICE_STATUS, "running", 5); 566745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = -1; 567745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 568745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = 0; 569745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 570745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 571745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return result; 572745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 573745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 574745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Monitor::stopService() { 575745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int result = 0; 576745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 577745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mHead == NULL) { 578745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Stopping MDNSD"); 579745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt property_set("ctl.stop", MDNS_SERVICE_NAME); 580745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt wait_for_property(MDNS_SERVICE_STATUS, "stopped", 5); 581745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = -1; 582745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 583745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt result = 0; 584745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 585745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 586745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return result; 587745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 588745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 589745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Monitor::run() { 590745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int pollCount = 1; 591745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 592745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize); 593745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize); 59447f8597b42b849d22c6cc128f27bba4a7692d371Robert Greenwalt LOG_ALWAYS_FATAL_IF((mPollFds == NULL), "initial calloc failed on mPollFds with a size of %d", 59547f8597b42b849d22c6cc128f27bba4a7692d371Robert Greenwalt ((int)sizeof(struct pollfd)) * mPollSize); 59647f8597b42b849d22c6cc128f27bba4a7692d371Robert Greenwalt LOG_ALWAYS_FATAL_IF((mPollRefs == NULL), "initial calloc failed on mPollRefs with a size of %d", 59747f8597b42b849d22c6cc128f27bba4a7692d371Robert Greenwalt ((int)sizeof(DNSServiceRef *)) * mPollSize); 598745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 599745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].fd = mCtrlSocketPair[0]; 600745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].events = POLLIN; 601745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 602745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("MDnsSdListener starting to monitor"); 603745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (1) { 604745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("Going to poll with pollCount %d", pollCount); 605745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int pollResults = poll(mPollFds, pollCount, 10000000); 606745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (pollResults < 0) { 607745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("Error in poll - got %d", errno); 608745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if (pollResults > 0) { 609745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("Monitor poll got data pollCount = %d, %d", pollCount, pollResults); 610745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt for(int i = 1; i < pollCount; i++) { 611745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mPollFds[i].revents != 0) { 612745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 613745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("Monitor found [%d].revents = %d - calling ProcessResults", 614745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt i, mPollFds[i].revents); 615745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 616745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceProcessResult(*(mPollRefs[i])); 617745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[i].revents = 0; 618745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 619745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 620745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("controlSocket shows revent= %d", mPollFds[0].revents); 621745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt switch (mPollFds[0].revents) { 622745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt case POLLIN: { 623745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt char readBuf[2]; 624745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt read(mCtrlSocketPair[0], &readBuf, 1); 625745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG) ALOGD("MDnsSdListener::Monitor got %c", readBuf[0]); 626745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (memcmp(RESCAN, readBuf, 1) == 0) { 627745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pollCount = rescan(); 628745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 629745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 630745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 631745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].revents = 0; 632745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 633745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("MDnsSdListener::Monitor poll timed out"); 634745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 635745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 636745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollFds); 637745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollRefs); 638745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 639745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 640745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define DBG_RESCAN 0 641745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 642745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltint MDnsSdListener::Monitor::rescan() { 643745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt// rescan the list from mHead and make new pollfds and serviceRefs 644745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) { 645745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGD("MDnsSdListener::Monitor poll rescanning - size=%d, live=%d", mPollSize, mLiveCount); 646745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 647745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 648745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element **prevPtr = &mHead; 649745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int i = 1; 650745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (mPollSize <= mLiveCount) { 651745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollSize = mLiveCount + 5; 652745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollFds); 653745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt free(mPollRefs); 654745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize); 655745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize); 65647f8597b42b849d22c6cc128f27bba4a7692d371Robert Greenwalt LOG_ALWAYS_FATAL_IF((mPollFds == NULL), "calloc failed on mPollFds with a size of %d", 65747f8597b42b849d22c6cc128f27bba4a7692d371Robert Greenwalt ((int)sizeof(struct pollfd)) * mPollSize); 65847f8597b42b849d22c6cc128f27bba4a7692d371Robert Greenwalt LOG_ALWAYS_FATAL_IF((mPollRefs == NULL), "calloc failed on mPollRefs with a size of %d", 65947f8597b42b849d22c6cc128f27bba4a7692d371Robert Greenwalt ((int)sizeof(DNSServiceRef *)) * mPollSize); 660745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 661a3ebcb8c2ceef6b92a672a24529cbd098f487965Edward Savage-Jones memset(mPollFds, 0, sizeof(struct pollfd) * mPollSize); 662a3ebcb8c2ceef6b92a672a24529cbd098f487965Edward Savage-Jones memset(mPollRefs, 0, sizeof(DNSServiceRef *) * mPollSize); 663745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 664745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].fd = mCtrlSocketPair[0]; 665745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[0].events = POLLIN; 666745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("mHead = %p", mHead); 667745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (*prevPtr != NULL) { 668745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("checking %p, mReady = %d", *prevPtr, (*prevPtr)->mReady); 669745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if ((*prevPtr)->mReady == 1) { 670745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt int fd = DNSServiceRefSockFD((*prevPtr)->mRef); 671745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (fd != -1) { 672745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD(" adding FD %d", fd); 673745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[i].fd = fd; 674745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollFds[i].events = POLLIN; 675745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mPollRefs[i] = &((*prevPtr)->mRef); 676745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt i++; 677745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 678745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt ALOGE("Error retreving socket FD for live ServiceRef"); 679745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 680745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt prevPtr = &((*prevPtr)->mNext); // advance to the next element 681745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else if ((*prevPtr)->mReady == -1) { 682745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD(" removing %p from play", *prevPtr); 683745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur = *prevPtr; 684745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt *prevPtr = (cur)->mNext; // change our notion of this element and don't advance 685745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete cur; 68679c5214e31471e75d79f50b6a282eebe76d2609bKenneth Tateno } else if ((*prevPtr)->mReady == 0) { 68779c5214e31471e75d79f50b6a282eebe76d2609bKenneth Tateno // Not ready so just skip this node and continue on 68879c5214e31471e75d79f50b6a282eebe76d2609bKenneth Tateno if (DBG_RESCAN) ALOGD("%p not ready. Continuing.", *prevPtr); 68979c5214e31471e75d79f50b6a282eebe76d2609bKenneth Tateno prevPtr = &((*prevPtr)->mNext); 690745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 691745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 692745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 693745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return i; 694745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 695745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 696745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltDNSServiceRef *MDnsSdListener::Monitor::allocateServiceRef(int id, Context *context) { 697745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (lookupServiceRef(id) != NULL) { 698745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete(context); 699745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 700745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 701745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *e = new Element(id, context); 702745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 703745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt e->mNext = mHead; 704745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mHead = e; 705745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 706745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return &(e->mRef); 707745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 708745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 709745e09fc5694e73920aaad18a626275597bdddb1Robert GreenwaltDNSServiceRef *MDnsSdListener::Monitor::lookupServiceRef(int id) { 710745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 711745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur = mHead; 712745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (cur != NULL) { 713745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mId == id) { 714745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt DNSServiceRef *result = &(cur->mRef); 715745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 716745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return result; 717745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 718745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur = cur->mNext; 719745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 720745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 721745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return NULL; 722745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 723745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 724745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Monitor::startMonitoring(int id) { 725745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("startMonitoring %d", id); 726745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 727745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur = mHead; 728745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (cur != NULL) { 729745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mId == id) { 730745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("marking %p as ready to be added", cur); 731745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mLiveCount++; 732745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur->mReady = 1; 733745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 734745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt write(mCtrlSocketPair[1], RESCAN, 1); // trigger a rescan for a fresh poll 735745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("triggering rescan"); 736745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 737745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 738745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur = cur->mNext; 739745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 740745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 741745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 742745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt 743745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListener::Monitor::freeServiceRef(int id) { 744745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("freeServiceRef %d", id); 745745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_lock(&mHeadMutex); 746745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element **prevPtr = &mHead; 747745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt Element *cur; 748745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt while (*prevPtr != NULL) { 749745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur = *prevPtr; 750745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mId == id) { 751745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (DBG_RESCAN) ALOGD("marking %p as ready to be removed", cur); 752745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt mLiveCount--; 753745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (cur->mReady == 1) { 754745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt cur->mReady = -1; // tell poll thread to delete 755745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt write(mCtrlSocketPair[1], RESCAN, 1); // trigger a rescan for a fresh poll 756745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt if (VDBG) ALOGD("triggering rescan"); 757745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } else { 758745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt *prevPtr = cur->mNext; 759745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt delete cur; 760745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 761745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 762745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt return; 763745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 764745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt prevPtr = &(cur->mNext); 765745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt } 766745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt pthread_mutex_unlock(&mHeadMutex); 767745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt} 768