Annotate

net/connect.lua @ 12547:e79c64b2dfed

util.watchdog: Allow passing a new timeout to :reset()
author Matthew Wild <mwild1@gmail.com>
date Sat, 11 Jun 2022 22:15:31 +0100
parent 12468:353836684009
child 12639:6d9ee0a3eb4b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8531
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;
12412
18a3a6218100 net.connect: When more targets are immediately available, try them after a delay
Matthew Wild <mwild1@gmail.com>
parents: 12411
diff changeset
4 local timer = require "util.timer";
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5
10484
b13a31cea7d9 net.connect: Add some TODOs and FIXMEs
Kim Alvefur <zash@zash.se>
parents: 10452
diff changeset
6 -- TODO #1246 Happy Eyeballs
10485
913276ba0c47 net.connect: Mention RFC 6724 regression
Kim Alvefur <zash@zash.se>
parents: 10484
diff changeset
7 -- FIXME RFC 6724
10452
fa11070c2cd7 net.connect: Add some TODO comments
Kim Alvefur <zash@zash.se>
parents: 10112
diff changeset
8 -- FIXME Error propagation from resolvers doesn't work
10484
b13a31cea7d9 net.connect: Add some TODOs and FIXMEs
Kim Alvefur <zash@zash.se>
parents: 10452
diff changeset
9 -- 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: 10452
diff changeset
10 -- FIXME #1429 Close DNS resolver object when done
10452
fa11070c2cd7 net.connect: Add some TODO comments
Kim Alvefur <zash@zash.se>
parents: 10112
diff changeset
11
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 local pending_connection_methods = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 local pending_connection_mt = {
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 __name = "pending_connection";
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 __index = pending_connection_methods;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 __tostring = function (p)
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 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
18 end;
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
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 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
22 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
23 end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25 -- 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
26 local pending_connections_map = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 local pending_connection_listeners = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30 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
31 p:log("debug", "Checking for targets...");
12412
18a3a6218100 net.connect: When more targets are immediately available, try them after a delay
Matthew Wild <mwild1@gmail.com>
parents: 12411
diff changeset
32 p.target_resolver:next(function (conn_type, ip, port, extra, more_targets_available)
8547
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8546
diff changeset
33 if not conn_type then
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8546
diff changeset
34 -- No more targets to try
11901
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 10945
diff changeset
35 p:log("debug", "No more connection targets to try", p.target_resolver.last_error);
12425
eabcc3ae22e9 net.connect: Improve handling of failure when attempts are still pending
Matthew Wild <mwild1@gmail.com>
parents: 12412
diff changeset
36 if next(p.conns) == nil then
eabcc3ae22e9 net.connect: Improve handling of failure when attempts are still pending
Matthew Wild <mwild1@gmail.com>
parents: 12412
diff changeset
37 p:log("debug", "No more targets, no pending connections. Connection failed.");
eabcc3ae22e9 net.connect: Improve handling of failure when attempts are still pending
Matthew Wild <mwild1@gmail.com>
parents: 12412
diff changeset
38 if p.listeners.onfail then
eabcc3ae22e9 net.connect: Improve handling of failure when attempts are still pending
Matthew Wild <mwild1@gmail.com>
parents: 12412
diff changeset
39 p.listeners.onfail(p.data, p.last_error or p.target_resolver.last_error or "unable to resolve service");
eabcc3ae22e9 net.connect: Improve handling of failure when attempts are still pending
Matthew Wild <mwild1@gmail.com>
parents: 12412
diff changeset
40 end
eabcc3ae22e9 net.connect: Improve handling of failure when attempts are still pending
Matthew Wild <mwild1@gmail.com>
parents: 12412
diff changeset
41 else
eabcc3ae22e9 net.connect: Improve handling of failure when attempts are still pending
Matthew Wild <mwild1@gmail.com>
parents: 12412
diff changeset
42 p:log("debug", "One or more connection attempts are still pending. Waiting for now.");
8547
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8546
diff changeset
43 end
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8546
diff changeset
44 return;
5e9c87376891 net.connect: Handle case when resolver runs out of targets
Matthew Wild <mwild1@gmail.com>
parents: 8546
diff changeset
45 end
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 p:log("debug", "Next target to try is %s:%d", ip, port);
12205
a2e6605303fa net.connect: Allow passing TLS context from resolver
Kim Alvefur <zash@zash.se>
parents: 11903
diff changeset
47 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: 11903
diff changeset
48 extra and extra.sslctx or p.options.sslctx, conn_type, extra);
8548
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8547
diff changeset
49 if not conn then
10112
b327f2870382 net.*: Remove tostring call from logging
Kim Alvefur <zash@zash.se>
parents: 9387
diff changeset
50 log("debug", "Connection attempt failed immediately: %s", err);
8548
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8547
diff changeset
51 p.last_error = err or "unknown reason";
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8547
diff changeset
52 return attempt_connection(p);
162f75ac2693 net.connect: Handle immediate failures of server.addclient
Matthew Wild <mwild1@gmail.com>
parents: 8547
diff changeset
53 end
12411
e132a4279914 net.connect: Support for multiple pending connection attempts
Matthew Wild <mwild1@gmail.com>
parents: 12205
diff changeset
54 p.conns[conn] = true;
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 pending_connections_map[conn] = p;
12412
18a3a6218100 net.connect: When more targets are immediately available, try them after a delay
Matthew Wild <mwild1@gmail.com>
parents: 12411
diff changeset
56 if more_targets_available then
18a3a6218100 net.connect: When more targets are immediately available, try them after a delay
Matthew Wild <mwild1@gmail.com>
parents: 12411
diff changeset
57 timer.add_task(0.250, function ()
18a3a6218100 net.connect: When more targets are immediately available, try them after a delay
Matthew Wild <mwild1@gmail.com>
parents: 12411
diff changeset
58 if not p.connected then
18a3a6218100 net.connect: When more targets are immediately available, try them after a delay
Matthew Wild <mwild1@gmail.com>
parents: 12411
diff changeset
59 p:log("debug", "Still not connected, making parallel connection attempt...");
18a3a6218100 net.connect: When more targets are immediately available, try them after a delay
Matthew Wild <mwild1@gmail.com>
parents: 12411
diff changeset
60 attempt_connection(p);
18a3a6218100 net.connect: When more targets are immediately available, try them after a delay
Matthew Wild <mwild1@gmail.com>
parents: 12411
diff changeset
61 end
18a3a6218100 net.connect: When more targets are immediately available, try them after a delay
Matthew Wild <mwild1@gmail.com>
parents: 12411
diff changeset
62 end);
18a3a6218100 net.connect: When more targets are immediately available, try them after a delay
Matthew Wild <mwild1@gmail.com>
parents: 12411
diff changeset
63 end
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64 end);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67 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
68 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
69 if not p then
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70 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
71 conn:close();
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 return;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 pending_connections_map[conn] = nil;
12411
e132a4279914 net.connect: Support for multiple pending connection attempts
Matthew Wild <mwild1@gmail.com>
parents: 12205
diff changeset
75 if p.connected then
e132a4279914 net.connect: Support for multiple pending connection attempts
Matthew Wild <mwild1@gmail.com>
parents: 12205
diff changeset
76 -- We already succeeded in connecting
e132a4279914 net.connect: Support for multiple pending connection attempts
Matthew Wild <mwild1@gmail.com>
parents: 12205
diff changeset
77 p.conns[conn] = nil;
e132a4279914 net.connect: Support for multiple pending connection attempts
Matthew Wild <mwild1@gmail.com>
parents: 12205
diff changeset
78 conn:close();
e132a4279914 net.connect: Support for multiple pending connection attempts
Matthew Wild <mwild1@gmail.com>
parents: 12205
diff changeset
79 return;
e132a4279914 net.connect: Support for multiple pending connection attempts
Matthew Wild <mwild1@gmail.com>
parents: 12205
diff changeset
80 end
e132a4279914 net.connect: Support for multiple pending connection attempts
Matthew Wild <mwild1@gmail.com>
parents: 12205
diff changeset
81 p.connected = true;
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82 p:log("debug", "Successfully connected");
9387
33e52f727f0f net.connect: Fix passing request table to new listener
Kim Alvefur <zash@zash.se>
parents: 9386
diff changeset
83 conn:setlistener(p.listeners, p.data);
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84 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
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 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
88 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
89 if not p then
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
90 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
91 return;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92 end
12411
e132a4279914 net.connect: Support for multiple pending connection attempts
Matthew Wild <mwild1@gmail.com>
parents: 12205
diff changeset
93 p.conns[conn] = nil;
12468
353836684009 net.connect: Fix accumulation of connection attempt references
Kim Alvefur <zash@zash.se>
parents: 12426
diff changeset
94 pending_connections_map[conn] = nil;
8546
d66916dc318a net.connect: Track last connection error
Matthew Wild <mwild1@gmail.com>
parents: 8536
diff changeset
95 p.last_error = reason or "unknown reason";
d66916dc318a net.connect: Track last connection error
Matthew Wild <mwild1@gmail.com>
parents: 8536
diff changeset
96 p:log("debug", "Connection attempt failed: %s", p.last_error);
12426
7a3da1acace1 net.connect: Improve logging on connection attempt failure
Matthew Wild <mwild1@gmail.com>
parents: 12425
diff changeset
97 if p.connected then
7a3da1acace1 net.connect: Improve logging on connection attempt failure
Matthew Wild <mwild1@gmail.com>
parents: 12425
diff changeset
98 p:log("debug", "Connection already established, ignoring failure");
7a3da1acace1 net.connect: Improve logging on connection attempt failure
Matthew Wild <mwild1@gmail.com>
parents: 12425
diff changeset
99 elseif next(p.conns) == nil then
12425
eabcc3ae22e9 net.connect: Improve handling of failure when attempts are still pending
Matthew Wild <mwild1@gmail.com>
parents: 12412
diff changeset
100 p:log("debug", "No pending connection attempts, and not yet connected");
eabcc3ae22e9 net.connect: Improve handling of failure when attempts are still pending
Matthew Wild <mwild1@gmail.com>
parents: 12412
diff changeset
101 attempt_connection(p);
12426
7a3da1acace1 net.connect: Improve logging on connection attempt failure
Matthew Wild <mwild1@gmail.com>
parents: 12425
diff changeset
102 else
7a3da1acace1 net.connect: Improve logging on connection attempt failure
Matthew Wild <mwild1@gmail.com>
parents: 12425
diff changeset
103 p:log("debug", "Other attempts are still pending, ignoring failure");
12425
eabcc3ae22e9 net.connect: Improve handling of failure when attempts are still pending
Matthew Wild <mwild1@gmail.com>
parents: 12412
diff changeset
104 end
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
105 end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
106
10623
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10612
diff changeset
107 local function connect(target_resolver, listeners, options, data)
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10612
diff changeset
108 local p = setmetatable({
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10612
diff changeset
109 id = new_id();
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10612
diff changeset
110 target_resolver = target_resolver;
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10612
diff changeset
111 listeners = assert(listeners);
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10612
diff changeset
112 options = options or {};
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10612
diff changeset
113 data = data;
12411
e132a4279914 net.connect: Support for multiple pending connection attempts
Matthew Wild <mwild1@gmail.com>
parents: 12205
diff changeset
114 conns = {};
10623
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10612
diff changeset
115 }, pending_connection_mt);
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
116
10623
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10612
diff changeset
117 p:log("debug", "Starting connection process");
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10612
diff changeset
118 attempt_connection(p);
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
119 end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
120
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
121 return {
10623
f51c88baeb8a Backed out changeset 44ef46e1a951 (not optimal API)
Matthew Wild <mwild1@gmail.com>
parents: 10612
diff changeset
122 connect = connect;
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
123 };