Comparison

net/adns.lua @ 8266:9a97dd174ec9

net.adns: Restructure to allow creating separate resolver objects, like net.dns
author Matthew Wild <mwild1@gmail.com>
date Mon, 25 Sep 2017 23:06:00 +0100
parent 7475:ee878fa78b8b
child 8280:9ca0e3128b62
comparison
equal deleted inserted replaced
8265:17ebd8ac8545 8266:9a97dd174ec9
5 -- This project is MIT/X11 licensed. Please see the 5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information. 6 -- COPYING file in the source package for more information.
7 -- 7 --
8 8
9 local server = require "net.server"; 9 local server = require "net.server";
10 local dns = require "net.dns"; 10 local new_resolver = require "net.dns".resolver;
11 11
12 local log = require "util.logger".init("adns"); 12 local log = require "util.logger".init("adns");
13 13
14 local coroutine, tostring, pcall = coroutine, tostring, pcall; 14 local coroutine, tostring, pcall = coroutine, tostring, pcall;
15 15
16 local function dummy_send(sock, data, i, j) return (j-i)+1; end 16 local function dummy_send(sock, data, i, j) return (j-i)+1; end
17 17
18 local _ENV = nil; 18 local _ENV = nil;
19 19
20 local function lookup(handler, qname, qtype, qclass) 20 local async_resolver_methods = {};
21 return coroutine.wrap(function (peek) 21 local async_resolver_mt = { __index = async_resolver_methods };
22 if peek then
23 log("debug", "Records for %s already cached, using those...", qname);
24 handler(peek);
25 return;
26 end
27 log("debug", "Records for %s not in cache, sending query (%s)...", qname, tostring(coroutine.running()));
28 local ok, err = dns.query(qname, qtype, qclass);
29 if ok then
30 coroutine.yield({ qclass or "IN", qtype or "A", qname, coroutine.running()}); -- Wait for reply
31 log("debug", "Reply for %s (%s)", qname, tostring(coroutine.running()));
32 end
33 if ok then
34 ok, err = pcall(handler, dns.peek(qname, qtype, qclass));
35 else
36 log("error", "Error sending DNS query: %s", err);
37 ok, err = pcall(handler, nil, err);
38 end
39 if not ok then
40 log("error", "Error in DNS response handler: %s", tostring(err));
41 end
42 end)(dns.peek(qname, qtype, qclass));
43 end
44 22
45 local function cancel(handle, call_handler, reason) 23 local query_methods = {};
46 log("warn", "Cancelling DNS lookup for %s", tostring(handle[3])); 24 local query_mt = { __index = query_methods };
47 dns.cancel(handle[1], handle[2], handle[3], handle[4], call_handler);
48 end
49 25
50 local function new_async_socket(sock, resolver) 26 local function new_async_socket(sock, resolver)
51 local peername = "<unknown>"; 27 local peername = "<unknown>";
52 local listener = {}; 28 local listener = {};
53 local handler = {}; 29 local handler = {};
54 local err; 30 local err;
55 function listener.onincoming(conn, data) 31 function listener.onincoming(conn, data)
56 if data then 32 if data then
57 dns.feed(handler, data); 33 resolver:feed(handler, data);
58 end 34 end
59 end 35 end
60 function listener.ondisconnect(conn, err) 36 function listener.ondisconnect(conn, err)
61 if err then 37 if err then
62 log("warn", "DNS socket for %s disconnected: %s", peername, err); 38 log("warn", "DNS socket for %s disconnected: %s", peername, err);
83 return sock:send(data); 59 return sock:send(data);
84 end 60 end
85 return handler; 61 return handler;
86 end 62 end
87 63
88 dns.socket_wrapper_set(new_async_socket); 64 function async_resolver_methods:lookup(handler, qname, qtype, qclass)
65 local resolver = self._resolver;
66 return coroutine.wrap(function (peek)
67 if peek then
68 log("debug", "Records for %s already cached, using those...", qname);
69 handler(peek);
70 return;
71 end
72 log("debug", "Records for %s not in cache, sending query (%s)...", qname, tostring(coroutine.running()));
73 local ok, err = resolver:query(qname, qtype, qclass);
74 if ok then
75 coroutine.yield(setmetatable({ resolver, qclass or "IN", qtype or "A", qname, coroutine.running()}, query_mt)); -- Wait for reply
76 log("debug", "Reply for %s (%s)", qname, tostring(coroutine.running()));
77 end
78 if ok then
79 ok, err = pcall(handler, resolver:peek(qname, qtype, qclass));
80 else
81 log("error", "Error sending DNS query: %s", err);
82 ok, err = pcall(handler, nil, err);
83 end
84 if not ok then
85 log("error", "Error in DNS response handler: %s", tostring(err));
86 end
87 end)(resolver:peek(qname, qtype, qclass));
88 end
89
90 function query_methods:cancel(call_handler, reason)
91 log("warn", "Cancelling DNS lookup for %s", tostring(self[4]));
92 self[1].cancel(self[2], self[3], self[4], self[5], call_handler);
93 end
94
95 local function new_async_resolver()
96 local resolver = new_resolver();
97 resolver:socket_wrapper_set(new_async_socket);
98 return setmetatable({ _resolver = resolver}, async_resolver_mt);
99 end
89 100
90 return { 101 return {
91 lookup = lookup; 102 lookup = function (...)
92 cancel = cancel; 103 return new_async_resolver():lookup(...);
104 end;
105 resolver = new_async_resolver;
93 new_async_socket = new_async_socket; 106 new_async_socket = new_async_socket;
94 }; 107 };