Software /
code /
prosody
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 |
parent | 174:f9aff1fc7e99 |
child | 176: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 |