Diff

plugins/mod_net_multiplex.lua @ 11120:b2331f3dfeea

Merge 0.11->trunk
author Matthew Wild <mwild1@gmail.com>
date Wed, 30 Sep 2020 09:50:33 +0100
parent 11024:1c7602c70d1f
child 12977:74b9e05af71e
line wrap: on
line diff
--- a/plugins/mod_net_multiplex.lua	Thu Oct 01 15:08:58 2020 +0100
+++ b/plugins/mod_net_multiplex.lua	Wed Sep 30 09:50:33 2020 +0100
@@ -1,22 +1,38 @@
 module:set_global();
 
+local array = require "util.array";
 local max_buffer_len = module:get_option_number("multiplex_buffer_size", 1024);
+local default_mode = module:get_option_number("network_default_read_size", 4096);
 
 local portmanager = require "core.portmanager";
 
 local available_services = {};
+local service_by_protocol = {};
+local available_protocols = array();
 
 local function add_service(service)
 	local multiplex_pattern = service.multiplex and service.multiplex.pattern;
+	local protocol_name = service.multiplex and service.multiplex.protocol;
+	if protocol_name then
+		module:log("debug", "Adding multiplex service %q with protocol %q", service.name, protocol_name);
+		service_by_protocol[protocol_name] = service;
+		available_protocols:push(protocol_name);
+	end
 	if multiplex_pattern then
 		module:log("debug", "Adding multiplex service %q with pattern %q", service.name, multiplex_pattern);
 		available_services[service] = multiplex_pattern;
-	else
+	elseif not protocol_name then
 		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);
+module:hook("service-removed", function (event)
+	available_services[event.service] = nil;
+	if event.service.multiplex and event.service.multiplex.protocol then
+		available_protocols:filter(function (p) return p ~= event.service.multiplex.protocol end);
+		service_by_protocol[event.service.multiplex.protocol] = nil;
+	end
+end);
 
 for _, services in pairs(portmanager.get_registered_services()) do
 	for _, service in ipairs(services) do
@@ -26,9 +42,22 @@
 
 local buffers = {};
 
-local listener = { default_mode = "*a" };
+local listener = { default_mode = max_buffer_len };
 
-function listener.onconnect()
+function listener.onconnect(conn)
+	local sock = conn:socket();
+	if sock.getalpn then
+		local selected_proto = sock:getalpn();
+		local service = service_by_protocol[selected_proto];
+		if service then
+			module:log("debug", "Routing incoming connection to %s based on ALPN %q", service.name, selected_proto);
+			local next_listener = service.listener;
+			conn:setlistener(next_listener);
+			conn:set_mode(next_listener.default_mode or default_mode);
+			local onconnect = next_listener.onconnect;
+			if onconnect then return onconnect(conn) end
+		end
+	end
 end
 
 function listener.onincoming(conn, data)
@@ -40,6 +69,7 @@
 			module:log("debug", "Routing incoming connection to %s", service.name);
 			local next_listener = service.listener;
 			conn:setlistener(next_listener);
+			conn:set_mode(next_listener.default_mode or default_mode);
 			local onconnect = next_listener.onconnect;
 			if onconnect then onconnect(conn) end
 			return next_listener.onincoming(conn, buf);
@@ -68,5 +98,10 @@
 	name = "multiplex_ssl";
 	config_prefix = "ssl";
 	encryption = "ssl";
+	ssl_config = {
+		alpn = function ()
+			return available_protocols;
+		end;
+	};
 	listener = listener;
 });