Mercurial > prosody-hg
comparison core/stanza_router.lua @ 175:5f71d290bb44
Routing code reorganization
| author | Waqas Hussain <waqas20@gmail.com> |
|---|---|
| date | Sat, 25 Oct 2008 06:49:48 +0500 |
| parents | f9aff1fc7e99 |
| children | e5cd2a03891d |
comparison
equal
deleted
inserted
replaced
| 174:f9aff1fc7e99 | 175:5f71d290bb44 |
|---|---|
| 6 require "core.servermanager" | 6 require "core.servermanager" |
| 7 | 7 |
| 8 local log = require "util.logger".init("stanzarouter") | 8 local log = require "util.logger".init("stanzarouter") |
| 9 | 9 |
| 10 local st = require "util.stanza"; | 10 local st = require "util.stanza"; |
| 11 local send = require "core.sessionmanager".send_to_session; | 11 local _send = require "core.sessionmanager".send_to_session; |
| 12 local send_s2s = require "core.s2smanager".send_to_host; | 12 local send_s2s = require "core.s2smanager".send_to_host; |
| 13 function send(session, stanza) | |
| 14 if session.type == "c2s" then | |
| 15 _send(session, stanza); | |
| 16 else | |
| 17 local xmlns = stanza.attr.xmlns; | |
| 18 --stanza.attr.xmlns = "jabber:server"; | |
| 19 stanza.attr.xmlns = nil; | |
| 20 log("debug", "sending s2s stanza: %s", tostring(stanza)); | |
| 21 send_s2s(session.host, host, stanza); -- TODO handle remote routing errors | |
| 22 stanza.attr.xmlns = xmlns; -- reset | |
| 23 end | |
| 24 end | |
| 13 local user_exists = require "core.usermanager".user_exists; | 25 local user_exists = require "core.usermanager".user_exists; |
| 14 | 26 |
| 15 local rostermanager = require "core.rostermanager"; | 27 local rostermanager = require "core.rostermanager"; |
| 28 local sessionmanager = require "core.sessionmanager"; | |
| 16 | 29 |
| 17 local s2s_verify_dialback = require "core.s2smanager".verify_dialback; | 30 local s2s_verify_dialback = require "core.s2smanager".verify_dialback; |
| 18 local s2s_make_authenticated = require "core.s2smanager".make_authenticated; | 31 local s2s_make_authenticated = require "core.s2smanager".make_authenticated; |
| 19 local format = string.format; | 32 local format = string.format; |
| 20 local tostring = tostring; | 33 local tostring = tostring; |
| 77 if res ~= origin and res.full_jid then -- to resource. FIXME is res.full_jid the correct check? Maybe it should be res.presence | 90 if res ~= origin and res.full_jid then -- to resource. FIXME is res.full_jid the correct check? Maybe it should be res.presence |
| 78 stanza.attr.to = res.full_jid; | 91 stanza.attr.to = res.full_jid; |
| 79 core_route_stanza(origin, stanza); | 92 core_route_stanza(origin, stanza); |
| 80 end | 93 end |
| 81 end | 94 end |
| 82 if not origin.presence then -- presence probes on initial presence | 95 if not origin.presence then -- presence probes on initial presence -- FIXME does unavailable qualify as initial presence? |
| 83 local probe = st.presence({from = origin.full_jid, type = "probe"}); | 96 local probe = st.presence({from = origin.full_jid, type = "probe"}); |
| 84 for jid in pairs(origin.roster) do -- probe all contacts we are subscribed to | 97 for jid in pairs(origin.roster) do -- probe all contacts we are subscribed to |
| 85 local subscription = origin.roster[jid].subscription; | 98 local subscription = origin.roster[jid].subscription; |
| 86 if subscription == "both" or subscription == "to" then | 99 if subscription == "both" or subscription == "to" then |
| 87 probe.attr.to = jid; | 100 probe.attr.to = jid; |
| 159 else | 172 else |
| 160 log("warn", "Unhandled origin: %s", origin.type); | 173 log("warn", "Unhandled origin: %s", origin.type); |
| 161 end | 174 end |
| 162 end | 175 end |
| 163 | 176 |
| 164 function is_authorized_to_see_presence(origin, username, host) | 177 function send_presence_of_available_resources(user, host, jid, recipient_session) |
| 165 local roster = datamanager.load(username, host, "roster") or {}; | 178 local h = hosts[host]; |
| 166 local item = roster[origin.username.."@"..origin.host]; | 179 local count = 0; |
| 167 return item and (item.subscription == "both" or item.subscription == "from"); | 180 if h and h.type == "local" then |
| 181 local u = h.sessions[user]; | |
| 182 if u then | |
| 183 for k, session in pairs(u.sessions) do | |
| 184 local pres = session.presence; | |
| 185 if pres then | |
| 186 pres.attr.to = jid; | |
| 187 pres.attr.from = session.full_jid; | |
| 188 send(recipient_session, pres); | |
| 189 pres.attr.to = nil; | |
| 190 pres.attr.from = nil; | |
| 191 count = count + 1; | |
| 192 end | |
| 193 end | |
| 194 end | |
| 195 end | |
| 196 return count; | |
| 197 end | |
| 198 | |
| 199 function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare) | |
| 200 local node, host = jid_split(to_bare); | |
| 201 if stanza.attr.type == "probe" then | |
| 202 if rostermanager.is_contact_subscribed(node, host, from_bare) then | |
| 203 if 0 == send_presence_of_available_resources(node, host, from_bare, origin) then | |
| 204 -- TODO send last recieved unavailable presence (or we MAY do nothing, which is fine too) | |
| 205 end | |
| 206 else | |
| 207 send(origin, st.presence({from=to_bare, to=from_bare, type="unsubscribed"})); | |
| 208 end | |
| 209 elseif stanza.attr.type == "subscribe" then | |
| 210 if rostermanager.is_contact_subscribed(node, host, from_bare) then | |
| 211 send(origin, st.presence({from=to_bare, to=from_bare, type="subscribed"})); -- already subscribed | |
| 212 else | |
| 213 sessionmanager.send_to_available_resources(node, host, st.presence({from=from_bare, type="subscribe"})); | |
| 214 -- TODO store when no resources online | |
| 215 end | |
| 216 elseif stanza.attr.type == "unsubscribe" then | |
| 217 if rostermanager.process_inbound_unsubscribe(node, host, from_bare) then | |
| 218 rostermanager.roster_push(node, host, from_bare); | |
| 219 end | |
| 220 elseif stanza.attr.type == "subscribed" then | |
| 221 if rostermanager.process_inbound_subscription_approval(node, host, from_bare) then | |
| 222 rostermanager.roster_push(node, host, from_bare); | |
| 223 send_presence_of_available_resources(node, host, from_bare, origin); | |
| 224 end | |
| 225 elseif stanza.attr.type == "unsubscribed" then | |
| 226 if rostermanager.process_inbound_subscription_approval(node, host, from_bare) then | |
| 227 rostermanager.roster_push(node, host, from_bare); | |
| 228 end | |
| 229 end -- discard any other type | |
| 168 end | 230 end |
| 169 | 231 |
| 170 function core_route_stanza(origin, stanza) | 232 function core_route_stanza(origin, stanza) |
| 171 -- Hooks | 233 -- Hooks |
| 172 --- ...later | 234 --- ...later |
| 189 local res = user.sessions[resource]; | 251 local res = user.sessions[resource]; |
| 190 if not res then | 252 if not res then |
| 191 -- if we get here, resource was not specified or was unavailable | 253 -- if we get here, resource was not specified or was unavailable |
| 192 if stanza.name == "presence" then | 254 if stanza.name == "presence" then |
| 193 if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" then | 255 if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" then |
| 194 if stanza.attr.type == "probe" then | 256 handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare); |
| 195 if is_authorized_to_see_presence(origin, node, host) then | |
| 196 for k in pairs(user.sessions) do -- return presence for all resources | |
| 197 local pres = user.sessions[k].presence; | |
| 198 if pres then | |
| 199 pres.attr.to = from; -- FIXME use from_bare or from? | |
| 200 pres.attr.from = user.sessions[k].full_jid; | |
| 201 send(origin, pres); | |
| 202 end | |
| 203 end | |
| 204 pres.attr.to = nil; | |
| 205 pres.attr.from = nil; | |
| 206 else | |
| 207 send(origin, st.presence({from=to_bare, to=from_bare, type="unsubscribed"})); | |
| 208 end | |
| 209 elseif stanza.attr.type == "subscribe" then | |
| 210 if rostermanager.is_contact_subscribed(node, host, from_bare) then | |
| 211 send(origin, st.presence(from=to_bare, to=from_bare, type="subscribed")); -- already subscribed | |
| 212 else | |
| 213 local pres = st.presence({from=from_bare}, type="subscribe"); | |
| 214 for k in pairs(user.sessions) do -- return presence for all resources | |
| 215 if user.sessions[k].presence then | |
| 216 send(user.sessions[k], pres); | |
| 217 end | |
| 218 end | |
| 219 end | |
| 220 elseif stanza.attr.type == "unsubscribe" then | |
| 221 if rostermanager.process_inbound_unsubscribe(node, host, from_bare) then | |
| 222 rostermanager.roster_push(node, host, from_bare); | |
| 223 end | |
| 224 elseif stanza.attr.type == "subscribed" then | |
| 225 if rostermanager.process_inbound_subscription_approval(node, host, from_bare) then | |
| 226 rostermanager.roster_push(node, host, from_bare); | |
| 227 for k in pairs(user.sessions) do -- return presence for all resources | |
| 228 local pres = user.sessions[k].presence; | |
| 229 if pres then | |
| 230 pres.attr.to = from; -- FIXME use from_bare or from? | |
| 231 pres.attr.from = user.sessions[k].full_jid; | |
| 232 send(origin, pres); | |
| 233 end | |
| 234 end | |
| 235 pres.attr.to = nil; | |
| 236 pres.attr.from = nil; | |
| 237 end | |
| 238 elseif stanza.attr.type == "unsubscribed" then | |
| 239 if rostermanager.process_inbound_subscription_approval(node, host, from_bare) then | |
| 240 rostermanager.roster_push(node, host, from_bare); | |
| 241 end | |
| 242 end -- discard any other type | |
| 243 else -- sender is available or unavailable | 257 else -- sender is available or unavailable |
| 244 for k in pairs(user.sessions) do -- presence broadcast to all user resources | 258 for k in pairs(user.sessions) do -- presence broadcast to all user resources. FIXME should this be just for available resources? Do we need to check subscription? |
| 245 if user.sessions[k].full_jid then | 259 if user.sessions[k].full_jid then |
| 246 stanza.attr.to = user.sessions[k].full_jid; -- reset at the end of function | 260 stanza.attr.to = user.sessions[k].full_jid; -- reset at the end of function |
| 247 send(user.sessions[k], stanza); | 261 send(user.sessions[k], stanza); |
| 248 end | 262 end |
| 249 end | 263 end |
| 267 end | 281 end |
| 268 else | 282 else |
| 269 -- user not online | 283 -- user not online |
| 270 if user_exists(node, host) then | 284 if user_exists(node, host) then |
| 271 if stanza.name == "presence" then | 285 if stanza.name == "presence" then |
| 272 if stanza.attr.type == "probe" and is_authorized_to_see_presence(origin, node, host) then -- FIXME what to do for not c2s? | 286 if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" then |
| 273 -- TODO send last recieved unavailable presence (or we MAY do nothing, which is fine too) | 287 handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare); |
| 274 else | 288 else |
| 275 -- TODO send unavailable presence | 289 -- TODO send unavailable presence or unsubscribed |
| 276 end | 290 end |
| 277 elseif stanza.name == "message" then | 291 elseif stanza.name == "message" then |
| 278 -- TODO send message error, or store offline messages | 292 -- TODO send message error, or store offline messages |
| 279 elseif stanza.name == "iq" then | 293 elseif stanza.name == "iq" then |
| 280 -- TODO send IQ error | 294 -- TODO send IQ error |
