File

net/resolvers/service.lua @ 10360:64ddcbc9a328

core.stanza_router: Do strict jidprep on c2s Be conservative in what you let your clients send, be liberal in what you let in via s2s. Being strict on s2s leads to interop problems and poor experiences, ie users being ejected from MUCs if something invalid enters. By starting with tightening up input into the network, we may be able to gradually approach a point where no invalid JIDs are allowed.
author Kim Alvefur <zash@zash.se>
date Mon, 09 Sep 2019 22:32:01 +0200
parent 10121:33f287519bf6
child 10386:cf93a951da37
line wrap: on
line source

local adns = require "net.adns";
local basic = require "net.resolvers.basic";
local unpack = table.unpack or unpack; -- luacheck: ignore 113

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, err)
		if not answer and not err then
			-- net.adns returns nil if there are zero records or nxdomain
			answer = {};
		end
		if answer then
			if #answer == 0 then
				if self.extra and self.extra.default_port then
					table.insert(targets, { self.hostname, self.extra.default_port, self.conn_type, self.extra });
				end
				ready();
				return;
			end

			if #answer == 1 and answer[1].srv.target == "." then -- No service here
				ready();
				return;
			end

			table.sort(answer, function (a, b) return a.srv.priority < b.srv.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.hostname, "SRV", "IN");
end

local function new(hostname, service, conn_type, extra)
	return setmetatable({
		hostname = hostname;
		service = service;
		conn_type = conn_type or "tcp";
		extra = extra;
	}, resolver_mt);
end

return {
	new = new;
};