DnsTransaction* dns_transaction_free(DnsTransaction *t) {
        DnsQueryCandidate *c;
        DnsZoneItem *i;
        DnsTransaction *z;

        if (!t)
                return NULL;

        log_debug("Freeing transaction %" PRIu16 ".", t->id);

        dns_transaction_close_connection(t);
        dns_transaction_stop_timeout(t);

        dns_packet_unref(t->sent);
        dns_transaction_reset_answer(t);

        dns_server_unref(t->server);

        if (t->scope) {
                hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
                LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);

                if (t->id != 0)
                        hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
        }

        while ((c = set_steal_first(t->notify_query_candidates)))
                set_remove(c->transactions, t);
        set_free(t->notify_query_candidates);

        while ((c = set_steal_first(t->notify_query_candidates_done)))
                set_remove(c->transactions, t);
        set_free(t->notify_query_candidates_done);

        while ((i = set_steal_first(t->notify_zone_items)))
                i->probe_transaction = NULL;
        set_free(t->notify_zone_items);

        while ((i = set_steal_first(t->notify_zone_items_done)))
                i->probe_transaction = NULL;
        set_free(t->notify_zone_items_done);

        while ((z = set_steal_first(t->notify_transactions)))
                set_remove(z->dnssec_transactions, t);
        set_free(t->notify_transactions);

        while ((z = set_steal_first(t->notify_transactions_done)))
                set_remove(z->dnssec_transactions, t);
        set_free(t->notify_transactions_done);

        dns_transaction_flush_dnssec_transactions(t);
        set_free(t->dnssec_transactions);

        dns_answer_unref(t->validated_keys);
        dns_resource_key_unref(t->key);

        return mfree(t);
}
DnsTransaction* dns_transaction_free(DnsTransaction *t) {
        DnsQueryCandidate *c;
        DnsZoneItem *i;
        DnsTransaction *z;

        if (!t)
                return NULL;

        log_debug("Freeing transaction %" PRIu16 ".", t->id);

        dns_transaction_close_connection(t);
        dns_transaction_stop_timeout(t);

        dns_packet_unref(t->sent);
        dns_transaction_reset_answer(t);

        dns_server_unref(t->server);

        if (t->scope) {
                hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
                LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);

                if (t->id != 0)
                        hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
        }

        while ((c = set_steal_first(t->notify_query_candidates)))
                set_remove(c->transactions, t);
        set_free(t->notify_query_candidates);

        while ((c = set_steal_first(t->notify_query_candidates_done)))
                set_remove(c->transactions, t);
        set_free(t->notify_query_candidates_done);

        while ((i = set_steal_first(t->notify_zone_items)))
                i->probe_transaction = NULL;
        set_free(t->notify_zone_items);

        while ((i = set_steal_first(t->notify_zone_items_done)))
                i->probe_transaction = NULL;
        set_free(t->notify_zone_items_done);

        while ((z = set_steal_first(t->notify_transactions)))
                set_remove(z->dnssec_transactions, t);
        set_free(t->notify_transactions);

        while ((z = set_steal_first(t->notify_transactions_done)))
                set_remove(z->dnssec_transactions, t);
        set_free(t->notify_transactions_done);

        dns_transaction_flush_dnssec_transactions(t);
        set_free(t->dnssec_transactions);

        dns_answer_unref(t->validated_keys);
        dns_resource_key_unref(t->key);

        return mfree(t);
}