aboutsummaryrefslogtreecommitdiffstats
path: root/net/connect.lua
diff options
context:
space:
mode:
authorMatthew Wild <mwild1@gmail.com>2018-02-23 15:53:45 +0000
committerMatthew Wild <mwild1@gmail.com>2018-02-23 15:53:45 +0000
commitc27281a72055b599acab5272f17b869914ef936d (patch)
tree640cb0fdc674f685e2cea71aea16ed303c083935 /net/connect.lua
parent2727b7b72307c1f5e59f8b2e943074307010d262 (diff)
downloadprosody-c27281a72055b599acab5272f17b869914ef936d.tar.gz
prosody-c27281a72055b599acab5272f17b869914ef936d.zip
net.connect: New API for outgoing connections, based on 'service resolvers'
Diffstat (limited to 'net/connect.lua')
-rw-r--r--net/connect.lua78
1 files changed, 78 insertions, 0 deletions
diff --git a/net/connect.lua b/net/connect.lua
new file mode 100644
index 00000000..dbd09694
--- /dev/null
+++ b/net/connect.lua
@@ -0,0 +1,78 @@
+local server = require "net.server";
+local log = require "util.logger".init("net.connect");
+local new_id = require "util.id".short;
+
+local pending_connection_methods = {};
+local pending_connection_mt = {
+ __name = "pending_connection";
+ __index = pending_connection_methods;
+ __tostring = function (p)
+ return "<pending connection "..p.id.." to "..tostring(p.target_resolver.hostname)..">";
+ end;
+};
+
+function pending_connection_methods:log(level, message, ...)
+ log(level, "[pending connection %s] "..message, self.id, ...);
+end
+
+-- pending_connections_map[conn] = pending_connection
+local pending_connections_map = {};
+
+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:log("debug", "Next target to try is %s:%d", ip, port);
+ local conn = assert(server.addclient(ip, port, pending_connection_listeners, p.options.pattern, p.options.sslctx, conn_type, extra));
+ p.conn = conn;
+ pending_connections_map[conn] = p;
+ end);
+end
+
+function pending_connection_listeners.onconnect(conn)
+ local p = pending_connections_map[conn];
+ if not p then
+ log("warn", "Successful connection, but unexpected! Closing.");
+ conn:close();
+ return;
+ end
+ pending_connections_map[conn] = nil;
+ p:log("debug", "Successfully connected");
+ if p.listeners.onattach then
+ p.listeners.onattach(conn, p.data);
+ end
+ conn:setlistener(p.listeners);
+ return p.listeners.onconnect(conn);
+end
+
+function pending_connection_listeners.ondisconnect(conn, reason)
+ local p = pending_connections_map[conn];
+ if not p then
+ log("warn", "Failed connection, but unexpected!");
+ return;
+ end
+ p:log("debug", "Connection attempt failed");
+ attempt_connection(p);
+end
+
+local function connect(target_resolver, listeners, options, data)
+ local p = setmetatable({
+ id = new_id();
+ target_resolver = target_resolver;
+ listeners = assert(listeners);
+ options = options or {};
+ cb = cb;
+ }, pending_connection_mt);
+
+ p:log("debug", "Starting connection process");
+ attempt_connection(p);
+end
+
+return {
+ connect = connect;
+};