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