Mercurial > prosody-modules
view mod_tcpproxy/mod_tcpproxy.lua @ 234:abcb59ab355c
Add new motd_sequential module. This module lets you define numbered messages shown to each user in order, but only once per user, and persistent across server restarts. Useful for notifying users of added features and changes in an
incremental fashion.
author | Jeff Mitchell <jeffrey.mitchell@gmail.com> |
---|---|
date | Wed, 04 Aug 2010 22:29:51 +0000 |
parents | 31e24026e4fd |
children | 07c1c3eaf0c4 |
line wrap: on
line source
local st = require "util.stanza"; local xmlns_ibb = "http://jabber.org/protocol/ibb"; local xmlns_tcp = "http://prosody.im/protocol/tcpproxy"; local host_attr, port_attr = xmlns_tcp.."\1host", xmlns_tcp.."\1port"; local base64 = require "util.encodings".base64; local b64, unb64 = base64.encode, base64.decode; local host = module.host; local open_connections = {}; local function new_session(jid, sid, conn) if not open_connections[jid] then open_connections[jid] = {}; end open_connections[jid][sid] = conn; end local function close_session(jid, sid) if open_connections[jid] then open_connections[jid][sid] = nil; if next(open_connections[jid]) == nil then open_connections[jid] = nil; end return true; end end function proxy_component(origin, stanza) local ibb_tag = stanza.tags[1]; if (not (stanza.name == "iq" and stanza.attr.type == "set") and stanza.name ~= "message") or (not (ibb_tag) or ibb_tag.attr.xmlns ~= xmlns_ibb) then if stanza.attr.type ~= "error" then origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); end return; end if ibb_tag.name == "open" then -- Starting a new stream local to_host, to_port = ibb_tag.attr[host_attr], ibb_tag.attr[port_attr]; local jid, sid = stanza.attr.from, ibb_tag.attr.sid; if not (to_host and to_port) then return origin.send(st.error_reply(stanza, "modify", "bad-request", "No host/port specified")); elseif not sid or sid == "" then return origin.send(st.error_reply(stanza, "modify", "bad-request", "No sid specified")); elseif ibb_tag.attr.stanza ~= "message" then return origin.send(st.error_reply(stanza, "modify", "bad-request", "Only 'message' stanza transport is supported")); end local conn, err = socket.tcp(); if not conn then return origin.send(st.error_reply(stanza, "wait", "resource-constraint", err)); end conn:settimeout(0); local success, err = conn:connect(to_host, to_port); if not success and err ~= "timeout" then return origin.send(st.error_reply(stanza, "wait", "remote-server-not-found", err)); end local listener,seq = {}, 0; function listener.onconnect(conn) origin.send(st.reply(stanza)); end function listener.onincoming(conn, data) origin.send(st.message({to=jid,from=host}) :tag("data", {xmlns=xmlns_ibb,seq=seq,sid=sid}) :text(b64(data))); seq = seq + 1; end function listener.ondisconnect(conn, err) origin.send(st.message({to=jid,from=host}) :tag("close", {xmlns=xmlns_ibb,sid=sid})); close_session(jid, sid); end conn = server.wrapclient(conn, to_host, to_port, listener, "*a" ); new_session(jid, sid, conn); elseif ibb_tag.name == "data" then local conn = open_connections[stanza.attr.from][ibb_tag.attr.sid]; if conn then local data = unb64(ibb_tag:get_text()); if data then conn:write(data); else return origin.send( st.error_reply(stanza, "modify", "bad-request", "Invalid data (base64?)") ); end else return origin.send(st.error_reply(stanza, "cancel", "item-not-found")); end elseif ibb_tag.name == "close" then if close_session(stanza.attr.from, ibb_tag.attr.sid) then origin.send(st.reply(stanza)); else return origin.send(st.error_reply(stanza, "cancel", "item-not-found")); end end end require "core.componentmanager".register_component(host, proxy_component);