- local co = coroutine.running ()
- if co then
- set (self.wanted, qclass, qtype, qname, co, true)
- set (self.yielded, co, qclass, qtype, qname, true)
- end end
-
-
-function resolver:receive (rset) -- - - - - - - - - - - - - - - - - receive
-
- -- print 'receive' print (self.socket)
- self.time = socket.gettime ()
- rset = rset or self.socket
-
- local response
- for i,sock in pairs (rset) do
-
- if self.socketset[sock] then
- local packet = sock:receive ()
- if packet then
-
- response = self:decode (packet)
- if response then
- -- print 'received response'
- -- self.print (response)
-
- for i,section in pairs { 'answer', 'authority', 'additional' } do
- for j,rr in pairs (response[section]) do
- self:remember (rr, response.question[1].type) end end
-
- -- retire the query
- local queries = self.active[response.header.id]
- if queries[response.question.raw] then
- queries[response.question.raw] = nil end
- if not next (queries) then self.active[response.header.id] = nil end
- if not next (self.active) then self:closeall () end
-
- -- was the query on the wanted list?
- local q = response.question
- local cos = get (self.wanted, q.class, q.type, q.name)
- if cos then
- for co in pairs (cos) do
- set (self.yielded, co, q.class, q.type, q.name, nil)
- if not self.yielded[co] then coroutine.resume (co) end
- end
- set (self.wanted, q.class, q.type, q.name, nil)
- end end end end end
-
- return response
- end
-
-
-function resolver:pulse () -- - - - - - - - - - - - - - - - - - - - - pulse
-
- -- print ':pulse'
- while self:receive () do end
- if not next (self.active) then return nil end
-
- self.time = socket.gettime ()
- for id,queries in pairs (self.active) do
- for question,o in pairs (queries) do
- if self.time >= o.retry then
-
- o.server = o.server + 1
- if o.server > #self.server then
- o.server = 1
- o.delay = o.delay + 1
- end
-
- if o.delay > #self.delays then
- print ('timeout')
- queries[question] = nil
- if not next (queries) then self.active[id] = nil end
- if not next (self.active) then return nil end
- else
- -- print ('retry', o.server, o.delay)
- self.socket[o.server]:send (o.packet)
- o.retry = self.time + self.delays[o.delay]
- end end end end
-
- if next (self.active) then return true end
- return nil
- end
-
-
-function resolver:lookup (qname, qtype, qclass) -- - - - - - - - - - lookup
- self:query (qname, qtype, qclass)
- while self:pulse () do socket.select (self.socket, nil, 4) end
- -- print (self.cache)
- return self:peek (qname, qtype, qclass)
- end
-
-
--- print ---------------------------------------------------------------- print
+ local co = coroutine.running();
+ if co then
+ 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
+ --print('receive'); print(self.socket);
+ self.time = socket.gettime();
+ rset = rset or self.socket;
+
+ local response;
+ for i,sock in pairs(rset) do
+
+ if self.socketset[sock] then
+ local packet = sock.receive();
+ if packet then
+ response = self:decode(packet);
+ if response and self.active[response.header.id]
+ and self.active[response.header.id][response.question.raw] then
+ --print('received response');
+ --self.print(response);
+
+ for j,rr in pairs(response.answer) do
+ if rr.name:sub(-#response.question[1].name, -1) == response.question[1].name then
+ self:remember(rr, response.question[1].type)
+ end
+ end
+
+ -- retire the query
+ local queries = self.active[response.header.id];
+ queries[response.question.raw] = nil;
+
+ if not next(queries) then self.active[response.header.id] = nil; end
+ if not next(self.active) then self:closeall(); end
+
+ -- was the query on the wanted list?
+ local q = response.question[1];
+ local cos = get(self.wanted, q.class, q.type, q.name);
+ if cos then
+ for co in pairs(cos) do
+ set(self.yielded, co, q.class, q.type, q.name, nil);
+ if coroutine.status(co) == "suspended" then coroutine.resume(co); end
+ end
+ set(self.wanted, q.class, q.type, q.name, nil);
+ end
+ end
+ end
+ end
+ end
+
+ return response;
+end
+
+
+function resolver:feed(sock, packet)
+ --print('receive'); print(self.socket);
+ self.time = socket.gettime();
+
+ local response = self:decode(packet);
+ if response and self.active[response.header.id]
+ and self.active[response.header.id][response.question.raw] then
+ --print('received response');
+ --self.print(response);
+
+ for j,rr in pairs(response.answer) do
+ self:remember(rr, response.question[1].type);
+ end
+
+ -- retire the query
+ local queries = self.active[response.header.id];
+ queries[response.question.raw] = nil;
+ if not next(queries) then self.active[response.header.id] = nil; end
+ if not next(self.active) then self:closeall(); end
+
+ -- was the query on the wanted list?
+ local q = response.question[1];
+ if q then
+ local cos = get(self.wanted, q.class, q.type, q.name);
+ if cos then
+ for co in pairs(cos) do
+ set(self.yielded, co, q.class, q.type, q.name, nil);
+ if coroutine.status(co) == "suspended" then coroutine.resume(co); end
+ end
+ set(self.wanted, q.class, q.type, q.name, nil);
+ end
+ end
+ end
+
+ return response;
+end
+
+function resolver:cancel(data)
+ local cos = get(self.wanted, unpack(data, 1, 3));
+ if cos then
+ cos[data[4]] = nil;
+ end
+end
+
+function resolver:pulse() -- - - - - - - - - - - - - - - - - - - - - pulse
+ --print(':pulse');
+ while self:receive() do end
+ if not next(self.active) then return nil; end
+
+ self.time = socket.gettime();
+ for id,queries in pairs(self.active) do
+ for question,o in pairs(queries) do
+ if self.time >= o.retry then
+
+ o.server = o.server + 1;
+ if o.server > #self.server then
+ o.server = 1;
+ o.delay = o.delay + 1;
+ end
+
+ if o.delay > #self.delays then
+ --print('timeout');
+ queries[question] = nil;
+ if not next(queries) then self.active[id] = nil; end
+ if not next(self.active) then return nil; end
+ else
+ --print('retry', o.server, o.delay);
+ local _a = self.socket[o.server];
+ if _a then _a:send(o.packet); end
+ o.retry = self.time + self.delays[o.delay];
+ end
+ end
+ end
+ end
+
+ if next(self.active) then return true; end
+ return nil;
+end
+
+
+function resolver:lookup(qname, qtype, qclass) -- - - - - - - - - - lookup
+ self:query (qname, qtype, qclass)
+ while self:pulse() do socket.select(self.socket, nil, 4); end
+ --print(self.cache);
+ return self:peek(qname, qtype, qclass);
+end
+
+function resolver:lookupex(handler, qname, qtype, qclass) -- - - - - - - - - - lookup
+ return self:peek(qname, qtype, qclass) or self:query(qname, qtype, qclass);
+end
+
+
+--print ---------------------------------------------------------------- print