]> git.saurik.com Git - apple/mdnsresponder.git/blobdiff - mDNSMacOSX/daemon.c
mDNSResponder-576.30.4.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / daemon.c
index 3b3ed393d0377e0538169326918551c2beb5f1fd..1b257ea21fbbb8cb6301c36814ba395269debe77 100644 (file)
@@ -2474,10 +2474,9 @@ mDNSlocal mDNSBool AllowSleepNow(mDNS *const m, mDNSs32 now)
         }
 
         m->SleepState = SleepState_Sleeping;
-        // We used to clear our interface list to empty state here before going to sleep.
-        // The applications that try to connect to an external server during maintenance wakes, saw
-        // DNS resolution errors as we don't have any interfaces (most queries use SuppressUnusable
-        // flag). Thus, we don't remove our interfaces anymore on sleep.
+               // Clear our interface list to empty state, ready to go to sleep
+               // As a side effect of doing this, we'll also cancel any outstanding SPS Resolve calls that didn't complete
+        mDNSMacOSXNetworkChanged(m);
     }
 
     LogSPS("AllowSleepNow: %s(%lX) %s at %ld (%d ticks remaining)",
@@ -2593,6 +2592,14 @@ mDNSlocal void KQWokenFlushBytes(int fd, __unused short filter, __unused void *c
     while (recv(fd, buffer, sizeof(buffer), MSG_DONTWAIT) > 0) continue;
 }
 
+mDNSlocal void SetLowWater(const KQSocketSet *const k, const int r)
+{
+    if (setsockopt(k->sktv4, SOL_SOCKET, SO_RCVLOWAT, &r, sizeof(r)) < 0)
+        LogMsg("SO_RCVLOWAT IPv4 %d error %d errno %d (%s)", k->sktv4, r, errno, strerror(errno));
+    if (setsockopt(k->sktv6, SOL_SOCKET, SO_RCVLOWAT, &r, sizeof(r)) < 0)
+        LogMsg("SO_RCVLOWAT IPv6 %d error %d errno %d (%s)", k->sktv6, r, errno, strerror(errno));
+}
+
 mDNSlocal void * KQueueLoop(void *m_param)
 {
     mDNS            *m = m_param;
@@ -2678,6 +2685,13 @@ mDNSlocal void * KQueueLoop(void *m_param)
         // 3. The timeout expires
         pthread_mutex_unlock(&PlatformStorage.BigMutex);
 
+        // If we woke up to receive a multicast, set low-water mark to dampen excessive wakeup rate
+        if (m->p->num_mcasts)
+        {
+            SetLowWater(&m->p->permanentsockets, 0x10000);
+            if (ticks > mDNSPlatformOneSecond / 8) ticks = mDNSPlatformOneSecond / 8;
+        }
+
 #if USE_SELECT_WITH_KQUEUEFD
         struct timeval timeout;
         timeout.tv_sec = ticks / mDNSPlatformOneSecond;
@@ -2705,6 +2719,13 @@ mDNSlocal void * KQueueLoop(void *m_param)
         // makes the event no longer valid. Now we have the lock, we call kevent again
         // and this time we can safely process the events it tells us about.
 
+        // If we changed UDP socket low-water mark, restore it, so we will be told about every packet
+        if (m->p->num_mcasts)
+        {
+            SetLowWater(&m->p->permanentsockets, 1);
+            m->p->num_mcasts = 0;
+        }
+
         static const struct timespec zero_timeout = { 0, 0 };
         int events_found;
         while ((events_found = kevent(KQueueFD, NULL, 0, new_events, kEventsToReadAtOnce, &zero_timeout)) != 0)