Software /
code /
prosody
Comparison
plugins/muc/muc.lib.lua @ 1989:97c3236cc4ac
MUC: Multiple sessions per nick.
author | Waqas Hussain <waqas20@gmail.com> |
---|---|
date | Sun, 18 Oct 2009 01:40:18 +0500 |
parent | 1862:115f274dd17f |
child | 1996:3e6b36c6d7b7 |
comparison
equal
deleted
inserted
replaced
1988:a6e7fe0fc3dd | 1989:97c3236cc4ac |
---|---|
104 elseif affiliation == "member" or not affiliation then | 104 elseif affiliation == "member" or not affiliation then |
105 return "participant"; | 105 return "participant"; |
106 end | 106 end |
107 end | 107 end |
108 | 108 |
109 function room_mt:broadcast_presence(stanza, code, nick) | 109 function room_mt:broadcast_presence(stanza, sid, code, nick) |
110 stanza = get_filtered_presence(stanza); | 110 stanza = get_filtered_presence(stanza); |
111 local occupant = self._occupants[stanza.attr.from]; | 111 local occupant = self._occupants[stanza.attr.from]; |
112 stanza:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) | 112 stanza:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
113 :tag("item", {affiliation=occupant.affiliation, role=occupant.role, nick=nick}):up(); | 113 :tag("item", {affiliation=occupant.affiliation, role=occupant.role, nick=nick}):up(); |
114 if code then | 114 if code then |
116 end | 116 end |
117 self:broadcast_except_nick(stanza, stanza.attr.from); | 117 self:broadcast_except_nick(stanza, stanza.attr.from); |
118 local me = self._occupants[stanza.attr.from]; | 118 local me = self._occupants[stanza.attr.from]; |
119 if me then | 119 if me then |
120 stanza:tag("status", {code='110'}); | 120 stanza:tag("status", {code='110'}); |
121 for jid in pairs(me.sessions) do | 121 stanza.attr.to = sid; |
122 stanza.attr.to = jid; | 122 self:route_stanza(stanza); |
123 self:route_stanza(stanza); | |
124 end | |
125 end | 123 end |
126 end | 124 end |
127 function room_mt:broadcast_message(stanza, historic) | 125 function room_mt:broadcast_message(stanza, historic) |
128 for occupant, o_data in pairs(self._occupants) do | 126 for occupant, o_data in pairs(self._occupants) do |
129 for jid in pairs(o_data.sessions) do | 127 for jid in pairs(o_data.sessions) do |
215 end | 213 end |
216 elseif type == "unavailable" then -- unavailable | 214 elseif type == "unavailable" then -- unavailable |
217 if current_nick then | 215 if current_nick then |
218 log("debug", "%s leaving %s", current_nick, room); | 216 log("debug", "%s leaving %s", current_nick, room); |
219 local occupant = self._occupants[current_nick]; | 217 local occupant = self._occupants[current_nick]; |
220 local old_session = occupant.sessions[from]; | |
221 local new_jid = next(occupant.sessions); | 218 local new_jid = next(occupant.sessions); |
222 if new_jid == from then new_jid = next(occupant.sessions, new_jid); end | 219 if new_jid == from then new_jid = next(occupant.sessions, new_jid); end |
223 if new_jid then | 220 if new_jid then |
221 local jid = occupant.jid; | |
224 occupant.jid = new_jid; | 222 occupant.jid = new_jid; |
225 occupant.sessions[from] = nil; | 223 occupant.sessions[from] = nil; |
226 local pr = st.clone(occupant[new_jid]) | 224 pr.attr.to = from; |
227 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) | 225 pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
228 :tag("item", {affiliation=occupant.affiliation, role=occupant.role}); | 226 :tag("item", {affiliation=occupant.affiliation, role='none'}):up() |
229 self:broadcast_except_nick(pr, current_nick); | 227 :tag("status", {code='110'}); |
228 self:route_stanza(pr); | |
229 if jid ~= new_jid then | |
230 pr = st.clone(occupant.sessions[new_jid]) | |
231 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) | |
232 :tag("item", {affiliation=occupant.affiliation, role=occupant.role}); | |
233 self:broadcast_except_nick(pr, current_nick); | |
234 end | |
230 else | 235 else |
231 occupant.role = 'none'; | 236 occupant.role = 'none'; |
232 self:broadcast_presence(pr); | 237 self:broadcast_presence(pr, from); |
233 self._occupants[current_nick] = nil; | 238 self._occupants[current_nick] = nil; |
234 end | 239 end |
235 self._jid_nick[from] = nil; | 240 self._jid_nick[from] = nil; |
236 end | 241 end |
237 elseif not type then -- available | 242 elseif not type then -- available |
238 if current_nick then | 243 if current_nick then |
239 --if #pr == #stanza or current_nick ~= to then -- commented because google keeps resending directed presence | 244 --if #pr == #stanza or current_nick ~= to then -- commented because google keeps resending directed presence |
240 if current_nick == to then -- simple presence | 245 if current_nick == to then -- simple presence |
241 log("debug", "%s broadcasted presence", current_nick); | 246 log("debug", "%s broadcasted presence", current_nick); |
242 self._occupants[current_nick].sessions[from] = pr; | 247 self._occupants[current_nick].sessions[from] = pr; |
243 self:broadcast_presence(pr); | 248 self:broadcast_presence(pr, from); |
244 else -- change nick | 249 else -- change nick |
245 if self._occupants[to] then | 250 local occupant = self._occupants[current_nick]; |
251 local is_multisession = next(occupant, next(occupant)); | |
252 if self._occupants[to] or is_multisession then | |
246 log("debug", "%s couldn't change nick", current_nick); | 253 log("debug", "%s couldn't change nick", current_nick); |
247 local reply = st.error_reply(stanza, "cancel", "conflict"):up(); | 254 local reply = st.error_reply(stanza, "cancel", "conflict"):up(); |
248 reply.tags[1].attr.code = "409"; | 255 reply.tags[1].attr.code = "409"; |
249 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | 256 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); |
250 else | 257 else |
251 local data = self._occupants[current_nick]; | 258 local data = self._occupants[current_nick]; |
252 local to_nick = select(3, jid_split(to)); | 259 local to_nick = select(3, jid_split(to)); |
253 if to_nick then | 260 if to_nick then |
254 log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to); | 261 log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to); |
255 local p = st.presence({type='unavailable', from=current_nick}); | 262 local p = st.presence({type='unavailable', from=current_nick}); |
256 self:broadcast_presence(p, '303', to_nick); | 263 self:broadcast_presence(p, from, '303', to_nick); |
257 self._occupants[current_nick] = nil; | 264 self._occupants[current_nick] = nil; |
258 self._occupants[to] = data; | 265 self._occupants[to] = data; |
259 self._jid_nick[from] = to; | 266 self._jid_nick[from] = to; |
260 pr.attr.from = to; | 267 pr.attr.from = to; |
261 self._occupants[to].sessions[from] = pr; | 268 self._occupants[to].sessions[from] = pr; |
262 self:broadcast_presence(pr); | 269 self:broadcast_presence(pr, from); |
263 else | 270 else |
264 --TODO malformed-jid | 271 --TODO malformed-jid |
265 end | 272 end |
266 end | 273 end |
267 end | 274 end |
271 -- :tag('status'):text('Replaced by new connection'):up()); -- send unavailable | 278 -- :tag('status'):text('Replaced by new connection'):up()); -- send unavailable |
272 -- self:handle_to_occupant(origin, stanza); -- resend available | 279 -- self:handle_to_occupant(origin, stanza); -- resend available |
273 --end | 280 --end |
274 else -- enter room | 281 else -- enter room |
275 local new_nick = to; | 282 local new_nick = to; |
283 local is_merge; | |
276 if self._occupants[to] then | 284 if self._occupants[to] then |
277 new_nick = nil; | 285 if jid_bare(from) ~= jid_bare(self._occupants[to].jid) then |
286 new_nick = nil; | |
287 end | |
288 is_merge = true; | |
278 end | 289 end |
279 if not new_nick then | 290 if not new_nick then |
280 log("debug", "%s couldn't join due to nick conflict: %s", from, to); | 291 log("debug", "%s couldn't join due to nick conflict: %s", from, to); |
281 local reply = st.error_reply(stanza, "cancel", "conflict"):up(); | 292 local reply = st.error_reply(stanza, "cancel", "conflict"):up(); |
282 reply.tags[1].attr.code = "409"; | 293 reply.tags[1].attr.code = "409"; |
287 self._affiliations[jid_bare(from)] = "owner"; | 298 self._affiliations[jid_bare(from)] = "owner"; |
288 end | 299 end |
289 local affiliation = self:get_affiliation(from); | 300 local affiliation = self:get_affiliation(from); |
290 local role = self:get_default_role(affiliation) | 301 local role = self:get_default_role(affiliation) |
291 if role then -- new occupant | 302 if role then -- new occupant |
292 self._occupants[to] = {affiliation=affiliation, role=role, jid=from, sessions={[from]=get_filtered_presence(stanza)}}; | 303 if not is_merge then |
304 self._occupants[to] = {affiliation=affiliation, role=role, jid=from, sessions={[from]=get_filtered_presence(stanza)}}; | |
305 else | |
306 self._occupants[to].sessions[from] = get_filtered_presence(stanza); | |
307 end | |
293 self._jid_nick[from] = to; | 308 self._jid_nick[from] = to; |
294 self:send_occupant_list(from); | 309 self:send_occupant_list(from); |
295 pr.attr.from = to; | 310 pr.attr.from = to; |
296 self:broadcast_presence(pr); | 311 if not is_merge then |
312 self:broadcast_presence(pr, from); | |
313 else | |
314 pr.attr.to = from; | |
315 self:route_stanza(pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) | |
316 :tag("item", {affiliation=affiliation, role=role}):up() | |
317 :tag("status", {code='110'})); | |
318 end | |
297 self:send_history(from); | 319 self:send_history(from); |
298 else -- banned | 320 else -- banned |
299 local reply = st.error_reply(stanza, "auth", "forbidden"):up(); | 321 local reply = st.error_reply(stanza, "auth", "forbidden"):up(); |
300 reply.tags[1].attr.code = "403"; | 322 reply.tags[1].attr.code = "403"; |
301 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | 323 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); |