static void dns_transaction_close_connection(DnsTransaction *t) {
assert(t);
- t->stream = dns_stream_free(t->stream);
+ if (t->stream) {
+ /* Let's detach the stream from our transaction, in case something else keeps a reference to it. */
+ t->stream->complete = NULL;
+ t->stream->on_packet = NULL;
+ t->stream->transaction = NULL;
+ t->stream = dns_stream_unref(t->stream);
+ }
+
t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
t->dns_udp_fd = safe_close(t->dns_udp_fd);
}
}
static int dns_transaction_maybe_restart(DnsTransaction *t) {
+ int r;
+
assert(t);
+ /* Returns > 0 if the transaction was restarted, 0 if not */
+
if (!t->server)
return 0;
log_debug("Server feature level is now lower than when we began our transaction. Restarting with new ID.");
dns_transaction_shuffle_id(t);
- return dns_transaction_go(t);
+
+ r = dns_transaction_go(t);
+ if (r < 0)
+ return r;
+
+ return 1;
}
static int on_stream_complete(DnsStream *s, int error) {
t = s->transaction;
p = dns_packet_ref(s->read_packet);
- t->stream = dns_stream_free(t->stream);
+ dns_transaction_close_connection(t);
if (ERRNO_IS_DISCONNECT(error)) {
usec_t usec;
r = dns_stream_write_packet(t->stream, t->sent);
if (r < 0) {
- t->stream = dns_stream_free(t->stream);
+ t->stream = dns_stream_unref(t->stream);
return r;
}
/* Let's then prune all outdated entries */
dns_cache_prune(&t->scope->cache);
- r = dns_cache_lookup(&t->scope->cache, t->key, &t->answer_rcode, &t->answer, &t->answer_authenticated);
+ r = dns_cache_lookup(&t->scope->cache, t->key, t->clamp_ttl, &t->answer_rcode, &t->answer, &t->answer_authenticated);
if (r < 0)
return r;
if (r > 0) {
assert(t);
+ /* Returns > 0 if the transaction is now pending, returns 0 if could be processed immediately and has finished
+ * now. */
+
assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
r = dns_transaction_prepare(t, ts);