net/connect.lua
author Kim Alvefur <zash@zash.se>
Fri, 27 May 2022 14:45:35 +0200
branch0.12
changeset 12530 252ed01896dd
parent 12209 a2e6605303fa
child 12415 e132a4279914
permissions -rw-r--r--
mod_smacks: Bounce unhandled stanzas from local origin (fix #1759) Sending stanzas with a remote session as origin when the stanzas have a local JID in the from attribute trips validation in core.stanza_router, leading to warnings: > Received a stanza claiming to be from remote.example, over a stream authed for localhost.example Using module:send() uses the local host as origin, which is fine here.
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 server = require "net.server";
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
local log = require "util.logger".init("net.connect");
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     3
local new_id = require "util.id".short;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     4
10488
b13a31cea7d9 net.connect: Add some TODOs and FIXMEs
Kim Alvefur <zash@zash.se>
parents: 10456
diff changeset
     5
-- TODO #1246 Happy Eyeballs
10489
913276ba0c47 net.connect: Mention RFC 6724 regression
Kim Alvefur <zash@zash.se>
parents: 10488
diff changeset
     6
-- FIXME RFC 6724
10456
fa11070c2cd7 net.connect: Add some TODO comments
Kim Alvefur <zash@zash.se>
parents: 10116
diff changeset
     7
-- FIXME Error propagation from resolvers doesn't work
10488
b13a31cea7d9 net.connect: Add some TODOs and FIXMEs
Kim Alvefur <zash@zash.se>
parents: 10456
diff changeset
     8
-- FIXME #1428 Reuse DNS resolver object between service and basic resolver
b13a31cea7d9 net.connect: Add some TODOs and FIXMEs
Kim Alvefur <zash@zash.se>
parents: 10456
diff changeset
     9
-- FIXME #1429 Close DNS resolver object when done
10456
fa11070c2cd7 net.connect: Add some TODO comments
Kim Alvefur <zash@zash.se>
parents: 10116
diff changeset
    10
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
local pending_connection_methods = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    12
local pending_connection_mt = {
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    13
	__name = "pending_connection";
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    14
	__index = pending_connection_methods;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    15
	__tostring = function (p)
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    16
		return "<pending connection "..p.id.." to "..tostring(p.target_resolver.hostname)..">";
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
	end;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    18
};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    19
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    20
function pending_connection_methods:log(level, message, ...)
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
	log(level, "[pending connection %s] "..message, self.id, ...);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    22
end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    23
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    24
-- pending_connections_map[conn] = pending_connection
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    25
local pending_connections_map = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    27
local pending_connection_listeners = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    29
local function attempt_connection(p)
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    30
	p:log("debug", "Checking for targets...");
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    31
	if p.conn then
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    32
		pending_connections_map[p.conn] = nil;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
		p.conn = nil;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    34
	end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    35
	p.target_resolver:next(function (conn_type, ip, port, extra)
8550
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8549
diff changeset
    36
		if not conn_type then
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8549
diff changeset
    37
			-- No more targets to try
11905
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 10949
diff changeset
    38
			p:log("debug", "No more connection targets to try", p.target_resolver.last_error);
8550
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8549
diff changeset
    39
			if p.listeners.onfail then
11907
baf69f254753 net.connect: Prefer last connection error over last resolver error
Kim Alvefur <zash@zash.se>
parents: 11905
diff changeset
    40
				p.listeners.onfail(p.data, p.last_error or p.target_resolver.last_error or "unable to resolve service");
8550
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8549
diff changeset
    41
			end
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8549
diff changeset
    42
			return;
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8549
diff changeset
    43
		end
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    44
		p:log("debug", "Next target to try is %s:%d", ip, port);
12209
a2e6605303fa net.connect: Allow passing TLS context from resolver
Kim Alvefur <zash@zash.se>
parents: 11907
diff changeset
    45
		local conn, err = server.addclient(ip, port, pending_connection_listeners, p.options.pattern or "*a",
a2e6605303fa net.connect: Allow passing TLS context from resolver
Kim Alvefur <zash@zash.se>
parents: 11907
diff changeset
    46
			extra and extra.sslctx or p.options.sslctx, conn_type, extra);
8551
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8550
diff changeset
    47
		if not conn then
10116
b327f2870382 net.*: Remove tostring call from logging
Kim Alvefur <zash@zash.se>
parents: 9390
diff changeset
    48
			log("debug", "Connection attempt failed immediately: %s", err);
8551
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8550
diff changeset
    49
			p.last_error = err or "unknown reason";
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8550
diff changeset
    50
			return attempt_connection(p);
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8550
diff changeset
    51
		end
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    52
		p.conn = conn;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    53
		pending_connections_map[conn] = p;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    54
	end);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    55
end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    56
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    57
function pending_connection_listeners.onconnect(conn)
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    58
	local p = pending_connections_map[conn];
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    59
	if not p then
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    60
		log("warn", "Successful connection, but unexpected! Closing.");
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    61
		conn:close();
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    62
		return;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
	end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    64
	pending_connections_map[conn] = nil;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    65
	p:log("debug", "Successfully connected");
9390
33e52f727f0f net.connect: Fix passing request table to new listener
Kim Alvefur <zash@zash.se>
parents: 9389
diff changeset
    66
	conn:setlistener(p.listeners, p.data);
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    67
	return p.listeners.onconnect(conn);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    69
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    70
function pending_connection_listeners.ondisconnect(conn, reason)
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    71
	local p = pending_connections_map[conn];
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    72
	if not p then
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    73
		log("warn", "Failed connection, but unexpected!");
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    74
		return;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    75
	end
8549
d66916dc318a net.connect: Track last connection error
Matthew Wild <mwild1@gmail.com>
parents: 8539
diff changeset
    76
	p.last_error = reason or "unknown reason";
d66916dc318a net.connect: Track last connection error
Matthew Wild <mwild1@gmail.com>
parents: 8539
diff changeset
    77
	p:log("debug", "Connection attempt failed: %s", p.last_error);
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    78
	attempt_connection(p);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    79
end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    80
10627
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10616
diff changeset
    81
local function connect(target_resolver, listeners, options, data)
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10616
diff changeset
    82
	local p = setmetatable({
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10616
diff changeset
    83
		id = new_id();
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10616
diff changeset
    84
		target_resolver = target_resolver;
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10616
diff changeset
    85
		listeners = assert(listeners);
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10616
diff changeset
    86
		options = options or {};
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10616
diff changeset
    87
		data = data;
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10616
diff changeset
    88
	}, pending_connection_mt);
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    89
10627
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10616
diff changeset
    90
	p:log("debug", "Starting connection process");
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10616
diff changeset
    91
	attempt_connection(p);
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
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    94
return {
10627
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10616
diff changeset
    95
	connect = connect;
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    96
};