<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,5 +1,6 @@
 #include &lt;sys/types.h&gt;
 #include &lt;sys/socket.h&gt;
+#include &lt;netinet/in.h&gt;
 #include &lt;unistd.h&gt;
 #include &quot;socket.h&quot;
 #include &quot;alloc.h&quot;
@@ -98,29 +99,46 @@ static int thisudp(struct dns_transmit *d)
 {
   const char *ip;
 
-  socketfree(d);
+  /* open a new socket if there isn't already one */
+  if (! d-&gt;s1) {
+    /* choose a random port number for this socket */
+    d-&gt;query[2] = dns_random(256);
+    d-&gt;query[3] = dns_random(256);
+
+    d-&gt;s1 = 1 + socket_udp();
+
+    if (! d-&gt;s1) {
+      dns_transmit_free(d);
+      return -1;
+    }
+
+    if (randombind(d) == -1) {
+      dns_transmit_free(d);
+      return -1;
+    }
+  }
 
   while (d-&gt;udploop &lt; 4) {
     for (;d-&gt;curserver &lt; 16;++d-&gt;curserver) {
       ip = d-&gt;servers + 4 * d-&gt;curserver;
       if (byte_diff(ip,4,&quot;\0\0\0\0&quot;)) {
-	d-&gt;query[2] = dns_random(256);
-	d-&gt;query[3] = dns_random(256);
-  
-        d-&gt;s1 = 1 + socket_udp();
-        if (!d-&gt;s1) { dns_transmit_free(d); return -1; }
-	if (randombind(d) == -1) { dns_transmit_free(d); return -1; }
-
-        if (socket_connect4(d-&gt;s1 - 1,ip,53) == 0)
-          if (send(d-&gt;s1 - 1,d-&gt;query + 2,d-&gt;querylen - 2,0) == d-&gt;querylen - 2) {
-            struct taia now;
-            taia_now(&amp;now);
-            taia_uint(&amp;d-&gt;deadline,timeouts[d-&gt;udploop]);
-            taia_add(&amp;d-&gt;deadline,&amp;d-&gt;deadline,&amp;now);
-            d-&gt;tcpstate = 0;
-            return 0;
-          }
-  
+	struct sockaddr_in sa;
+
+	/* set the destination address */
+	byte_zero(&amp;sa, sizeof sa);
+	sa.sin_family = AF_INET;
+	uint16_pack_big((char *) &amp;sa.sin_port, 53);
+	byte_copy((char *) &amp;sa.sin_addr, 4, ip);
+
+        if (sendto(d-&gt;s1 - 1,d-&gt;query + 2,d-&gt;querylen - 2,0, (struct sockaddr *) &amp;sa, sizeof sa) == d-&gt;querylen - 2) {
+          struct taia now;
+          taia_now(&amp;now);
+          taia_uint(&amp;d-&gt;deadline,timeouts[d-&gt;udploop]);
+          taia_add(&amp;d-&gt;deadline,&amp;d-&gt;deadline,&amp;now);
+          d-&gt;tcpstate = 0;
+          return 0;
+        }
+
         socketfree(d);
       }
     }</diff>
      <filename>dns_transmit.c</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>debbbf2f6e481e1ffb12cf819bf8bb0b6d2f52e1</id>
    </parent>
  </parents>
  <author>
    <name>Nick Andrew</name>
    <email>nick@nick-andrew.net</email>
  </author>
  <url>http://github.com/nickandrew/djbdns/commit/4c155b646086305964868ba2e4e9aaec8be79fcb</url>
  <id>4c155b646086305964868ba2e4e9aaec8be79fcb</id>
  <committed-date>2009-06-13T19:35:44-07:00</committed-date>
  <authored-date>2009-06-12T18:24:14-07:00</authored-date>
  <message>Reuse the socket when resending the same query

Previously, dnscache would create a new socket for each UDP request sent
to a name server. If one query required several requests to different
servers because, say, the server responses timed out, dnscache would
close and reopen the socket each time.

Now, each time a request is resent to a different nameserver, reuse
the socket.  Don't bind the socket to a destination, and use sendto()
instead of send(). Process the first response received. The socket is
subsequently closed, so any later responses will be ignored.

In a high latency situation (e.g. 5 second RTT on responses) this
results in a considerable improvement in speed and reliability. A
query for 'A www.telstra.net' took 310 sec in unpatched dnscache
and 16 sec after this change was applied.

Signed-off-by: Nick Andrew &lt;nick@nick-andrew.net&gt;</message>
  <tree>2feeec8456d4cb8a255e9b0dab8d36e5ded5f314</tree>
  <committer>
    <name>Nick Andrew</name>
    <email>nick@nick-andrew.net</email>
  </committer>
</commit>
