}
}
+bool dns_cache_expiry_in_one_second(DnsCache *c, usec_t t) {
+ DnsCacheItem *i;
+
+ assert(c);
+
+ /* Check if any items expire within the next second */
+ i = prioq_peek(c->by_expiry);
+ if (!i)
+ return false;
+
+ if (i->until <= usec_add(t, USEC_PER_SEC))
+ return true;
+
+ return false;
+}
+
static int dns_cache_item_prioq_compare_func(const void *a, const void *b) {
const DnsCacheItem *x = a, *y = b;
unsigned dns_cache_size(DnsCache *cache);
int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p, usec_t ts, unsigned max_rr);
+
+bool dns_cache_expiry_in_one_second(DnsCache *c, usec_t t);
.protocol = protocol,
.family = family,
.resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC,
+ .mdns_goodbye_event_source = NULL,
};
if (protocol == DNS_PROTOCOL_DNS) {
sd_event_source_disable_unref(s->announce_event_source);
+ sd_event_source_disable_unref(s->mdns_goodbye_event_source);
+
dns_cache_flush(&s->cache);
dns_zone_flush(&s->zone);
return 0;
}
+static int mdns_goodbye_callback(sd_event_source *s, uint64_t usec, void *userdata) {
+ DnsScope *scope = userdata;
+ int r;
+
+ assert(s);
+ assert(scope);
+
+ scope->mdns_goodbye_event_source = sd_event_source_disable_unref(scope->mdns_goodbye_event_source);
+
+ dns_cache_prune(&scope->cache);
+
+ if (dns_cache_expiry_in_one_second(&scope->cache, usec)) {
+ r = sd_event_add_time_relative(
+ scope->manager->event,
+ &scope->mdns_goodbye_event_source,
+ CLOCK_BOOTTIME,
+ USEC_PER_SEC,
+ 0,
+ mdns_goodbye_callback,
+ scope);
+ if (r < 0)
+ return log_error_errno(r, "mDNS: Failed to re-schedule goodbye callback: %m");
+ }
+
+ return 0;
+}
+
static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
Manager *m = userdata;
log_debug("Got a goodbye packet");
/* See the section 10.1 of RFC6762 */
rr->ttl = 1;
+
+ /* Look at the cache 1 second later and remove stale entries.
+ * This is particularly useful to keep service browsers updated on service removal,
+ * as there are no other reliable triggers to propogate that info. */
+ if (!scope->mdns_goodbye_event_source) {
+ r = sd_event_add_time_relative(
+ scope->manager->event,
+ &scope->mdns_goodbye_event_source,
+ CLOCK_BOOTTIME,
+ USEC_PER_SEC,
+ 0,
+ mdns_goodbye_callback,
+ scope);
+ if (r < 0)
+ return r;
+ }
}
}