aboutsummaryrefslogtreecommitdiffstats
path: root/net/connect.lua
diff options
context:
space:
mode:
Diffstat (limited to 'net/connect.lua')
-rw-r--r--net/connect.lua52
1 files changed, 39 insertions, 13 deletions
diff --git a/net/connect.lua b/net/connect.lua
index 4b602be4..0e39cf36 100644
--- a/net/connect.lua
+++ b/net/connect.lua
@@ -1,8 +1,8 @@
-local server = require "net.server";
-local log = require "util.logger".init("net.connect");
-local new_id = require "util.id".short;
+local server = require "prosody.net.server";
+local log = require "prosody.util.logger".init("net.connect");
+local new_id = require "prosody.util.id".short;
+local timer = require "prosody.util.timer";
--- TODO #1246 Happy Eyeballs
-- FIXME RFC 6724
-- FIXME Error propagation from resolvers doesn't work
-- FIXME #1428 Reuse DNS resolver object between service and basic resolver
@@ -28,16 +28,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 +50,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 +71,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 +89,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 +110,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");