- qname, qtype, qclass = standardize (qname, qtype, qclass)
- local rrs = get (self.cache, qclass, qtype, qname)
- if not rrs then return nil end
- if prune (rrs, socket.gettime ()) and qtype == '*' or not next (rrs) then
- set (self.cache, qclass, qtype, qname, nil) return nil end
- if self.unsorted[rrs] then table.sort (rrs, comp_mx) end
- return rrs
- end
-
-
-function resolver:purge (soft) -- - - - - - - - - - - - - - - - - - - purge
- if soft == 'soft' then
- self.time = socket.gettime ()
- for class,types in pairs (self.cache or {}) do
- for type,names in pairs (types) do
- for name,rrs in pairs (names) do
- prune (rrs, self.time, 'soft')
- end end end
- else self.cache = {} end
- end
-
-
-function resolver:query (qname, qtype, qclass) -- - - - - - - - - - -- query
-
- qname, qtype, qclass = standardize (qname, qtype, qclass)
-
- if not self.server then self:adddefaultnameservers () end
-
- local question = encodeQuestion (qname, qtype, qclass)
- local peek = self:peek (qname, qtype, qclass)
- if peek then return peek end
-
- local header, id = encodeHeader ()
- --print ('query id', id, qclass, qtype, qname)
- local o = { packet = header..question,
- server = 1,
- 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 {}
- self.active[id][question] = o
-
- -- remember which coroutine wants the answer
- 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 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 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[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: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