aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/mod_net_multiplex.lua
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/mod_net_multiplex.lua')
-rw-r--r--plugins/mod_net_multiplex.lua70
1 files changed, 70 insertions, 0 deletions
diff --git a/plugins/mod_net_multiplex.lua b/plugins/mod_net_multiplex.lua
new file mode 100644
index 00000000..d666b907
--- /dev/null
+++ b/plugins/mod_net_multiplex.lua
@@ -0,0 +1,70 @@
+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];
+ buffers[conn] = nil;
+ 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
+
+module:provides("net", {
+ name = "multiplex";
+ config_prefix = "";
+ listener = listener;
+});
+
+module:provides("net", {
+ name = "multiplex_ssl";
+ config_prefix = "ssl";
+ listener = listener;
+});