aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wild <mwild1@gmail.com>2012-07-28 01:14:31 +0100
committerMatthew Wild <mwild1@gmail.com>2012-07-28 01:14:31 +0100
commit81bef2c93b53e006cbeebdffc80040af6b4daf68 (patch)
tree2732225257e7b8ade28695dad7c0df3f7cea00b1
parent8eec29745633bd84c2d325d42dbeeb4afd37d516 (diff)
parent47619af14cd24fcb48b4d2b4c4653f72b882087e (diff)
downloadprosody-81bef2c93b53e006cbeebdffc80040af6b4daf68.tar.gz
prosody-81bef2c93b53e006cbeebdffc80040af6b4daf68.zip
Merge with Florob
-rw-r--r--TODO1
-rw-r--r--core/certmanager.lua11
-rw-r--r--core/loggingmanager.lua10
-rw-r--r--core/moduleapi.lua4
-rw-r--r--core/portmanager.lua35
-rw-r--r--core/rostermanager.lua12
-rw-r--r--core/s2smanager.lua8
-rw-r--r--core/sessionmanager.lua15
-rw-r--r--core/stanza_router.lua12
-rw-r--r--core/usermanager.lua4
-rw-r--r--net/http.lua5
-rw-r--r--net/server_event.lua37
-rw-r--r--net/server_select.lua59
-rw-r--r--plugins/adhoc/adhoc.lib.lua7
-rw-r--r--plugins/adhoc/mod_adhoc.lua1
-rw-r--r--plugins/mod_admin_adhoc.lua125
-rw-r--r--plugins/mod_admin_telnet.lua208
-rw-r--r--plugins/mod_announce.lua4
-rw-r--r--plugins/mod_auth_cyrus.lua4
-rw-r--r--plugins/mod_bosh.lua4
-rw-r--r--plugins/mod_c2s.lua38
-rw-r--r--plugins/mod_component.lua6
-rw-r--r--plugins/mod_dialback.lua10
-rw-r--r--plugins/mod_disco.lua2
-rw-r--r--plugins/mod_iq.lua5
-rw-r--r--plugins/mod_message.lua11
-rw-r--r--plugins/mod_motd.lua2
-rw-r--r--plugins/mod_pep.lua3
-rw-r--r--plugins/mod_posix.lua12
-rw-r--r--plugins/mod_presence.lua17
-rw-r--r--plugins/mod_pubsub.lua2
-rw-r--r--plugins/mod_register.lua4
-rw-r--r--plugins/mod_roster.lua2
-rw-r--r--plugins/mod_s2s/mod_s2s.lua75
-rw-r--r--plugins/mod_s2s/s2sout.lib.lua135
-rw-r--r--plugins/mod_saslauth.lua4
-rw-r--r--plugins/mod_vcard.lua13
-rw-r--r--plugins/mod_watchregistrations.lua2
-rw-r--r--plugins/mod_welcome.lua2
-rw-r--r--plugins/muc/mod_muc.lua38
-rw-r--r--plugins/muc/muc.lib.lua4
-rwxr-xr-xprosodyctl2
-rw-r--r--util-src/pposix.c67
-rw-r--r--util/dataforms.lua10
-rw-r--r--util/datamanager.lua18
-rw-r--r--util/logger.lua2
-rw-r--r--util/sasl.lua2
-rw-r--r--util/sasl_cyrus.lua8
-rw-r--r--util/stanza.lua4
-rw-r--r--util/throttle.lua3
50 files changed, 641 insertions, 428 deletions
diff --git a/TODO b/TODO
index a49bb52b..40e775a3 100644
--- a/TODO
+++ b/TODO
@@ -5,5 +5,6 @@
- Web interface
== 1.0 ==
+- Statistics
- Clustering
- World domination
diff --git a/core/certmanager.lua b/core/certmanager.lua
index d524a07e..20a6d609 100644
--- a/core/certmanager.lua
+++ b/core/certmanager.lua
@@ -11,14 +11,17 @@ local log = require "util.logger".init("certmanager");
local ssl = ssl;
local ssl_newcontext = ssl and ssl.newcontext;
-local setmetatable, tostring = setmetatable, tostring;
+local tostring = tostring;
local prosody = prosody;
local resolve_path = configmanager.resolve_relative_path;
local config_path = prosody.paths.config;
-local luasec_major, luasec_minor = ssl._VERSION:match("^(%d+)%.(%d+)");
-local luasec_has_noticket = tonumber(luasec_major)>0 or tonumber(luasec_minor)>=4;
+local luasec_has_noticket;
+if ssl then
+ local luasec_major, luasec_minor = ssl._VERSION:match("^(%d+)%.(%d+)");
+ luasec_has_noticket = tonumber(luasec_major)>0 or tonumber(luasec_minor)>=4;
+end
module "certmanager"
@@ -78,7 +81,7 @@ function create_context(host, mode, user_ssl_config)
else
reason = "Reason: "..tostring(reason):lower();
end
- log("error", "SSL/TLS: Failed to load %s: %s (for %s)", file, reason, host);
+ log("error", "SSL/TLS: Failed to load '%s': %s (for %s)", file, reason, host);
else
log("error", "SSL/TLS: Error initialising for %s: %s", host, err);
end
diff --git a/core/loggingmanager.lua b/core/loggingmanager.lua
index 56a3ee2c..ce25b0e8 100644
--- a/core/loggingmanager.lua
+++ b/core/loggingmanager.lua
@@ -7,14 +7,12 @@
--
-local format, rep = string.format, string.rep;
-local pcall = pcall;
-local debug = debug;
-local tostring, setmetatable, rawset, pairs, ipairs, type =
- tostring, setmetatable, rawset, pairs, ipairs, type;
+local format = string.format;
+local setmetatable, rawset, pairs, ipairs, type =
+ setmetatable, rawset, pairs, ipairs, type;
local io_open, io_write = io.open, io.write;
local math_max, rep = math.max, string.rep;
-local os_date, os_getenv = os.date, os.getenv;
+local os_date = os.date;
local getstyle, setstyle = require "util.termcolours".getstyle, require "util.termcolours".setstyle;
if os.getenv("__FLUSH_LOG") then
diff --git a/core/moduleapi.lua b/core/moduleapi.lua
index 2bcf9b84..54077826 100644
--- a/core/moduleapi.lua
+++ b/core/moduleapi.lua
@@ -14,8 +14,6 @@ local logger = require "util.logger";
local pluginloader = require "util.pluginloader";
local timer = require "util.timer";
-local multitable_new = require "util.multitable".new;
-
local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat;
local error, setmetatable, type = error, setmetatable, type;
local ipairs, pairs, select, unpack = ipairs, pairs, select, unpack;
@@ -338,4 +336,4 @@ function api:load_resource(path, mode)
return io.open(path, mode);
end
-return api;
+return api; \ No newline at end of file
diff --git a/core/portmanager.lua b/core/portmanager.lua
index b563fb10..3fcc8173 100644
--- a/core/portmanager.lua
+++ b/core/portmanager.lua
@@ -52,13 +52,6 @@ local function error_to_friendly_message(service_name, port, err)
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
return friendly_message;
end
@@ -110,22 +103,28 @@ function activate(service_name)
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
+ local err;
-- 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]
+ ssl, err = certmanager.create_context(service_info.name.." port "..port, "server", ssl_config and (ssl_config[port]
or (ssl_config.certificate and ssl_config)));
+ if not ssl then
+ log("error", "Error binding encrypted port for %s: %s", service_info.name, error_to_friendly_message(service_name, port, err) or "unknown error");
+ end
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));
- else
- log("debug", "Added listening service %s to [%s]:%d", service_name, interface, port);
- active_services:add(service_name, interface, port, {
- server = handler;
- service = service_info;
- });
+ if not err then
+ -- 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));
+ else
+ log("debug", "Added listening service %s to [%s]:%d", service_name, interface, port);
+ active_services:add(service_name, interface, port, {
+ server = handler;
+ service = service_info;
+ });
+ end
end
end
end
diff --git a/core/rostermanager.lua b/core/rostermanager.lua
index 9d1ff5e2..ac4f4e3d 100644
--- a/core/rostermanager.lua
+++ b/core/rostermanager.lua
@@ -83,15 +83,15 @@ end
function load_roster(username, host)
local jid = username.."@"..host;
- log("debug", "load_roster: asked for: "..jid);
+ log("debug", "load_roster: asked for: %s", jid);
local user = bare_sessions[jid];
local roster;
if user then
roster = user.roster;
if roster then return roster; end
- log("debug", "load_roster: loading for new user: "..username.."@"..host);
+ log("debug", "load_roster: loading for new user: %s@%s", username, host);
else -- Attempt to load roster for non-loaded user
- log("debug", "load_roster: loading for offline user: "..username.."@"..host);
+ log("debug", "load_roster: loading for offline user: %s@%s", username, host);
end
local data, err = datamanager.load(username, host, "roster");
roster = data or {};
@@ -99,7 +99,7 @@ function load_roster(username, host)
if not roster[false] then roster[false] = { broken = err or nil }; end
if roster[jid] then
roster[jid] = nil;
- log("warn", "roster for "..jid.." has a self-contact");
+ log("warn", "roster for %s has a self-contact", jid);
end
if not err then
hosts[host].events.fire_event("roster-load", username, host, roster);
@@ -108,7 +108,7 @@ function load_roster(username, host)
end
function save_roster(username, host, roster)
- log("debug", "save_roster: saving roster for "..username.."@"..host);
+ log("debug", "save_roster: saving roster for %s@%s", username, host);
if not roster then
roster = hosts[host] and hosts[host].sessions[username] and hosts[host].sessions[username].roster;
--if not roster then
@@ -238,7 +238,7 @@ function set_contact_pending_out(username, host, jid) -- subscribe
roster[jid] = item;
end
item.ask = "subscribe";
- log("debug", "set_contact_pending_out: saving roster; set "..username.."@"..host..".roster["..jid.."].ask=subscribe");
+ log("debug", "set_contact_pending_out: saving roster; set %s@%s.roster[%q].ask=subscribe", username, host, jid);
return save_roster(username, host, roster);
end
function unsubscribe(username, host, jid)
diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index 9e0a91d1..76dde9d2 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -74,7 +74,7 @@ function make_authenticated(session, host)
else
return false;
end
- session.log("debug", "connection %s->%s is now authenticated for %s", session.from_host or "(unknown)", session.to_host or "(unknown)", host);
+ session.log("debug", "connection %s->%s is now authenticated for %s", session.from_host, session.to_host, host);
mark_connected(session);
@@ -87,7 +87,7 @@ function mark_connected(session)
local from, to = session.from_host, session.to_host;
- session.log("info", session.direction.." s2s connection "..from.."->"..to.." complete");
+ session.log("info", "%s s2s connection %s->%s complete", session.direction, from, to);
local event_data = { session = session };
if session.type == "s2sout" then
@@ -105,7 +105,7 @@ function mark_connected(session)
if session.direction == "outgoing" then
if sendq then
- session.log("debug", "sending "..#sendq.." queued stanzas across new outgoing connection to "..session.to_host);
+ session.log("debug", "sending %d queued stanzas across new outgoing connection to %s", #sendq, session.to_host);
for i, data in ipairs(sendq) do
send(data[1]);
sendq[i] = nil;
@@ -133,7 +133,7 @@ local resting_session = { -- Resting, not dead
function retire_session(session, reason)
local log = session.log or log;
for k in pairs(session) do
- if k ~= "trace" and k ~= "log" and k ~= "id" then
+ if k ~= "trace" and k ~= "log" and k ~= "id" and k ~= "conn" then
session[k] = nil;
end
end
diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua
index 37c1626a..6945b8de 100644
--- a/core/sessionmanager.lua
+++ b/core/sessionmanager.lua
@@ -6,8 +6,8 @@
-- COPYING file in the source package for more information.
--
-local tonumber, tostring, setmetatable = tonumber, tostring, setmetatable;
-local ipairs, pairs, print, next= ipairs, pairs, print, next;
+local tostring, setmetatable = tostring, setmetatable;
+local pairs, next= pairs, next;
local hosts = hosts;
local full_sessions = full_sessions;
@@ -15,7 +15,6 @@ local bare_sessions = bare_sessions;
local logger = require "util.logger";
local log = logger.init("sessionmanager");
-local error = error;
local rm_load_roster = require "core.rostermanager".load_roster;
local config_get = require "core.configmanager".get;
local resourceprep = require "util.encodings".stringprep.resourceprep;
@@ -23,12 +22,8 @@ local nodeprep = require "util.encodings".stringprep.nodeprep;
local uuid_generate = require "util.uuid".generate;
local initialize_filters = require "util.filters".initialize;
-local fire_event = prosody.events.fire_event;
-local add_task = require "util.timer".add_task;
local gettime = require "socket".gettime;
-local st = require "util.stanza";
-
local newproxy = newproxy;
local getmetatable = getmetatable;
@@ -43,7 +38,7 @@ function new_session(conn)
getmetatable(session.trace).__gc = function () open_sessions = open_sessions - 1; end;
end
open_sessions = open_sessions + 1;
- log("debug", "open sessions now: ".. open_sessions);
+ log("debug", "open sessions now: %d", open_sessions);
local filter = initialize_filters(session);
local w = conn.write;
@@ -82,13 +77,13 @@ function retire_session(session)
end
end
- function session.send(data) log("debug", "Discarding data sent to resting session: %s", tostring(data)); end
+ function session.send(data) log("debug", "Discarding data sent to resting session: %s", tostring(data)); return false; end
function session.data(data) log("debug", "Discarding data received from resting session: %s", tostring(data)); end
return setmetatable(session, resting_session);
end
function destroy_session(session, err)
- (session.log or log)("info", "Destroying session for %s (%s@%s)%s", session.full_jid or "(unknown)", session.username or "(unknown)", session.host or "(unknown)", err and (": "..err) or "");
+ (session.log or log)("debug", "Destroying session for %s (%s@%s)%s", session.full_jid or "(unknown)", session.username or "(unknown)", session.host or "(unknown)", err and (": "..err) or "");
if session.destroyed then return; end
-- Remove session/resource from user's session list
diff --git a/core/stanza_router.lua b/core/stanza_router.lua
index f01c0fee..94753678 100644
--- a/core/stanza_router.lua
+++ b/core/stanza_router.lua
@@ -17,6 +17,18 @@ local jid_prepped_split = require "util.jid".prepped_split;
local full_sessions = _G.prosody.full_sessions;
local bare_sessions = _G.prosody.bare_sessions;
+local core_post_stanza, core_process_stanza, core_route_stanza;
+
+function deprecated_warning(f)
+ _G[f] = function(...)
+ log("warn", "Using the global %s() is deprecated, use module:send() or prosody.%s(). %s", f, f, debug.traceback());
+ return prosody[f](...);
+ end
+end
+deprecated_warning"core_post_stanza";
+deprecated_warning"core_process_stanza";
+deprecated_warning"core_route_stanza";
+
local function handle_unhandled_stanza(host, origin, stanza)
local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns or "jabber:client", origin.type;
if name == "iq" and xmlns == "jabber:client" then
diff --git a/core/usermanager.lua b/core/usermanager.lua
index 50aee701..3aba5786 100644
--- a/core/usermanager.lua
+++ b/core/usermanager.lua
@@ -91,8 +91,8 @@ function delete_user(username, host)
return hosts[host].users.delete_user(username);
end
-function get_sasl_handler(host)
- return hosts[host].users.get_sasl_handler();
+function get_sasl_handler(host, session)
+ return hosts[host].users.get_sasl_handler(session);
end
function get_provider(host)
diff --git a/net/http.lua b/net/http.lua
index f2061e00..273eee09 100644
--- a/net/http.lua
+++ b/net/http.lua
@@ -7,7 +7,7 @@
--
local socket = require "socket"
-local mime = require "mime"
+local b64 = require "util.encodings".base64.encode;
local url = require "socket.url"
local httpstream_new = require "util.httpstream".new;
@@ -154,7 +154,7 @@ function request(u, ex, callback)
};
if req.userinfo then
- headers["Authorization"] = "Basic "..mime.b64(req.userinfo);
+ headers["Authorization"] = "Basic "..b64(req.userinfo);
end
if ex then
@@ -203,7 +203,6 @@ function destroy_request(request)
if request.conn then
request.conn = nil;
request.handler:close()
- listener.ondisconnect(request.handler, "closed");
end
end
diff --git a/net/server_event.lua b/net/server_event.lua
index 03a7708c..f2626f5f 100644
--- a/net/server_event.lua
+++ b/net/server_event.lua
@@ -33,8 +33,6 @@ local cfg = {
}
local function use(x) return rawget(_G, x); end
-local print = use "print"
-local pcall = use "pcall"
local ipairs = use "ipairs"
local string = use "string"
local select = use "select"
@@ -117,7 +115,6 @@ do
local addevent = base.addevent
local coroutine_wrap, coroutine_yield = coroutine.wrap,coroutine.yield
- local string_len = string.len
-- Private methods
function interface_mt:_position(new_position)
@@ -212,7 +209,6 @@ do
self:_lock( false, false, false ) -- unlock the interface; sending, closing etc allowed
self.send = self.conn.send -- caching table lookups with new client object
self.receive = self.conn.receive
- local onsomething
if not call_onconnect then -- trigger listener
self:onstatus("ssl-handshake-complete");
end
@@ -249,7 +245,7 @@ do
return true
end
function interface_mt:_destroy() -- close this interface + events and call last listener
- debug( "closing client with id:", self.id )
+ debug( "closing client with id:", self.id, self.fatalerror )
self:_lock( true, true, true ) -- first of all, lock the interface to avoid further actions
local _
_ = self.eventread and self.eventread:close( ) -- close events; this must be called outside of the event callbacks!
@@ -313,7 +309,7 @@ do
if self.nowriting then return nil, "locked" end
--vdebug( "try to send data to client, id/data:", self.id, data )
data = tostring( data )
- local len = string_len( data )
+ local len = #data
local total = len + self.writebufferlen
if total > cfg.MAX_SEND_LENGTH then -- check buffer length
local err = "send buffer exceeded"
@@ -328,22 +324,22 @@ do
end
return true
end
- function interface_mt:close(now)
+ function interface_mt:close()
if self.nointerface then return nil, "locked"; end
debug( "try to close client connection with id:", self.id )
if self.type == "client" then
self.fatalerror = "client to close"
- if ( not self.eventwrite ) or now then -- try to close immediately
- self:_lock( true, true, true )
- self:_close()
- return true
- else -- wait for incomplete write request
+ if self.eventwrite then -- wait for incomplete write request
self:_lock( true, true, false )
debug "closing delayed until writebuffer is empty"
return nil, "writebuffer not empty, waiting"
+ else -- close now
+ self:_lock( true, true, true )
+ self:_close()
+ return true
end
else
- debug( "try to close server with id:", tostring(self.id), "args:", tostring(now) )
+ debug( "try to close server with id:", tostring(self.id))
self.fatalerror = "server to close"
self:_lock( true )
self:_close( 0 ) -- add new event to remove the server interface
@@ -470,9 +466,7 @@ do
local string_sub = string.sub -- caching table lookups
local string_len = string.len
local addevent = base.addevent
- local coroutine_wrap = coroutine.wrap
local socket_gettime = socket.gettime
- local coroutine_yield = coroutine.yield
function handleclient( client, ip, port, server, pattern, listener, sslctx ) -- creates an client interface
--vdebug("creating client interfacce...")
local interface = {
@@ -602,16 +596,14 @@ do
end
local buffer, err, part = interface.conn:receive( interface._pattern ) -- receive buffer with "pattern"
--vdebug( "read data:", tostring(buffer), "error:", tostring(err), "part:", tostring(part) )
- buffer = buffer or part or ""
- local len = string_len( buffer )
- if len > cfg.MAX_READ_LENGTH then -- check buffer length
+ buffer = buffer or part
+ if buffer and #buffer > cfg.MAX_READ_LENGTH then -- check buffer length
interface.fatalerror = "receive buffer exceeded"
debug( "fatal error:", interface.fatalerror )
interface:_close()
interface.eventread = nil
return -1
end
- interface.onincoming( interface, buffer, err ) -- send new data to listener
if err and ( err ~= "timeout" and err ~= "wantread" ) then
if "wantwrite" == err then -- need to read on write event
if not interface.eventwrite then -- register new write event if needed
@@ -631,6 +623,8 @@ do
interface.eventread = nil
return -1
end
+ else
+ interface.onincoming( interface, buffer, err ) -- send new data to listener
end
if interface.noreading then
interface.eventread = nil;
@@ -742,7 +736,7 @@ end )( )
local addclient, wrapclient
do
- function wrapclient( client, ip, port, listeners, pattern, sslctx, startssl )
+ function wrapclient( client, ip, port, listeners, pattern, sslctx )
local interface = handleclient( client, ip, port, nil, pattern, listeners, sslctx )
interface:_start_connection(sslctx)
return interface, client
@@ -778,9 +772,6 @@ do
local res, err = client:connect( addr, serverport ) -- connect
if res or ( err == "timeout" ) then
local ip, port = client:getsockname( )
- local server = function( )
- return nil, "this is a dummy server interface"
- end
local interface = wrapclient( client, ip, serverport, listener, pattern, sslctx, startssl )
interface:_start_connection( startssl )
debug( "new connection id:", interface.id )
diff --git a/net/server_select.lua b/net/server_select.lua
index de637f70..9104dace 100644
--- a/net/server_select.lua
+++ b/net/server_select.lua
@@ -19,7 +19,6 @@ end
local log, table_concat = require ("util.logger").init("socket"), table.concat;
local out_put = function (...) return log("debug", table_concat{...}); end
local out_error = function (...) return log("warn", table_concat{...}); end
-local mem_free = collectgarbage
----------------------------------// DECLARATION //--
@@ -34,7 +33,6 @@ local pairs = use "pairs"
local ipairs = use "ipairs"
local tonumber = use "tonumber"
local tostring = use "tostring"
-local collectgarbage = use "collectgarbage"
--// lua libs //--
@@ -49,7 +47,6 @@ local os_difftime = os.difftime
local math_min = math.min
local math_huge = math.huge
local table_concat = table.concat
-local table_remove = table.remove
local string_len = string.len
local string_sub = string.sub
local coroutine_wrap = coroutine.wrap
@@ -67,7 +64,6 @@ local ssl_wrap = ( luasec and luasec.wrap )
local socket_bind = luasocket.bind
local socket_sleep = luasocket.sleep
local socket_select = luasocket.select
-local ssl_newcontext = ( luasec and luasec.newcontext )
--// functions //--
@@ -84,7 +80,6 @@ local getsettings
local closesocket
local removesocket
local removeserver
-local changetimeout
local wrapconnection
local changesettings
@@ -314,22 +309,28 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport
end
return false, "setoption not implemented";
end
- handler.close = function( self, forced )
+ handler.force_close = function ( self, err )
+ if bufferqueuelen ~= 0 then
+ out_put("server.lua: discarding unwritten data for ", tostring(ip), ":", tostring(clientport))
+ for i = bufferqueuelen, 1, -1 do
+ bufferqueue[i] = nil;
+ end
+ bufferqueuelen = 0;
+ end
+ return self:close(err);
+ end
+ handler.close = function( self, err )
if not handler then return true; end
_readlistlen = removesocket( _readlist, socket, _readlistlen )
_readtimes[ handler ] = nil
if bufferqueuelen ~= 0 then
- if not ( forced or fatalerror ) then
- handler.sendbuffer( )
- if bufferqueuelen ~= 0 then -- try again...
- if handler then
- handler.write = nil -- ... but no further writing allowed
- end
- toclose = true
- return false
+ handler.sendbuffer() -- Try now to send any outstanding data
+ if bufferqueuelen ~= 0 then -- Still not empty, so we'll try again later
+ if handler then
+ handler.write = nil -- ... but no further writing allowed
end
- else
- send( socket, table_concat( bufferqueue, "", 1, bufferqueuelen ), 1, bufferlen ) -- forced send
+ toclose = true
+ return false
end
end
if socket then
@@ -347,7 +348,8 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport
local _handler = handler;
handler = nil
if disconnect then
- disconnect(_handler, "closed");
+ disconnect(_handler, err or false);
+ disconnect = nil
end
end
if server then
@@ -450,8 +452,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport
local buffer = buffer or part or ""
local len = string_len( buffer )
if len > maxreadlen then
- disconnect( handler, "receive buffer exceeded" )
- handler:close( true )
+ handler:close( "receive buffer exceeded" )
return false
end
local count = len * STAT_UNIT
@@ -463,14 +464,12 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport
else -- connections was closed or fatal error
out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " read error: ", tostring(err) )
fatalerror = true
- disconnect( handler, err )
- _ = handler and handler:close( )
+ _ = handler and handler:force_close( err )
return false
end
end
local _sendbuffer = function( ) -- this function sends data
local succ, err, byte, buffer, count;
- local count;
if socket then
buffer = table_concat( bufferqueue, "", 1, bufferqueuelen )
succ, err, byte = send( socket, buffer, 1, bufferlen )
@@ -480,7 +479,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport
_ = _cleanqueue and clean( bufferqueue )
--out_put( "server.lua: sended '", buffer, "', bytes: ", tostring(succ), ", error: ", tostring(err), ", part: ", tostring(byte), ", to: ", tostring(ip), ":", tostring(clientport) )
else
- succ, err, count = false, "closed", 0;
+ succ, err, count = false, "unexpected close", 0;
end
if succ then -- sending succesful
bufferqueuelen = 0
@@ -491,7 +490,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport
drain(handler)
end
_ = needtls and handler:starttls(nil)
- _ = toclose and handler:close( )
+ _ = toclose and handler:force_close( )
return true
elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write
buffer = string_sub( buffer, byte + 1, bufferlen ) -- new buffer
@@ -503,8 +502,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport
else -- connection was closed during sending or fatal error
out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " write error: ", tostring(err) )
fatalerror = true
- disconnect( handler, err )
- _ = handler and handler:close( )
+ _ = handler and handler:force_close( err )
return false
end
end
@@ -546,9 +544,8 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport
end
end
out_put( "server.lua: ssl handshake error: ", tostring(err or "handshake too long") )
- disconnect( handler, "ssl handshake failed" )
- _ = handler and handler:close( true ) -- forced disconnect
- return false, err -- handshake failed
+ _ = handler and handler:force_close("ssl handshake failed")
+ return false, err -- handshake failed
end
)
end
@@ -810,7 +807,7 @@ loop = function(once) -- this is the main loop of the program
end
for handler, err in pairs( _closelist ) do
handler.disconnect( )( handler, err )
- handler:close( true ) -- forced disconnect
+ handler:force_close() -- forced disconnect
end
clean( _closelist )
_currenttime = luasocket_gettime( )
@@ -896,7 +893,7 @@ addtimer( function( )
if os_difftime( _currenttime - timestamp ) > _sendtimeout then
--_writetimes[ handler ] = nil
handler.disconnect( )( handler, "send timeout" )
- handler:close( true ) -- forced disconnect
+ handler:force_close() -- forced disconnect
end
end
for handler, timestamp in pairs( _readtimes ) do
diff --git a/plugins/adhoc/adhoc.lib.lua b/plugins/adhoc/adhoc.lib.lua
index eff3caff..acdae6b9 100644
--- a/plugins/adhoc/adhoc.lib.lua
+++ b/plugins/adhoc/adhoc.lib.lua
@@ -12,7 +12,7 @@ local states = {}
local _M = {};
-function _cmdtag(desc, status, sessionid, action)
+local function _cmdtag(desc, status, sessionid, action)
local cmd = st.stanza("command", { xmlns = xmlns_cmd, node = desc.node, status = status });
if sessionid then cmd.attr.sessionid = sessionid; end
if action then cmd.attr.action = action; end
@@ -35,6 +35,7 @@ function _M.handle_cmd(command, origin, stanza)
local data, state = command:handler(dataIn, states[sessionid]);
states[sessionid] = state;
local stanza = st.reply(stanza);
+ local cmdtag;
if data.status == "completed" then
states[sessionid] = nil;
cmdtag = command:cmdtag("completed", sessionid);
@@ -64,8 +65,8 @@ function _M.handle_cmd(command, origin, stanza)
if (action == "prev") or (action == "next") or (action == "complete") then
actions:tag(action):up();
else
- module:log("error", 'Command "'..command.name..
- '" at node "'..command.node..'" provided an invalid action "'..action..'"');
+ module:log("error", "Command %q at node %q provided an invalid action %q",
+ command.name, command.node, action);
end
end
cmdtag:add_child(actions);
diff --git a/plugins/adhoc/mod_adhoc.lua b/plugins/adhoc/mod_adhoc.lua
index 49d07103..69b2c8da 100644
--- a/plugins/adhoc/mod_adhoc.lua
+++ b/plugins/adhoc/mod_adhoc.lua
@@ -100,3 +100,4 @@ local function adhoc_removed(event)
end
module:handle_items("adhoc", adhoc_added, adhoc_removed);
+module:handle_items("adhoc-provider", adhoc_added, adhoc_removed);
diff --git a/plugins/mod_admin_adhoc.lua b/plugins/mod_admin_adhoc.lua
index 4d2c60d7..50493abe 100644
--- a/plugins/mod_admin_adhoc.lua
+++ b/plugins/mod_admin_adhoc.lua
@@ -23,10 +23,19 @@ local timer_add_task = require "util.timer".add_task;
local dataforms_new = require "util.dataforms".new;
local array = require "util.array";
local modulemanager = require "modulemanager";
+local core_post_stanza = prosody.core_post_stanza;
module:depends("adhoc");
local adhoc_new = module:require "adhoc".new;
+local function generate_error_message(errors)
+ local errmsg = {};
+ for name, err in pairs(errors) do
+ errmsg[#errmsg + 1] = name .. ": " .. err;
+ end
+ return { status = "completed", error = { message = t_concat(errmsg, "\n") } };
+end
+
function add_user_command_handler(self, data, state)
local add_user_layout = dataforms_new{
title = "Adding a User";
@@ -42,9 +51,9 @@ function add_user_command_handler(self, data, state)
if data.action == "cancel" then
return { status = "canceled" };
end
- local fields = add_user_layout:data(data.form);
- if not fields.accountjid then
- return { status = "completed", error = { message = "You need to specify a JID." } };
+ local fields, err = add_user_layout:data(data.form);
+ if err then
+ return generate_error_message(err);
end
local username, host, resource = jid.split(fields.accountjid);
if data.to ~= host then
@@ -55,15 +64,14 @@ function add_user_command_handler(self, data, state)
return { status = "completed", error = { message = "Account already exists" } };
else
if usermanager_create_user(username, fields.password, host) then
- module:log("info", "Created new account " .. username.."@"..host);
+ module:log("info", "Created new account %s@%s", username, host);
return { status = "completed", info = "Account successfully created" };
else
return { status = "completed", error = { message = "Failed to write data to disk" } };
end
end
else
- module:log("debug", (fields.accountjid or "<nil>") .. " " .. (fields.password or "<nil>") .. " "
- .. (fields["password-verify"] or "<nil>"));
+ module:log("debug", "Invalid data, password mismatch or empty username while creating account for %s", fields.accountjid or "<nil>");
return { status = "completed", error = { message = "Invalid data.\nPassword mismatch, or empty username" } };
end
else
@@ -85,9 +93,9 @@ function change_user_password_command_handler(self, data, state)
if data.action == "cancel" then
return { status = "canceled" };
end
- local fields = change_user_password_layout:data(data.form);
- if not fields.accountjid or fields.accountjid == "" or not fields.password then
- return { status = "completed", error = { message = "Please specify username and password" } };
+ local fields, err = change_user_password_layout:data(data.form);
+ if err then
+ return generate_error_message(err);
end
local username, host, resource = jid.split(fields.accountjid);
if data.to ~= host then
@@ -126,16 +134,19 @@ function delete_user_command_handler(self, data, state)
if data.action == "cancel" then
return { status = "canceled" };
end
- local fields = delete_user_layout:data(data.form);
+ local fields, err = delete_user_layout:data(data.form);
+ if err then
+ return generate_error_message(err);
+ end
local failed = {};
local succeeded = {};
for _, aJID in ipairs(fields.accountjids) do
local username, host, resource = jid.split(aJID);
if (host == data.to) and usermanager_user_exists(username, host) and disconnect_user(aJID) and usermanager_create_user(username, nil, host) then
- module:log("debug", "User " .. aJID .. " has been deleted");
+ module:log("debug", "User %s has been deleted", aJID);
succeeded[#succeeded+1] = aJID;
else
- module:log("debug", "Tried to delete non-existant user "..aJID);
+ module:log("debug", "Tried to delete non-existant user %s", aJID);
failed[#failed+1] = aJID;
end
end
@@ -154,7 +165,7 @@ function disconnect_user(match_jid)
local sessions = host.sessions[node] and host.sessions[node].sessions;
for resource, session in pairs(sessions or {}) do
if not givenResource or (resource == givenResource) then
- module:log("debug", "Disconnecting "..node.."@"..hostname.."/"..resource);
+ module:log("debug", "Disconnecting %s@%s/%s", node, hostname, resource);
session:close();
end
end
@@ -175,7 +186,10 @@ function end_user_session_handler(self, data, state)
return { status = "canceled" };
end
- local fields = end_user_session_layout:data(data.form);
+ local fields, err = end_user_session_layout:data(data.form);
+ if err then
+ return generate_error_message(err);
+ end
local failed = {};
local succeeded = {};
for _, aJID in ipairs(fields.accountjids) do
@@ -223,9 +237,9 @@ function get_user_password_handler(self, data, state)
if data.action == "cancel" then
return { status = "canceled" };
end
- local fields = get_user_password_layout:data(data.form);
- if not fields.accountjid then
- return { status = "completed", error = { message = "Please specify a JID." } };
+ local fields, err = get_user_password_layout:data(data.form);
+ if err then
+ return generate_error_message(err);
end
local user, host, resource = jid.split(fields.accountjid);
local accountjid = "";
@@ -261,10 +275,10 @@ function get_user_roster_handler(self, data, state)
return { status = "canceled" };
end
- local fields = get_user_roster_layout:data(data.form);
+ local fields, err = get_user_roster_layout:data(data.form);
- if not fields.accountjid then
- return { status = "completed", error = { message = "Please specify a JID" } };
+ if err then
+ return generate_error_message(err);
end
local user, host, resource = jid.split(fields.accountjid);
@@ -323,10 +337,10 @@ function get_user_stats_handler(self, data, state)
return { status = "canceled" };
end
- local fields = get_user_stats_layout:data(data.form);
+ local fields, err = get_user_stats_layout:data(data.form);
- if not fields.accountjid then
- return { status = "completed", error = { message = "Please specify a JID." } };
+ if err then
+ return generate_error_message(err);
end
local user, host, resource = jid.split(fields.accountjid);
@@ -376,7 +390,11 @@ function get_online_users_command_handler(self, data, state)
return { status = "canceled" };
end
- local fields = get_online_users_layout:data(data.form);
+ local fields, err = get_online_users_layout:data(data.form);
+
+ if err then
+ return generate_error_message(err);
+ end
local max_items = nil
if fields.max_items ~= "all" then
@@ -436,11 +454,9 @@ function load_module_handler(self, data, state)
if data.action == "cancel" then
return { status = "canceled" };
end
- local fields = layout:data(data.form);
- if (not fields.module) or (fields.module == "") then
- return { status = "completed", error = {
- message = "Please specify a module."
- } };
+ local fields, err = layout:data(data.form);
+ if err then
+ return generate_error_message(err);
end
if modulemanager.is_loaded(data.to, fields.module) then
return { status = "completed", info = "Module already loaded" };
@@ -453,7 +469,6 @@ function load_module_handler(self, data, state)
'". Error was: "'..tostring(err or "<unspecified>")..'"' } };
end
else
- local modules = array.collect(keys(hosts[data.to].modules)):sort();
return { status = "executing", form = layout }, "executing";
end
end
@@ -470,11 +485,9 @@ function reload_modules_handler(self, data, state)
if data.action == "cancel" then
return { status = "canceled" };
end
- local fields = layout:data(data.form);
- if #fields.modules == 0 then
- return { status = "completed", error = {
- message = "Please specify a module. (This means your client misbehaved, as this field is required)"
- } };
+ local fields, err = layout:data(data.form);
+ if err then
+ return generate_error_message(err);
end
local ok_list, err_list = {}, {};
for _, module in ipairs(fields.modules) do
@@ -538,7 +551,11 @@ function shut_down_service_handler(self, data, state)
return { status = "canceled" };
end
- local fields = shut_down_service_layout:data(data.form);
+ local fields, err = shut_down_service_layout:data(data.form);
+
+ if err then
+ return generate_error_message(err);
+ end
if fields.announcement and #fields.announcement > 0 then
local message = st.message({type = "headline"}, fields.announcement):up()
@@ -566,11 +583,9 @@ function unload_modules_handler(self, data, state)
if data.action == "cancel" then
return { status = "canceled" };
end
- local fields = layout:data(data.form);
- if #fields.modules == 0 then
- return { status = "completed", error = {
- message = "Please specify a module. (This means your client misbehaved, as this field is required)"
- } };
+ local fields, err = layout:data(data.form);
+ if err then
+ return generate_error_message(err);
end
local ok_list, err_list = {}, {};
for _, module in ipairs(fields.modules) do
@@ -605,17 +620,17 @@ local reload_modules_desc = adhoc_new("Reload modules", "http://prosody.im/proto
local shut_down_service_desc = adhoc_new("Shut Down Service", "http://jabber.org/protocol/admin#shutdown", shut_down_service_handler, "global_admin");
local unload_modules_desc = adhoc_new("Unload modules", "http://prosody.im/protocol/modules#unload", unload_modules_handler, "admin");
-module:add_item("adhoc", add_user_desc);
-module:add_item("adhoc", change_user_password_desc);
-module:add_item("adhoc", config_reload_desc);
-module:add_item("adhoc", delete_user_desc);
-module:add_item("adhoc", end_user_session_desc);
-module:add_item("adhoc", get_user_password_desc);
-module:add_item("adhoc", get_user_roster_desc);
-module:add_item("adhoc", get_user_stats_desc);
-module:add_item("adhoc", get_online_users_desc);
-module:add_item("adhoc", list_modules_desc);
-module:add_item("adhoc", load_module_desc);
-module:add_item("adhoc", reload_modules_desc);
-module:add_item("adhoc", shut_down_service_desc);
-module:add_item("adhoc", unload_modules_desc);
+module:provides("adhoc", add_user_desc);
+module:provides("adhoc", change_user_password_desc);
+module:provides("adhoc", config_reload_desc);
+module:provides("adhoc", delete_user_desc);
+module:provides("adhoc", end_user_session_desc);
+module:provides("adhoc", get_user_password_desc);
+module:provides("adhoc", get_user_roster_desc);
+module:provides("adhoc", get_user_stats_desc);
+module:provides("adhoc", get_online_users_desc);
+module:provides("adhoc", list_modules_desc);
+module:provides("adhoc", load_module_desc);
+module:provides("adhoc", reload_modules_desc);
+module:provides("adhoc", shut_down_service_desc);
+module:provides("adhoc", unload_modules_desc);
diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua
index cdac7d4e..ebd817b5 100644
--- a/plugins/mod_admin_telnet.lua
+++ b/plugins/mod_admin_telnet.lua
@@ -13,7 +13,7 @@ local _G = _G;
local prosody = _G.prosody;
local hosts = prosody.hosts;
-local console_listener = { default_port = 5582; default_mode = "*l"; interface = "127.0.0.1" };
+local console_listener = { default_port = 5582; default_mode = "*a"; interface = "127.0.0.1" };
local hostmanager = require "core.hostmanager";
local modulemanager = require "core.modulemanager";
@@ -30,6 +30,7 @@ local envloadfile = require "util.envload".envloadfile;
local commands = module:shared("commands")
local def_env = module:shared("env");
local default_env_mt = { __index = def_env };
+local core_post_stanza = prosody.core_post_stanza;
local function redirect_output(_G, session)
local env = setmetatable({ print = session.print }, { __index = function (t, k) return rawget(_G, k); end });
@@ -81,67 +82,74 @@ end
function console_listener.onincoming(conn, data)
local session = sessions[conn];
- -- Handle data
- (function(session, data)
- local useglobalenv;
-
- if data:match("^>") then
- data = data:gsub("^>", "");
- useglobalenv = true;
- elseif data == "\004" then
- commands["bye"](session, data);
- return;
- else
- local command = data:lower();
- command = data:match("^%w+") or data:match("%p");
- if commands[command] then
- commands[command](session, data);
- return;
+ local partial = session.partial_data;
+ if partial then
+ data = partial..data;
+ end
+
+ for line in data:gmatch("[^\n]*[\n\004]") do
+ -- Handle data (loop allows us to break to add \0 after response)
+ repeat
+ local useglobalenv;
+
+ if line:match("^>") then
+ line = line:gsub("^>", "");
+ useglobalenv = true;
+ elseif line == "\004" then
+ commands["bye"](session, line);
+ break;
+ else
+ local command = line:match("^%w+") or line:match("%p");
+ if commands[command] then
+ commands[command](session, line);
+ break;
+ end
end
- end
- session.env._ = data;
-
- local chunkname = "=console";
- local env = (useglobalenv and redirect_output(_G, session)) or session.env or nil
- local chunk, err = envload("return "..data, chunkname, env);
- if not chunk then
- chunk, err = envload(data, chunkname, env);
+ session.env._ = line;
+
+ local chunkname = "=console";
+ local env = (useglobalenv and redirect_output(_G, session)) or session.env or nil
+ local chunk, err = envload("return "..line, chunkname, env);
if not chunk then
- err = err:gsub("^%[string .-%]:%d+: ", "");
- err = err:gsub("^:%d+: ", "");
- err = err:gsub("'<eof>'", "the end of the line");
- session.print("Sorry, I couldn't understand that... "..err);
- return;
+ chunk, err = envload(line, chunkname, env);
+ if not chunk then
+ err = err:gsub("^%[string .-%]:%d+: ", "");
+ err = err:gsub("^:%d+: ", "");
+ err = err:gsub("'<eof>'", "the end of the line");
+ session.print("Sorry, I couldn't understand that... "..err);
+ break;
+ end
end
- end
-
- local ranok, taskok, message = pcall(chunk);
- if not (ranok or message or useglobalenv) and commands[data:lower()] then
- commands[data:lower()](session, data);
- return;
- end
-
- if not ranok then
- session.print("Fatal error while running command, it did not complete");
- session.print("Error: "..taskok);
- return;
- end
-
- if not message then
- session.print("Result: "..tostring(taskok));
- return;
- elseif (not taskok) and message then
- session.print("Command completed with a problem");
- session.print("Message: "..tostring(message));
- return;
- end
+ local ranok, taskok, message = pcall(chunk);
+
+ if not (ranok or message or useglobalenv) and commands[line:lower()] then
+ commands[line:lower()](session, line);
+ break;
+ end
+
+ if not ranok then
+ session.print("Fatal error while running command, it did not complete");
+ session.print("Error: "..taskok);
+ break;
+ end
+
+ if not message then
+ session.print("Result: "..tostring(taskok));
+ break;
+ elseif (not taskok) and message then
+ session.print("Command completed with a problem");
+ session.print("Message: "..tostring(message));
+ break;
+ end
+
+ session.print("OK: "..tostring(message));
+ until true
- session.print("OK: "..tostring(message));
- end)(session, data);
-
- session.send(string.char(0));
+ session.send(string.char(0));
+ end
+ session.partial_data = data:match("[^\n]+$");
end
function console_listener.ondisconnect(conn, err)
@@ -191,6 +199,7 @@ function commands.help(session, data)
print [[s2s - Commands to manage sessions between this server and others]]
print [[module - Commands to load/reload/unload modules/plugins]]
print [[host - Commands to activate, deactivate and list virtual hosts]]
+ print [[user - Commands to create and delete users, and change their passwords]]
print [[server - Uptime, version, shutting down, etc.]]
print [[config - Reloading the configuration, etc.]]
print [[console - Help regarding the console itself]]
@@ -202,6 +211,7 @@ function commands.help(session, data)
elseif section == "s2s" then
print [[s2s:show(domain) - Show all s2s connections for the given domain (or all if no domain given)]]
print [[s2s:close(from, to) - Close a connection from one domain to another]]
+ print [[s2s:closeall(host) - Close all the incoming/outgoing s2s sessions to specified host]]
elseif section == "module" then
print [[module:load(module, host) - Load the specified module on the specified host (or all hosts if none given)]]
print [[module:reload(module, host) - The same, but unloads and loads the module (saving state if the module supports it)]]
@@ -211,6 +221,10 @@ function commands.help(session, data)
print [[host:activate(hostname) - Activates the specified host]]
print [[host:deactivate(hostname) - Disconnects all clients on this host and deactivates]]
print [[host:list() - List the currently-activated hosts]]
+ elseif section == "user" then
+ print [[user:create(jid, password) - Create the specified user account]]
+ print [[user:password(jid, password) - Set the password for the specified user account]]
+ print [[user:delete(jid, password) - Permanently remove the specified user account]]
elseif section == "server" then
print [[server:version() - Show the server's version number]]
print [[server:uptime() - Show how long the server has been running]]
@@ -679,7 +693,6 @@ function def_env.s2s:showcert(domain)
end
local domain_certs = array.collect(values(cert_set));
-- Phew. We now have a array of unique certificates presented by domain.
- local print = self.session.print;
local n_certs = #domain_certs;
if n_certs == 0 then
@@ -773,6 +786,40 @@ function def_env.s2s:close(from, to)
return true, "Closed "..count.." s2s session"..((count == 1 and "") or "s");
end
+function def_env.s2s:closeall(host)
+ local count = 0;
+
+ if not host or type(host) ~= "string" then return false, "wrong syntax: please use s2s:closeall('hostname.tld')"; end
+ if hosts[host] then
+ for session in pairs(incoming_s2s) do
+ if session.to_host == host then
+ (session.close or s2smanager.destroy_session)(session);
+ count = count + 1;
+ end
+ end
+ for _, session in pairs(hosts[host].s2sout) do
+ (session.close or s2smanager.destroy_session)(session);
+ count = count + 1;
+ end
+ else
+ for session in pairs(incoming_s2s) do
+ if session.from_host == host then
+ (session.close or s2smanager.destroy_session)(session);
+ count = count + 1;
+ end
+ end
+ for _, h in pairs(hosts) do
+ if h.s2sout[host] then
+ (h.s2sout[host].close or s2smanager.destroy_session)(h.s2sout[host]);
+ count = count + 1;
+ end
+ end
+ end
+
+ if count == 0 then return false, "No sessions to close.";
+ else return true, "Closed "..count.." s2s session"..((count == 1 and "") or "s"); end
+end
+
def_env.host = {}; def_env.hosts = def_env.host;
function def_env.host:activate(hostname, config)
@@ -860,6 +907,53 @@ function def_env.muc:room(room_jid)
return setmetatable({ room = room_obj }, console_room_mt);
end
+local um = require"core.usermanager";
+
+def_env.user = {};
+function def_env.user:create(jid, password)
+ local username, host = jid_split(jid);
+ local ok, err = um.create_user(username, password, host);
+ if ok then
+ return true, "User created";
+ else
+ return nil, "Could not create user: "..err;
+ end
+end
+
+function def_env.user:delete(jid)
+ local username, host = jid_split(jid);
+ local ok, err = um.delete_user(username, host);
+ if ok then
+ return true, "User deleted";
+ else
+ return nil, "Could not delete user: "..err;
+ end
+end
+
+function def_env.user:passwd(jid, password)
+ local username, host = jid_split(jid);
+ local ok, err = um.set_password(username, password, host);
+ if ok then
+ return true, "User created";
+ else
+ return nil, "Could not change password for user: "..err;
+ end
+end
+
+def_env.xmpp = {};
+
+local st = require "util.stanza";
+function def_env.xmpp:ping(localhost, remotehost)
+ if hosts[localhost] then
+ core_post_stanza(hosts[localhost],
+ st.iq{ from=localhost, to=remotehost, type="get", id="ping" }
+ :tag("ping", {xmlns="urn:xmpp:ping"}));
+ return true, "Sent ping";
+ else
+ return nil, "No such host";
+ end
+end
+
-------------
function printbanner(session)
diff --git a/plugins/mod_announce.lua b/plugins/mod_announce.lua
index 77555bec..0cfd284c 100644
--- a/plugins/mod_announce.lua
+++ b/plugins/mod_announce.lua
@@ -25,7 +25,7 @@ function send_to_online(message, host)
for username in pairs(host_session.sessions) do
c = c + 1;
message.attr.to = username.."@"..hostname;
- core_post_stanza(host_session, message);
+ module:send(message);
end
end
end
@@ -96,5 +96,5 @@ end
local adhoc_new = module:require "adhoc".new;
local announce_desc = adhoc_new("Send Announcement to Online Users", "http://jabber.org/protocol/admin#announce", announce_handler, "admin");
-module:add_item("adhoc", announce_desc);
+module:provides("adhoc", announce_desc);
diff --git a/plugins/mod_auth_cyrus.lua b/plugins/mod_auth_cyrus.lua
index 447fae51..e4493f04 100644
--- a/plugins/mod_auth_cyrus.lua
+++ b/plugins/mod_auth_cyrus.lua
@@ -14,6 +14,7 @@ local cyrus_service_realm = module:get_option("cyrus_service_realm");
local cyrus_service_name = module:get_option("cyrus_service_name");
local cyrus_application_name = module:get_option("cyrus_application_name");
local require_provisioning = module:get_option("cyrus_require_provisioning") or false;
+local host_fqdn = module:get_option("cyrus_server_fqdn");
prosody.unlock_globals(); --FIXME: Figure out why this is needed and
-- why cyrussasl isn't caught by the sandbox
@@ -23,7 +24,8 @@ local new_sasl = function(realm)
return cyrus_new(
cyrus_service_realm or realm,
cyrus_service_name or "xmpp",
- cyrus_application_name or "prosody"
+ cyrus_application_name or "prosody",
+ host_fqdn
);
end
diff --git a/plugins/mod_bosh.lua b/plugins/mod_bosh.lua
index 8b612286..f6e3095e 100644
--- a/plugins/mod_bosh.lua
+++ b/plugins/mod_bosh.lua
@@ -14,7 +14,7 @@ local sm = require "core.sessionmanager";
local sm_destroy_session = sm.destroy_session;
local new_uuid = require "util.uuid".generate;
local fire_event = prosody.events.fire_event;
-local core_process_stanza = core_process_stanza;
+local core_process_stanza = prosody.core_process_stanza;
local st = require "util.stanza";
local logger = require "util.logger";
local log = logger.init("mod_bosh");
@@ -56,7 +56,7 @@ local trusted_proxies = module:get_option_set("trusted_proxies", {"127.0.0.1"}).
local function get_ip_from_request(request)
local ip = request.conn:ip();
- local forwarded_for = request.headers["x-forwarded-for"];
+ local forwarded_for = request.headers.x_forwarded_for;
if forwarded_for then
forwarded_for = forwarded_for..", "..ip;
for forwarded_ip in forwarded_for:gmatch("[^%s,]+") do
diff --git a/plugins/mod_c2s.lua b/plugins/mod_c2s.lua
index 55c53e2d..2318ecad 100644
--- a/plugins/mod_c2s.lua
+++ b/plugins/mod_c2s.lua
@@ -24,9 +24,11 @@ local xmlns_xmpp_streams = "urn:ietf:params:xml:ns:xmpp-streams";
local log = module._log;
local c2s_timeout = module:get_option_number("c2s_timeout");
+local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5);
local opt_keepalives = module:get_option_boolean("tcp_keepalives", false);
local sessions = module:shared("sessions");
+local core_process_stanza = prosody.core_process_stanza;
local stream_callbacks = { default_ns = "jabber:client", handlestanza = core_process_stanza };
local listener = {};
@@ -75,7 +77,7 @@ end
function stream_callbacks.streamclosed(session)
session.log("debug", "Received </stream:stream>");
- session:close();
+ session:close(false);
end
function stream_callbacks.error(session, error, data)
@@ -121,9 +123,9 @@ local function session_close(session, reason)
session.send("<?xml version='1.0'?>");
session.send(st.stanza("stream:stream", default_stream_attr):top_tag());
end
- if reason then
+ if reason then -- nil == no err, initiated by us, false == initiated by client
if type(reason) == "string" then -- assume stream error
- log("info", "Disconnecting client, <stream:error> is: %s", reason);
+ log("debug", "Disconnecting client, <stream:error> is: %s", reason);
session.send(st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' }));
elseif type(reason) == "table" then
if reason.condition then
@@ -134,17 +136,36 @@ local function session_close(session, reason)
if reason.extra then
stanza:add_child(reason.extra);
end
- log("info", "Disconnecting client, <stream:error> is: %s", tostring(stanza));
+ log("debug", "Disconnecting client, <stream:error> is: %s", tostring(stanza));
session.send(stanza);
elseif reason.name then -- a stanza
- log("info", "Disconnecting client, <stream:error> is: %s", tostring(reason));
+ log("debug", "Disconnecting client, <stream:error> is: %s", tostring(reason));
session.send(reason);
end
end
end
+
session.send("</stream:stream>");
- session.conn:close();
- listener.ondisconnect(session.conn, (reason and (reason.text or reason.condition)) or reason or "session closed");
+ function session.send() return false; end
+
+ local reason = (reason and (reason.text or reason.condition)) or reason;
+ session.log("info", "c2s stream for %s closed: %s", session.full_jid or ("<"..session.ip..">"), reason or "session closed");
+
+ -- Authenticated incoming stream may still be sending us stanzas, so wait for </stream:stream> from remote
+ local conn = session.conn;
+ if reason == nil and not session.notopen and session.type == "c2s" then
+ -- Grace time to process data from authenticated cleanly-closed stream
+ add_task(stream_close_timeout, function ()
+ if not session.destroyed then
+ session.log("warn", "Failed to receive a stream close response, closing connection anyway...");
+ sm_destroy_session(session, reason);
+ conn:close();
+ end
+ end);
+ else
+ sm_destroy_session(session, reason);
+ conn:close();
+ end
end
end
@@ -208,10 +229,9 @@ end
function listener.ondisconnect(conn, err)
local session = sessions[conn];
if session then
- (session.log or log)("info", "Client disconnected: %s", err);
+ (session.log or log)("info", "Client disconnected: %s", err or "connection closed");
sm_destroy_session(session, err);
sessions[conn] = nil;
- session = nil;
end
end
diff --git a/plugins/mod_component.lua b/plugins/mod_component.lua
index 738124cc..751de59b 100644
--- a/plugins/mod_component.lua
+++ b/plugins/mod_component.lua
@@ -18,6 +18,8 @@ local jid_split = require "util.jid".split;
local new_xmpp_stream = require "util.xmppstream".new;
local uuid_gen = require "util.uuid".generate;
+local core_process_stanza = prosody.core_process_stanza;
+
local log = module._log;
@@ -124,7 +126,7 @@ local xmlns_xmpp_streams = "urn:ietf:params:xml:ns:xmpp-streams";
function stream_callbacks.error(session, error, data, data2)
if session.destroyed then return; end
- module:log("warn", "Error processing component stream: "..tostring(error));
+ module:log("warn", "Error processing component stream: %s", tostring(error));
if error == "no-stream" then
session:close("invalid-namespace");
elseif error == "parse-error" then
@@ -169,8 +171,6 @@ function stream_callbacks.streamclosed(session)
session:close();
end
-local core_process_stanza = core_process_stanza;
-
function stream_callbacks.handlestanza(session, stanza)
-- Namespaces are icky.
if not stanza.attr.xmlns and stanza.name == "handshake" then
diff --git a/plugins/mod_dialback.lua b/plugins/mod_dialback.lua
index 2299c0dc..69616a57 100644
--- a/plugins/mod_dialback.lua
+++ b/plugins/mod_dialback.lua
@@ -41,6 +41,11 @@ module:hook("stanza/jabber:server:dialback:verify", function(event)
-- We are being asked to verify the key, to ensure it was generated by us
origin.log("debug", "verifying that dialback key is ours...");
local attr = stanza.attr;
+ if attr.type then
+ module:log("warn", "Ignoring incoming session from %s claiming a dialback key for %s is %s",
+ origin.from_host or "(unknown)", attr.from or "(unknown)", attr.type);
+ return true;
+ end
-- COMPAT: Grr, ejabberd breaks this one too?? it is black and white in XEP-220 example 34
--if attr.from ~= origin.to_host then error("invalid-from"); end
local type;
@@ -84,7 +89,7 @@ module:hook("stanza/jabber:server:dialback:result", function(event)
origin.from_host = from;
end
if not origin.to_host then
- origin.to_host = nameprep(attr.to);
+ origin.to_host = to;
end
origin.log("debug", "asking %s if key %s belongs to them", from, stanza[1]);
@@ -102,7 +107,6 @@ module:hook("stanza/jabber:server:dialback:verify", function(event)
if origin.type == "s2sout_unauthed" or origin.type == "s2sout" then
local attr = stanza.attr;
local dialback_verifying = dialback_requests[attr.from.."/"..(attr.id or "")];
- module:log("debug", tostring(dialback_verifying).." "..attr.from.." "..origin.to_host);
if dialback_verifying and attr.from == origin.to_host then
local valid;
if attr.type == "valid" then
@@ -110,7 +114,7 @@ module:hook("stanza/jabber:server:dialback:verify", function(event)
valid = "valid";
else
-- Warn the original connection that is was not verified successfully
- log("warn", "authoritative server for "..(attr.from or "(unknown)").." denied the key");
+ log("warn", "authoritative server for %s denied the key", attr.from or "(unknown)");
valid = "invalid";
end
if not dialback_verifying.sends2s then
diff --git a/plugins/mod_disco.lua b/plugins/mod_disco.lua
index c3a9c54d..6587d435 100644
--- a/plugins/mod_disco.lua
+++ b/plugins/mod_disco.lua
@@ -32,7 +32,7 @@ do -- validate disco_items
end
end
-module:add_identity("server", "im", "Prosody"); -- FIXME should be in the non-existing mod_router
+module:add_identity("server", "im", module:get_option_string("name", "Prosody")); -- FIXME should be in the non-existing mod_router
module:add_feature("http://jabber.org/protocol/disco#info");
module:add_feature("http://jabber.org/protocol/disco#items");
diff --git a/plugins/mod_iq.lua b/plugins/mod_iq.lua
index 6412ad11..8044a533 100644
--- a/plugins/mod_iq.lua
+++ b/plugins/mod_iq.lua
@@ -17,10 +17,7 @@ if module:get_host_type() == "local" then
local origin, stanza = data.origin, data.stanza;
local session = full_sessions[stanza.attr.to];
- if session then
- -- TODO fire post processing event
- session.send(stanza);
- else -- resource not online
+ if not (session and session.send(stanza)) then
if stanza.attr.type == "get" or stanza.attr.type == "set" then
origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
end
diff --git a/plugins/mod_message.lua b/plugins/mod_message.lua
index ebff2fe7..0b0ad8e4 100644
--- a/plugins/mod_message.lua
+++ b/plugins/mod_message.lua
@@ -35,10 +35,13 @@ local function process_to_bare(bare, origin, stanza)
if user then -- some resources are connected
local recipients = user.top_resources;
if recipients then
+ local sent;
for i=1,#recipients do
- recipients[i].send(stanza);
+ sent = recipients[i].send(stanza) or sent;
+ end
+ if sent then
+ return true;
end
- return true;
end
end
-- no resources are online
@@ -65,9 +68,7 @@ module:hook("message/full", function(data)
local origin, stanza = data.origin, data.stanza;
local session = full_sessions[stanza.attr.to];
- if session then
- -- TODO fire post processing event
- session.send(stanza);
+ if session and session.send(stanza) then
return true;
else -- resource not online
return process_to_bare(jid_bare(stanza.attr.to), origin, stanza);
diff --git a/plugins/mod_motd.lua b/plugins/mod_motd.lua
index 39b74de9..ddde9c78 100644
--- a/plugins/mod_motd.lua
+++ b/plugins/mod_motd.lua
@@ -24,7 +24,7 @@ module:hook("presence/bare", function (event)
local motd_stanza =
st.message({ to = session.full_jid, from = motd_jid })
:tag("body"):text(motd_text);
- core_route_stanza(hosts[host], motd_stanza);
+ module:send(motd_stanza);
module:log("debug", "MOTD send to user %s", session.full_jid);
end
end, 1);
diff --git a/plugins/mod_pep.lua b/plugins/mod_pep.lua
index bbdd5f19..c2261e5f 100644
--- a/plugins/mod_pep.lua
+++ b/plugins/mod_pep.lua
@@ -17,6 +17,7 @@ local pairs, ipairs = pairs, ipairs;
local next = next;
local type = type;
local calculate_hash = require "util.caps".calculate_hash;
+local core_post_stanza = prosody.core_post_stanza;
local NULL = {};
local data = {};
@@ -32,7 +33,7 @@ module.restore = function(state)
hash_map = state.hash_map or {};
end
-module:add_identity("pubsub", "pep", "Prosody");
+module:add_identity("pubsub", "pep", module:get_option_string("name", "Prosody"));
module:add_feature("http://jabber.org/protocol/pubsub#publish");
local function subscription_presence(user_bare, recipient)
diff --git a/plugins/mod_posix.lua b/plugins/mod_posix.lua
index 1670ac95..db594ccc 100644
--- a/plugins/mod_posix.lua
+++ b/plugins/mod_posix.lua
@@ -34,19 +34,19 @@ module:hook("server-started", function ()
if gid then
local success, msg = pposix.setgid(gid);
if success then
- module:log("debug", "Changed group to "..gid.." successfully.");
+ module:log("debug", "Changed group to %s successfully.", gid);
else
- module:log("error", "Failed to change group to "..gid..". Error: "..msg);
- prosody.shutdown("Failed to change group to "..gid);
+ module:log("error", "Failed to change group to %s. Error: %s", gid, msg);
+ prosody.shutdown("Failed to change group to %s", gid);
end
end
if uid then
local success, msg = pposix.setuid(uid);
if success then
- module:log("debug", "Changed user to "..uid.." successfully.");
+ module:log("debug", "Changed user to %s successfully.", uid);
else
- module:log("error", "Failed to change user to "..uid..". Error: "..msg);
- prosody.shutdown("Failed to change user to "..uid);
+ module:log("error", "Failed to change user to %s. Error: %s", uid, msg);
+ prosody.shutdown("Failed to change user to %s", uid);
end
end
end);
diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua
index 6d039d83..dac86ae6 100644
--- a/plugins/mod_presence.lua
+++ b/plugins/mod_presence.lua
@@ -14,6 +14,7 @@ local t_concat, t_insert = table.concat, table.insert;
local s_find = string.find;
local tonumber = tonumber;
+local core_post_stanza = prosody.core_post_stanza;
local st = require "util.stanza";
local jid_split = require "util.jid".split;
local jid_bare = require "util.jid".bare;
@@ -160,7 +161,7 @@ function send_presence_of_available_resources(user, host, jid, recipient_session
end
end
end
- log("debug", "broadcasted presence of "..count.." resources from "..user.."@"..host.." to "..jid);
+ log("debug", "broadcasted presence of %d resources from %s@%s to %s", count, user, host, jid);
return count;
end
@@ -169,7 +170,7 @@ function handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_
if to_bare == from_bare then return; end -- No self contacts
local st_from, st_to = stanza.attr.from, stanza.attr.to;
stanza.attr.from, stanza.attr.to = from_bare, to_bare;
- log("debug", "outbound presence "..stanza.attr.type.." from "..from_bare.." for "..to_bare);
+ log("debug", "outbound presence %s from %s for %s", stanza.attr.type, from_bare, to_bare);
if stanza.attr.type == "probe" then
stanza.attr.from, stanza.attr.to = st_from, st_to;
return;
@@ -214,7 +215,7 @@ function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_b
local node, host = jid_split(to_bare);
local st_from, st_to = stanza.attr.from, stanza.attr.to;
stanza.attr.from, stanza.attr.to = from_bare, to_bare;
- log("debug", "inbound presence "..stanza.attr.type.." from "..from_bare.." for "..to_bare);
+ log("debug", "inbound presence %s from %s for %s", stanza.attr.type, from_bare, to_bare);
if stanza.attr.type == "probe" then
local result, err = rostermanager.is_contact_subscribed(node, host, from_bare);
@@ -352,13 +353,15 @@ module:hook("resource-unbind", function(event)
-- Send unavailable presence
if session.presence then
local pres = st.presence{ type = "unavailable" };
- if not(err) or err == "closed" then err = "connection closed"; end
- pres:tag("status"):text("Disconnected: "..err):up();
+ if err then
+ pres:tag("status"):text("Disconnected: "..err):up();
+ end
session:dispatch_stanza(pres);
elseif session.directed then
local pres = st.presence{ type = "unavailable", from = session.full_jid };
- if not(err) or err == "closed" then err = "connection closed"; end
- pres:tag("status"):text("Disconnected: "..err):up();
+ if err then
+ pres:tag("status"):text("Disconnected: "..err):up();
+ end
for jid in pairs(session.directed) do
pres.attr.to = jid;
core_post_stanza(session, pres, true);
diff --git a/plugins/mod_pubsub.lua b/plugins/mod_pubsub.lua
index 2cbd7184..40b119cc 100644
--- a/plugins/mod_pubsub.lua
+++ b/plugins/mod_pubsub.lua
@@ -201,7 +201,7 @@ function simple_broadcast(node, jids, item)
for jid in pairs(jids) do
module:log("debug", "Sending notification to %s", jid);
message.attr.to = jid;
- core_post_stanza(hosts[module.host], message);
+ module:send(message);
end
end
diff --git a/plugins/mod_register.lua b/plugins/mod_register.lua
index 755b718e..6c690c3b 100644
--- a/plugins/mod_register.lua
+++ b/plugins/mod_register.lua
@@ -120,10 +120,10 @@ local function handle_registration_stanza(event)
for jid, item in pairs(roster) do
if jid and jid ~= "pending" then
if item.subscription == "both" or item.subscription == "from" or (roster.pending and roster.pending[jid]) then
- core_post_stanza(hosts[host], st.presence({type="unsubscribed", from=bare, to=jid}));
+ module:send(st.presence({type="unsubscribed", from=bare, to=jid}));
end
if item.subscription == "both" or item.subscription == "to" or item.ask then
- core_post_stanza(hosts[host], st.presence({type="unsubscribe", from=bare, to=jid}));
+ module:send(st.presence({type="unsubscribe", from=bare, to=jid}));
end
end
end
diff --git a/plugins/mod_roster.lua b/plugins/mod_roster.lua
index 96cc15f2..bfb2d927 100644
--- a/plugins/mod_roster.lua
+++ b/plugins/mod_roster.lua
@@ -18,7 +18,7 @@ local pairs, ipairs = pairs, ipairs;
local rm_remove_from_roster = require "core.rostermanager".remove_from_roster;
local rm_add_to_roster = require "core.rostermanager".add_to_roster;
local rm_roster_push = require "core.rostermanager".roster_push;
-local core_post_stanza = core_post_stanza;
+local core_post_stanza = prosody.core_post_stanza;
module:add_feature("jabber:iq:roster");
diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua
index f6c20606..321ed0d7 100644
--- a/plugins/mod_s2s/mod_s2s.lua
+++ b/plugins/mod_s2s/mod_s2s.lua
@@ -10,7 +10,7 @@ module:set_global();
local prosody = prosody;
local hosts = prosody.hosts;
-local core_process_stanza = core_process_stanza;
+local core_process_stanza = prosody.core_process_stanza;
local tostring, type = tostring, type;
local t_insert = table.insert;
@@ -30,7 +30,8 @@ local cert_verify_identity = require "util.x509".verify_identity;
local s2sout = module:require("s2sout");
-local connect_timeout = module:get_option_number("s2s_timeout", 60);
+local connect_timeout = module:get_option_number("s2s_timeout", 90);
+local stream_close_timeout = module:get_option_number("s2s_close_timeout", 5);
local sessions = module:shared("sessions");
@@ -97,9 +98,10 @@ function route_to_existing_session(event)
log("error", "WARNING! This might, possibly, be a bug, but it might not...");
log("error", "We are going to send from %s instead of %s", tostring(host.from_host), tostring(from_host));
end
- host.sends2s(stanza);
- host.log("debug", "stanza sent over "..host.type);
- return true;
+ if host.sends2s(stanza) then
+ host.log("debug", "stanza sent over %s", host.type);
+ return true;
+ end
end
end
end
@@ -288,19 +290,7 @@ end
function stream_callbacks.streamclosed(session)
(session.log or log)("debug", "Received </stream:stream>");
- session:close();
-end
-
-function stream_callbacks.streamdisconnected(session, err)
- if err and err ~= "closed" and session.direction == "outgoing" and session.notopen then
- (session.log or log)("debug", "s2s connection attempt failed: %s", err);
- if s2sout.attempt_connection(session, err) then
- (session.log or log)("debug", "...so we're going to try another target");
- return true; -- Session lives for now
- end
- end
- (session.log or log)("info", "s2s disconnected: %s->%s (%s)", tostring(session.from_host), tostring(session.to_host), tostring(err or "closed"));
- s2s_destroy_session(session, err);
+ session:close(false);
end
function stream_callbacks.error(session, error, data)
@@ -352,9 +342,9 @@ local function session_close(session, reason, remote_reason)
session.sends2s("<?xml version='1.0'?>");
session.sends2s(st.stanza("stream:stream", default_stream_attr):top_tag());
end
- if reason then
+ if reason then -- nil == no err, initiated by us, false == initiated by remote
if type(reason) == "string" then -- assume stream error
- log("info", "Disconnecting %s[%s], <stream:error> is: %s", session.host or "(unknown host)", session.type, reason);
+ log("debug", "Disconnecting %s[%s], <stream:error> is: %s", session.host or "(unknown host)", session.type, reason);
session.sends2s(st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' }));
elseif type(reason) == "table" then
if reason.condition then
@@ -365,20 +355,35 @@ local function session_close(session, reason, remote_reason)
if reason.extra then
stanza:add_child(reason.extra);
end
- log("info", "Disconnecting %s[%s], <stream:error> is: %s", session.host or "(unknown host)", session.type, tostring(stanza));
+ log("debug", "Disconnecting %s[%s], <stream:error> is: %s", session.host or "(unknown host)", session.type, tostring(stanza));
session.sends2s(stanza);
elseif reason.name then -- a stanza
- log("info", "Disconnecting %s->%s[%s], <stream:error> is: %s", session.from_host or "(unknown host)", session.to_host or "(unknown host)", session.type, tostring(reason));
+ log("debug", "Disconnecting %s->%s[%s], <stream:error> is: %s", session.from_host or "(unknown host)", session.to_host or "(unknown host)", session.type, tostring(reason));
session.sends2s(reason);
end
end
end
+
session.sends2s("</stream:stream>");
- if session.notopen or not session.conn:close() then
- session.conn:close(true); -- Force FIXME: timer?
+ function session.sends2s() return false; end
+
+ local reason = remote_reason or (reason and (reason.text or reason.condition)) or reason;
+ session.log("info", "%s s2s stream %s->%s closed: %s", session.direction, session.from_host or "(unknown host)", session.to_host or "(unknown host)", reason or "stream closed");
+
+ -- Authenticated incoming stream may still be sending us stanzas, so wait for </stream:stream> from remote
+ local conn = session.conn;
+ if reason == nil and not session.notopen and session.type == "s2sin" then
+ add_task(stream_close_timeout, function ()
+ if not session.destroyed then
+ session.log("warn", "Failed to receive a stream close response, closing connection anyway...");
+ s2s_destroy_session(session, reason);
+ conn:close();
+ end
+ end);
+ else
+ s2s_destroy_session(session, reason);
+ conn:close(); -- Close immediately, as this is an outgoing connection or is not authed
end
- session.conn:close();
- listener.ondisconnect(session.conn, remote_reason or (reason and (reason.text or reason.condition)) or reason or "stream closed");
end
end
@@ -413,11 +418,9 @@ local function initialize_session(session)
return handlestanza(session, stanza);
end
- local conn = session.conn;
add_task(connect_timeout, function ()
- if session.conn ~= conn or session.connecting
- or session.type == "s2sin" or session.type == "s2sout" then
- return; -- Ok, we're connect[ed|ing]
+ if session.type == "s2sin" or session.type == "s2sout" then
+ return; -- Ok, we're connected
end
-- Not connected, need to close session and clean up
(session.log or log)("debug", "Destroying incomplete session %s->%s due to inactivity",
@@ -474,11 +477,17 @@ end
function listener.ondisconnect(conn, err)
local session = sessions[conn];
if session then
- if stream_callbacks.streamdisconnected(session, err) then
- return; -- Connection lives, for now
+ if err and session.direction == "outgoing" and session.notopen then
+ (session.log or log)("debug", "s2s connection attempt failed: %s", err);
+ if s2sout.attempt_connection(session, err) then
+ (session.log or log)("debug", "...so we're going to try another target");
+ return; -- Session lives for now
+ end
end
+ (session.log or log)("debug", "s2s disconnected: %s->%s (%s)", tostring(session.from_host), tostring(session.to_host), tostring(err or "connection closed"));
+ s2s_destroy_session(session, err);
+ sessions[conn] = nil;
end
- sessions[conn] = nil;
end
function listener.register_outgoing(conn, session)
diff --git a/plugins/mod_s2s/s2sout.lib.lua b/plugins/mod_s2s/s2sout.lib.lua
index 48a49036..17978b39 100644
--- a/plugins/mod_s2s/s2sout.lib.lua
+++ b/plugins/mod_s2s/s2sout.lib.lua
@@ -95,14 +95,14 @@ function s2sout.attempt_connection(host_session, err)
handle = nil;
host_session.connecting = nil;
if answer then
- log("debug", to_host.." has SRV records, handling...");
+ log("debug", "%s has SRV records, handling...", to_host);
local srv_hosts = {};
host_session.srv_hosts = srv_hosts;
for _, record in ipairs(answer) do
t_insert(srv_hosts, record.srv);
end
if #srv_hosts == 1 and srv_hosts[1].target == "." then
- log("debug", to_host.." does not provide a XMPP service");
+ log("debug", "%s does not provide a XMPP service", to_host);
s2s_destroy_session(host_session, err); -- Nothing to see here
return;
end
@@ -115,7 +115,7 @@ function s2sout.attempt_connection(host_session, err)
log("debug", "Best record found, will connect to %s:%d", connect_host, connect_port);
end
else
- log("debug", to_host.." has no SRV records, falling back to A/AAAA");
+ log("debug", "%s has no SRV records, falling back to A/AAAA", to_host);
end
-- Try with SRV, or just the plain hostname if no SRV
local ok, err = s2sout.try_connect(host_session, connect_host, connect_port);
@@ -170,92 +170,91 @@ function s2sout.try_connect(host_session, connect_host, connect_port, err)
local IPs = {};
host_session.ip_hosts = IPs;
local handle4, handle6;
- local has_other = false;
+ local have_other_result = not(has_ipv4) or not(has_ipv6) or false;
if has_ipv4 then
- handle4 = adns.lookup(function (reply, err)
- handle4 = nil;
-
- -- COMPAT: This is a compromise for all you CNAME-(ab)users :)
- if not (reply and reply[#reply] and reply[#reply].a) then
- local count = max_dns_depth;
- reply = dns.peek(connect_host, "CNAME", "IN");
- while count > 0 and reply and reply[#reply] and not reply[#reply].a and reply[#reply].cname do
- log("debug", "Looking up %s (DNS depth is %d)", tostring(reply[#reply].cname), count);
- reply = dns.peek(reply[#reply].cname, "A", "IN") or dns.peek(reply[#reply].cname, "CNAME", "IN");
- count = count - 1;
+ handle4 = adns.lookup(function (reply, err)
+ handle4 = nil;
+
+ -- COMPAT: This is a compromise for all you CNAME-(ab)users :)
+ if not (reply and reply[#reply] and reply[#reply].a) then
+ local count = max_dns_depth;
+ reply = dns.peek(connect_host, "CNAME", "IN");
+ while count > 0 and reply and reply[#reply] and not reply[#reply].a and reply[#reply].cname do
+ log("debug", "Looking up %s (DNS depth is %d)", tostring(reply[#reply].cname), count);
+ reply = dns.peek(reply[#reply].cname, "A", "IN") or dns.peek(reply[#reply].cname, "CNAME", "IN");
+ count = count - 1;
+ end
end
- end
- -- end of CNAME resolving
+ -- end of CNAME resolving
- if reply and reply[#reply] and reply[#reply].a then
- for _, ip in ipairs(reply) do
- log("debug", "DNS reply for %s gives us %s", connect_host, ip.a);
- IPs[#IPs+1] = new_ip(ip.a, "IPv4");
+ if reply and reply[#reply] and reply[#reply].a then
+ for _, ip in ipairs(reply) do
+ log("debug", "DNS reply for %s gives us %s", connect_host, ip.a);
+ IPs[#IPs+1] = new_ip(ip.a, "IPv4");
+ end
end
- end
- if has_other then
- if #IPs > 0 then
- rfc3484_dest(host_session.ip_hosts, sources);
- for i = 1, #IPs do
- IPs[i] = {ip = IPs[i], port = connect_port};
+ if have_other_result then
+ if #IPs > 0 then
+ rfc3484_dest(host_session.ip_hosts, sources);
+ for i = 1, #IPs do
+ IPs[i] = {ip = IPs[i], port = connect_port};
+ end
+ host_session.ip_choice = 0;
+ s2sout.try_next_ip(host_session);
+ else
+ log("debug", "DNS lookup failed to get a response for %s", connect_host);
+ host_session.ip_hosts = nil;
+ if not s2sout.attempt_connection(host_session, "name resolution failed") then -- Retry if we can
+ log("debug", "No other records to try for %s - destroying", host_session.to_host);
+ err = err and (": "..err) or "";
+ s2s_destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't
+ end
end
- host_session.ip_choice = 0;
- s2sout.try_next_ip(host_session);
else
- log("debug", "DNS lookup failed to get a response for %s", connect_host);
- host_session.ip_hosts = nil;
- if not s2sout.attempt_connection(host_session, "name resolution failed") then -- Retry if we can
- log("debug", "No other records to try for %s - destroying", host_session.to_host);
- err = err and (": "..err) or "";
- s2s_destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't
- end
+ have_other_result = true;
end
- else
- has_other = true;
- end
- end, connect_host, "A", "IN");
+ end, connect_host, "A", "IN");
else
- has_other = true;
+ have_other_result = true;
end
if has_ipv6 then
- handle6 = adns.lookup(function (reply, err)
- handle6 = nil;
+ handle6 = adns.lookup(function (reply, err)
+ handle6 = nil;
- if reply and reply[#reply] and reply[#reply].aaaa then
- for _, ip in ipairs(reply) do
- log("debug", "DNS reply for %s gives us %s", connect_host, ip.aaaa);
- IPs[#IPs+1] = new_ip(ip.aaaa, "IPv6");
+ if reply and reply[#reply] and reply[#reply].aaaa then
+ for _, ip in ipairs(reply) do
+ log("debug", "DNS reply for %s gives us %s", connect_host, ip.aaaa);
+ IPs[#IPs+1] = new_ip(ip.aaaa, "IPv6");
+ end
end
- end
- if has_other then
- if #IPs > 0 then
- rfc3484_dest(host_session.ip_hosts, sources);
- for i = 1, #IPs do
- IPs[i] = {ip = IPs[i], port = connect_port};
+ if have_other_result then
+ if #IPs > 0 then
+ rfc3484_dest(host_session.ip_hosts, sources);
+ for i = 1, #IPs do
+ IPs[i] = {ip = IPs[i], port = connect_port};
+ end
+ host_session.ip_choice = 0;
+ s2sout.try_next_ip(host_session);
+ else
+ log("debug", "DNS lookup failed to get a response for %s", connect_host);
+ host_session.ip_hosts = nil;
+ if not s2sout.attempt_connection(host_session, "name resolution failed") then -- Retry if we can
+ log("debug", "No other records to try for %s - destroying", host_session.to_host);
+ err = err and (": "..err) or "";
+ s2s_destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't
+ end
end
- host_session.ip_choice = 0;
- s2sout.try_next_ip(host_session);
else
- log("debug", "DNS lookup failed to get a response for %s", connect_host);
- host_session.ip_hosts = nil;
- if not s2sout.attempt_connection(host_session, "name resolution failed") then -- Retry if we can
- log("debug", "No other records to try for %s - destroying", host_session.to_host);
- err = err and (": "..err) or "";
- s2s_destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't
- end
+ have_other_result = true;
end
- else
- has_other = true;
- end
- end, connect_host, "AAAA", "IN");
+ end, connect_host, "AAAA", "IN");
else
- has_other = true;
+ have_other_result = true;
end
-
return true;
elseif host_session.ip_hosts and #host_session.ip_hosts > host_session.ip_choice then -- Not our first attempt, and we also have IPs left to try
s2sout.try_next_ip(host_session);
diff --git a/plugins/mod_saslauth.lua b/plugins/mod_saslauth.lua
index 804db5f9..f6abd3b8 100644
--- a/plugins/mod_saslauth.lua
+++ b/plugins/mod_saslauth.lua
@@ -208,7 +208,7 @@ module:hook("stanza/urn:ietf:params:xml:ns:xmpp-sasl:auth", function(event)
session.sasl_handler = nil; -- allow starting a new SASL negotiation before completing an old one
end
if not session.sasl_handler then
- session.sasl_handler = usermanager_get_sasl_handler(module.host);
+ session.sasl_handler = usermanager_get_sasl_handler(module.host, session);
end
local mechanism = stanza.attr.mechanism;
if not session.secure and (secure_auth_only or (mechanism == "PLAIN" and not allow_unencrypted_plain_auth)) then
@@ -246,7 +246,7 @@ module:hook("stream-features", function(event)
if secure_auth_only and not origin.secure then
return;
end
- origin.sasl_handler = usermanager_get_sasl_handler(module.host);
+ origin.sasl_handler = usermanager_get_sasl_handler(module.host, origin);
local mechanisms = st.stanza("mechanisms", mechanisms_attr);
for mechanism in pairs(origin.sasl_handler:mechanisms()) do
if mechanism ~= "PLAIN" or origin.secure or allow_unencrypted_plain_auth then
diff --git a/plugins/mod_vcard.lua b/plugins/mod_vcard.lua
index e2f1dfb8..d3c27cc0 100644
--- a/plugins/mod_vcard.lua
+++ b/plugins/mod_vcard.lua
@@ -46,13 +46,8 @@ end
module:hook("iq/bare/vcard-temp:vCard", handle_vcard);
module:hook("iq/host/vcard-temp:vCard", handle_vcard);
--- COMPAT: https://support.process-one.net/browse/EJAB-1045
-if module:get_option("vcard_compatibility") then
- module:hook("iq/full", function(data)
- local stanza = data.stanza;
- local payload = stanza.tags[1];
- if stanza.attr.type == "get" and payload.name == "vCard" and payload.attr.xmlns == "vcard-temp" then
- return handle_vcard(data);
- end
- end, 1);
+-- COMPAT w/0.8
+if module:get_option("vcard_compatibility") ~= nil then
+ module:log("error", "The vcard_compatibility option has been removed, see"..
+ "mod_compat_vcard in prosody-modules if you still need this.");
end
diff --git a/plugins/mod_watchregistrations.lua b/plugins/mod_watchregistrations.lua
index ef18d713..abca90bd 100644
--- a/plugins/mod_watchregistrations.lua
+++ b/plugins/mod_watchregistrations.lua
@@ -25,6 +25,6 @@ module:hook("user-registered", function (user)
for jid in registration_watchers do
module:log("debug", "Notifying %s", jid);
message.attr.to = jid;
- core_route_stanza(hosts[host], message);
+ module:send(message);
end
end);
diff --git a/plugins/mod_welcome.lua b/plugins/mod_welcome.lua
index 8f9cca2a..e498f0b3 100644
--- a/plugins/mod_welcome.lua
+++ b/plugins/mod_welcome.lua
@@ -16,6 +16,6 @@ module:hook("user-registered",
local welcome_stanza =
st.message({ to = user.username.."@"..user.host, from = host })
:tag("body"):text(welcome_text:gsub("$(%w+)", user));
- core_route_stanza(hosts[host], welcome_stanza);
+ module:send(welcome_stanza);
module:log("debug", "Welcomed user %s@%s", user.username, user.host);
end);
diff --git a/plugins/muc/mod_muc.lua b/plugins/muc/mod_muc.lua
index 43b8423d..0fa172ee 100644
--- a/plugins/muc/mod_muc.lua
+++ b/plugins/muc/mod_muc.lua
@@ -29,11 +29,11 @@ local st = require "util.stanza";
local uuid_gen = require "util.uuid".generate;
local datamanager = require "util.datamanager";
local um_is_admin = require "core.usermanager".is_admin;
+local hosts = hosts;
rooms = {};
local rooms = rooms;
local persistent_rooms = datamanager.load(nil, muc_host, "persistent") or {};
-local component = hosts[module.host];
-- Configurable options
local max_history_messages = module:get_option_number("max_history_messages");
@@ -42,7 +42,7 @@ local function is_admin(jid)
return um_is_admin(jid, module.host);
end
-local function room_route_stanza(room, stanza) core_post_stanza(component, stanza); end
+local function room_route_stanza(room, stanza) module:send(stanza); end
local function room_save(room, forced)
local node = jid_split(room.jid);
persistent_rooms[room.jid] = room._data.persistent;
@@ -65,19 +65,27 @@ local function room_save(room, forced)
if forced then datamanager.store(nil, muc_host, "persistent", persistent_rooms); end
end
+local persistent_errors = false;
for jid in pairs(persistent_rooms) do
local node = jid_split(jid);
- local data = datamanager.load(node, muc_host, "config") or {};
- local room = muc_new_room(jid, {
- max_history_length = max_history_messages;
- });
- room._data = data._data;
- room._data.max_history_length = max_history_messages; -- Overwrite old max_history_length in data with current settings
- room._affiliations = data._affiliations;
- room.route_stanza = room_route_stanza;
- room.save = room_save;
- rooms[jid] = room;
+ local data = datamanager.load(node, muc_host, "config");
+ if data then
+ local room = muc_new_room(jid, {
+ max_history_length = max_history_messages;
+ });
+ room._data = data._data;
+ room._data.max_history_length = max_history_messages; -- Overwrite old max_history_length in data with current settings
+ room._affiliations = data._affiliations;
+ room.route_stanza = room_route_stanza;
+ room.save = room_save;
+ rooms[jid] = room;
+ else -- missing room data
+ persistent_rooms[jid] = nil;
+ module:log("error", "Missing data for room '%s', removing from persistent room list", jid);
+ persistent_errors = true;
+ end
end
+if persistent_errors then datamanager.store(nil, muc_host, "persistent", persistent_rooms); end
local host_room = muc_new_room(muc_host, {
max_history_length = max_history_messages;
@@ -160,11 +168,11 @@ module:hook("presence/host", handle_to_domain, -1);
hosts[module.host].send = function(stanza) -- FIXME do a generic fix
if stanza.attr.type == "result" or stanza.attr.type == "error" then
- core_post_stanza(component, stanza);
+ module:send(stanza);
else error("component.send only supports result and error stanzas at the moment"); end
end
-prosody.hosts[module:get_host()].muc = { rooms = rooms };
+hosts[module:get_host()].muc = { rooms = rooms };
module.save = function()
return {rooms = rooms};
@@ -180,5 +188,5 @@ module.restore = function(data)
room.save = room_save;
rooms[jid] = room;
end
- prosody.hosts[module:get_host()].muc = { rooms = rooms };
+ hosts[module:get_host()].muc = { rooms = rooms };
end
diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua
index 5178cb1e..a40dc05f 100644
--- a/plugins/muc/muc.lib.lua
+++ b/plugins/muc/muc.lib.lua
@@ -856,7 +856,7 @@ function room_mt:handle_to_room(origin, stanza) -- presence changes and groupcha
if not occupant then -- not in room
origin.send(st.error_reply(stanza, "cancel", "not-acceptable"));
elseif occupant.role == "visitor" then
- origin.send(st.error_reply(stanza, "cancel", "forbidden"));
+ origin.send(st.error_reply(stanza, "auth", "forbidden"));
else
local from = stanza.attr.from;
stanza.attr.from = current_nick;
@@ -867,7 +867,7 @@ function room_mt:handle_to_room(origin, stanza) -- presence changes and groupcha
self:set_subject(current_nick, subject); -- TODO use broadcast_message_stanza
else
stanza.attr.from = from;
- origin.send(st.error_reply(stanza, "cancel", "forbidden"));
+ origin.send(st.error_reply(stanza, "auth", "forbidden"));
end
else
self:broadcast_message(stanza, self:get_historylength() > 0);
diff --git a/prosodyctl b/prosodyctl
index 0817db35..c658921b 100755
--- a/prosodyctl
+++ b/prosodyctl
@@ -688,7 +688,7 @@ function cert_commands.key(arg)
show_message("There was a problem, see OpenSSL output");
else
show_usage("cert key HOSTNAME <bits>", "Generates a RSA key named HOSTNAME.key\n "
- .."Promps for a key size if none given")
+ .."Prompts for a key size if none given")
end
end
diff --git a/util-src/pposix.c b/util-src/pposix.c
index dae48390..65f8b4ab 100644
--- a/util-src/pposix.c
+++ b/util-src/pposix.c
@@ -34,6 +34,11 @@
#include "lua.h"
#include "lauxlib.h"
+#if (defined(_SVID_SOURCE) && !defined(WITHOUT_MALLINFO))
+ #include <malloc.h>
+ #define WITH_MALLINFO
+#endif
+
/* Daemonization support */
static int lc_daemonize(lua_State *L)
@@ -581,6 +586,62 @@ int lc_uname(lua_State* L)
return 1;
}
+int lc_setenv(lua_State* L)
+{
+ const char *var = luaL_checkstring(L, 1);
+ const char *value;
+
+ /* If the second argument is nil or nothing, unset the var */
+ if(lua_isnoneornil(L, 2))
+ {
+ if(unsetenv(var) != 0)
+ {
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(errno));
+ return 2;
+ }
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+
+ value = luaL_checkstring(L, 2);
+
+ if(setenv(var, value, 1) != 0)
+ {
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(errno));
+ return 2;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+#ifdef WITH_MALLINFO
+int lc_meminfo(lua_State* L)
+{
+ struct mallinfo info = mallinfo();
+ lua_newtable(L);
+ /* This is the total size of memory allocated with sbrk by malloc, in bytes. */
+ lua_pushinteger(L, info.arena);
+ lua_setfield(L, -2, "allocated");
+ /* This is the total size of memory allocated with mmap, in bytes. */
+ lua_pushinteger(L, info.hblkhd);
+ lua_setfield(L, -2, "allocated_mmap");
+ /* This is the total size of memory occupied by chunks handed out by malloc. */
+ lua_pushinteger(L, info.uordblks);
+ lua_setfield(L, -2, "used");
+ /* This is the total size of memory occupied by free (not in use) chunks. */
+ lua_pushinteger(L, info.fordblks);
+ lua_setfield(L, -2, "unused");
+ /* This is the size of the top-most releasable chunk that normally borders the
+ end of the heap (i.e., the high end of the virtual address space's data segment). */
+ lua_pushinteger(L, info.keepcost);
+ lua_setfield(L, -2, "returnable");
+ return 1;
+}
+#endif
+
/* Register functions */
int luaopen_util_pposix(lua_State *L)
@@ -612,6 +673,12 @@ int luaopen_util_pposix(lua_State *L)
{ "uname", lc_uname },
+ { "setenv", lc_setenv },
+
+#ifdef WITH_MALLINFO
+ { "meminfo", lc_meminfo },
+#endif
+
{ NULL, NULL }
};
diff --git a/util/dataforms.lua b/util/dataforms.lua
index 8cb39144..55bad998 100644
--- a/util/dataforms.lua
+++ b/util/dataforms.lua
@@ -185,7 +185,7 @@ field_readers["list-multi"] =
function (field_tag, required)
local result = {};
for value in field_tag:childtags("value") do
- result[#result+1] = value;
+ result[#result+1] = value:get_text();
end
return result, (required and #result == 0 and "Required value missing" or nil);
end
@@ -202,10 +202,10 @@ field_readers["text-multi"] =
field_readers["list-single"] =
field_readers["text-single"];
- local boolean_values = {
- ["1"] = true, ["true"] = true,
- ["0"] = false, ["false"] = false,
- };
+local boolean_values = {
+ ["1"] = true, ["true"] = true,
+ ["0"] = false, ["false"] = false,
+};
field_readers["boolean"] =
function (field_tag, required)
diff --git a/util/datamanager.lua b/util/datamanager.lua
index 884d1161..344d2eb1 100644
--- a/util/datamanager.lua
+++ b/util/datamanager.lua
@@ -116,18 +116,18 @@ function load(username, host, datastore)
if not data then
local mode = lfs.attributes(getpath(username, host, datastore), "mode");
if not mode then
- log("debug", "Assuming empty "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ log("debug", "Assuming empty %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
return nil;
else -- file exists, but can't be read
-- TODO more detailed error checking and logging?
- log("error", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ log("error", "Failed to load %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
return nil, "Error reading storage";
end
end
local success, ret = pcall(data);
if not success then
- log("error", "Unable to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ log("error", "Unable to load %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
return nil, "Error reading storage";
end
return ret;
@@ -146,7 +146,7 @@ function store(username, host, datastore, data)
-- save the datastore
local f, msg = io_open(getpath(username, host, datastore, nil, true), "w+");
if not f then
- log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ log("error", "Unable to write to %s storage ('%s') for user: %s@%s", datastore, msg, username or "nil", host or "nil");
return nil, "Error saving to storage";
end
f:write("return ");
@@ -167,7 +167,7 @@ function list_append(username, host, datastore, data)
-- save the datastore
local f, msg = io_open(getpath(username, host, datastore, "list", true), "a+");
if not f then
- log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ log("error", "Unable to write to %s storage ('%s') for user: %s@%s", datastore, msg, username or "nil", host or "nil");
return;
end
f:write("item(");
@@ -185,7 +185,7 @@ function list_store(username, host, datastore, data)
-- save the datastore
local f, msg = io_open(getpath(username, host, datastore, "list", true), "w+");
if not f then
- log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ log("error", "Unable to write to %s storage ('%s') for user: %s@%s", datastore, msg, username or "nil", host or "nil");
return;
end
for _, d in ipairs(data) do
@@ -209,18 +209,18 @@ function list_load(username, host, datastore)
if not data then
local mode = lfs.attributes(getpath(username, host, datastore, "list"), "mode");
if not mode then
- log("debug", "Assuming empty "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ log("debug", "Assuming empty %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
return nil;
else -- file exists, but can't be read
-- TODO more detailed error checking and logging?
- log("error", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ log("error", "Failed to load %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
return nil, "Error reading storage";
end
end
local success, ret = pcall(data);
if not success then
- log("error", "Unable to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ log("error", "Unable to load %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
return nil, "Error reading storage";
end
return items;
diff --git a/util/logger.lua b/util/logger.lua
index 4fadb4b9..26206d4d 100644
--- a/util/logger.lua
+++ b/util/logger.lua
@@ -23,8 +23,6 @@ function init(name)
local log_warn = make_logger(name, "warn");
local log_error = make_logger(name, "error");
- --name = nil; -- While this line is not commented, will automatically fill in file/line number info
- local namelen = #name;
return function (level, message, ...)
if level == "debug" then
return log_debug(message, ...);
diff --git a/util/sasl.lua b/util/sasl.lua
index 17d10b80..afb3861b 100644
--- a/util/sasl.lua
+++ b/util/sasl.lua
@@ -35,7 +35,7 @@ local mechanisms = {};
local backend_mechanism = {};
-- register a new SASL mechanims
-local function registerMechanism(name, backends, f)
+function registerMechanism(name, backends, f)
assert(type(name) == "string", "Parameter name MUST be a string.");
assert(type(backends) == "string" or type(backends) == "table", "Parameter backends MUST be either a string or a table.");
assert(type(f) == "function", "Parameter f MUST be a function.");
diff --git a/util/sasl_cyrus.lua b/util/sasl_cyrus.lua
index 002118fd..19684587 100644
--- a/util/sasl_cyrus.lua
+++ b/util/sasl_cyrus.lua
@@ -78,11 +78,15 @@ local function init(service_name)
end
-- create a new SASL object which can be used to authenticate clients
-function new(realm, service_name, app_name)
+-- host_fqdn may be nil in which case gethostname() gives the value.
+-- For GSSAPI, this determines the hostname in the service ticket (after
+-- reverse DNS canonicalization, only if [libdefaults] rdns = true which
+-- is the default).
+function new(realm, service_name, app_name, host_fqdn)
init(app_name or service_name);
- local st, ret = pcall(cyrussasl.server_new, service_name, nil, realm, nil, nil)
+ local st, ret = pcall(cyrussasl.server_new, service_name, host_fqdn, realm, nil, nil)
if not st then
log("error", "Creating SASL server connection failed: %s", ret);
return nil;
diff --git a/util/stanza.lua b/util/stanza.lua
index 1449f707..5c430f1d 100644
--- a/util/stanza.lua
+++ b/util/stanza.lua
@@ -133,14 +133,14 @@ function stanza_mt:children()
end
function stanza_mt:childtags(name, xmlns)
- xmlns = xmlns or self.attr.xmlns;
local tags = self.tags;
local start_i, max_i = 1, #tags;
return function ()
for i = start_i, max_i do
local v = tags[i];
if (not name or v.name == name)
- and (not xmlns or xmlns == v.attr.xmlns) then
+ and ((not xmlns and self.attr.xmlns == v.attr.xmlns)
+ or v.attr.xmlns == xmlns) then
start_i = i+1;
return v;
end
diff --git a/util/throttle.lua b/util/throttle.lua
index 2e901158..55e1d07b 100644
--- a/util/throttle.lua
+++ b/util/throttle.lua
@@ -1,6 +1,7 @@
local gettime = require "socket".gettime;
local setmetatable = setmetatable;
+local floor = math.floor;
module "throttle"
@@ -11,7 +12,7 @@ function throttle:update()
local newt = gettime();
local elapsed = newt - self.t;
self.t = newt;
- local balance = self.rate * elapsed + self.balance;
+ local balance = floor(self.rate * elapsed) + self.balance;
if balance > self.max then
self.balance = self.max;
else