Mercurial > prosody-hg
comparison 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 |
| parents | 876171084ea3 |
| children | 276f62d14437 |
comparison
equal
deleted
inserted
replaced
| 10464:8d3acf16c404 | 10465:09697a673015 |
|---|---|
| 1 module:set_global(); | 1 module:set_global(); |
| 2 | 2 |
| 3 local array = require "util.array"; | |
| 3 local max_buffer_len = module:get_option_number("multiplex_buffer_size", 1024); | 4 local max_buffer_len = module:get_option_number("multiplex_buffer_size", 1024); |
| 4 | 5 |
| 5 local portmanager = require "core.portmanager"; | 6 local portmanager = require "core.portmanager"; |
| 6 | 7 |
| 7 local available_services = {}; | 8 local available_services = {}; |
| 9 local service_by_protocol = {}; | |
| 10 local available_protocols = array(); | |
| 8 | 11 |
| 9 local function add_service(service) | 12 local function add_service(service) |
| 10 local multiplex_pattern = service.multiplex and service.multiplex.pattern; | 13 local multiplex_pattern = service.multiplex and service.multiplex.pattern; |
| 14 local protocol_name = service.multiplex and service.multiplex.protocol; | |
| 15 if protocol_name then | |
| 16 module:log("debug", "Adding multiplex service %q with protocol %q", service.name, protocol_name); | |
| 17 service_by_protocol[protocol_name] = service; | |
| 18 available_protocols:push(protocol_name); | |
| 19 end | |
| 11 if multiplex_pattern then | 20 if multiplex_pattern then |
| 12 module:log("debug", "Adding multiplex service %q with pattern %q", service.name, multiplex_pattern); | 21 module:log("debug", "Adding multiplex service %q with pattern %q", service.name, multiplex_pattern); |
| 13 available_services[service] = multiplex_pattern; | 22 available_services[service] = multiplex_pattern; |
| 14 else | 23 elseif not protocol_name then |
| 15 module:log("debug", "Service %q is not multiplex-capable", service.name); | 24 module:log("debug", "Service %q is not multiplex-capable", service.name); |
| 16 end | 25 end |
| 26 module:log("info", "available_protocols = %q", available_protocols); | |
| 17 end | 27 end |
| 18 module:hook("service-added", function (event) add_service(event.service); end); | 28 module:hook("service-added", function (event) add_service(event.service); end); |
| 19 module:hook("service-removed", function (event) available_services[event.service] = nil; end); | 29 module:hook("service-removed", function (event) |
| 30 available_services[event.service] = nil; | |
| 31 if event.service.multiplex and event.service.multiplex.protocol then | |
| 32 available_protocols:filter(function (p) return p ~= event.service.multiplex.protocol end); | |
| 33 service_by_protocol[event.service.multiplex.protocol] = nil; | |
| 34 end | |
| 35 end); | |
| 20 | 36 |
| 21 for _, services in pairs(portmanager.get_registered_services()) do | 37 for _, services in pairs(portmanager.get_registered_services()) do |
| 22 for _, service in ipairs(services) do | 38 for _, service in ipairs(services) do |
| 23 add_service(service); | 39 add_service(service); |
| 24 end | 40 end |
| 26 | 42 |
| 27 local buffers = {}; | 43 local buffers = {}; |
| 28 | 44 |
| 29 local listener = { default_mode = "*a" }; | 45 local listener = { default_mode = "*a" }; |
| 30 | 46 |
| 31 function listener.onconnect() | 47 function listener.onconnect(conn) |
| 48 local sock = conn:socket(); | |
| 49 if sock.getalpn then | |
| 50 local selected_proto = sock:getalpn(); | |
| 51 module:log("debug", "ALPN selected is %s", selected_proto); | |
| 52 local service = service_by_protocol[selected_proto]; | |
| 53 if service then | |
| 54 module:log("debug", "Routing incoming connection to %s", service.name); | |
| 55 local next_listener = service.listener; | |
| 56 conn:setlistener(next_listener); | |
| 57 local onconnect = next_listener.onconnect; | |
| 58 if onconnect then return onconnect(conn) end | |
| 59 end | |
| 60 end | |
| 32 end | 61 end |
| 33 | 62 |
| 34 function listener.onincoming(conn, data) | 63 function listener.onincoming(conn, data) |
| 35 if not data then return; end | 64 if not data then return; end |
| 36 local buf = buffers[conn]; | 65 local buf = buffers[conn]; |
| 66 | 95 |
| 67 module:provides("net", { | 96 module:provides("net", { |
| 68 name = "multiplex_ssl"; | 97 name = "multiplex_ssl"; |
| 69 config_prefix = "ssl"; | 98 config_prefix = "ssl"; |
| 70 encryption = "ssl"; | 99 encryption = "ssl"; |
| 100 ssl_config = { | |
| 101 alpn = function () | |
| 102 return available_protocols; | |
| 103 end; | |
| 104 }; | |
| 71 listener = listener; | 105 listener = listener; |
| 72 }); | 106 }); |
