This fixes up the DNS timeout management.
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [email protected]\
#   19a08w1tobnxdhy0
# target_branch: http://bzr.squid-cache.org/bzr/squid3/trunk/
# testament_sha1: 12df0be1bcabe9d4ae82e03f1d6e58035baac06c
# timestamp: 2012-03-05 10:44:36 +0100
# source_branch: http://www.squid-cache.org/bzr/squid3/trunk/
# base_revision_id: [email protected]\
#   d3ba1y2dk0sobhwa
# 
# Begin patch
=== modified file 'src/dns_internal.cc'
--- src/dns_internal.cc	2012-03-02 17:33:04 +0000
+++ src/dns_internal.cc	2012-03-04 22:24:58 +0000
@@ -149,6 +149,7 @@
     unsigned short do_searchpath;
     rfc1035_message *message;
     int ancount;
+    const char *error;
 };
 InstanceIdDefinitions(idns_query,  "dns");
 
@@ -232,7 +233,7 @@
 static void idnsParseWIN32Registry(void);
 static void idnsParseWIN32SearchList(const char *);
 #endif
-static void idnsCacheQuery(idns_query * q);
+static void idnsStartQuery(idns_query * q, IDNSCB * callback, void *data);
 static void idnsSendQuery(idns_query * q);
 static IOCB idnsReadVCHeader;
 static void idnsDoSendQueryVC(nsvc *vc);
@@ -906,8 +907,6 @@
     int x = -1, y = -1;
     int ns;
 
-    q->start_t = current_time;
-
     do {
         ns = q->nsends % nns;
 
@@ -923,7 +922,7 @@
 
         q->nsends++;
 
-        q->queue_t = q->sent_t = current_time;
+        q->sent_t = current_time;
 
         if (y < 0 && nameservers[ns].S.IsIPv6())
             debugs(50, 1, "idnsSendQuery: FD " << DnsSocketB << ": sendto: " << xstrerror());
@@ -999,13 +998,70 @@
 }
 
 static void
-idnsCallback(idns_query *q, rfc1035_rr *answers, int n, const char *error)
+idnsCallback(idns_query *q, const char *error)
 {
     IDNSCB *callback;
     void *cbdata;
 
+    if (error)
+        q->error = error;
+
+    if (q->master)
+        q = q->master;
+
+    idns_query *q2;
+    // If any of our subqueries are still pending then wait for them to complete before continuing
+    for ( q2 = q; q2; q2 = q2->slave) {
+        if (q2->pending) {
+            return;
+        }
+    }
+
+    /* Merge results */
+    rfc1035_message *message = q->message;
+    q->message = NULL;
+    int n = q->ancount;
+    error = q->error;
+
+    while ( (q2 = q->slave) ) {
+        debugs(78, 6, HERE << "Merging DNS results " << q->name << " A has " << n << " RR, AAAA has " << q2->ancount << " RR");
+        q->slave = q2->slave;
+        if ( !q2->error ) {
+            if (n > 0) {
+                // two sets of RR need merging
+                rfc1035_rr *result = (rfc1035_rr*) xmalloc( sizeof(rfc1035_rr)*(n + q2->ancount) );
+                if (Config.dns.v4_first) {
+                    memcpy(result, message->answer, (sizeof(rfc1035_rr)*n) );
+                    memcpy(result+n, q2->message->answer, (sizeof(rfc1035_rr)*q2->ancount) );
+                } else {
+                    memcpy(result, q2->message->answer, (sizeof(rfc1035_rr)*q2->ancount) );
+                    memcpy(result+q2->ancount, message->answer, (sizeof(rfc1035_rr)*n) );
+                }
+                n += q2->ancount;
+                // HACK WARNING, the answer rr:s have been copied in-place to
+                // result, do not free them here
+                safe_free(message->answer);
+                safe_free(q2->message->answer);
+                message->answer = result;
+                message->ancount += q2->message->ancount;
+            } else {
+                // first response empty or failed, just use the second
+                rfc1035MessageDestroy(&message);
+                message = q2->message;
+                q2->message = NULL;
+                n = q2->ancount;
+                error = NULL;
+            }
+        }
+        rfc1035MessageDestroy(&q2->message);
+        cbdataFree(q2);
+    }
+
+    debugs(78, 6, HERE << "Sending " << n << " (" << (error ? error : "OK") << ") DNS results to caller.");
+
     callback = q->callback;
     q->callback = NULL;
+    const rfc1035_rr *answers = message ? message->answer : NULL;
 
     if (cbdataReferenceValidDone(q->callback_data, &cbdata))
         callback(cbdata, answers, n, error);
@@ -1026,6 +1082,9 @@
         hash_remove_link(idns_lookup_hash, &q->hash);
         q->hash.key = NULL;
     }
