diff options
Diffstat (limited to 'core/portmanager.lua')
-rw-r--r-- | core/portmanager.lua | 59 |
1 files changed, 43 insertions, 16 deletions
diff --git a/core/portmanager.lua b/core/portmanager.lua index c5bb936a..00f09c6b 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -1,7 +1,20 @@ +local config = require "core.configmanager"; +local certmanager = require "core.certmanager"; +local server = require "net.server"; +local log = require "util.logger".init("portmanager"); local multitable = require "util.multitable"; +local set = require "util.set"; + +local table = table; +local setmetatable, rawset, rawget = setmetatable, rawset, rawget; +local type, tonumber, ipairs, pairs = type, tonumber, ipairs, pairs; + +local prosody = prosody; local fire_event = prosody.events.fire_event; +module "portmanager"; + --- Config local default_interfaces = { "*" }; @@ -50,8 +63,6 @@ local function error_to_friendly_message(service_name, port, err) return friendly_message; end -module("portmanager", package.seeall); - prosody.events.add_handler("item-added/net-provider", function (event) local item = event.item; register_service(item.name, item); @@ -63,7 +74,7 @@ end); --- Public API -function activate_service(service_name) +function activate(service_name) local service_info = services[service_name][1]; if not service_info then return nil, "Unknown service: "..service_name; @@ -76,13 +87,14 @@ function activate_service(service_name) config_prefix = ""; end - local bind_interfaces = set.new(config.get("*", config_prefix.."interfaces") + local bind_interfaces = config.get("*", config_prefix.."interfaces") or config.get("*", config_prefix.."interface") -- COMPAT w/pre-0.9 or (service_info.private and default_local_interfaces) or config.get("*", "interfaces") or config.get("*", "interface") -- COMPAT w/pre-0.9 or listener.default_interface -- COMPAT w/pre0.9 - or default_interfaces); + or default_interfaces + bind_interfaces = set.new(type(bind_interfaces)~="table" and {bind_interfaces} or bind_interfaces); local bind_ports = set.new(config.get("*", config_prefix.."ports") or service_info.default_ports @@ -91,19 +103,20 @@ function activate_service(service_name) }); local mode = listener.default_mode or "*a"; - local ssl; - if service_info.encryption == "ssl" then - ssl = prosody.global_ssl_ctx; - if not ssl then - return nil, "global-ssl-context-required"; - end - end for interface in bind_interfaces do for port in bind_ports do + port = tonumber(port); if #active_services:search(nil, interface, port) > 0 then log("error", "Multiple services configured to listen on the same port ([%s]:%d): %s, %s", interface, port, active_services:search(nil, interface, port)[1][1].service.name or "<unnamed>", service_name or "<unnamed>"); else + -- Create SSL context for this service/port + if service_info.encryption == "ssl" then + local ssl_config = config.get("*", config_prefix.."ssl"); + ssl = certmanager.create_context(service_info.name.." port "..port, "server", ssl_config and (ssl_config[port] + or (ssl_config.certificate and ssl_config))); + end + -- Start listening on interface+port local handler, err = server.addserver(interface, port, listener, mode, ssl); if not handler then log("error", "Failed to open server port %d on %s, %s", port, interface, error_to_friendly_message(service_name, port, err)); @@ -126,9 +139,7 @@ function deactivate(service_name) if not active then return; end for interface, ports in pairs(active) do for port, active_service in pairs(ports) do - active_service:close(); - active_services:remove(service_name, interface, port, active_service); - log("debug", "Removed listening service %s from [%s]:%d", service_name, interface, port); + close(interface, port); end end log("info", "Deactivated service '%s'", service_name); @@ -139,7 +150,7 @@ function register_service(service_name, service_info) if not active_services:get(service_name) then log("debug", "No active service for %s, activating...", service_name); - local ok, err = activate_service(service_name); + local ok, err = activate(service_name); if not ok then log("error", "Failed to activate service '%s': %s", service_name, err or "unknown error"); end @@ -165,6 +176,22 @@ function unregister_service(service_name, service_info) fire_event("service-removed", { name = service_name, service = service_info }); end +function close(interface, port) + local service, server = get_service_at(interface, port); + if not service then + return false, "port-not-open"; + end + server:close(); + active_services:remove(service.name, interface, port); + log("debug", "Removed listening service %s from [%s]:%d", service.name, interface, port); + return true; +end + +function get_service_at(interface, port) + local data = active_services:search(nil, interface, port)[1][1]; + return data.service, data.server; +end + function get_service(service_name) return services[service_name]; end |