Mercurial > prosody-hg
comparison net/connect.lua @ 8531:601681acea73
net.connect: New API for outgoing connections, based on 'service resolvers'
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Fri, 23 Feb 2018 15:53:45 +0000 |
| parents | |
| children | c3f234e4ac23 |
comparison
equal
deleted
inserted
replaced
| 8530:075df839c110 | 8531:601681acea73 |
|---|---|
| 1 local server = require "net.server"; | |
| 2 local log = require "util.logger".init("net.connect"); | |
| 3 local new_id = require "util.id".short; | |
| 4 | |
| 5 local pending_connection_methods = {}; | |
| 6 local pending_connection_mt = { | |
| 7 __name = "pending_connection"; | |
| 8 __index = pending_connection_methods; | |
| 9 __tostring = function (p) | |
| 10 return "<pending connection "..p.id.." to "..tostring(p.target_resolver.hostname)..">"; | |
| 11 end; | |
| 12 }; | |
| 13 | |
| 14 function pending_connection_methods:log(level, message, ...) | |
| 15 log(level, "[pending connection %s] "..message, self.id, ...); | |
| 16 end | |
| 17 | |
| 18 -- pending_connections_map[conn] = pending_connection | |
| 19 local pending_connections_map = {}; | |
| 20 | |
| 21 local pending_connection_listeners = {}; | |
| 22 | |
| 23 local function attempt_connection(p) | |
| 24 p:log("debug", "Checking for targets..."); | |
| 25 if p.conn then | |
| 26 pending_connections_map[p.conn] = nil; | |
| 27 p.conn = nil; | |
| 28 end | |
| 29 p.target_resolver:next(function (conn_type, ip, port, extra) | |
| 30 p:log("debug", "Next target to try is %s:%d", ip, port); | |
| 31 local conn = assert(server.addclient(ip, port, pending_connection_listeners, p.options.pattern, p.options.sslctx, conn_type, extra)); | |
| 32 p.conn = conn; | |
| 33 pending_connections_map[conn] = p; | |
| 34 end); | |
| 35 end | |
| 36 | |
| 37 function pending_connection_listeners.onconnect(conn) | |
| 38 local p = pending_connections_map[conn]; | |
| 39 if not p then | |
| 40 log("warn", "Successful connection, but unexpected! Closing."); | |
| 41 conn:close(); | |
| 42 return; | |
| 43 end | |
| 44 pending_connections_map[conn] = nil; | |
| 45 p:log("debug", "Successfully connected"); | |
| 46 if p.listeners.onattach then | |
| 47 p.listeners.onattach(conn, p.data); | |
| 48 end | |
| 49 conn:setlistener(p.listeners); | |
| 50 return p.listeners.onconnect(conn); | |
| 51 end | |
| 52 | |
| 53 function pending_connection_listeners.ondisconnect(conn, reason) | |
| 54 local p = pending_connections_map[conn]; | |
| 55 if not p then | |
| 56 log("warn", "Failed connection, but unexpected!"); | |
| 57 return; | |
| 58 end | |
| 59 p:log("debug", "Connection attempt failed"); | |
| 60 attempt_connection(p); | |
| 61 end | |
| 62 | |
| 63 local function connect(target_resolver, listeners, options, data) | |
| 64 local p = setmetatable({ | |
| 65 id = new_id(); | |
| 66 target_resolver = target_resolver; | |
| 67 listeners = assert(listeners); | |
| 68 options = options or {}; | |
| 69 cb = cb; | |
| 70 }, pending_connection_mt); | |
| 71 | |
| 72 p:log("debug", "Starting connection process"); | |
| 73 attempt_connection(p); | |
| 74 end | |
| 75 | |
| 76 return { | |
| 77 connect = connect; | |
| 78 }; |