+
+    rfc1035MessageDestroy(&message);
+    cbdataFree(q);
 }
 
 static void
@@ -1097,8 +1156,7 @@
             // Strange: A TCP DNS response with the truncation bit (TC) set.
             // Return an error and cleanup; no point in trying TCP again.
             debugs(78, 3, HERE << "TCP DNS response");
-            idnsCallback(q, NULL, 0, "Truncated TCP DNS response");
-            cbdataFree(q);
+            idnsCallback(q, "Truncated TCP DNS response");
         }
 
         return;
@@ -1122,6 +1180,7 @@
             return;
         }
 
+        // Do searchpath processing on the master A query only, ignoring any AAAA query
         if (q->rcode == 3 && !q->master && q->do_searchpath && q->attempt < MAX_ATTEMPT) {
             assert(NULL == message->answer);
             strcpy(q->name, q->orig);
@@ -1139,7 +1198,7 @@
 
             rfc1035MessageDestroy(&message);
 
-            // cleanup stale AAAA query
+            // cleanup slave AAAA query
             while (idns_query *slave = q->slave) {
                 dlinkDelete(&slave->lru, &lru_list);
                 q->slave = slave->slave;
@@ -1154,11 +1213,12 @@
             q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, 0);
             if (q->sz < 0) {
                 /* problem with query data -- query not sent */
-                idnsCallback(static_cast<idns_query *>(q->callback_data), NULL, 0, "Internal error");
-                cbdataFree(q);
+                idnsCallback(q, "Internal error");
                 return;
             }
 
+            q->nsends = 0;
+
             idnsSendQuery(q);
             if (Ip::EnableIpv6)
                 idnsSendSlaveAAAAQuery(q);
@@ -1169,57 +1229,11 @@
     q->message = message;
     q->ancount = n;
 
-    if (q->master)
-        q = q->master;
-
-    idns_query *q2;
-    // If any of our subqueries are still pending then wait for them to complete before continuing
-    for ( q2 = q; q2; q2 = q2->slave) {
-        if (q2->pending) {
-            return;
-        }
-    }
-
-    /* Merge results */
-    message = q->message;
-    n = q->ancount;
-
-    while ( (q2 = q->slave) ) {
-        debugs(78, 6, HERE << "Merging DNS results " << q->name << " A has " << n << " RR, AAAA has " << q2->ancount << " RR");
-        q->slave = q2->slave;
-        if ( q2->ancount >= 0 ) {
-            if (n > 0 ) {
-                // two sets of RR need merging
-                rfc1035_rr *result = (rfc1035_rr*) xmalloc( sizeof(rfc1035_rr)*(n + q2->ancount) );
-                if (Config.dns.v4_first) {
-                    memcpy(result, message->answer, (sizeof(rfc1035_rr)*n) );
-                    memcpy(result+n, q2->message->answer, (sizeof(rfc1035_rr)*q2->ancount) );
-                } else {
-                    memcpy(result, q2->message->answer, (sizeof(rfc1035_rr)*q2->ancount) );
-                    memcpy(result+q2->ancount, message->answer, (sizeof(rfc1035_rr)*n) );
-                }
-                n += q2->ancount;
-                safe_free(message->answer);
-                message->answer = result;
-                message->ancount += q2->message->ancount;
-                safe_free(q2->message->answer);
-                q2->message->answer = NULL;
-            } else if (n < 0 || q2->ancount > 0) {
-                // first set empty / failed
-                rfc1035MessageDestroy(&message);
-                message = q->message = q2->message;
-                q2->message = NULL;
-                n = q2->ancount;
-            }
-        }
-        rfc1035MessageDestroy(&q2->message);
-        cbdataFree(q2);
-    }
-
-    debugs(78, 6, HERE << "Sending " << n << " DNS results to caller.");
-    idnsCallback(q, message->answer, n, rfc1035ErrorMessage(n));
-    rfc1035MessageDestroy(&message);
-    cbdataFree(q);
+    if (n >= 0)
+        idnsCallback(q, NULL);
+    else
+        idnsCallback(q, rfc1035ErrorMessage(q->rcode));
+
 }
 
 static void
