net/resolvers/service.lua
author Kim Alvefur <zash@zash.se>
Wed, 21 Dec 2022 21:34:07 +0100
changeset 12816 b2d422b88cd6
parent 12812 12bd40b8e105
child 12817 4be161c25e14
permissions -rw-r--r--
Revert unintentionally committed parts of 12bd40b8e105
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
local adns = require "net.adns";
9391
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8778
diff changeset
     2
local basic = require "net.resolvers.basic";
10444
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10405
diff changeset
     3
local inet_pton = require "util.net".pton;
10388
94c9c574cd8a net.resolvers: Apply IDNA conversion to ascii for DNS lookups (fixes #1426)
Kim Alvefur <zash@zash.se>
parents: 9400
diff changeset
     4
local idna_to_ascii = require "util.encodings".idna.to_ascii;
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     5
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     6
local methods = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
local resolver_mt = { __index = methods };
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
12405
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
     9
local function new_target_selector(rrset)
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    10
	local rr_count = rrset and #rrset;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    11
	if not rr_count or rr_count == 0 then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    12
		rrset = nil;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    13
	else
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    14
		table.sort(rrset, function (a, b) return a.srv.priority < b.srv.priority end);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    15
	end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    16
	local rrset_pos = 1;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    17
	local priority_bucket, bucket_total_weight, bucket_len, bucket_used;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    18
	return function ()
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    19
		if not rrset then return; end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    20
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    21
		if not priority_bucket or bucket_used >= bucket_len then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    22
			if rrset_pos > rr_count then return; end -- Used up all records
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    23
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    24
			-- Going to start on a new priority now. Gather up all the next
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    25
			-- records with the same priority and add them to priority_bucket
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    26
			priority_bucket, bucket_total_weight, bucket_len, bucket_used = {}, 0, 0, 0;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    27
			local current_priority;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    28
			repeat
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    29
				local curr_record = rrset[rrset_pos].srv;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    30
				if not current_priority then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    31
					current_priority = curr_record.priority;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    32
				elseif current_priority ~= curr_record.priority then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    33
					break;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    34
				end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    35
				table.insert(priority_bucket, curr_record);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    36
				bucket_total_weight = bucket_total_weight + curr_record.weight;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    37
				bucket_len = bucket_len + 1;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    38
				rrset_pos = rrset_pos + 1;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    39
			until rrset_pos > rr_count;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    40
		end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    41
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    42
		bucket_used = bucket_used + 1;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    43
		local n, running_total = math.random(0, bucket_total_weight), 0;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    44
		local target_record;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    45
		for i = 1, bucket_len do
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    46
			local candidate = priority_bucket[i];
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    47
			if candidate then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    48
				running_total = running_total + candidate.weight;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    49
				if running_total >= n then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    50
					target_record = candidate;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    51
					bucket_total_weight = bucket_total_weight - candidate.weight;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    52
					priority_bucket[i] = nil;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    53
					break;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    54
				end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    55
			end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    56
		end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    57
		return target_record;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    58
	end;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    59
end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    60
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    61
-- Find the next target to connect to, and
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    62
-- pass it to cb()
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
function methods:next(cb)
12405
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    64
	if self.resolver or self._get_next_target then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    65
		if not self.resolver then -- Do we have a basic resolver currently?
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    66
			-- We don't, so fetch a new SRV target, create a new basic resolver for it
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    67
			local next_srv_target = self._get_next_target and self._get_next_target();
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    68
			if not next_srv_target then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    69
				-- No more SRV targets left
10654
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10488
diff changeset
    70
				cb(nil);
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10488
diff changeset
    71
				return;
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10488
diff changeset
    72
			end
12405
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    73
			-- Create a new basic resolver for this SRV target
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    74
			self.resolver = basic.new(next_srv_target.target, next_srv_target.port, self.conn_type, self.extra);
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    75
		end
12405
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    76
		-- Look up the next (basic) target from the current target's resolver
9391
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8778
diff changeset
    77
		self.resolver:next(function (...)
11905
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11714
diff changeset
    78
			if self.resolver then
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11714
diff changeset
    79
				self.last_error = self.resolver.last_error;
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11714
diff changeset
    80
			end
9391
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8778
diff changeset
    81
			if ... == nil then
10654
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10488
diff changeset
    82
				self.resolver = nil;
9391
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8778
diff changeset
    83
				self:next(cb);
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8778
diff changeset
    84
			else
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8778
diff changeset
    85
				cb(...);
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8778
diff changeset
    86
			end
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8778
diff changeset
    87
		end);
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    88
		return;
12405
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    89
	elseif self.in_progress then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    90
		cb(nil);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
    91
		return;
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    92
	end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    93
10389
62a7042e0771 net.resolvers: Abort on hostnames not passing IDNA validation
Kim Alvefur <zash@zash.se>
parents: 10388
diff changeset
    94
	if not self.hostname then
12029
6ed7fd28f5e3 net.resolvers: Report when hostname fails IDNA
Kim Alvefur <zash@zash.se>
parents: 11905
diff changeset
    95
		self.last_error = "hostname failed IDNA";
10389
62a7042e0771 net.resolvers: Abort on hostnames not passing IDNA validation
Kim Alvefur <zash@zash.se>
parents: 10388
diff changeset
    96
		cb(nil);
10404
4c2d789a106b net.resolvers: Fix traceback from hostname failing IDNA
Kim Alvefur <zash@zash.se>
parents: 10389
diff changeset
    97
		return;
10389
62a7042e0771 net.resolvers: Abort on hostnames not passing IDNA validation
Kim Alvefur <zash@zash.se>
parents: 10388
diff changeset
    98
	end
62a7042e0771 net.resolvers: Abort on hostnames not passing IDNA validation
Kim Alvefur <zash@zash.se>
parents: 10388
diff changeset
    99
12405
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
   100
	self.in_progress = true;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
   101
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   102
	local function ready()
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   103
		self:next(cb);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   104
	end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   105
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   106
	-- Resolve DNS to target list
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   107
	local dns_resolver = adns.resolver();
10125
33f287519bf6 net.resolvers.service: Fix DNS fallback
Kim Alvefur <zash@zash.se>
parents: 9695
diff changeset
   108
	dns_resolver:lookup(function (answer, err)
33f287519bf6 net.resolvers.service: Fix DNS fallback
Kim Alvefur <zash@zash.se>
parents: 9695
diff changeset
   109
		if not answer and not err then
33f287519bf6 net.resolvers.service: Fix DNS fallback
Kim Alvefur <zash@zash.se>
parents: 9695
diff changeset
   110
			-- net.adns returns nil if there are zero records or nxdomain
33f287519bf6 net.resolvers.service: Fix DNS fallback
Kim Alvefur <zash@zash.se>
parents: 9695
diff changeset
   111
			answer = {};
33f287519bf6 net.resolvers.service: Fix DNS fallback
Kim Alvefur <zash@zash.se>
parents: 9695
diff changeset
   112
		end
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   113
		if answer then
12816
b2d422b88cd6 Revert unintentionally committed parts of 12bd40b8e105
Kim Alvefur <zash@zash.se>
parents: 12812
diff changeset
   114
			if self.extra and not answer.secure then
b2d422b88cd6 Revert unintentionally committed parts of 12bd40b8e105
Kim Alvefur <zash@zash.se>
parents: 12812
diff changeset
   115
				self.extra.use_dane = false;
b2d422b88cd6 Revert unintentionally committed parts of 12bd40b8e105
Kim Alvefur <zash@zash.se>
parents: 12812
diff changeset
   116
			elseif answer.bogus then
12133
7a68d5828f3b net.resolvers: Report DNSSEC validation errors instead of NoError
Kim Alvefur <zash@zash.se>
parents: 12029
diff changeset
   117
				self.last_error = "Validation error in SRV lookup";
7a68d5828f3b net.resolvers: Report DNSSEC validation errors instead of NoError
Kim Alvefur <zash@zash.se>
parents: 12029
diff changeset
   118
				ready();
7a68d5828f3b net.resolvers: Report DNSSEC validation errors instead of NoError
Kim Alvefur <zash@zash.se>
parents: 12029
diff changeset
   119
				return;
11714
26a8cc9d9eb7 net.resolvers.service: Only do DANE with secure SRV records
Kim Alvefur <zash@zash.se>
parents: 10974
diff changeset
   120
			end
26a8cc9d9eb7 net.resolvers.service: Only do DANE with secure SRV records
Kim Alvefur <zash@zash.se>
parents: 10974
diff changeset
   121
9396
e2733f504d9e net.resolvers.service: Early return on empty result set
Kim Alvefur <zash@zash.se>
parents: 9395
diff changeset
   122
			if #answer == 0 then
9397
bcd94cc355d3 net.resolvers.service: Add support for fallback to bare domain and default port
Kim Alvefur <zash@zash.se>
parents: 9396
diff changeset
   123
				if self.extra and self.extra.default_port then
12405
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
   124
					self.resolver = basic.new(self.hostname, self.extra.default_port, self.conn_type, self.extra);
11905
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11714
diff changeset
   125
				else
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11714
diff changeset
   126
					self.last_error = "zero SRV records found";
9397
bcd94cc355d3 net.resolvers.service: Add support for fallback to bare domain and default port
Kim Alvefur <zash@zash.se>
parents: 9396
diff changeset
   127
				end
9396
e2733f504d9e net.resolvers.service: Early return on empty result set
Kim Alvefur <zash@zash.se>
parents: 9395
diff changeset
   128
				ready();
e2733f504d9e net.resolvers.service: Early return on empty result set
Kim Alvefur <zash@zash.se>
parents: 9395
diff changeset
   129
				return;
e2733f504d9e net.resolvers.service: Early return on empty result set
Kim Alvefur <zash@zash.se>
parents: 9395
diff changeset
   130
			end
e2733f504d9e net.resolvers.service: Early return on empty result set
Kim Alvefur <zash@zash.se>
parents: 9395
diff changeset
   131
9395
f2d71e4284b7 net.resolvers.service: Understand when service is explicitly unavailable
Kim Alvefur <zash@zash.se>
parents: 9391
diff changeset
   132
			if #answer == 1 and answer[1].srv.target == "." then -- No service here
11905
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11714
diff changeset
   133
				self.last_error = "service explicitly unavailable";
9395
f2d71e4284b7 net.resolvers.service: Understand when service is explicitly unavailable
Kim Alvefur <zash@zash.se>
parents: 9391
diff changeset
   134
				ready();
f2d71e4284b7 net.resolvers.service: Understand when service is explicitly unavailable
Kim Alvefur <zash@zash.se>
parents: 9391
diff changeset
   135
				return;
f2d71e4284b7 net.resolvers.service: Understand when service is explicitly unavailable
Kim Alvefur <zash@zash.se>
parents: 9391
diff changeset
   136
			end
f2d71e4284b7 net.resolvers.service: Understand when service is explicitly unavailable
Kim Alvefur <zash@zash.se>
parents: 9391
diff changeset
   137
12405
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents: 12133
diff changeset
   138
			self._get_next_target = new_target_selector(answer);
11905
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11714
diff changeset
   139
		else
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11714
diff changeset
   140
			self.last_error = err;
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   141
		end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   142
		ready();
9398
794eda565c69 net.resolvers.service: Rename internal variable since net.connect uses it for __tostring
Kim Alvefur <zash@zash.se>
parents: 9397
diff changeset
   143
	end, "_" .. self.service .. "._" .. self.conn_type .. "." .. self.hostname, "SRV", "IN");
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   144
end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   145
9398
794eda565c69 net.resolvers.service: Rename internal variable since net.connect uses it for __tostring
Kim Alvefur <zash@zash.se>
parents: 9397
diff changeset
   146
local function new(hostname, service, conn_type, extra)
10444
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10405
diff changeset
   147
	local is_ip = inet_pton(hostname);
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10405
diff changeset
   148
	if not is_ip and hostname:sub(1,1) == '[' then
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10405
diff changeset
   149
		is_ip = inet_pton(hostname:sub(2,-2));
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10405
diff changeset
   150
	end
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10405
diff changeset
   151
	if is_ip and extra and extra.default_port then
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10405
diff changeset
   152
		return basic.new(hostname, extra.default_port, conn_type, extra);
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10405
diff changeset
   153
	end
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10405
diff changeset
   154
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   155
	return setmetatable({
10388
94c9c574cd8a net.resolvers: Apply IDNA conversion to ascii for DNS lookups (fixes #1426)
Kim Alvefur <zash@zash.se>
parents: 9400
diff changeset
   156
		hostname = idna_to_ascii(hostname);
9391
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8778
diff changeset
   157
		service = service;
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   158
		conn_type = conn_type or "tcp";
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   159
		extra = extra;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   160
	}, resolver_mt);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   161
end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   162
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   163
return {
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   164
	new = new;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   165
};