2 * Copyright (C) 2010 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <arpa/inet.h>
22 #include <netinet/in.h>
26 #include <sys/socket.h>
27 #include <sys/types.h>
30 #define LOG_TAG "MDnsDS"
34 #include <cutils/log.h>
35 #include <cutils/properties.h>
36 #include <sysutils/SocketClient.h>
38 #include "MDnsSdListener.h"
39 #include "ResponseCode.h"
41 #define MDNS_SERVICE_NAME "mdnsd"
42 #define MDNS_SERVICE_STATUS "init.svc.mdnsd"
44 MDnsSdListener::MDnsSdListener() :
45 FrameworkListener("mdns", true) {
46 Monitor *m = new Monitor();
47 registerCmd(new Handler(m, this));
50 MDnsSdListener::Handler::Handler(Monitor *m, MDnsSdListener *listener) :
51 NetdCommand("mdnssd") {
52 if (DBG) ALOGD("MDnsSdListener::Hander starting up");
57 MDnsSdListener::Handler::~Handler() {}
59 void MDnsSdListener::Handler::discover(SocketClient *cli,
64 const int requestFlags) {
66 ALOGD("discover(%s, %s, %s, %d, %d)", iface, regType, domain, requestId,
69 Context *context = new Context(requestId, mListener);
70 DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context);
72 ALOGE("requestId %d already in use during discover call", requestId);
73 cli->sendMsg(ResponseCode::CommandParameterError,
74 "RequestId already in use during discover call", false);
77 if (VDBG) ALOGD("using ref %p", ref);
78 DNSServiceFlags nativeFlags = iToFlags(requestFlags);
79 int interfaceInt = ifaceNameToI(iface);
81 DNSServiceErrorType result = DNSServiceBrowse(ref, nativeFlags, interfaceInt, regType,
82 domain, &MDnsSdListenerDiscoverCallback, context);
83 if (result != kDNSServiceErr_NoError) {
84 ALOGE("Discover request %d got an error from DNSServiceBrowse %d", requestId, result);
85 mMonitor->freeServiceRef(requestId);
86 cli->sendMsg(ResponseCode::CommandParameterError,
87 "Discover request got an error from DNSServiceBrowse", false);
90 mMonitor->startMonitoring(requestId);
91 if (VDBG) ALOGD("discover successful");
92 cli->sendMsg(ResponseCode::CommandOkay, "Discover operation started", false);
96 void MDnsSdListenerDiscoverCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
97 uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName,
98 const char *regType, const char *replyDomain, void *inContext) {
99 MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
101 int refNumber = context->mRefNumber;
103 if (errorCode != kDNSServiceErr_NoError) {
104 asprintf(&msg, "%d %d", refNumber, errorCode);
105 context->mListener->sendBroadcast(ResponseCode::ServiceDiscoveryFailed, msg, false);
106 if (DBG) ALOGE("discover failure for %d, error= %d", refNumber, errorCode);
109 if (flags & kDNSServiceFlagsAdd) {
111 ALOGD("Discover found new serviceName %s, regType %s and domain %s for %d",
112 serviceName, regType, replyDomain, refNumber);
114 respCode = ResponseCode::ServiceDiscoveryServiceAdded;
117 ALOGD("Discover lost serviceName %s, regType %s and domain %s for %d",
118 serviceName, regType, replyDomain, refNumber);
120 respCode = ResponseCode::ServiceDiscoveryServiceRemoved;
122 asprintf(&msg, "%d %s %s %s", refNumber, serviceName, regType, replyDomain);
123 context->mListener->sendBroadcast(respCode, msg, false);
128 void MDnsSdListener::Handler::stop(SocketClient *cli, int argc, char **argv, const char *str) {
131 asprintf(&msg, "Invalid number of arguments to %s", str);
132 cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
136 int requestId = atoi(argv[2]);
137 DNSServiceRef *ref = mMonitor->lookupServiceRef(requestId);
139 if (DBG) ALOGE("%s stop used unknown requestId %d", str, requestId);
140 cli->sendMsg(ResponseCode::CommandParameterError, "Unknown requestId", false);
143 if (VDBG) ALOGD("Stopping %s with ref %p", str, ref);
144 DNSServiceRefDeallocate(*ref);
145 mMonitor->freeServiceRef(requestId);
147 asprintf(&msg, "%s stopped", str);
148 cli->sendMsg(ResponseCode::CommandOkay, msg, false);
152 void MDnsSdListener::Handler::serviceRegister(SocketClient *cli, int requestId,
153 const char *interfaceName, const char *serviceName, const char *serviceType,
154 const char *domain, const char *host, int port, int txtLen, void *txtRecord) {
156 ALOGD("serviceRegister(%d, %s, %s, %s, %s, %s, %d, %d, <binary>)", requestId,
157 interfaceName, serviceName, serviceType, domain, host, port, txtLen);
159 Context *context = new Context(requestId, mListener);
160 DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context);
163 ALOGE("requestId %d already in use during register call", requestId);
164 cli->sendMsg(ResponseCode::CommandParameterError,
165 "RequestId already in use during register call", false);
168 DNSServiceFlags nativeFlags = 0;
169 int interfaceInt = ifaceNameToI(interfaceName);
170 DNSServiceErrorType result = DNSServiceRegister(ref, interfaceInt, nativeFlags, serviceName,
171 serviceType, domain, host, port, txtLen, txtRecord, &MDnsSdListenerRegisterCallback,
173 if (result != kDNSServiceErr_NoError) {
174 ALOGE("service register request %d got an error from DNSServiceRegister %d", requestId,
176 mMonitor->freeServiceRef(requestId);
177 cli->sendMsg(ResponseCode::CommandParameterError,
178 "serviceRegister request got an error from DNSServiceRegister", false);
181 mMonitor->startMonitoring(requestId);
182 if (VDBG) ALOGD("serviceRegister successful");
183 cli->sendMsg(ResponseCode::CommandOkay, "serviceRegister started", false);
187 void MDnsSdListenerRegisterCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
188 DNSServiceErrorType errorCode, const char *serviceName, const char *regType,
189 const char *domain, void *inContext) {
190 MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
192 int refNumber = context->mRefNumber;
193 if (errorCode != kDNSServiceErr_NoError) {
194 asprintf(&msg, "%d %d", refNumber, errorCode);
195 context->mListener->sendBroadcast(ResponseCode::ServiceRegistrationFailed, msg, false);
196 if (DBG) ALOGE("register failure for %d, error= %d", refNumber, errorCode);
198 asprintf(&msg, "%d %s", refNumber, serviceName);
199 context->mListener->sendBroadcast(ResponseCode::ServiceRegistrationSucceeded, msg, false);
200 if (VDBG) ALOGD("register succeeded for %d as %s", refNumber, serviceName);
206 void MDnsSdListener::Handler::resolveService(SocketClient *cli, int requestId,
207 const char *interfaceName, const char *serviceName, const char *regType,
208 const char *domain) {
210 ALOGD("resolveService(%d, %s, %s, %s, %s)", requestId, interfaceName,
211 serviceName, regType, domain);
213 Context *context = new Context(requestId, mListener);
214 DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context);
216 ALOGE("request Id %d already in use during resolve call", requestId);
217 cli->sendMsg(ResponseCode::CommandParameterError,
218 "RequestId already in use during resolve call", false);
221 DNSServiceFlags nativeFlags = 0;
222 int interfaceInt = ifaceNameToI(interfaceName);
223 DNSServiceErrorType result = DNSServiceResolve(ref, nativeFlags, interfaceInt, serviceName,
224 regType, domain, &MDnsSdListenerResolveCallback, context);
225 if (result != kDNSServiceErr_NoError) {
226 ALOGE("service resolve request %d got an error from DNSServiceResolve %d", requestId,
228 mMonitor->freeServiceRef(requestId);
229 cli->sendMsg(ResponseCode::CommandParameterError,
230 "resolveService got an error from DNSServiceResolve", false);
233 mMonitor->startMonitoring(requestId);
234 if (VDBG) ALOGD("resolveService successful");
235 cli->sendMsg(ResponseCode::CommandOkay, "resolveService started", false);
239 void MDnsSdListenerResolveCallback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interface,
240 DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port,
241 uint16_t txtLen, const unsigned char *txtRecord, void *inContext) {
242 MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
244 int refNumber = context->mRefNumber;
246 if (errorCode != kDNSServiceErr_NoError) {
247 asprintf(&msg, "%d %d", refNumber, errorCode);
248 context->mListener->sendBroadcast(ResponseCode::ServiceResolveFailed, msg, false);
249 if (DBG) ALOGE("resolve failure for %d, error= %d", refNumber, errorCode);
251 asprintf(&msg, "%d %s %s %d %d", refNumber, fullname, hosttarget, port, txtLen);
252 context->mListener->sendBroadcast(ResponseCode::ServiceResolveSuccess, msg, false);
254 ALOGD("resolve succeeded for %d finding %s at %s:%d with txtLen %d",
255 refNumber, fullname, hosttarget, port, txtLen);
261 void MDnsSdListener::Handler::getAddrInfo(SocketClient *cli, int requestId,
262 const char *interfaceName, uint32_t protocol, const char *hostname) {
263 if (VDBG) ALOGD("getAddrInfo(%d, %s %d, %s)", requestId, interfaceName, protocol, hostname);
264 Context *context = new Context(requestId, mListener);
265 DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context);
267 ALOGE("request ID %d already in use during getAddrInfo call", requestId);
268 cli->sendMsg(ResponseCode::CommandParameterError,
269 "RequestId already in use during getAddrInfo call", false);
272 DNSServiceFlags nativeFlags = 0;
273 int interfaceInt = ifaceNameToI(interfaceName);
274 DNSServiceErrorType result = DNSServiceGetAddrInfo(ref, nativeFlags, interfaceInt, protocol,
275 hostname, &MDnsSdListenerGetAddrInfoCallback, context);
276 if (result != kDNSServiceErr_NoError) {
277 ALOGE("getAddrInfo request %d got an error from DNSServiceGetAddrInfo %d", requestId,
279 mMonitor->freeServiceRef(requestId);
280 cli->sendMsg(ResponseCode::CommandParameterError,
281 "getAddrInfo request got an error from DNSServiceGetAddrInfo", false);
284 mMonitor->startMonitoring(requestId);
285 if (VDBG) ALOGD("getAddrInfo successful");
286 cli->sendMsg(ResponseCode::CommandOkay, "getAddrInfo started", false);
290 void MDnsSdListenerGetAddrInfoCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
291 uint32_t interface, DNSServiceErrorType errorCode, const char *hostname,
292 const struct sockaddr *const sa, uint32_t ttl, void *inContext) {
293 MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
294 int refNumber = context->mRefNumber;
296 if (errorCode != kDNSServiceErr_NoError) {
298 asprintf(&msg, "%d %d", refNumber, errorCode);
299 context->mListener->sendBroadcast(ResponseCode::ServiceGetAddrInfoFailed, msg, false);
300 if (DBG) ALOGE("getAddrInfo failure for %d, error= %d", refNumber, errorCode);
303 char addr[INET6_ADDRSTRLEN];
305 if (sa->sa_family == AF_INET) {
306 inet_ntop(sa->sa_family, &(((struct sockaddr_in *)sa)->sin_addr), addr, sizeof(addr));
308 inet_ntop(sa->sa_family, &(((struct sockaddr_in6 *)sa)->sin6_addr), addr, sizeof(addr));
310 asprintf(&msg, "%d %s %d %s", refNumber, hostname, ttl, addr);
311 context->mListener->sendBroadcast(ResponseCode::ServiceGetAddrInfoSuccess, msg, false);
313 ALOGD("getAddrInfo succeeded for %d: %s", refNumber, msg);
319 void MDnsSdListener::Handler::setHostname(SocketClient *cli, int requestId,
320 const char *hostname) {
321 if (VDBG) ALOGD("setHostname(%d, %s)", requestId, hostname);
322 Context *context = new Context(requestId, mListener);
323 DNSServiceRef *ref = mMonitor->allocateServiceRef(requestId, context);
325 ALOGE("request Id %d already in use during setHostname call", requestId);
326 cli->sendMsg(ResponseCode::CommandParameterError,
327 "RequestId already in use during setHostname call", false);
330 DNSServiceFlags nativeFlags = 0;
331 DNSServiceErrorType result = DNSSetHostname(ref, nativeFlags, hostname,
332 &MDnsSdListenerSetHostnameCallback, context);
333 if (result != kDNSServiceErr_NoError) {
334 ALOGE("setHostname request %d got an error from DNSSetHostname %d", requestId, result);
335 mMonitor->freeServiceRef(requestId);
336 cli->sendMsg(ResponseCode::CommandParameterError,
337 "setHostname got an error from DNSSetHostname", false);
340 mMonitor->startMonitoring(requestId);
341 if (VDBG) ALOGD("setHostname successful");
342 cli->sendMsg(ResponseCode::CommandOkay, "setHostname started", false);
346 void MDnsSdListenerSetHostnameCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
347 DNSServiceErrorType errorCode, const char *hostname, void *inContext) {
348 MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
350 int refNumber = context->mRefNumber;
351 if (errorCode != kDNSServiceErr_NoError) {
352 asprintf(&msg, "%d %d", refNumber, errorCode);
353 context->mListener->sendBroadcast(ResponseCode::ServiceSetHostnameFailed, msg, false);
354 if (DBG) ALOGE("setHostname failure for %d, error= %d", refNumber, errorCode);
356 asprintf(&msg, "%d %s", refNumber, hostname);
357 context->mListener->sendBroadcast(ResponseCode::ServiceSetHostnameSuccess, msg, false);
358 if (VDBG) ALOGD("setHostname succeeded for %d. Set to %s", refNumber, hostname);
364 int MDnsSdListener::Handler::ifaceNameToI(const char *iface) {
368 const char *MDnsSdListener::Handler::iToIfaceName(int i) {
372 DNSServiceFlags MDnsSdListener::Handler::iToFlags(int i) {
376 int MDnsSdListener::Handler::flagsToI(DNSServiceFlags flags) {
380 int MDnsSdListener::Handler::runCommand(SocketClient *cli,
381 int argc, char **argv) {
384 asprintf( &msg, "Invalid number of arguments to mdnssd: %i", argc);
386 cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
393 if (strcmp(cmd, "discover") == 0) {
395 cli->sendMsg(ResponseCode::CommandParameterError,
396 "Invalid number of arguments to mdnssd discover", false);
399 int requestId = atoi(argv[2]);
400 char *serviceType = argv[3];
402 discover(cli, NULL, serviceType, NULL, requestId, 0);
403 } else if (strcmp(cmd, "stop-discover") == 0) {
404 stop(cli, argc, argv, "discover");
405 } else if (strcmp(cmd, "register") == 0) {
407 cli->sendMsg(ResponseCode::CommandParameterError,
408 "Invalid number of arguments to mdnssd register", false);
411 int requestId = atoi(argv[2]);
412 char *serviceName = argv[3];
413 char *serviceType = argv[4];
414 int port = atoi(argv[5]);
415 char *interfaceName = NULL; // will use all
416 char *domain = NULL; // will use default
417 char *host = NULL; // will use default hostname
419 void *textRecord = NULL;
421 serviceRegister(cli, requestId, interfaceName, serviceName,
422 serviceType, domain, host, port, textLen, textRecord);
423 } else if (strcmp(cmd, "stop-register") == 0) {
424 stop(cli, argc, argv, "register");
425 } else if (strcmp(cmd, "resolve") == 0) {
427 cli->sendMsg(ResponseCode::CommandParameterError,
428 "Invalid number of arguments to mdnssd resolve", false);
431 int requestId = atoi(argv[2]);
432 char *interfaceName = NULL; // will use all
433 char *serviceName = argv[3];
434 char *regType = argv[4];
435 char *domain = argv[5];
436 resolveService(cli, requestId, interfaceName, serviceName, regType, domain);
437 } else if (strcmp(cmd, "stop-resolve") == 0) {
438 stop(cli, argc, argv, "resolve");
439 } else if (strcmp(cmd, "start-service") == 0) {
440 if (mMonitor->startService()) {
441 cli->sendMsg(ResponseCode::CommandOkay, "Service Started", false);
443 cli->sendMsg(ResponseCode::ServiceStartFailed, "Service already running", false);
445 } else if (strcmp(cmd, "stop-service") == 0) {
446 if (mMonitor->stopService()) {
447 cli->sendMsg(ResponseCode::CommandOkay, "Service Stopped", false);
449 cli->sendMsg(ResponseCode::ServiceStopFailed, "Service still in use", false);
451 } else if (strcmp(cmd, "sethostname") == 0) {
453 cli->sendMsg(ResponseCode::CommandParameterError,
454 "Invalid number of arguments to mdnssd sethostname", false);
457 int requestId = atoi(argv[2]);
458 char *hostname = argv[3];
459 setHostname(cli, requestId, hostname);
460 } else if (strcmp(cmd, "stop-sethostname") == 0) {
461 stop(cli, argc, argv, "sethostname");
462 } else if (strcmp(cmd, "getaddrinfo") == 0) {
464 cli->sendMsg(ResponseCode::CommandParameterError,
465 "Invalid number of arguments to mdnssd getaddrinfo", false);
468 int requestId = atoi(argv[2]);
469 char *hostname = argv[3];
470 char *interfaceName = NULL; // default
471 int protocol = 0; // intelligient heuristic (both v4 + v6)
472 getAddrInfo(cli, requestId, interfaceName, protocol, hostname);
473 } else if (strcmp(cmd, "stop-getaddrinfo") == 0) {
474 stop(cli, argc, argv, "getaddrinfo");
476 if (VDBG) ALOGE("Unknown cmd %s", cmd);
477 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown mdnssd cmd", false);
483 MDnsSdListener::Monitor::Monitor() {
485 pthread_mutex_init(&mHeadMutex, NULL);
486 socketpair(AF_LOCAL, SOCK_STREAM, 0, mCtrlSocketPair);
487 pthread_create(&mThread, NULL, MDnsSdListener::Monitor::threadStart, this);
490 void *MDnsSdListener::Monitor::threadStart(void *obj) {
491 Monitor *monitor = reinterpret_cast<Monitor *>(obj);
499 int MDnsSdListener::Monitor::startService() {
501 char property_value[PROPERTY_VALUE_MAX];
502 pthread_mutex_lock(&mHeadMutex);
503 property_get(MDNS_SERVICE_STATUS, property_value, "");
504 if (strcmp("running", property_value) != 0) {
505 ALOGD("Starting MDNSD");
506 property_set("ctl.start", MDNS_SERVICE_NAME);
507 wait_for_property(MDNS_SERVICE_STATUS, "running", 5);
512 pthread_mutex_unlock(&mHeadMutex);
516 int MDnsSdListener::Monitor::stopService() {
518 pthread_mutex_lock(&mHeadMutex);
520 ALOGD("Stopping MDNSD");
521 property_set("ctl.stop", MDNS_SERVICE_NAME);
522 wait_for_property(MDNS_SERVICE_STATUS, "stopped", 5);
527 pthread_mutex_unlock(&mHeadMutex);
531 void MDnsSdListener::Monitor::run() {
535 mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize);
536 mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize);
538 mPollFds[0].fd = mCtrlSocketPair[0];
539 mPollFds[0].events = POLLIN;
541 if (VDBG) ALOGD("MDnsSdListener starting to monitor");
543 if (VDBG) ALOGD("Going to poll with pollCount %d", pollCount);
544 int pollResults = poll(mPollFds, pollCount, 10000000);
545 if (pollResults < 0) {
546 ALOGE("Error in poll - got %d", errno);
547 } else if (pollResults > 0) {
548 if (VDBG) ALOGD("Monitor poll got data pollCount = %d, %d", pollCount, pollResults);
549 for(int i = 1; i < pollCount; i++) {
550 if (mPollFds[i].revents != 0) {
552 ALOGD("Monitor found [%d].revents = %d - calling ProcessResults",
553 i, mPollFds[i].revents);
555 DNSServiceProcessResult(*(mPollRefs[i]));
556 mPollFds[i].revents = 0;
559 if (VDBG) ALOGD("controlSocket shows revent= %d", mPollFds[0].revents);
560 switch (mPollFds[0].revents) {
563 read(mCtrlSocketPair[0], &readBuf, 1);
564 if (DBG) ALOGD("MDnsSdListener::Monitor got %c", readBuf[0]);
565 if (memcmp(RESCAN, readBuf, 1) == 0) {
566 pollCount = rescan();
570 mPollFds[0].revents = 0;
572 if (VDBG) ALOGD("MDnsSdListener::Monitor poll timed out");
581 int MDnsSdListener::Monitor::rescan() {
582 // rescan the list from mHead and make new pollfds and serviceRefs
584 ALOGD("MDnsSdListener::Monitor poll rescanning - size=%d, live=%d", mPollSize, mLiveCount);
587 pthread_mutex_lock(&mHeadMutex);
588 Element **prevPtr = &mHead;
590 if (mPollSize <= mLiveCount) {
591 mPollSize = mLiveCount + 5;
594 mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize);
595 mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize);
597 memset(mPollFds, sizeof(struct pollfd) * mPollSize, 0);
598 memset(mPollRefs, sizeof(DNSServiceRef *) * mPollSize, 0);
600 mPollFds[0].fd = mCtrlSocketPair[0];
601 mPollFds[0].events = POLLIN;
602 if (DBG_RESCAN) ALOGD("mHead = %p", mHead);
603 while (*prevPtr != NULL) {
604 if (DBG_RESCAN) ALOGD("checking %p, mReady = %d", *prevPtr, (*prevPtr)->mReady);
605 if ((*prevPtr)->mReady == 1) {
606 int fd = DNSServiceRefSockFD((*prevPtr)->mRef);
608 if (DBG_RESCAN) ALOGD(" adding FD %d", fd);
610 mPollFds[i].events = POLLIN;
611 mPollRefs[i] = &((*prevPtr)->mRef);
614 ALOGE("Error retreving socket FD for live ServiceRef");
616 prevPtr = &((*prevPtr)->mNext); // advance to the next element
617 } else if ((*prevPtr)->mReady == -1) {
618 if (DBG_RESCAN) ALOGD(" removing %p from play", *prevPtr);
619 Element *cur = *prevPtr;
620 *prevPtr = (cur)->mNext; // change our notion of this element and don't advance
624 pthread_mutex_unlock(&mHeadMutex);
628 DNSServiceRef *MDnsSdListener::Monitor::allocateServiceRef(int id, Context *context) {
629 if (lookupServiceRef(id) != NULL) {
633 Element *e = new Element(id, context);
634 pthread_mutex_lock(&mHeadMutex);
637 pthread_mutex_unlock(&mHeadMutex);
641 DNSServiceRef *MDnsSdListener::Monitor::lookupServiceRef(int id) {
642 pthread_mutex_lock(&mHeadMutex);
643 Element *cur = mHead;
644 while (cur != NULL) {
645 if (cur->mId == id) {
646 DNSServiceRef *result = &(cur->mRef);
647 pthread_mutex_unlock(&mHeadMutex);
652 pthread_mutex_unlock(&mHeadMutex);
656 void MDnsSdListener::Monitor::startMonitoring(int id) {
657 if (VDBG) ALOGD("startMonitoring %d", id);
658 pthread_mutex_lock(&mHeadMutex);
659 Element *cur = mHead;
660 while (cur != NULL) {
661 if (cur->mId == id) {
662 if (DBG_RESCAN) ALOGD("marking %p as ready to be added", cur);
665 pthread_mutex_unlock(&mHeadMutex);
666 write(mCtrlSocketPair[1], RESCAN, 1); // trigger a rescan for a fresh poll
667 if (VDBG) ALOGD("triggering rescan");
672 pthread_mutex_unlock(&mHeadMutex);
675 #define NAP_TIME 200 // 200 ms between polls
676 static int wait_for_property(const char *name, const char *desired_value, int maxwait)
678 char value[PROPERTY_VALUE_MAX] = {'\0'};
679 int maxnaps = (maxwait * 1000) / NAP_TIME;
685 while (maxnaps-- > 0) {
686 usleep(NAP_TIME * 1000);
687 if (property_get(name, value, NULL)) {
688 if (desired_value == NULL || strcmp(value, desired_value) == 0) {
693 return -1; /* failure */
696 void MDnsSdListener::Monitor::freeServiceRef(int id) {
697 if (VDBG) ALOGD("freeServiceRef %d", id);
698 pthread_mutex_lock(&mHeadMutex);
699 Element **prevPtr = &mHead;
701 while (*prevPtr != NULL) {
703 if (cur->mId == id) {
704 if (DBG_RESCAN) ALOGD("marking %p as ready to be removed", cur);
706 if (cur->mReady == 1) {
707 cur->mReady = -1; // tell poll thread to delete
708 write(mCtrlSocketPair[1], RESCAN, 1); // trigger a rescan for a fresh poll
709 if (VDBG) ALOGD("triggering rescan");
711 *prevPtr = cur->mNext;
714 pthread_mutex_unlock(&mHeadMutex);
717 prevPtr = &(cur->mNext);
719 pthread_mutex_unlock(&mHeadMutex);