net/connect.lua
author Kim Alvefur <zash@zash.se>
Tue, 22 Nov 2022 23:56:01 +0100
branch0.11
changeset 12801 be09ac8300a7
parent 9390 33e52f727f0f
child 10116 b327f2870382
permissions -rw-r--r--
util.stanza: Allow U+7F Allowed by XML despite arguably being a control character. Drops the part of the range meant to rule out octets invalid in UTF-8 (\247 starts a 4-byte sequence), since UTF-8 correctness is validated by util.encodings.utf8.valid().
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
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     5
local pending_connection_methods = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     6
local pending_connection_mt = {
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
	__name = "pending_connection";
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
	__index = pending_connection_methods;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     9
	__tostring = function (p)
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    10
		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
    11
	end;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    12
};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    13
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    14
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
    15
	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
    16
end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    18
-- 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
    19
local pending_connections_map = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    20
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
local pending_connection_listeners = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    22
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    23
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
    24
	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
    25
	if p.conn then
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
		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
    27
		p.conn = nil;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
	end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    29
	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
    30
		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
    31
			-- No more targets to try
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8549
diff changeset
    32
			p:log("debug", "No more connection targets to try");
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8549
diff changeset
    33
			if p.listeners.onfail then
8552
69e942c2990f net.connect: Improve error message
Matthew Wild <mwild1@gmail.com>
parents: 8551
diff changeset
    34
				p.listeners.onfail(p.data, p.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
    35
			end
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8549
diff changeset
    36
			return;
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8549
diff changeset
    37
		end
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    38
		p:log("debug", "Next target to try is %s:%d", ip, port);
8551
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8550
diff changeset
    39
		local conn, err = server.addclient(ip, port, pending_connection_listeners, p.options.pattern or "*a", p.options.sslctx, conn_type, extra);
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8550
diff changeset
    40
		if not conn then
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8550
diff changeset
    41
			log("debug", "Connection attempt failed immediately: %s", tostring(err));
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8550
diff changeset
    42
			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
    43
			return attempt_connection(p);
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8550
diff changeset
    44
		end
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    45
		p.conn = conn;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    46
		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
    47
	end);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    48
end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    49
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    50
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
    51
	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
    52
	if not p then
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    53
		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
    54
		conn:close();
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    55
		return;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    56
	end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    57
	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
    58
	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
    59
	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
    60
	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
    61
end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    62
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
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
    64
	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
    65
	if not p then
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    66
		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
    67
		return;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
	end
8549
d66916dc318a net.connect: Track last connection error
Matthew Wild <mwild1@gmail.com>
parents: 8539
diff changeset
    69
	p.last_error = reason or "unknown reason";
d66916dc318a net.connect: Track last connection error
Matthew Wild <mwild1@gmail.com>
parents: 8539
diff changeset
    70
	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
    71
	attempt_connection(p);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    72
end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    73
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    74
local function connect(target_resolver, listeners, options, data)
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    75
	local p = setmetatable({
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    76
		id = new_id();
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    77
		target_resolver = target_resolver;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    78
		listeners = assert(listeners);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    79
		options = options or {};
8553
f841d359da65 net.connect: Fix to store correct parameter
Matthew Wild <mwild1@gmail.com>
parents: 8552
diff changeset
    80
		data = data;
8534
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    81
	}, pending_connection_mt);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    82
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    83
	p:log("debug", "Starting connection process");
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    84
	attempt_connection(p);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    85
end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    86
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    87
return {
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    88
	connect = connect;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    89
};