Changeset

1788:45779d67c26c

Merge with 0.5
author Matthew Wild <mwild1@gmail.com>
date Fri, 18 Sep 2009 02:48:52 +0100
parents 1784:b2bfd3b93da6 (current diff) 1787:c4dff34f3d32 (diff)
children 1789:23a66fdf541e
files net/adns.lua net/dns.lua net/server.lua
diffstat 2 files changed, 67 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/net/adns.lua	Fri Sep 18 05:16:26 2009 +0500
+++ b/net/adns.lua	Fri Sep 18 02:48:52 2009 +0100
@@ -11,6 +11,7 @@
 
 local log = require "util.logger".init("adns");
 
+local t_insert, t_remove = table.insert, table.remove;
 local coroutine, tostring, pcall = coroutine, tostring, pcall;
 
 module "adns"
@@ -41,13 +42,20 @@
 	end
 end
 
-function new_async_socket(sock)
-	local newconn = {};
+function new_async_socket(sock, resolver)
+	local newconn, peername = {}, "<unknown>";
 	local listener = {};
 	function listener.incoming(conn, data)
 		dns.feed(sock, data);
 	end
-	function listener.disconnect()
+	function listener.disconnect(conn, err)
+		log("warn", "DNS socket for %s disconnected: %s", peername, err);
+		local servers = resolver.server;
+		if resolver.socketset[newconn.handler] == resolver.best_server and resolver.best_server == #servers then
+			log("error", "Exhausted all %d configured DNS servers, next lookup will try %s again", #servers, servers[1]);
+		end
+		
+		resolver:servfail(conn); -- Let the magic commence
 	end
 	newconn.handler, newconn._socket = server.wrapclient(sock, "dns", 53, listener);
 	if not newconn.handler then
@@ -58,7 +66,7 @@
 	end
 	newconn.handler.settimeout = function () end
 	newconn.handler.setsockname = function (_, ...) return sock:setsockname(...); end
-	newconn.handler.setpeername = function (_, ...) local ret = sock:setpeername(...); _.setsend(sock.send); return ret; end
+	newconn.handler.setpeername = function (_, ...) peername = (...); local ret = sock:setpeername(...); _.setsend(sock.send); return ret; end
 	newconn.handler.connect = function (_, ...) return sock:connect(...) end	
 	newconn.handler.send = function (_, data) _.write(data); return _.sendbuffer(); end	
 	return newconn.handler;
--- a/net/dns.lua	Fri Sep 18 05:16:26 2009 +0500
+++ b/net/dns.lua	Fri Sep 18 02:48:52 2009 +0100
@@ -488,7 +488,7 @@
 -- socket layer -------------------------------------------------- socket layer
 
 
-resolver.delays = { 1, 3, 11, 45 }
+resolver.delays = { 1, 3  }
 
 
 function resolver:addnameserver (address)    -- - - - - - - - - - addnameserver
@@ -529,16 +529,25 @@
   if sock then  return sock  end
 
   sock = socket.udp ()
-  if self.socket_wrapper then  sock = self.socket_wrapper (sock)  end
+  if self.socket_wrapper then  sock = self.socket_wrapper (sock, self)  end
   sock:settimeout (0)
   -- todo: attempt to use a random port, fallback to 0
   sock:setsockname ('*', 0)
   sock:setpeername (self.server[servernum], 53)
   self.socket[servernum] = sock
-  self.socketset[sock] = sock
+  self.socketset[sock] = servernum
   return sock
   end
 
+function resolver:voidsocket (sock)
+  if self.socket[sock] then
+    self.socketset[self.socket[sock]] = nil
+    self.socket[sock] = nil
+  elseif self.socketset[sock] then
+    self.socket[self.socketset[sock]] = nil
+    self.socketset[sock] = nil
+  end
+end
 
 function resolver:socket_wrapper_set (func)  -- - - - - - - socket_wrapper_set
   self.socket_wrapper = func
@@ -612,10 +621,9 @@
   local header, id = encodeHeader ()
   --print ('query  id', id, qclass, qtype, qname)
   local o = { packet = header..question,
-              server = 1,
+              server = self.best_server,
               delay  = 1,
               retry  = socket.gettime () + self.delays[1] }
-  self:getsocket (o.server):send (o.packet)
 
   -- remember the query
   self.active[id] = self.active[id] or {}
@@ -627,9 +635,49 @@
     set (self.wanted, qclass, qtype, qname, co, true)
     --set (self.yielded, co, qclass, qtype, qname, true)
   end
+  
+  self:getsocket (o.server):send (o.packet)
+
 end
 
+function resolver:servfail(sock)
+  -- Resend all queries for this server
+  
+  local num = self.socketset[sock]
+  
+  -- Socket is dead now
+  self:voidsocket(sock);
+  
+  -- Find all requests to the down server, and retry on the next server
+  self.time = socket.gettime ()
+  for id,queries in pairs (self.active) do
+    for question,o in pairs (queries) do
+      if o.server == num then -- This request was to the broken server
+        o.server = o.server + 1 -- Use next server
+        if o.server > #self.server then
+          o.server = 1
+        end
 
+        o.retries = (o.retries or 0) + 1;
+        if o.retries >= #self.server then
+          --print ('timeout')
+          queries[question] = nil
+        else
+          local _a = self:getsocket(o.server);
+          if _a then _a:send (o.packet) end
+        end
+      end
+    end
+  end
+   
+   if num == self.best_server then
+   	self.best_server = self.best_server + 1
+   	if self.best_server > #self.server then
+   		-- Exhausted all servers, try first again
+   		self.best_server = 1
+   	end
+   end
+end
 
 function resolver:receive (rset)    -- - - - - - - - - - - - - - - - -  receive
 
@@ -832,7 +880,8 @@
 
   -- this function seems to be redundant with resolver.new ()
 
-  local r = { active = {}, cache = {}, unsorted = {}, wanted = {}, yielded = {} }
+  local r = { active = {}, cache = {}, unsorted = {}, wanted = {}, yielded = {}, 
+              best_server = 1 }
   setmetatable (r, resolver)
   setmetatable (r.cache, cache_metatable)
   setmetatable (r.unsorted, { __mode = 'kv' })