Merge 0.6->0.7
[prosody.git] / prosody
diff --git a/prosody b/prosody
index 52251dacb31c42ffb9dd1ec282aad2f6227f81c7..0bcfce4b3f5ca696eb2b54f7fc2574c43a9bc36c 100755 (executable)
--- a/prosody
+++ b/prosody
@@ -1,7 +1,7 @@
 #!/usr/bin/env lua
 -- Prosody IM
--- Copyright (C) 2008-2009 Matthew Wild
--- Copyright (C) 2008-2009 Waqas Hussain
+-- Copyright (C) 2008-2010 Matthew Wild
+-- Copyright (C) 2008-2010 Waqas Hussain
 -- 
 -- This project is MIT/X11 licensed. Please see the
 -- COPYING file in the source package for more information.
@@ -32,29 +32,6 @@ if CFG_DATADIR then
        end
 end
 
--- Required to be able to find packages installed with luarocks
-pcall(require, "luarocks.require");
-
--- Replace require() with one that doesn't pollute _G, required
--- for neat sandboxing of modules
-do
-       local _realG = _G;
-       local _real_require = require;
-       function require(...)
-               local curr_env = getfenv(2);
-               local curr_env_mt = getmetatable(getfenv(2));
-               local _realG_mt = getmetatable(_realG);
-               if curr_env_mt and curr_env_mt.__index and not curr_env_mt.__newindex and _realG_mt then
-                       local old_newindex
-                       old_newindex, _realG_mt.__newindex = _realG_mt.__newindex, curr_env;
-                       local ret = _real_require(...);
-                       _realG_mt.__newindex = old_newindex;
-                       return ret;
-               end
-               return _real_require(...);
-       end
-end
-
 -- Load the config-parsing module
 config = require "core.configmanager"
 
@@ -110,17 +87,68 @@ function read_config()
 end
 
 function load_libraries()
+       -- Load socket framework
+       server = require "net.server"
+end    
+
+function init_logging()
        -- Initialize logging
        require "core.loggingmanager"
-       
+end
+
+function check_dependencies()
        -- Check runtime dependencies
        if not require "util.dependencies".check_dependencies() then
                os.exit(1);
        end
-       
-       -- Load socket framework
-       server = require "net.server"
-end    
+end
+
+function sandbox_require()
+       -- Replace require() with one that doesn't pollute _G, required
+       -- for neat sandboxing of modules
+       local _realG = _G;
+       local _real_require = require;
+       function require(...)
+               local curr_env = getfenv(2);
+               local curr_env_mt = getmetatable(getfenv(2));
+               local _realG_mt = getmetatable(_realG);
+               if curr_env_mt and curr_env_mt.__index and not curr_env_mt.__newindex and _realG_mt then
+                       local old_newindex
+                       old_newindex, _realG_mt.__newindex = _realG_mt.__newindex, curr_env;
+                       local ret = _real_require(...);
+                       _realG_mt.__newindex = old_newindex;
+                       return ret;
+               end
+               return _real_require(...);
+       end
+end
+
+function set_function_metatable()
+       local mt = {};
+       function mt.__index(f, upvalue)
+               local i, name, value = 0;
+               repeat
+                       i = i + 1;
+                       name, value = debug.getupvalue(f, i);
+               until name == upvalue or name == nil;
+               return value;
+       end
+       function mt.__newindex(f, upvalue, value)
+               local i, name = 0;
+               repeat
+                       i = i + 1;
+                       name = debug.getupvalue(f, i);
+               until name == upvalue or name == nil;
+               if name then
+                       debug.setupvalue(f, i, value);
+               end
+       end
+       function mt.__tostring(f)
+               local info = debug.getinfo(f);
+               return ("function(%s:%d)"):format(info.short_src:match("[^\\/]*$"), info.linedefined);
+       end
+       debug.setmetatable(function() end, mt);
+end
 
 function init_global_state()
        bare_sessions = {};
@@ -185,12 +213,9 @@ function init_global_state()
        end
 
        -- Load SSL settings from config, and create a ctx table
-       local global_ssl_ctx = rawget(_G, "ssl") and config.get("*", "core", "ssl");
-       if global_ssl_ctx then
-               local default_ssl_ctx = { mode = "server", protocol = "sslv23", capath = "/etc/ssl/certs", verify = "none", options = "no_sslv2" };
-               setmetatable(global_ssl_ctx, { __index = default_ssl_ctx });
-               prosody.global_ssl_ctx = global_ssl_ctx;
-       end
+       local certmanager = require "core.certmanager";
+       local global_ssl_ctx = certmanager.create_context("*", "server");
+       prosody.global_ssl_ctx = global_ssl_ctx;
 
        local cl = require "net.connlisteners";
        function prosody.net_activate_ports(option, listener, default, conntype)
@@ -208,14 +233,41 @@ function init_global_state()
                                if type(port) ~= "number" then
                                        log("error", "Non-numeric "..ports_option..": "..tostring(port));
                                else
-                                       cl.start(listener, { 
-                                               ssl = conntype ~= "tcp" and global_ssl_ctx,
+                                       local ok, err = cl.start(listener, {
+                                               ssl = conntype == "ssl" and global_ssl_ctx,
                                                port = port,
                                                interface = (option and config.get("*", "core", option.."_interface"))
                                                        or cl.get(listener).default_interface
                                                        or config.get("*", "core", "interface"),
                                                type = conntype
                                        });
+                                       if not ok then
+                                               local friendly_message = err;
+                                               if err:match(" in use") then
+                                                       if port == 5222 or port == 5223 or port == 5269 then
+                                                               friendly_message = "check that Prosody or another XMPP server is "
+                                                                       .."not already running and using this port";
+                                                       elseif port == 80 or port == 81 then
+                                                               friendly_message = "check that a HTTP server is not already using "
+                                                                       .."this port";
+                                                       elseif port == 5280 then
+                                                               friendly_message = "check that Prosody or a BOSH connection manager "
+                                                                       .."is not already running";
+                                                       else
+                                                               friendly_message = "this port is in use by another application";
+                                                       end
+                                               elseif err:match("permission") then
+                                                       friendly_message = "Prosody does not have sufficient privileges to use this port";
+                                               elseif err == "no ssl context" then
+                                                       if not config.get("*", "core", "ssl") then
+                                                               friendly_message = "there is no 'ssl' config under Host \"*\" which is "
+                                                                       .."require for legacy SSL ports";
+                                                       else
+                                                               friendly_message = "initializing SSL support failed, see previous log entries";
+                                                       end
+                                               end
+                                               log("error", "Failed to open server port %d, %s", port, friendly_message);
+                                       end
                                end
                        end
                end
@@ -283,7 +335,7 @@ function init_data_store()
 end
 
 function prepare_to_start()
-       log("debug", "Prosody is using the %s backend for connection handling", server.get_backend());
+       log("info", "Prosody is using the %s backend for connection handling", server.get_backend());
        -- Signal to modules that we are ready to start
        eventmanager.fire_event("server-starting");
        prosody.events.fire_event("server-starting");
@@ -387,7 +439,13 @@ function cleanup()
 end
 
 -- Are you ready? :)
+-- These actions are in a strict order, as many depend on
+-- previous steps to have already been performed
 read_config();
+init_logging();
+check_dependencies();
+sandbox_require();
+set_function_metatable();
 load_libraries();
 init_global_state();
 read_version();