Software /
code /
prosody
Diff
plugins/mod_net_multiplex.lua @ 10465:09697a673015
mod_net_multiplex: Add support for using ALPN
Potentially a bit more efficient since it can jump to the selected
protocol on connect instead of waiting for some data to look at.
Adds a 'protocol' field to net providers for this purpose.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Fri, 29 Nov 2019 23:27:51 +0100 |
parent | 9465:876171084ea3 |
child | 10466:276f62d14437 |
line wrap: on
line diff
--- a/plugins/mod_net_multiplex.lua Fri Nov 29 23:25:59 2019 +0100 +++ b/plugins/mod_net_multiplex.lua Fri Nov 29 23:27:51 2019 +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 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 + module:log("info", "available_protocols = %q", available_protocols); 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 @@ -28,7 +44,20 @@ local listener = { default_mode = "*a" }; -function listener.onconnect() +function listener.onconnect(conn) + local sock = conn:socket(); + if sock.getalpn then + local selected_proto = sock:getalpn(); + module:log("debug", "ALPN selected is %s", selected_proto); + local service = service_by_protocol[selected_proto]; + if service then + module:log("debug", "Routing incoming connection to %s", service.name); + local next_listener = service.listener; + conn:setlistener(next_listener); + local onconnect = next_listener.onconnect; + if onconnect then return onconnect(conn) end + end + end end function listener.onincoming(conn, data) @@ -68,5 +97,10 @@ name = "multiplex_ssl"; config_prefix = "ssl"; encryption = "ssl"; + ssl_config = { + alpn = function () + return available_protocols; + end; + }; listener = listener; });