aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/adns.lua16
-rw-r--r--net/dns.lua61
2 files changed, 67 insertions, 10 deletions
diff --git a/net/adns.lua b/net/adns.lua
index 7ee54da3..9438bf45 100644
--- a/net/adns.lua
+++ b/net/adns.lua
@@ -11,6 +11,7 @@ local dns = require "net.dns";
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 @@ function cancel(handle, call_handler)
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 @@ function new_async_socket(sock)
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;
diff --git a/net/dns.lua b/net/dns.lua
index 592471bb..ff07d26e 100644
--- a/net/dns.lua
+++ b/net/dns.lua
@@ -488,7 +488,7 @@ function resolver:decode (packet, force) -- - - - - - - - - - - - - - decode
-- socket layer -------------------------------------------------- socket layer
-resolver.delays = { 1, 3, 11, 45 }
+resolver.delays = { 1, 3 }
function resolver:addnameserver (address) -- - - - - - - - - - addnameserver
@@ -529,16 +529,25 @@ function resolver:getsocket (servernum) -- - - - - - - - - - - - - getsocket
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 @@ function resolver:query (qname, qtype, qclass) -- - - - - - - - - - -- query
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 @@ function resolver:query (qname, qtype, qclass) -- - - - - - - - - - -- query
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 @@ function dns.resolver () -- - - - - - - - - - - - - - - - - - - - - resolver
-- 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' })