aboutsummaryrefslogtreecommitdiffstats
path: root/net/connect.lua
diff options
context:
space:
mode:
Diffstat (limited to 'net/connect.lua')
-rw-r--r--net/connect.lua45
1 files changed, 36 insertions, 9 deletions
diff --git a/net/connect.lua b/net/connect.lua
index 4b602be4..d85afcff 100644
--- a/net/connect.lua
+++ b/net/connect.lua
@@ -1,6 +1,7 @@
local server = require "net.server";
local log = require "util.logger".init("net.connect");
local new_id = require "util.id".short;
+local timer = require "util.timer";
-- TODO #1246 Happy Eyeballs
-- FIXME RFC 6724
@@ -28,16 +29,17 @@ local pending_connection_listeners = {};
local function attempt_connection(p)
p:log("debug", "Checking for targets...");
- if p.conn then
- pending_connections_map[p.conn] = nil;
- p.conn = nil;
- end
- p.target_resolver:next(function (conn_type, ip, port, extra)
+ p.target_resolver:next(function (conn_type, ip, port, extra, more_targets_available)
if not conn_type then
-- No more targets to try
p:log("debug", "No more connection targets to try", p.target_resolver.last_error);
- if p.listeners.onfail then
- p.listeners.onfail(p.data, p.last_error or p.target_resolver.last_error or "unable to resolve service");
+ if next(p.conns) == nil then
+ p:log("debug", "No more targets, no pending connections. Connection failed.");
+ if p.listeners.onfail then
+ p.listeners.onfail(p.data, p.last_error or p.target_resolver.last_error or "unable to resolve service");
+ end
+ else
+ p:log("debug", "One or more connection attempts are still pending. Waiting for now.");
end
return;
end
@@ -49,8 +51,16 @@ local function attempt_connection(p)
p.last_error = err or "unknown reason";
return attempt_connection(p);
end
- p.conn = conn;
+ p.conns[conn] = true;
pending_connections_map[conn] = p;
+ if more_targets_available then
+ timer.add_task(0.250, function ()
+ if not p.connected then
+ p:log("debug", "Still not connected, making parallel connection attempt...");
+ attempt_connection(p);
+ end
+ end);
+ end
end);
end
@@ -62,6 +72,13 @@ function pending_connection_listeners.onconnect(conn)
return;
end
pending_connections_map[conn] = nil;
+ if p.connected then
+ -- We already succeeded in connecting
+ p.conns[conn] = nil;
+ conn:close();
+ return;
+ end
+ p.connected = true;
p:log("debug", "Successfully connected");
conn:setlistener(p.listeners, p.data);
return p.listeners.onconnect(conn);
@@ -73,9 +90,18 @@ function pending_connection_listeners.ondisconnect(conn, reason)
log("warn", "Failed connection, but unexpected!");
return;
end
+ p.conns[conn] = nil;
+ pending_connections_map[conn] = nil;
p.last_error = reason or "unknown reason";
p:log("debug", "Connection attempt failed: %s", p.last_error);
- attempt_connection(p);
+ if p.connected then
+ p:log("debug", "Connection already established, ignoring failure");
+ elseif next(p.conns) == nil then
+ p:log("debug", "No pending connection attempts, and not yet connected");
+ attempt_connection(p);
+ else
+ p:log("debug", "Other attempts are still pending, ignoring failure");
+ end
end
local function connect(target_resolver, listeners, options, data)
@@ -85,6 +111,7 @@ local function connect(target_resolver, listeners, options, data)
listeners = assert(listeners);
options = options or {};
data = data;
+ conns = {};
}, pending_connection_mt);
p:log("debug", "Starting connection process");