1 local server
= require
"net.server";
2 local log = require
"util.logger".init("net.connect");
3 local new_id
= require
"util.id".short
;
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
)..">";
14 function pending_connection_methods
:log(level
, message
, ...)
15 log(level
, "[pending connection %s] "..message
, self
.id
, ...);
18 -- pending_connections_map[conn] = pending_connection
19 local pending_connections_map
= {};
21 local pending_connection_listeners
= {};
23 local function attempt_connection(p
)
24 p
:log("debug", "Checking for targets...");
26 pending_connections_map
[p
.conn
] = nil;
29 p
.target_resolver
:next(function (conn_type
, ip
, port
, extra
)
31 -- No more targets to try
32 p
:log("debug", "No more connection targets to try");
33 if p
.listeners
.onfail
then
34 p
.listeners
.onfail(p
.data
, p
.last_error
or "unable to resolve service");
38 p
:log("debug", "Next target to try is %s:%d", ip
, port
);
39 local conn
, err
= server
.addclient(ip
, port
, pending_connection_listeners
, p
.options
.pattern
or "*a", p
.options
.sslctx
, conn_type
, extra
);
41 log("debug", "Connection attempt failed immediately: %s", err
);
42 p
.last_error
= err
or "unknown reason";
43 return attempt_connection(p
);
46 pending_connections_map
[conn
] = p
;
50 function pending_connection_listeners
.onconnect(conn
)
51 local p
= pending_connections_map
[conn
];
53 log("warn", "Successful connection, but unexpected! Closing.");
57 pending_connections_map
[conn
] = nil;
58 p
:log("debug", "Successfully connected");
59 conn
:setlistener(p
.listeners
, p
.data
);
60 return p
.listeners
.onconnect(conn
);
63 function pending_connection_listeners
.ondisconnect(conn
, reason
)
64 local p
= pending_connections_map
[conn
];
66 log("warn", "Failed connection, but unexpected!");
69 p
.last_error
= reason
or "unknown reason";
70 p
:log("debug", "Connection attempt failed: %s", p
.last_error
);
71 attempt_connection(p
);
74 local function connect(target_resolver
, listeners
, options
, data
)
75 local p
= setmetatable({
77 target_resolver
= target_resolver
;
78 listeners
= assert(listeners
);
79 options
= options
or {};
81 }, pending_connection_mt
);
83 p
:log("debug", "Starting connection process");
84 attempt_connection(p
);