comparison core/portmanager.lua @ 10411:db2a06b9ff98

Merge 0.11->trunk
author Kim Alvefur <zash@zash.se>
date Sat, 16 Nov 2019 16:52:31 +0100
parents 1dbabbebb53c
children 9af6ab2623b0
comparison
equal deleted inserted replaced
10410:659b577f280c 10411:db2a06b9ff98
7 local multitable = require "util.multitable"; 7 local multitable = require "util.multitable";
8 local set = require "util.set"; 8 local set = require "util.set";
9 9
10 local table = table; 10 local table = table;
11 local setmetatable, rawset, rawget = setmetatable, rawset, rawget; 11 local setmetatable, rawset, rawget = setmetatable, rawset, rawget;
12 local type, tonumber, tostring, ipairs = type, tonumber, tostring, ipairs; 12 local type, tonumber, ipairs = type, tonumber, ipairs;
13 local pairs = pairs;
13 14
14 local prosody = prosody; 15 local prosody = prosody;
15 local fire_event = prosody.events.fire_event; 16 local fire_event = prosody.events.fire_event;
16 17
17 local _ENV = nil; 18 local _ENV = nil;
93 or {service_info.default_port 94 or {service_info.default_port
94 or listener.default_port -- COMPAT w/pre-0.9 95 or listener.default_port -- COMPAT w/pre-0.9
95 } 96 }
96 bind_ports = set.new(type(bind_ports) ~= "table" and { bind_ports } or bind_ports ); 97 bind_ports = set.new(type(bind_ports) ~= "table" and { bind_ports } or bind_ports );
97 98
98 local mode, ssl = listener.default_mode or default_mode; 99 local mode = listener.default_mode or default_mode;
99 local hooked_ports = {}; 100 local hooked_ports = {};
100 101
101 for interface in bind_interfaces do 102 for interface in bind_interfaces do
102 for port in bind_ports do 103 for port in bind_ports do
103 local port_number = tonumber(port); 104 local port_number = tonumber(port);
104 if not port_number then 105 if not port_number then
105 log("error", "Invalid port number specified for service '%s': %s", service_info.name, tostring(port)); 106 log("error", "Invalid port number specified for service '%s': %s", service_info.name, port);
106 elseif #active_services:search(nil, interface, port_number) > 0 then 107 elseif #active_services:search(nil, interface, port_number) > 0 then
107 log("error", "Multiple services configured to listen on the same port ([%s]:%d): %s, %s", interface, port, 108 log("error", "Multiple services configured to listen on the same port ([%s]:%d): %s, %s", interface, port,
108 active_services:search(nil, interface, port)[1][1].service.name or "<unnamed>", service_name or "<unnamed>"); 109 active_services:search(nil, interface, port)[1][1].service.name or "<unnamed>", service_name or "<unnamed>");
109 else 110 else
110 local err; 111 local ssl, cfg, err;
111 -- Create SSL context for this service/port 112 -- Create SSL context for this service/port
112 if service_info.encryption == "ssl" then 113 if service_info.encryption == "ssl" then
113 local global_ssl_config = config.get("*", "ssl") or {}; 114 local global_ssl_config = config.get("*", "ssl") or {};
114 local prefix_ssl_config = config.get("*", config_prefix.."ssl") or global_ssl_config; 115 local prefix_ssl_config = config.get("*", config_prefix.."ssl") or global_ssl_config;
115 log("debug", "Creating context for direct TLS service %s on port %d", service_info.name, port); 116 log("debug", "Creating context for direct TLS service %s on port %d", service_info.name, port);
116 ssl, err = certmanager.create_context(service_info.name.." port "..port, "server", 117 ssl, err, cfg = certmanager.create_context(service_info.name.." port "..port, "server",
117 prefix_ssl_config[interface], 118 prefix_ssl_config[interface],
118 prefix_ssl_config[port], 119 prefix_ssl_config[port],
119 prefix_ssl_config, 120 prefix_ssl_config,
120 service_info.ssl_config or {}, 121 service_info.ssl_config or {},
121 global_ssl_config[interface], 122 global_ssl_config[interface],
125 error_to_friendly_message(service_name, port_number, err) or "unknown error"); 126 error_to_friendly_message(service_name, port_number, err) or "unknown error");
126 end 127 end
127 end 128 end
128 if not err then 129 if not err then
129 -- Start listening on interface+port 130 -- Start listening on interface+port
130 local handler, err = server.addserver(interface, port_number, listener, mode, ssl); 131 local handler, err = server.listen(interface, port_number, listener, {
132 read_size = mode,
133 tls_ctx = ssl,
134 tls_direct = service_info.encryption == "ssl";
135 sni_hosts = {},
136 });
131 if not handler then 137 if not handler then
132 log("error", "Failed to open server port %d on %s, %s", port_number, interface, 138 log("error", "Failed to open server port %d on %s, %s", port_number, interface,
133 error_to_friendly_message(service_name, port_number, err)); 139 error_to_friendly_message(service_name, port_number, err));
134 else 140 else
135 table.insert(hooked_ports, "["..interface.."]:"..port_number); 141 table.insert(hooked_ports, "["..interface.."]:"..port_number);
136 log("debug", "Added listening service %s to [%s]:%d", service_name, interface, port_number); 142 log("debug", "Added listening service %s to [%s]:%d", service_name, interface, port_number);
137 active_services:add(service_name, interface, port_number, { 143 active_services:add(service_name, interface, port_number, {
138 server = handler; 144 server = handler;
139 service = service_info; 145 service = service_info;
146 tls_cfg = cfg;
140 }); 147 });
141 end 148 end
142 end 149 end
143 end 150 end
144 end 151 end
220 return services; 227 return services;
221 end 228 end
222 229
223 -- Event handlers 230 -- Event handlers
224 231
232 local function add_sni_host(host, service)
233 -- local global_ssl_config = config.get(host, "ssl") or {};
234 for name, interface, port, n, active_service --luacheck: ignore 213
235 in active_services:iter(service, nil, nil, nil) do
236 if active_service.server.hosts and active_service.tls_cfg then
237 -- local config_prefix = (active_service.config_prefix or name).."_";
238 -- if config_prefix == "_" then
239 -- config_prefix = "";
240 -- end
241 -- local prefix_ssl_config = config.get(host, config_prefix.."ssl") or global_ssl_config;
242 -- FIXME only global 'ssl' settings are mixed in here
243 -- TODO per host and per service settings should be merged in,
244 -- without overriding the per-host certificate
245 local ssl, err, cfg = certmanager.create_context(host, "server");
246 if ssl then
247 active_service.server.hosts[host] = ssl;
248 if not active_service.tls_cfg.certificate then
249 active_service.server.tls_ctx = ssl;
250 active_service.tls_cfg = cfg;
251 end
252 else
253 log("error", "err = %q", err);
254 end
255 end
256 end
257 end
225 prosody.events.add_handler("item-added/net-provider", function (event) 258 prosody.events.add_handler("item-added/net-provider", function (event)
226 local item = event.item; 259 local item = event.item;
227 register_service(item.name, item); 260 register_service(item.name, item);
261 for host in pairs(prosody.hosts) do
262 add_sni_host(host, item.name);
263 end
228 end); 264 end);
229 prosody.events.add_handler("item-removed/net-provider", function (event) 265 prosody.events.add_handler("item-removed/net-provider", function (event)
230 local item = event.item; 266 local item = event.item;
231 unregister_service(item.name, item); 267 unregister_service(item.name, item);
268 end);
269
270 prosody.events.add_handler("host-activated", add_sni_host);
271 prosody.events.add_handler("host-deactivated", function (host)
272 for name, interface, port, n, active_service --luacheck: ignore 213
273 in active_services:iter(nil, nil, nil, nil) do
274 if active_service.tls_cfg then
275 active_service.server.hosts[host] = nil;
276 end
277 end
232 end); 278 end);
233 279
234 return { 280 return {
235 activate = activate; 281 activate = activate;
236 deactivate = deactivate; 282 deactivate = deactivate;