diff -r b2bfd3b93da6 -r 45779d67c26c net/dns.lua --- 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' })