net/connect.lua
author Matthew Wild <mwild1@gmail.com>
Mon, 20 Feb 2023 18:10:15 +0000
branch0.12
changeset 12898 0598d822614f
parent 12209 a2e6605303fa
child 12415 e132a4279914
permissions -rw-r--r--
mod_websocket: Fire pre-session-close event (fixes #1800) This event was added in a7c183bb4e64 and is required to make mod_smacks know that a session was intentionally closed and shouldn't be hibernated (see fcea4d9e7502). Because this was missing from mod_websocket's session.close(), mod_smacks would always attempt to hibernate websocket sessions even if they closed cleanly. That mod_websocket has its own copy of session.close() is something to fix another day (probably not in the stable branch). So for now this commit makes the minimal change to get things working again. Thanks to Damian and the Jitsi team for reporting.
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
};