comparison core/portmanager.lua @ 11200:bf8f2da84007

Merge 0.11->trunk
author Kim Alvefur <zash@zash.se>
date Thu, 05 Nov 2020 22:31:25 +0100
parents 85f1cbfd364a
children 77785c5d6773
comparison
equal deleted inserted replaced
11199:6c7c50a4de32 11200:bf8f2da84007
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
161 end 168 end
162 169
163 local function register_service(service_name, service_info) 170 local function register_service(service_name, service_info)
164 table.insert(services[service_name], service_info); 171 table.insert(services[service_name], service_info);
165 172
166 if not active_services:get(service_name) then 173 if not active_services:get(service_name) and prosody.process_type == "prosody" then
167 log("debug", "No active service for %s, activating...", service_name); 174 log("debug", "No active service for %s, activating...", service_name);
168 local ok, err = activate(service_name); 175 local ok, err = activate(service_name);
169 if not ok then 176 if not ok then
170 log("error", "Failed to activate service '%s': %s", service_name, err or "unknown error"); 177 log("error", "Failed to activate service '%s': %s", service_name, err or "unknown error");
171 end 178 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 for name, interface, port, n, active_service --luacheck: ignore 213
234 in active_services:iter(service, nil, nil, nil) do
235 if active_service.server.hosts and active_service.tls_cfg then
236 local config_prefix = (active_service.config_prefix or name).."_";
237 if config_prefix == "_" then config_prefix = ""; end
238 local prefix_ssl_config = config.get(host, config_prefix.."ssl");
239 local autocert = certmanager.find_host_cert(host);
240 -- luacheck: ignore 211/cfg
241 local ssl, err, cfg = certmanager.create_context(host, "server", prefix_ssl_config, autocert, active_service.tls_cfg);
242 if ssl then
243 active_service.server.hosts[host] = ssl;
244 else
245 log("error", "Error creating TLS context for SNI host %s: %s", host, err);
246 end
247 end
248 end
249 end
225 prosody.events.add_handler("item-added/net-provider", function (event) 250 prosody.events.add_handler("item-added/net-provider", function (event)
226 local item = event.item; 251 local item = event.item;
227 register_service(item.name, item); 252 register_service(item.name, item);
253 for host in pairs(prosody.hosts) do
254 add_sni_host(host, item.name);
255 end
228 end); 256 end);
229 prosody.events.add_handler("item-removed/net-provider", function (event) 257 prosody.events.add_handler("item-removed/net-provider", function (event)
230 local item = event.item; 258 local item = event.item;
231 unregister_service(item.name, item); 259 unregister_service(item.name, item);
260 end);
261
262 prosody.events.add_handler("host-activated", add_sni_host);
263 prosody.events.add_handler("host-deactivated", function (host)
264 for name, interface, port, n, active_service --luacheck: ignore 213
265 in active_services:iter(nil, nil, nil, nil) do
266 if active_service.tls_cfg then
267 active_service.server.hosts[host] = nil;
268 end
269 end
232 end); 270 end);
233 271
234 return { 272 return {
235 activate = activate; 273 activate = activate;
236 deactivate = deactivate; 274 deactivate = deactivate;