@@ -1328,7 +1342,7 @@
         if ((time_msec_t)tvSubMsec(q->queue_t, current_time) < Config.Timeout.idns_retransmit )
             break;
 
-        /* Query timer expired? */
+        /* Query timer still running? */
         if ((time_msec_t)tvSubMsec(q->sent_t, current_time) < (Config.Timeout.idns_retransmit * 1 << ((q->nsends - 1) / nns))) {
             dlinkDelete(&q->lru, &lru_list);
             q->queue_t = current_time;
@@ -1341,6 +1355,7 @@
                std::setw(4) << q->query_id << ": timeout" );
 
         dlinkDelete(&q->lru, &lru_list);
+        q->pending = 0;
 
         if ((time_msec_t)tvSubMsec(q->start_t, current_time) < Config.Timeout.idns_query) {
             idnsSendQuery(q);
@@ -1351,11 +1366,9 @@
                    std::setw(5)<< std::setprecision(2) << tvSubDsec(q->start_t, current_time) << " seconds");
 
             if (q->rcode != 0)
-                idnsCallback(q, NULL, -q->rcode, rfc1035ErrorMessage(q->rcode));
+                idnsCallback(q, rfc1035ErrorMessage(q->rcode));
             else
-                idnsCallback(q, NULL, -16, "Timeout");
-
-            cbdataFree(q);
+                idnsCallback(q, "Timeout");
         }
     }
 
@@ -1606,10 +1619,16 @@
 }
 
 static void
-idnsCacheQuery(idns_query *q)
+idnsStartQuery(idns_query *q, IDNSCB * callback, void *data)
 {
+    q->start_t = current_time;
+    q->callback = callback;
+    q->callback_data = cbdataReference(data);
+
     q->hash.key = q->orig;
     hash_join(idns_lookup_hash, &q->hash);
+
+    idnsSendQuery(q);
 }
 
 static void
@@ -1621,6 +1640,7 @@
     q->master = master;
     q->query_id = idnsQueryID();
     q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, Config.dns.packet_max);
+    q->start_t = master->start_t;
     q->slave = master->slave;
 
     debugs(78, 3, HERE << "buf is " << q->sz << " bytes for " << q->name <<
@@ -1681,11 +1701,7 @@
     debugs(78, 3, "idnsALookup: buf is " << q->sz << " bytes for " << q->name <<
            ", id = 0x" << std::hex << q->query_id);
 
-    q->callback = callback;
-    q->callback_data = cbdataReference(data);
-
-    idnsCacheQuery(q);
-    idnsSendQuery(q);
+    idnsStartQuery(q, callback, data);
 
     if (Ip::EnableIpv6)
         idnsSendSlaveAAAAQuery(q);
@@ -1733,11 +1749,7 @@
     debugs(78, 3, "idnsPTRLookup: buf is " << q->sz << " bytes for " << ip <<
            ", id = 0x" << std::hex << q->query_id);
 
-    q->callback = callback;
-    q->callback_data = cbdataReference(data);
-
-    idnsCacheQuery(q);
-    idnsSendQuery(q);
+    idnsStartQuery(q, callback, data);
 }
 
 #if SQUID_SNMP

