19 |
19 |
20 local modules_handle_stanza = require "core.modulemanager".handle_stanza; |
20 local modules_handle_stanza = require "core.modulemanager".handle_stanza; |
21 |
21 |
22 local format = string.format; |
22 local format = string.format; |
23 local tostring = tostring; |
23 local tostring = tostring; |
|
24 local t_concat = table.concat; |
|
25 local t_insert = table.insert; |
|
26 local tonumber = tonumber; |
|
27 local s_find = string.find; |
24 |
28 |
25 local jid_split = require "util.jid".split; |
29 local jid_split = require "util.jid".split; |
26 local print = print; |
30 local print = print; |
27 |
31 |
28 function core_process_stanza(origin, stanza) |
32 function core_process_stanza(origin, stanza) |
89 if res ~= origin and res.full_jid then -- to resource. FIXME is res.full_jid the correct check? Maybe it should be res.presence |
93 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 stanza.attr.to = res.full_jid; |
94 stanza.attr.to = res.full_jid; |
91 core_route_stanza(origin, stanza); |
95 core_route_stanza(origin, stanza); |
92 end |
96 end |
93 end |
97 end |
94 if not origin.presence then -- presence probes on initial presence -- FIXME does unavailable qualify as initial presence? |
98 if stanza.attr.type == nil and not origin.presence then -- initial presence |
95 local probe = st.presence({from = origin.full_jid, type = "probe"}); |
99 local probe = st.presence({from = origin.full_jid, type = "probe"}); |
96 for jid in pairs(origin.roster) do -- probe all contacts we are subscribed to |
100 for jid in pairs(origin.roster) do -- probe all contacts we are subscribed to |
97 local subscription = origin.roster[jid].subscription; |
101 local subscription = origin.roster[jid].subscription; |
98 if subscription == "both" or subscription == "to" then |
102 if subscription == "both" or subscription == "to" then |
99 probe.attr.to = jid; |
103 probe.attr.to = jid; |
100 core_route_stanza(origin, probe); |
104 core_route_stanza(origin, probe); |
101 end |
105 end |
102 end |
106 end |
103 for _, res in pairs(hosts[host].sessions[node].sessions) do -- broadcast from all resources |
107 for _, res in pairs(hosts[host].sessions[node].sessions) do -- broadcast from all available resources |
104 if res ~= origin and stanza.attr.type ~= "unavailable" and res.presence then -- FIXME does unavailable qualify as initial presence? |
108 if res ~= origin and res.presence then |
105 res.presence.attr.to = origin.full_jid; |
109 res.presence.attr.to = origin.full_jid; |
106 core_route_stanza(res, res.presence); |
110 core_route_stanza(res, res.presence); |
107 res.presence.attr.to = nil; |
111 res.presence.attr.to = nil; |
108 end |
112 end |
109 end |
113 end |
110 -- TODO resend subscription requests |
114 if origin.roster.pending then -- resend incoming subscription requests |
111 end |
115 for jid in pairs(origin.roster.pending) do |
112 origin.presence = stanza; |
116 origin.send(st.presence({type="subscribe", from=jid})); -- TODO add to attribute? Use original? |
|
117 end |
|
118 end |
|
119 local request = st.presence({type="subscribe", from=origin.username.."@"..origin.host}); |
|
120 for jid, item in pairs(origin.roster) do -- resend outgoing subscription requests |
|
121 if item.ask then |
|
122 request.attr.to = jid; |
|
123 core_route_stanza(origin, request); |
|
124 end |
|
125 end |
|
126 end |
|
127 origin.priority = 0; |
|
128 if stanza.attr.type == "unavailable" then |
|
129 origin.presence = nil; |
|
130 else |
|
131 origin.presence = stanza; |
|
132 local priority = stanza:child_with_name("priority"); |
|
133 if priority and #priority > 0 then |
|
134 priority = t_concat(priority); |
|
135 if s_find(priority, "^[+-]?[0-9]+$") then |
|
136 priority = tonumber(priority); |
|
137 if priority < -128 then priority = -128 end |
|
138 if priority > 127 then priority = 127 end |
|
139 origin.priority = priority; |
|
140 end |
|
141 end |
|
142 end |
113 stanza.attr.to = nil; -- reset it |
143 stanza.attr.to = nil; -- reset it |
114 else |
144 else |
115 -- TODO error, bad type |
145 -- TODO error, bad type |
116 end |
146 end |
117 end |
147 end |
187 function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare) |
217 function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare) |
188 local node, host = jid_split(to_bare); |
218 local node, host = jid_split(to_bare); |
189 local st_from, st_to = stanza.attr.from, stanza.attr.to; |
219 local st_from, st_to = stanza.attr.from, stanza.attr.to; |
190 stanza.attr.from, stanza.attr.to = from_bare, to_bare; |
220 stanza.attr.from, stanza.attr.to = from_bare, to_bare; |
191 if stanza.attr.type == "probe" then |
221 if stanza.attr.type == "probe" then |
|
222 log("debug", "inbound probe from "..from_bare.." for "..to_bare); |
192 if rostermanager.is_contact_subscribed(node, host, from_bare) then |
223 if rostermanager.is_contact_subscribed(node, host, from_bare) then |
193 if 0 == send_presence_of_available_resources(node, host, from_bare, origin) then |
224 if 0 == send_presence_of_available_resources(node, host, from_bare, origin) then |
194 -- TODO send last recieved unavailable presence (or we MAY do nothing, which is fine too) |
225 -- TODO send last recieved unavailable presence (or we MAY do nothing, which is fine too) |
195 end |
226 end |
196 else |
227 else |
250 -- if we get here, resource was not specified or was unavailable |
281 -- if we get here, resource was not specified or was unavailable |
251 if stanza.name == "presence" then |
282 if stanza.name == "presence" then |
252 if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" then |
283 if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" then |
253 handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare); |
284 handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare); |
254 else -- sender is available or unavailable |
285 else -- sender is available or unavailable |
255 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? |
286 for _, session in pairs(user.sessions) do -- presence broadcast to all user resources. |
256 if user.sessions[k].full_jid then |
287 if session.full_jid then -- FIXME should this be just for available resources? Do we need to check subscription? |
257 stanza.attr.to = user.sessions[k].full_jid; -- reset at the end of function |
288 stanza.attr.to = session.full_jid; -- reset at the end of function |
258 user.sessions[k].send(stanza); |
289 session.send(stanza); |
259 end |
290 end |
260 end |
291 end |
261 end |
292 end |
262 elseif stanza.name == "message" then -- select a resource to recieve message |
293 elseif stanza.name == "message" then -- select a resource to recieve message |
263 for k in pairs(user.sessions) do |
294 local priority = 0; |
264 if user.sessions[k].full_jid then |
295 local recipients = {}; |
265 res = user.sessions[k]; |
296 for _, session in pairs(user.sessions) do -- find resource with greatest priority |
266 break; |
297 local p = session.priority; |
267 end |
298 if p > priority then |
268 end |
299 priority = p; |
269 -- TODO find resource with greatest priority |
300 recipients = {session}; |
270 res.send(stanza); |
301 elseif p == priority then |
|
302 t_insert(recipients, session); |
|
303 end |
|
304 end |
|
305 for _, session in pairs(recipient) do |
|
306 session.send(stanza); |
|
307 end |
271 else |
308 else |
272 -- TODO send IQ error |
309 -- TODO send IQ error |
273 end |
310 end |
274 else |
311 else |
275 -- User + resource is online... |
312 -- User + resource is online... |