15 local modules_handle_stanza = require "core.modulemanager".handle_stanza; |
15 local modules_handle_stanza = require "core.modulemanager".handle_stanza; |
16 local component_handle_stanza = require "core.componentmanager".handle_stanza; |
16 local component_handle_stanza = require "core.componentmanager".handle_stanza; |
17 |
17 |
18 local handle_outbound_presence_subscriptions_and_probes = require "core.presencemanager".handle_outbound_presence_subscriptions_and_probes; |
18 local handle_outbound_presence_subscriptions_and_probes = require "core.presencemanager".handle_outbound_presence_subscriptions_and_probes; |
19 local handle_inbound_presence_subscriptions_and_probes = require "core.presencemanager".handle_inbound_presence_subscriptions_and_probes; |
19 local handle_inbound_presence_subscriptions_and_probes = require "core.presencemanager".handle_inbound_presence_subscriptions_and_probes; |
|
20 local handle_normal_presence = require "core.presencemanager".handle_normal_presence; |
20 |
21 |
21 local format = string.format; |
22 local format = string.format; |
22 local tostring = tostring; |
23 local tostring = tostring; |
23 local t_concat = table.concat; |
24 local t_concat = table.concat; |
24 local t_insert = table.insert; |
25 local t_insert = table.insert; |
103 if origin.type == "c2s" or origin.type == "c2s_unauthed" then |
104 if origin.type == "c2s" or origin.type == "c2s_unauthed" then |
104 local session = origin; |
105 local session = origin; |
105 |
106 |
106 if stanza.name == "presence" and origin.roster then |
107 if stanza.name == "presence" and origin.roster then |
107 if stanza.attr.type == nil or stanza.attr.type == "unavailable" then |
108 if stanza.attr.type == nil or stanza.attr.type == "unavailable" then |
108 for jid in pairs(origin.roster) do -- broadcast to all interested contacts |
109 handle_normal_presence(origin, stanza, core_route_stanza); |
109 local subscription = origin.roster[jid].subscription; |
|
110 if subscription == "both" or subscription == "from" then |
|
111 stanza.attr.to = jid; |
|
112 core_route_stanza(origin, stanza); |
|
113 end |
|
114 end |
|
115 local node, host = jid_split(stanza.attr.from); |
|
116 for _, res in pairs(hosts[host].sessions[node].sessions) do -- broadcast to all resources |
|
117 if res ~= origin and res.full_jid then -- to resource. FIXME is res.full_jid the correct check? Maybe it should be res.presence |
|
118 stanza.attr.to = res.full_jid; |
|
119 core_route_stanza(origin, stanza); |
|
120 end |
|
121 end |
|
122 if stanza.attr.type == nil and not origin.presence then -- initial presence |
|
123 local probe = st.presence({from = origin.full_jid, type = "probe"}); |
|
124 for jid in pairs(origin.roster) do -- probe all contacts we are subscribed to |
|
125 local subscription = origin.roster[jid].subscription; |
|
126 if subscription == "both" or subscription == "to" then |
|
127 probe.attr.to = jid; |
|
128 core_route_stanza(origin, probe); |
|
129 end |
|
130 end |
|
131 for _, res in pairs(hosts[host].sessions[node].sessions) do -- broadcast from all available resources |
|
132 if res ~= origin and res.presence then |
|
133 res.presence.attr.to = origin.full_jid; |
|
134 core_route_stanza(res, res.presence); |
|
135 res.presence.attr.to = nil; |
|
136 end |
|
137 end |
|
138 if origin.roster.pending then -- resend incoming subscription requests |
|
139 for jid in pairs(origin.roster.pending) do |
|
140 origin.send(st.presence({type="subscribe", from=jid})); -- TODO add to attribute? Use original? |
|
141 end |
|
142 end |
|
143 local request = st.presence({type="subscribe", from=origin.username.."@"..origin.host}); |
|
144 for jid, item in pairs(origin.roster) do -- resend outgoing subscription requests |
|
145 if item.ask then |
|
146 request.attr.to = jid; |
|
147 core_route_stanza(origin, request); |
|
148 end |
|
149 end |
|
150 for _, msg in ipairs(offlinemanager.load(node, host) or {}) do |
|
151 origin.send(msg); -- FIXME do we need to modify to/from in any way? |
|
152 end |
|
153 offlinemanager.deleteAll(node, host); |
|
154 end |
|
155 origin.priority = 0; |
|
156 if stanza.attr.type == "unavailable" then |
|
157 origin.presence = nil; |
|
158 else |
|
159 origin.presence = stanza; |
|
160 local priority = stanza:child_with_name("priority"); |
|
161 if priority and #priority > 0 then |
|
162 priority = t_concat(priority); |
|
163 if s_find(priority, "^[+-]?[0-9]+$") then |
|
164 priority = tonumber(priority); |
|
165 if priority < -128 then priority = -128 end |
|
166 if priority > 127 then priority = 127 end |
|
167 origin.priority = priority; |
|
168 end |
|
169 end |
|
170 end |
|
171 stanza.attr.to = nil; -- reset it |
|
172 else |
110 else |
173 log("warn", "Unhandled c2s presence: %s", tostring(stanza)); |
111 log("warn", "Unhandled c2s presence: %s", tostring(stanza)); |
174 if (stanza.attr.xmlns == "jabber:client" or stanza.attr.xmlns == "jabber:server") and stanza.attr.type ~= "error" then |
112 if (stanza.attr.xmlns == "jabber:client" or stanza.attr.xmlns == "jabber:server") and stanza.attr.type ~= "error" then |
175 origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); -- FIXME correct error? |
113 origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); -- FIXME correct error? |
176 end |
114 end |