-
---[[
--- Helper function to deal with errors processing component stanzas
-local function handleerr(err) log("error", "Traceback[component]: %s: %s", tostring(err), debug.traceback()); end
-function stream_callbacks.handlestanza(a, b)
- xpcall(function () core_process_stanza(a, b) end, handleerr);
-end
-]]
-
---- Closing a component connection
-local stream_xmlns_attr = {xmlns='urn:ietf:params:xml:ns:xmpp-streams'};
-local function session_close(session, reason)
- local log = session.log or log;
- if session.conn then
- if reason then
- if type(reason) == "string" then -- assume stream error
- log("info", "Disconnecting component, <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
- local stanza = st.stanza("stream:error"):tag(reason.condition, stream_xmlns_attr):up();
- if reason.text then
- stanza:tag("text", stream_xmlns_attr):text(reason.text):up();
- end
- if reason.extra then
- stanza:add_child(reason.extra);
- end
- log("info", "Disconnecting component, <stream:error> is: %s", tostring(stanza));
- session.send(stanza);
- elseif reason.name then -- a stanza
- log("info", "Disconnecting component, <stream:error> is: %s", tostring(reason));
- session.send(reason);
- end
- end
- end
- session.send("</stream:stream>");
- session.conn.close();
- component_listener.disconnect(session.conn, "stream error");
- end
-end
-
---- Component connlistener
-function component_listener.listener(conn, data)
- local session = sessions[conn];
- if not session then
- local _send = conn.write;
- session = { type = "component", conn = conn, send = function (data) return _send(tostring(data)); end };
- sessions[conn] = session;
-
- -- Logging functions --
-
- local conn_name = "xep114-"..tostring(conn):match("[a-f0-9]+$");
- session.log = logger.init(conn_name);
- session.close = session_close;
-
- session.log("info", "Incoming XEP-0114 connection");
-
- local parser = lxp.new(init_xmlhandlers(session, stream_callbacks), "|");
- session.parser = parser;
-
- session.notopen = true;
-
- function session.data(conn, data)
- local ok, err = parser:parse(data);
- if ok then return; end
- session:close("xml-not-well-formed");
- end
-
- session.dispatch_stanza = stream_callbacks.handlestanza;
-
- end
- if data then
- session.data(conn, data);
- end
-end
-
-function component_listener.disconnect(conn, err)
- local session = sessions[conn];
- if session then
- (session.log or log)("info", "component disconnected: %s (%s)", tostring(session.host), tostring(err));
- if session.host then
- if session.component then
- deregister_component(session.host);
- end
- end
- sessions[conn] = nil;
- session = nil;
- collectgarbage("collect");
- end
-end
-
-connlisteners.register('component', component_listener);
-
-module:add_event_hook("server-starting", function () connlisteners.start("component"); end);