=== modified file 'src/fqdncache.cc'
--- src/fqdncache.cc	2012-01-20 18:55:04 +0000
+++ src/fqdncache.cc	2012-03-04 22:24:58 +0000
@@ -134,7 +134,7 @@
 static int fqdncacheParse(fqdncache_entry *, const char *buf);
 #else
 static IDNSCB fqdncacheHandleReply;
-static int fqdncacheParse(fqdncache_entry *, rfc1035_rr *, int, const char *error_message);
+static int fqdncacheParse(fqdncache_entry *, const rfc1035_rr *, int, const char *error_message);
 #endif
 static void fqdncacheRelease(fqdncache_entry *);
 static fqdncache_entry *fqdncacheCreateEntry(const char *name);
@@ -417,7 +417,7 @@
 
 #else
 static int
-fqdncacheParse(fqdncache_entry *f, rfc1035_rr * answers, int nr, const char *error_message)
+fqdncacheParse(fqdncache_entry *f, const rfc1035_rr * answers, int nr, const char *error_message)
 {
     int k;
     int ttl = 0;
@@ -496,7 +496,7 @@
 #if USE_DNSHELPER
 fqdncacheHandleReply(void *data, char *reply)
 #else
-fqdncacheHandleReply(void *data, rfc1035_rr * answers, int na, const char *error_message)
+fqdncacheHandleReply(void *data, const rfc1035_rr * answers, int na, const char *error_message)
 #endif
 {
     fqdncache_entry *f;

=== modified file 'src/ipcache.cc'
--- src/ipcache.cc	2012-01-20 18:55:04 +0000
+++ src/ipcache.cc	2012-03-04 22:24:58 +0000
@@ -144,7 +144,7 @@
 #if USE_DNSHELPER
 static int ipcacheParse(ipcache_entry *, const char *buf);
 #else
-static int ipcacheParse(ipcache_entry *, rfc1035_rr *, int, const char *error);
+static int ipcacheParse(ipcache_entry *, const rfc1035_rr *, int, const char *error);
 #endif
 static ipcache_entry *ipcache_get(const char *);
 static void ipcacheLockEntry(ipcache_entry *);
@@ -458,7 +458,7 @@
 
 #else
 static int
-ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_message)
+ipcacheParse(ipcache_entry *i, const rfc1035_rr * answers, int nr, const char *error_message)
 {
     int k;
     int j = 0;
@@ -592,7 +592,7 @@
 #if USE_DNSHELPER
 ipcacheHandleReply(void *data, char *reply)
 #else
-ipcacheHandleReply(void *data, rfc1035_rr * answers, int na, const char *error_message)
+ipcacheHandleReply(void *data, const rfc1035_rr * answers, int na, const char *error_message)
 #endif
 {
     ipcache_entry *i;

=== modified file 'src/typedefs.h'
--- src/typedefs.h	2012-01-20 18:55:04 +0000
+++ src/typedefs.h	2012-03-04 22:24:58 +0000
@@ -137,7 +137,7 @@
 typedef int HLPSAVAIL(void *);
 typedef void HLPSONEQ(void *);
 typedef void HLPCMDOPTS(int *argc, char **argv);
-typedef void IDNSCB(void *, rfc1035_rr *, int, const char *);
+typedef void IDNSCB(void *, const rfc1035_rr *, int, const char *);
 
 /* MD5 cache keys */
 typedef unsigned char cache_key;

# Begin bundle
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

Reply via email to