net.resolvers.service: net.connect resolver that uses SRV records
authorKim Alvefur <zash@zash.se>
Thu, 27 Sep 2018 12:25:46 +0200
changeset 9391 a5d11627ce5d
parent 9390 33e52f727f0f
child 9392 9ae575efbb1f
net.resolvers.service: net.connect resolver that uses SRV records
net/resolvers/service.lua
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/net/resolvers/service.lua	Thu Sep 27 12:25:46 2018 +0200
@@ -0,0 +1,57 @@
+local adns = require "net.adns";
+local basic = require "net.resolvers.basic";
+
+local methods = {};
+local resolver_mt = { __index = methods };
+
+-- Find the next target to connect to, and
+-- pass it to cb()
+function methods:next(cb)
+	if self.targets then
+		if #self.targets == 0 then
+			cb(nil);
+			return;
+		end
+		local next_target = table.remove(self.targets, 1);
+		self.resolver = basic.new(unpack(next_target, 1, 4));
+		self.resolver:next(function (...)
+			if ... == nil then
+				self:next(cb);
+			else
+				cb(...);
+			end
+		end);
+		return;
+	end
+
+	local targets = {};
+	local function ready()
+		self.targets = targets;
+		self:next(cb);
+	end
+
+	-- Resolve DNS to target list
+	local dns_resolver = adns.resolver();
+	dns_resolver:lookup(function (answer)
+		if answer then
+			table.sort(answer, function (a, b) return a.priority > b.priority end);
+			for _, record in ipairs(answer) do
+				table.insert(targets, { record.srv.target, record.srv.port, self.conn_type, self.extra });
+			end
+		end
+		ready();
+	end, "_" .. self.service .. "._" .. self.conn_type .. "." .. self.domain, "SRV", "IN");
+end
+
+local function new(domain, service, conn_type, extra)
+	return setmetatable({
+		domain = domain;
+		service = service;
+		conn_type = conn_type or "tcp";
+		extra = extra;
+	}, resolver_mt);
+end
+
+return {
+	new = new;
+};