static int dns_transaction_make_packet_mdns(DnsTransaction *t) {

        _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
        bool add_known_answers = false;
        DnsTransaction *other;
        Iterator i;
        DnsResourceKey *tkey;
        _cleanup_set_free_ Set *keys = NULL;
        unsigned qdcount;
        unsigned nscount = 0;
        usec_t ts;
        int r;

        assert(t);
        assert(t->scope->protocol == DNS_PROTOCOL_MDNS);

        /* Discard any previously prepared packet, so we can start over and coalesce again */
        t->sent = dns_packet_unref(t->sent);

        r = dns_packet_new_query(&p, t->scope->protocol, 0, false);
        if (r < 0)
                return r;

        r = dns_packet_append_key(p, t->key, 0, NULL);
        if (r < 0)
                return r;

        qdcount = 1;

        if (dns_key_is_shared(t->key))
                add_known_answers = true;

        if (t->key->type == DNS_TYPE_ANY) {
                r = set_ensure_allocated(&keys, &dns_resource_key_hash_ops);
                if (r < 0)
                        return r;

                r = set_put(keys, t->key);
                if (r < 0)
                        return r;
        }

        /*
         * For mDNS, we want to coalesce as many open queries in pending transactions into one single
         * query packet on the wire as possible. To achieve that, we iterate through all pending transactions
         * in our current scope, and see whether their timing contraints allow them to be sent.
         */

        assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);

        LIST_FOREACH(transactions_by_scope, other, t->scope->transactions) {

                /* Skip ourselves */
                if (other == t)
                        continue;

                if (other->state != DNS_TRANSACTION_PENDING)
                        continue;

                if (other->next_attempt_after > ts)
                        continue;

                if (qdcount >= UINT16_MAX)
                        break;

                r = dns_packet_append_key(p, other->key, 0, NULL);

                /*
                 * If we can't stuff more questions into the packet, just give up.
                 * One of the 'other' transactions will fire later and take care of the rest.
                 */
                if (r == -EMSGSIZE)
                        break;

                if (r < 0)
                        return r;

                r = dns_transaction_prepare(other, ts);
                if (r <= 0)
                        continue;

                ts += transaction_get_resend_timeout(other);

                r = sd_event_add_time(
                                other->scope->manager->event,
                                &other->timeout_event_source,
                                clock_boottime_or_monotonic(),
                                ts, 0,
                                on_transaction_timeout, other);
                if (r < 0)
                        return r;

                (void) sd_event_source_set_description(other->timeout_event_source, "dns-transaction-timeout");

                other->state = DNS_TRANSACTION_PENDING;
                other->next_attempt_after = ts;

                qdcount++;

                if (dns_key_is_shared(other->key))
                        add_known_answers = true;

                if (other->key->type == DNS_TYPE_ANY) {
                        r = set_ensure_allocated(&keys, &dns_resource_key_hash_ops);
                        if (r < 0)
                                return r;

                        r = set_put(keys, other->key);
                        if (r < 0)
                                return r;
                }
        }

        DNS_PACKET_HEADER(p)->qdcount = htobe16(qdcount);

        /* Append known answer section if we're asking for any shared record */
        if (add_known_answers) {
                r = dns_cache_export_shared_to_packet(&t->scope->cache, p);
                if (r < 0)
                        return r;
        }

        SET_FOREACH(tkey, keys, i) {
                _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
                bool tentative;

                r = dns_zone_lookup(&t->scope->zone, tkey, t->scope->link->ifindex, &answer, NULL, &tentative);
                if (r < 0)
                        return r;

                r = dns_packet_append_answer(p, answer);
                if (r < 0)
                        return r;

                nscount += dns_answer_size(answer);
        }
        DNS_PACKET_HEADER(p)->nscount = htobe16(nscount);

        t->sent = TAKE_PTR(p);

        return 0;
}