File

plugins/adhoc/adhoc.lib.lua @ 10486:479e96e554c8

net.server_epoll: Add debug logging for delayed reading In :onreadable, if there is still buffered incoming data after reading from the socket (as indicated by the :dirty method, usually because LuaSocket has an 8k buffer that's full but it read a smaller amount), another attempt to read is scheduled via this :pausefor method. This is also called from some other places where it would be pointless to read because there shouldn't be any data. In the delayed read case, this should report that the socket is "dirty". If it reports that the socket is "clean" then the question is where the buffer contents went? If this doesn't get logged after the scheduled time (0.000001s by default) then this would suggests a problem with timer or scheduling.
author Kim Alvefur <zash@zash.se>
date Sat, 07 Dec 2019 19:05:10 +0100
parent 8472:d88dc6827675
child 10565:421b2f8369fd
line wrap: on
line source

-- Copyright (C) 2009-2010 Florian Zeitz
--
-- This file is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--

local st, uuid = require "util.stanza", require "util.uuid";

local xmlns_cmd = "http://jabber.org/protocol/commands";

local states = {}

local _M = {};

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

	return cmd;
end

function _M.new(name, node, handler, permission)
	return { name = name, node = node, handler = handler, cmdtag = _cmdtag, permission = (permission or "user") };
end

function _M.handle_cmd(command, origin, stanza)
	local cmdtag = stanza.tags[1]
	local sessionid = cmdtag.attr.sessionid or uuid.generate();
	local dataIn = {
		to = stanza.attr.to;
		from = stanza.attr.from;
		action = cmdtag.attr.action or "execute";
		form = cmdtag:get_child("x", "jabber:x:data");
	};

	local data, state = command:handler(dataIn, states[sessionid]);
	states[sessionid] = state;
	local cmdreply;
	if data.status == "completed" then
		states[sessionid] = nil;
		cmdreply = command:cmdtag("completed", sessionid);
	elseif data.status == "canceled" then
		states[sessionid] = nil;
		cmdreply = command:cmdtag("canceled", sessionid);
	elseif data.status == "error" then
		states[sessionid] = nil;
		local reply = st.error_reply(stanza, data.error.type, data.error.condition, data.error.message);
		origin.send(reply);
		return true;
	else
		cmdreply = command:cmdtag("executing", sessionid);
		data.actions = data.actions or { "complete" };
	end

	for name, content in pairs(data) do
		if name == "info" then
			cmdreply:tag("note", {type="info"}):text(content):up();
		elseif name == "warn" then
			cmdreply:tag("note", {type="warn"}):text(content):up();
		elseif name == "error" then
			cmdreply:tag("note", {type="error"}):text(content.message):up();
		elseif name == "actions" then
			local actions = st.stanza("actions", { execute = content.default });
			for _, action in ipairs(content) do
				if (action == "prev") or (action == "next") or (action == "complete") then
					actions:tag(action):up();
				else
					module:log("error", "Command %q at node %q provided an invalid action %q",
						command.name, command.node, action);
				end
			end
			cmdreply:add_child(actions);
		elseif name == "form" then
			cmdreply:add_child((content.layout or content):form(content.values));
		elseif name == "result" then
			cmdreply:add_child((content.layout or content):form(content.values, "result"));
		elseif name == "other" then
			cmdreply:add_child(content);
		end
	end
	local reply = st.reply(stanza);
	reply:add_child(cmdreply);
	origin.send(reply);

	return true;
end

return _M;