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 });