1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
module:set_global();
local max_buffer_len = module:get_option_number("multiplex_buffer_size", 1024);
local portmanager = require "core.portmanager";
local available_services = {};
local function add_service(service)
local multiplex_pattern = service.multiplex and service.multiplex.pattern;
if multiplex_pattern then
module:log("debug", "Adding multiplex service %q with pattern %q", service.name, multiplex_pattern);
available_services[service] = multiplex_pattern;
else
module:log("debug", "Service %q is not multiplex-capable", service.name);
end
end
module:hook("service-added", function (event) add_service(event.service); end);
module:hook("service-removed", function (event) available_services[event.service] = nil; end);
for service_name, services in pairs(portmanager.get_registered_services()) do
for i, service in ipairs(services) do
add_service(service);
end
end
local buffers = {};
local listener = { default_mode = "*a" };
function listener.onconnect()
end
function listener.onincoming(conn, data)
if not data then return; end
local buf = buffers[conn];
buf = buf and buf..data or data;
for service, multiplex_pattern in pairs(available_services) do
if buf:match(multiplex_pattern) then
module:log("debug", "Routing incoming connection to %s", service.name);
local listener = service.listener;
conn:setlistener(listener);
local onconnect = listener.onconnect;
if onconnect then onconnect(conn) end
return listener.onincoming(conn, buf);
end
end
if #buf > max_buffer_len then -- Give up
conn:close();
else
buffers[conn] = buf;
end
end
function listener.ondisconnect(conn, err)
buffers[conn] = nil; -- warn if no buffer?
end
listener.ondetach = listener.ondisconnect;
module:provides("net", {
name = "multiplex";
config_prefix = "";
listener = listener;
});
module:provides("net", {
name = "multiplex_ssl";
config_prefix = "ssl";
encryption = "ssl";
listener = listener;
});
|