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