Mercurial > prosody-modules
comparison mod_bidi/mod_bidi.lua @ 1121:c714ed7de4ee
mod_bidi: Clean up and use 0.9+ routing APIs
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Fri, 02 Aug 2013 17:35:39 +0200 |
| parents | 4e235e565693 |
| children | 6094d57c5387 |
comparison
equal
deleted
inserted
replaced
| 1120:fc26a33fc2f3 | 1121:c714ed7de4ee |
|---|---|
| 2 -- http://xmpp.org/extensions/xep-0288.html | 2 -- http://xmpp.org/extensions/xep-0288.html |
| 3 -- Copyright (C) 2013 Kim Alvefur | 3 -- Copyright (C) 2013 Kim Alvefur |
| 4 -- | 4 -- |
| 5 -- This file is MIT/X11 licensed. | 5 -- This file is MIT/X11 licensed. |
| 6 -- | 6 -- |
| 7 local s2smanager = require"core.s2smanager"; | |
| 8 local add_filter = require "util.filters".add_filter; | 7 local add_filter = require "util.filters".add_filter; |
| 9 local st = require "util.stanza"; | 8 local st = require "util.stanza"; |
| 10 local jid_split = require"util.jid".prepped_split; | 9 local jid_split = require"util.jid".prepped_split; |
| 11 | 10 local core_process_stanza = prosody.core_process_stanza; |
| 11 local traceback = debug.traceback; | |
| 12 local hosts = hosts; | |
| 12 local xmlns_bidi_feature = "urn:xmpp:features:bidi" | 13 local xmlns_bidi_feature = "urn:xmpp:features:bidi" |
| 13 local xmlns_bidi = "urn:xmpp:bidi"; | 14 local xmlns_bidi = "urn:xmpp:bidi"; |
| 14 local noop = function () end | 15 local bidi_sessions = module:shared"sessions"; |
| 15 local core_process_stanza = prosody.core_process_stanza or core_process_stanza; | |
| 16 local traceback = debug.traceback; | |
| 17 | 16 |
| 18 local function handleerr(err) log("error", "Traceback[s2s]: %s: %s", tostring(err), traceback()); end | 17 local function handleerr(err) log("error", "Traceback[s2s]: %s: %s", tostring(err), traceback()); end |
| 19 local function handlestanza(session, stanza) | 18 local function handlestanza(session, stanza) |
| 20 if stanza.attr.xmlns == "jabber:client" then --COMPAT: Prosody pre-0.6.2 may send jabber:client | 19 if stanza.attr.xmlns == "jabber:client" then --COMPAT: Prosody pre-0.6.2 may send jabber:client |
| 21 stanza.attr.xmlns = nil; | 20 stanza.attr.xmlns = nil; |
| 25 return xpcall(function () return core_process_stanza(session, stanza) end, handleerr); | 24 return xpcall(function () return core_process_stanza(session, stanza) end, handleerr); |
| 26 end | 25 end |
| 27 end | 26 end |
| 28 | 27 |
| 29 local function new_bidi(origin) | 28 local function new_bidi(origin) |
| 30 local bidi_session, remote_host; | 29 if origin.type == "s2sin" then -- then we create an "outgoing" bidirectional session |
| 31 origin.log("debug", "Creating bidirectional session wrapper"); | |
| 32 if origin.direction == "incoming" then -- then we create an "outgoing" bidirectional session | |
| 33 local conflicting_session = hosts[origin.to_host].s2sout[origin.from_host] | 30 local conflicting_session = hosts[origin.to_host].s2sout[origin.from_host] |
| 34 if conflicting_session then | 31 if conflicting_session then |
| 35 conflicting_session.log("info", "We already have an outgoing connection to %s, closing it...", origin.from_host); | 32 conflicting_session.log("info", "We already have an outgoing connection to %s, closing it...", origin.from_host); |
| 36 conflicting_session:close{ condition = "conflict", text = "Replaced by bidirectional stream" } | 33 conflicting_session:close{ condition = "conflict", text = "Replaced by bidirectional stream" } |
| 37 s2smanager.destroy_session(conflicting_session); | 34 s2smanager.destroy_session(conflicting_session); |
| 38 end | 35 end |
| 39 remote_host = origin.from_host; | 36 bidi_sessions[origin.from_host] = origin; |
| 40 bidi_session = s2smanager.new_outgoing(origin.to_host, origin.from_host) | 37 elseif origin.type == "s2sout" then -- handle incoming stanzas correctly |
| 41 else -- outgoing -- then we create an "incoming" bidirectional session | 38 local bidi_session = { |
| 39 type = "s2sin"; | |
| 40 is_bidi = true; orig_session = origin; | |
| 41 to_host = origin.from_host; | |
| 42 from_host = origin.to_host; | |
| 43 hosts = {}; | |
| 44 } | |
| 45 origin.bidi_session = bidi_session; | |
| 46 setmetatable(bidi_session, { __index = origin }); | |
| 47 module:fire_event("s2s-authenticated", { session = bidi_session, host = origin.to_host }); | |
| 42 remote_host = origin.to_host; | 48 remote_host = origin.to_host; |
| 43 bidi_session = s2smanager.new_incoming(origin.conn) | |
| 44 bidi_session.to_host = origin.from_host; | |
| 45 bidi_session.from_host = origin.to_host; | |
| 46 add_filter(origin, "stanzas/in", function(stanza) | 49 add_filter(origin, "stanzas/in", function(stanza) |
| 47 if stanza.attr.xmlns ~= nil then return stanza end | 50 if stanza.attr.xmlns ~= nil then return stanza end |
| 48 local _, host = jid_split(stanza.attr.from); | 51 local _, host = jid_split(stanza.attr.from); |
| 49 if host ~= remote_host then return stanza end | 52 if host ~= remote_host then return stanza end |
| 50 handlestanza(bidi_session, stanza); | 53 handlestanza(bidi_session, stanza); |
| 51 end, 1); | 54 end, 1); |
| 52 end | 55 end |
| 53 origin.bidi_session = bidi_session; | 56 end |
| 54 bidi_session.sends2s = origin.sends2s; | |
| 55 bidi_session.bounce_sendq = noop; | |
| 56 bidi_session.notopen = nil; | |
| 57 bidi_session.is_bidi = true; | |
| 58 bidi_session.bidi_session = false; | |
| 59 bidi_session.orig_session = origin; | |
| 60 bidi_session.secure = origin.secure; | |
| 61 bidi_session.cert_identity_status = origin.cert_identity_status; | |
| 62 bidi_session.cert_chain_status = origin.cert_chain_status; | |
| 63 bidi_session.close = function(...) | |
| 64 return origin.close(...); | |
| 65 end | |
| 66 | 57 |
| 67 bidi_session.log("info", "Bidirectional session established"); | 58 module:hook("route/remote", function(event) |
| 68 module:fire_event("s2s-authenticated", { session = bidi_session, host = remote_host }); | 59 local from_host, to_host, stanza = event.from_host, event.to_host, event.stanza; |
| 69 return bidi_session; | 60 if from_host ~= module.host then return end |
| 70 end | 61 local to_session = bidi_sessions[to_host] |
| 62 if not to_session then return end | |
| 63 return to_session.sends2s(stanza); | |
| 64 end, -2); | |
| 71 | 65 |
| 72 -- Incoming s2s | 66 -- Incoming s2s |
| 73 module:hook("s2s-stream-features", function(event) | 67 module:hook("s2s-stream-features", function(event) |
| 74 local origin, features = event.origin, event.features; | 68 local origin, features = event.origin, event.features; |
| 75 if not origin.is_bidi and not hosts[module.host].s2sout[origin.from_host] then | 69 if not origin.is_bidi and not hosts[module.host].s2sout[origin.from_host] then |
| 109 module:hook("s2sin-established", enable_bidi); | 103 module:hook("s2sin-established", enable_bidi); |
| 110 module:hook("s2sout-established", enable_bidi); | 104 module:hook("s2sout-established", enable_bidi); |
| 111 | 105 |
| 112 function disable_bidi(event) | 106 function disable_bidi(event) |
| 113 local session = event.session; | 107 local session = event.session; |
| 114 if session.bidi_session then | 108 if session.type == "s2sin" then -- then we create an "outgoing" bidirectional session |
| 115 local bidi_session = session.bidi_session; | 109 bidi_sessions[session.from_host] = nil; |
| 116 session.bidi_session, bidi_session.orig_session = nil, nil; | |
| 117 session.log("debug", "Tearing down bidirectional stream"); | |
| 118 s2smanager.destroy_session(bidi_session, event.reason); | |
| 119 elseif session.orig_session then | |
| 120 local orig_session = session.orig_session; | |
| 121 orig_session.bidi_session, session.orig_session = nil, nil; | |
| 122 orig_session.log("debug", "Tearing down bidirectional stream"); | |
| 123 s2smanager.destroy_session(orig_session, event.reason); | |
| 124 end | 110 end |
| 125 end | 111 end |
| 126 | 112 |
| 127 module:hook("s2sin-destroyed", disable_bidi); | 113 module:hook("s2sin-destroyed", disable_bidi); |
| 128 module:hook("s2sout-destroyed", disable_bidi); | 114 module:hook("s2sout-destroyed", disable_bidi); |
