• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 #include "MDnsSdListener.h"
18 
19 #include <arpa/inet.h>
20 #include <dirent.h>
21 #include <errno.h>
22 #include <inttypes.h>
23 #include <linux/if.h>
24 #include <net/if.h>
25 #include <netdb.h>
26 #include <netinet/in.h>
27 #include <pthread.h>
28 #include <resolv.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/poll.h>
32 #include <sys/socket.h>
33 #include <sys/types.h>
34 #include <thread>
35 
36 #define LOG_TAG "MDnsDS"
37 #define DBG 1
38 #define VDBG 1
39 
40 #include <cutils/properties.h>
41 #include <log/log.h>
42 #include <netdutils/ThreadUtil.h>
43 #include <sysutils/SocketClient.h>
44 
45 #include "Controllers.h"
46 #include "MDnsEventReporter.h"
47 #include "netid_client.h"
48 
49 using android::net::gCtls;
50 
51 #define MDNS_SERVICE_NAME "mdnsd"
52 #define MDNS_SERVICE_STATUS "init.svc.mdnsd"
53 
54 #define CEIL(x, y) (((x) + (y) - 1) / (y))
55 
56 constexpr char RESCAN[] = "1";
57 
58 using android::net::mdns::aidl::DiscoveryInfo;
59 using android::net::mdns::aidl::GetAddressInfo;
60 using android::net::mdns::aidl::IMDnsEventListener;
61 using android::net::mdns::aidl::RegistrationInfo;
62 using android::net::mdns::aidl::ResolutionInfo;
63 
ifaceIndexToNetId(uint32_t interfaceIndex)64 static unsigned ifaceIndexToNetId(uint32_t interfaceIndex) {
65     char interfaceName[IFNAMSIZ] = {};
66     unsigned netId;
67     if (if_indextoname(interfaceIndex, interfaceName) == nullptr) {
68         ALOGE("Interface %d was not found", interfaceIndex);
69         return NETID_UNSET;
70     } else if ((netId = gCtls->netCtrl.getNetworkForInterface(interfaceName)) == NETID_UNSET) {
71         ALOGE("Network was not found for interface %s", interfaceName);
72         return NETID_UNSET;
73     }
74     return netId;
75 }
76 
discover(uint32_t ifIndex,const char * regType,const char * domain,const int requestId,const int requestFlags)77 int MDnsSdListener::discover(uint32_t ifIndex, const char* regType, const char* domain,
78                              const int requestId, const int requestFlags) {
79     if (VDBG) {
80         ALOGD("discover(%d, %s, %s, %d, %d)", ifIndex, regType, domain ? domain : "null", requestId,
81               requestFlags);
82     }
83     Context* context = new Context(requestId);
84     DNSServiceRef* ref = mMonitor.allocateServiceRef(requestId, context);
85     if (ref == nullptr) {
86         ALOGE("requestId %d already in use during discover call", requestId);
87         return -EBUSY;
88     }
89     if (VDBG) ALOGD("using ref %p", ref);
90 
91     DNSServiceErrorType result = DNSServiceBrowse(ref, requestFlags, ifIndex, regType, domain,
92                                                   &MDnsSdListenerDiscoverCallback, context);
93     if (result != kDNSServiceErr_NoError) {
94         ALOGE("Discover request %d got an error from DNSServiceBrowse %d", requestId, result);
95         mMonitor.freeServiceRef(requestId);
96         // Return kDNSServiceErr_* directly instead of transferring to an UNIX error.
97         // This can help caller to know what going wrong from mdnsresponder side.
98         return -result;
99     }
100     mMonitor.startMonitoring(requestId);
101     if (VDBG) ALOGD("discover successful");
102     return 0;
103 }
104 
MDnsSdListenerDiscoverCallback(DNSServiceRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * serviceName,const char * regType,const char * replyDomain,void * inContext)105 void MDnsSdListenerDiscoverCallback(DNSServiceRef /* sdRef */, DNSServiceFlags flags,
106                                     uint32_t ifIndex, DNSServiceErrorType errorCode,
107                                     const char* serviceName, const char* regType,
108                                     const char* replyDomain, void* inContext) {
109     MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
110     int refNumber = context->mRefNumber;
111     const std::lock_guard lock(MDnsEventReporter::getInstance().mMutex);
112     const auto& listeners = MDnsEventReporter::getInstance().getEventListeners();
113     if (listeners.empty()) {
114         ALOGI("Discover callback not sent since no IMDnsEventListener receiver is available.");
115         return;
116     }
117 
118     DiscoveryInfo info;
119     info.id = refNumber;
120     info.serviceName = serviceName;
121     info.registrationType = regType;
122     info.interfaceIdx = ifIndex;
123     // If the network is not found, still send the event and let
124     // the service decide what to do with a callback with an empty network
125     info.netId = ifaceIndexToNetId(ifIndex);
126     if (errorCode == kDNSServiceErr_NoError) {
127         if (flags & kDNSServiceFlagsAdd) {
128             if (VDBG) {
129                 ALOGD("Discover found new serviceName %s, regType %s and domain %s for %d",
130                       serviceName, regType, replyDomain, refNumber);
131             }
132             info.result = IMDnsEventListener::SERVICE_FOUND;
133         } else {
134             if (VDBG) {
135                 ALOGD("Discover lost serviceName %s, regType %s and domain %s for %d", serviceName,
136                       regType, replyDomain, refNumber);
137             }
138             info.result = IMDnsEventListener::SERVICE_LOST;
139         }
140     } else {
141         if (DBG) ALOGE("discover failure for %d, error= %d", refNumber, errorCode);
142         info.result = IMDnsEventListener::SERVICE_DISCOVERY_FAILED;
143     }
144 
145     for (const auto& it : listeners) {
146         it->getListener()->onServiceDiscoveryStatus(info);
147     }
148 }
149 
stop(int requestId)150 int MDnsSdListener::stop(int requestId) {
151     DNSServiceRef* ref = mMonitor.lookupServiceRef(requestId);
152     if (ref == nullptr) {
153         if (DBG) ALOGE("Stop used unknown requestId %d", requestId);
154         return -ESRCH;
155     }
156     if (VDBG) ALOGD("Stopping operation with ref %p", ref);
157     mMonitor.deallocateServiceRef(ref);
158     mMonitor.freeServiceRef(requestId);
159     return 0;
160 }
161 
serviceRegister(int requestId,const char * serviceName,const char * serviceType,const char * domain,const char * host,int port,const std::vector<unsigned char> & txtRecord,uint32_t ifIndex)162 int MDnsSdListener::serviceRegister(int requestId, const char* serviceName, const char* serviceType,
163                                     const char* domain, const char* host, int port,
164                                     const std::vector<unsigned char>& txtRecord, uint32_t ifIndex) {
165     if (VDBG) {
166         ALOGD("serviceRegister(%d, %d, %s, %s, %s, %s, %d, <binary>)", requestId, ifIndex,
167               serviceName, serviceType, domain ? domain : "null", host ? host : "null", port);
168     }
169     Context* context = new Context(requestId);
170     DNSServiceRef* ref = mMonitor.allocateServiceRef(requestId, context);
171     if (ref == nullptr) {
172         ALOGE("requestId %d already in use during register call", requestId);
173         return -EBUSY;
174     }
175     port = htons(port);
176     DNSServiceFlags nativeFlags = 0;
177     DNSServiceErrorType result = DNSServiceRegister(
178             ref, nativeFlags, ifIndex, serviceName, serviceType, domain, host, port,
179             txtRecord.size(), &txtRecord.front(), &MDnsSdListenerRegisterCallback, context);
180     if (result != kDNSServiceErr_NoError) {
181         ALOGE("service register request %d got an error from DNSServiceRegister %d", requestId,
182                 result);
183         mMonitor.freeServiceRef(requestId);
184         // Return kDNSServiceErr_* directly instead of transferring to an UNIX error.
185         // This can help caller to know what going wrong from mdnsresponder side.
186         return -result;
187     }
188     mMonitor.startMonitoring(requestId);
189     if (VDBG) ALOGD("serviceRegister successful");
190     return 0;
191 }
192 
MDnsSdListenerRegisterCallback(DNSServiceRef,DNSServiceFlags,DNSServiceErrorType errorCode,const char * serviceName,const char * regType,const char *,void * inContext)193 void MDnsSdListenerRegisterCallback(DNSServiceRef /* sdRef */, DNSServiceFlags /* flags */,
194                                     DNSServiceErrorType errorCode, const char* serviceName,
195                                     const char* regType, const char* /* domain */,
196                                     void* inContext) {
197     MDnsSdListener::Context* context = reinterpret_cast<MDnsSdListener::Context*>(inContext);
198     int refNumber = context->mRefNumber;
199     const std::lock_guard lock(MDnsEventReporter::getInstance().mMutex);
200     const auto& listeners = MDnsEventReporter::getInstance().getEventListeners();
201     if (listeners.empty()) {
202         ALOGI("Register callback not sent since no IMDnsEventListener receiver is available.");
203         return;
204     }
205 
206     RegistrationInfo info;
207     info.id = refNumber;
208     info.serviceName = serviceName;
209     info.registrationType = regType;
210     if (errorCode == kDNSServiceErr_NoError) {
211         if (VDBG) ALOGD("register succeeded for %d as %s", refNumber, serviceName);
212         info.result = IMDnsEventListener::SERVICE_REGISTERED;
213     } else {
214         if (DBG) ALOGE("register failure for %d, error= %d", refNumber, errorCode);
215         info.result = IMDnsEventListener::SERVICE_REGISTRATION_FAILED;
216     }
217 
218     for (const auto& it : listeners) {
219         it->getListener()->onServiceRegistrationStatus(info);
220     }
221 }
222 
resolveService(int requestId,uint32_t ifIndex,const char * serviceName,const char * regType,const char * domain)223 int MDnsSdListener::resolveService(int requestId, uint32_t ifIndex, const char* serviceName,
224                                    const char* regType, const char* domain) {
225     if (VDBG) {
226         ALOGD("resolveService(%d, %d, %s, %s, %s)", requestId, ifIndex, serviceName, regType,
227               domain);
228     }
229     Context* context = new Context(requestId);
230     DNSServiceRef* ref = mMonitor.allocateServiceRef(requestId, context);
231     if (ref == nullptr) {
232         ALOGE("request Id %d already in use during resolve call", requestId);
233         return -EBUSY;
234     }
235     DNSServiceFlags nativeFlags = 0;
236     DNSServiceErrorType result = DNSServiceResolve(ref, nativeFlags, ifIndex, serviceName, regType,
237                                                    domain, &MDnsSdListenerResolveCallback, context);
238     if (result != kDNSServiceErr_NoError) {
239         ALOGE("service resolve request %d on iface %d: got an error from DNSServiceResolve %d",
240               requestId, ifIndex, result);
241         mMonitor.freeServiceRef(requestId);
242         // Return kDNSServiceErr_* directly instead of transferring to an UNIX error.
243         // This can help caller to know what going wrong from mdnsresponder side.
244         return -result;
245     }
246     mMonitor.startMonitoring(requestId);
247     if (VDBG) ALOGD("resolveService successful");
248     return 0;
249 }
250 
MDnsSdListenerResolveCallback(DNSServiceRef,DNSServiceFlags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * fullname,const char * hosttarget,uint16_t port,uint16_t txtLen,const unsigned char * txtRecord,void * inContext)251 void MDnsSdListenerResolveCallback(DNSServiceRef /* sdRef */, DNSServiceFlags /* flags */,
252                                    uint32_t ifIndex, DNSServiceErrorType errorCode,
253                                    const char* fullname, const char* hosttarget, uint16_t port,
254                                    uint16_t txtLen, const unsigned char* txtRecord,
255                                    void* inContext) {
256     MDnsSdListener::Context* context = reinterpret_cast<MDnsSdListener::Context*>(inContext);
257     int refNumber = context->mRefNumber;
258     const std::lock_guard lock(MDnsEventReporter::getInstance().mMutex);
259     const auto& listeners = MDnsEventReporter::getInstance().getEventListeners();
260     if (listeners.empty()) {
261         ALOGI("Resolve callback not sent since no IMDnsEventListener receiver is available.");
262         return;
263     }
264     port = ntohs(port);
265 
266     ResolutionInfo info;
267     info.id = refNumber;
268     info.port = port;
269     info.serviceFullName = fullname;
270     info.hostname = hosttarget;
271     info.txtRecord = std::vector<unsigned char>(txtRecord, txtRecord + txtLen);
272     info.interfaceIdx = ifIndex;
273     if (errorCode == kDNSServiceErr_NoError) {
274         if (VDBG) {
275             ALOGD("resolve succeeded for %d finding %s at %s:%d with txtLen %d", refNumber,
276                   fullname, hosttarget, port, txtLen);
277         }
278         info.result = IMDnsEventListener::SERVICE_RESOLVED;
279     } else {
280         if (DBG) ALOGE("resolve failure for %d, error= %d", refNumber, errorCode);
281         info.result = IMDnsEventListener::SERVICE_RESOLUTION_FAILED;
282     }
283 
284     for (const auto& it : listeners) {
285         it->getListener()->onServiceResolutionStatus(info);
286     }
287 }
288 
getAddrInfo(int requestId,uint32_t ifIndex,uint32_t protocol,const char * hostname)289 int MDnsSdListener::getAddrInfo(int requestId, uint32_t ifIndex, uint32_t protocol,
290                                 const char* hostname) {
291     if (VDBG) ALOGD("getAddrInfo(%d, %u %d, %s)", requestId, ifIndex, protocol, hostname);
292     Context* context = new Context(requestId);
293     DNSServiceRef* ref = mMonitor.allocateServiceRef(requestId, context);
294     if (ref == nullptr) {
295         ALOGE("request ID %d already in use during getAddrInfo call", requestId);
296         return -EBUSY;
297     }
298     DNSServiceFlags nativeFlags = 0;
299     DNSServiceErrorType result =
300             DNSServiceGetAddrInfo(ref, nativeFlags, ifIndex, protocol, hostname,
301                                   &MDnsSdListenerGetAddrInfoCallback, context);
302     if (result != kDNSServiceErr_NoError) {
303         ALOGE("getAddrInfo request %d got an error from DNSServiceGetAddrInfo %d", requestId,
304                 result);
305         mMonitor.freeServiceRef(requestId);
306         // Return kDNSServiceErr_* directly instead of transferring to an UNIX error.
307         // This can help caller to know what going wrong from mdnsresponder side.
308         return -result;
309     }
310     mMonitor.startMonitoring(requestId);
311     if (VDBG) ALOGD("getAddrInfo successful");
312     return 0;
313 }
314 
MDnsSdListenerGetAddrInfoCallback(DNSServiceRef,DNSServiceFlags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * hostname,const struct sockaddr * const sa,uint32_t,void * inContext)315 void MDnsSdListenerGetAddrInfoCallback(DNSServiceRef /* sdRef */, DNSServiceFlags /* flags */,
316                                        uint32_t ifIndex, DNSServiceErrorType errorCode,
317                                        const char* hostname, const struct sockaddr* const sa,
318                                        uint32_t /* ttl */, void* inContext) {
319     MDnsSdListener::Context *context = reinterpret_cast<MDnsSdListener::Context *>(inContext);
320     int refNumber = context->mRefNumber;
321     const std::lock_guard lock(MDnsEventReporter::getInstance().mMutex);
322     const auto& listeners = MDnsEventReporter::getInstance().getEventListeners();
323     if (listeners.empty()) {
324         ALOGI("Get address callback not sent since no IMDnsEventListener receiver is available.");
325         return;
326     }
327 
328     GetAddressInfo info;
329     info.id = refNumber;
330     info.hostname = hostname;
331     info.interfaceIdx = ifIndex;
332     // If the network is not found, still send the event with an empty network
333     // and let the service decide what to do with it
334     info.netId = ifaceIndexToNetId(ifIndex);
335     if (errorCode == kDNSServiceErr_NoError) {
336         char addr[INET6_ADDRSTRLEN];
337         if (sa->sa_family == AF_INET) {
338             inet_ntop(sa->sa_family, &(((struct sockaddr_in *)sa)->sin_addr), addr, sizeof(addr));
339         } else {
340             inet_ntop(sa->sa_family, &(((struct sockaddr_in6 *)sa)->sin6_addr), addr, sizeof(addr));
341         }
342         info.address = addr;
343         if (VDBG) {
344             ALOGD("getAddrInfo succeeded for %d:", refNumber);
345         }
346         info.result = IMDnsEventListener::SERVICE_GET_ADDR_SUCCESS;
347     } else {
348         if (DBG) ALOGE("getAddrInfo failure for %d, error= %d", refNumber, errorCode);
349         info.result = IMDnsEventListener::SERVICE_GET_ADDR_FAILED;
350     }
351     for (const auto& it : listeners) {
352         it->getListener()->onGettingServiceAddressStatus(info);
353     }
354 }
355 
startDaemon()356 int MDnsSdListener::startDaemon() {
357     if (!mMonitor.startService()) {
358         ALOGE("Failed to start: Service already running");
359         return -EBUSY;
360     }
361     return 0;
362 }
363 
stopDaemon()364 int MDnsSdListener::stopDaemon() {
365     if (!mMonitor.stopService()) {
366         ALOGE("Failed to stop: Service still in use");
367         return -EBUSY;
368     }
369     return 0;
370 }
371 
Monitor()372 MDnsSdListener::Monitor::Monitor() {
373     mHead = nullptr;
374     mLiveCount = 0;
375     mPollFds = nullptr;
376     mPollRefs = nullptr;
377     mPollSize = 10;
378     socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, mCtrlSocketPair);
379 
380     mRescanThread = new std::thread(&Monitor::run, this);
381     if (!mRescanThread->joinable()) ALOGE("Unable to launch thread.");
382 }
383 
~Monitor()384 MDnsSdListener::Monitor::~Monitor() {
385     if (VDBG) ALOGD("Monitor recycling");
386     close(mCtrlSocketPair[1]);  // interrupt poll in MDnsSdListener::Monitor::run() and revent will
387                                 // be 17 = POLLIN | POLLHUP
388     mRescanThread->join();
389     delete mRescanThread;
390     if (VDBG) ALOGD("Monitor recycled");
391 }
392 #define NAP_TIME 200  // 200 ms between polls
wait_for_property(const char * name,const char * desired_value,int maxwait)393 static int wait_for_property(const char *name, const char *desired_value, int maxwait)
394 {
395     char value[PROPERTY_VALUE_MAX] = {'\0'};
396     int maxnaps = (maxwait * 1000) / NAP_TIME;
397 
398     if (maxnaps < 1) {
399         maxnaps = 1;
400     }
401 
402     while (maxnaps-- > 0) {
403         usleep(NAP_TIME * 1000);
404         if (property_get(name, value, nullptr)) {
405             if (desired_value == nullptr || strcmp(value, desired_value) == 0) {
406                 return 0;
407             }
408         }
409     }
410     return -1; /* failure */
411 }
412 
startService()413 int MDnsSdListener::Monitor::startService() {
414     char property_value[PROPERTY_VALUE_MAX];
415     std::lock_guard guard(mMutex);
416     property_get(MDNS_SERVICE_STATUS, property_value, "");
417     if (strcmp("running", property_value) != 0) {
418         ALOGD("Starting MDNSD");
419         property_set("ctl.start", MDNS_SERVICE_NAME);
420         wait_for_property(MDNS_SERVICE_STATUS, "running", 5);
421         return -1;
422     }
423     return 0;
424 }
425 
stopService()426 int MDnsSdListener::Monitor::stopService() {
427     std::lock_guard guard(mMutex);
428     if (mHead == nullptr) {
429         ALOGD("Stopping MDNSD");
430         property_set("ctl.stop", MDNS_SERVICE_NAME);
431         wait_for_property(MDNS_SERVICE_STATUS, "stopped", 5);
432         return -1;
433     }
434     return 0;
435 }
436 
run()437 void MDnsSdListener::Monitor::run() {
438     int pollCount = 1;
439 
440     mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize);
441     mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize);
442     LOG_ALWAYS_FATAL_IF((mPollFds == nullptr), "initial calloc failed on mPollFds with a size of %d",
443             ((int)sizeof(struct pollfd)) * mPollSize);
444     LOG_ALWAYS_FATAL_IF((mPollRefs == nullptr), "initial calloc failed on mPollRefs with a size of %d",
445             ((int)sizeof(DNSServiceRef *)) * mPollSize);
446 
447     mPollFds[0].fd = mCtrlSocketPair[0];
448     mPollFds[0].events = POLLIN;
449 
450     if (VDBG) ALOGD("MDnsSdListener starting to monitor");
451     while (1) {
452         if (VDBG) ALOGD("Going to poll with pollCount %d", pollCount);
453         int pollResults = poll(mPollFds, pollCount, 10000000);
454         if (VDBG) ALOGD("pollResults=%d", pollResults);
455         if (pollResults < 0) {
456             ALOGE("Error in poll - got %d", errno);
457         } else if (pollResults > 0) {
458             if (VDBG) ALOGD("Monitor poll got data pollCount = %d, %d", pollCount, pollResults);
459             for(int i = 1; i < pollCount; i++) {
460                 if (mPollFds[i].revents != 0) {
461                     if (VDBG) {
462                         ALOGD("Monitor found [%d].revents = %d - calling ProcessResults",
463                                 i, mPollFds[i].revents);
464                     }
465                     std::lock_guard guard(mMutex);
466                     DNSServiceProcessResult(*(mPollRefs[i]));
467                     mPollFds[i].revents = 0;
468                 }
469             }
470             if (VDBG) ALOGD("controlSocket shows revent= %d", mPollFds[0].revents);
471             if (mPollFds[0].revents & POLLHUP) {
472                 free(mPollFds);
473                 free(mPollRefs);
474                 if (VDBG) ALOGD("Monitor thread leaving.");
475                 return;
476             }
477             if (mPollFds[0].revents == POLLIN) {
478                 char readBuf[2];
479                 read(mCtrlSocketPair[0], &readBuf, 1);
480                 if (DBG) ALOGD("MDnsSdListener::Monitor got %c", readBuf[0]);
481                 if (memcmp(RESCAN, readBuf, 1) == 0) {
482                     pollCount = rescan();
483                 }
484             }
485             mPollFds[0].revents = 0;
486         } else {
487             if (VDBG) ALOGD("MDnsSdListener::Monitor poll timed out");
488         }
489     }
490     free(mPollFds);
491     free(mPollRefs);
492 }
493 
494 #define DBG_RESCAN 0
495 
rescan()496 int MDnsSdListener::Monitor::rescan() {
497 // rescan the list from mHead and make new pollfds and serviceRefs
498     if (VDBG) {
499         ALOGD("MDnsSdListener::Monitor poll rescanning - size=%d, live=%d", mPollSize, mLiveCount);
500     }
501     std::lock_guard guard(mMutex);
502     Element **prevPtr = &mHead;
503     int i = 1;
504     if (mPollSize <= mLiveCount) {
505         mPollSize = mLiveCount + 5;
506         free(mPollFds);
507         free(mPollRefs);
508         mPollFds = (struct pollfd *)calloc(sizeof(struct pollfd), mPollSize);
509         mPollRefs = (DNSServiceRef **)calloc(sizeof(DNSServiceRef *), mPollSize);
510         LOG_ALWAYS_FATAL_IF((mPollFds == nullptr), "calloc failed on mPollFds with a size of %d",
511                 ((int)sizeof(struct pollfd)) * mPollSize);
512         LOG_ALWAYS_FATAL_IF((mPollRefs == nullptr), "calloc failed on mPollRefs with a size of %d",
513                 ((int)sizeof(DNSServiceRef *)) * mPollSize);
514     } else {
515         memset(mPollFds, 0, sizeof(struct pollfd) * mPollSize);
516         memset(mPollRefs, 0, sizeof(DNSServiceRef *) * mPollSize);
517     }
518     mPollFds[0].fd = mCtrlSocketPair[0];
519     mPollFds[0].events = POLLIN;
520     if (DBG_RESCAN) ALOGD("mHead = %p", mHead);
521     while (*prevPtr != nullptr) {
522         if (DBG_RESCAN) ALOGD("checking %p, mReady = %d", *prevPtr, (*prevPtr)->mReady);
523         if ((*prevPtr)->mReady == 1) {
524             int fd = DNSServiceRefSockFD((*prevPtr)->mRef);
525             if (fd != -1) {
526                 if (DBG_RESCAN) ALOGD("  adding FD %d", fd);
527                 mPollFds[i].fd = fd;
528                 mPollFds[i].events = POLLIN;
529                 mPollRefs[i] = &((*prevPtr)->mRef);
530                 i++;
531             } else {
532                 ALOGE("Error retreving socket FD for live ServiceRef");
533             }
534             prevPtr = &((*prevPtr)->mNext); // advance to the next element
535         } else if ((*prevPtr)->mReady == -1) {
536             if (DBG_RESCAN) ALOGD("  removing %p from  play", *prevPtr);
537             Element *cur = *prevPtr;
538             *prevPtr = (cur)->mNext; // change our notion of this element and don't advance
539             delete cur;
540         } else if ((*prevPtr)->mReady == 0) {
541             // Not ready so just skip this node and continue on
542             if (DBG_RESCAN) ALOGD("%p not ready.  Continuing.", *prevPtr);
543             prevPtr = &((*prevPtr)->mNext);
544         }
545     }
546 
547     return i;
548 }
549 
allocateServiceRef(int id,Context * context)550 DNSServiceRef *MDnsSdListener::Monitor::allocateServiceRef(int id, Context *context) {
551     if (lookupServiceRef(id) != nullptr) {
552         delete(context);
553         return nullptr;
554     }
555     Element *e = new Element(id, context);
556     std::lock_guard guard(mMutex);
557     e->mNext = mHead;
558     mHead = e;
559     return &(e->mRef);
560 }
561 
lookupServiceRef(int id)562 DNSServiceRef *MDnsSdListener::Monitor::lookupServiceRef(int id) {
563     std::lock_guard guard(mMutex);
564     Element *cur = mHead;
565     while (cur != nullptr) {
566         if (cur->mId == id) {
567             DNSServiceRef *result = &(cur->mRef);
568             return result;
569         }
570         cur = cur->mNext;
571     }
572     return nullptr;
573 }
574 
startMonitoring(int id)575 void MDnsSdListener::Monitor::startMonitoring(int id) {
576     if (VDBG) ALOGD("startMonitoring %d", id);
577     std::lock_guard guard(mMutex);
578     for (Element* cur = mHead; cur != nullptr; cur = cur->mNext) {
579         if (cur->mId == id) {
580             if (DBG_RESCAN) ALOGD("marking %p as ready to be added", cur);
581             mLiveCount++;
582             cur->mReady = 1;
583             write(mCtrlSocketPair[1], RESCAN, 1);  // trigger a rescan for a fresh poll
584             if (VDBG) ALOGD("triggering rescan");
585             return;
586         }
587     }
588 }
589 
freeServiceRef(int id)590 void MDnsSdListener::Monitor::freeServiceRef(int id) {
591     if (VDBG) ALOGD("freeServiceRef %d", id);
592     std::lock_guard guard(mMutex);
593     Element* cur;
594     for (Element** prevPtr = &mHead; *prevPtr != nullptr; prevPtr = &(cur->mNext)) {
595         cur = *prevPtr;
596         if (cur->mId == id) {
597             if (DBG_RESCAN) ALOGD("marking %p as ready to be removed", cur);
598             mLiveCount--;
599             if (cur->mReady == 1) {
600                 cur->mReady = -1; // tell poll thread to delete
601                 cur->mRef = nullptr; // do not process further results
602                 write(mCtrlSocketPair[1], RESCAN, 1); // trigger a rescan for a fresh poll
603                 if (VDBG) ALOGD("triggering rescan");
604             } else {
605                 *prevPtr = cur->mNext;
606                 delete cur;
607             }
608             return;
609         }
610     }
611 }
612 
deallocateServiceRef(DNSServiceRef * ref)613 void MDnsSdListener::Monitor::deallocateServiceRef(DNSServiceRef* ref) {
614     std::lock_guard guard(mMutex);
615     DNSServiceRefDeallocate(*ref);
616     *ref = nullptr;
617 }
618