X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/blobdiff_plain/51601d487eaddf41da63f4b9d4dd2609f5978980..b8d5688b3ede9438aa8ad9679403f1d4e3faddb5:/mDNSMacOSX/daemon.c diff --git a/mDNSMacOSX/daemon.c b/mDNSMacOSX/daemon.c index 3b3ed39..1b257ea 100644 --- a/mDNSMacOSX/daemon.c +++ b/mDNSMacOSX/daemon.c @@ -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)