plugins/mod_presence.lua
changeset 3153 fd435cab928f
parent 3112 c311fdffccce
child 3156 89b64966f511
equal deleted inserted replaced
3152:c6091977624b 3153:fd435cab928f
    29 function core_route_stanza(origin, stanza)
    29 function core_route_stanza(origin, stanza)
    30 	if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then
    30 	if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then
    31 		local node, host = jid_split(stanza.attr.to);
    31 		local node, host = jid_split(stanza.attr.to);
    32 		host = hosts[host];
    32 		host = hosts[host];
    33 		if node and host and host.type == "local" then
    33 		if node and host and host.type == "local" then
    34 			handle_inbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to), core_route_stanza);
    34 			handle_inbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to));
    35 			return;
    35 			return;
    36 		end
    36 		end
    37 	end
    37 	end
    38 	_core_route_stanza(origin, stanza);
    38 	_core_route_stanza(origin, stanza);
    39 end
    39 end
    62 	end
    62 	end
    63 end
    63 end
    64 
    64 
    65 local ignore_presence_priority = module:get_option("ignore_presence_priority");
    65 local ignore_presence_priority = module:get_option("ignore_presence_priority");
    66 
    66 
    67 function handle_normal_presence(origin, stanza, core_route_stanza)
    67 function handle_normal_presence(origin, stanza)
    68 	if ignore_presence_priority then
    68 	if ignore_presence_priority then
    69 		local priority = stanza:child_with_name("priority");
    69 		local priority = stanza:child_with_name("priority");
    70 		if priority and priority[1] ~= "0" then
    70 		if priority and priority[1] ~= "0" then
    71 			for i=#priority.tags,1,-1 do priority.tags[i] = nil; end
    71 			for i=#priority.tags,1,-1 do priority.tags[i] = nil; end
    72 			for i=#priority,1,-1 do priority[i] = nil; end
    72 			for i=#priority,1,-1 do priority[i] = nil; end
   157 		end
   157 		end
   158 	end
   158 	end
   159 	stanza.attr.to = nil; -- reset it
   159 	stanza.attr.to = nil; -- reset it
   160 end
   160 end
   161 
   161 
   162 function send_presence_of_available_resources(user, host, jid, recipient_session, core_route_stanza, stanza)
   162 function send_presence_of_available_resources(user, host, jid, recipient_session, stanza)
   163 	local h = hosts[host];
   163 	local h = hosts[host];
   164 	local count = 0;
   164 	local count = 0;
   165 	if h and h.type == "local" then
   165 	if h and h.type == "local" then
   166 		local u = h.sessions[user];
   166 		local u = h.sessions[user];
   167 		if u then
   167 		if u then
   179 	end
   179 	end
   180 	log("debug", "broadcasted presence of "..count.." resources from "..user.."@"..host.." to "..jid);
   180 	log("debug", "broadcasted presence of "..count.." resources from "..user.."@"..host.." to "..jid);
   181 	return count;
   181 	return count;
   182 end
   182 end
   183 
   183 
   184 function handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza)
   184 function handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare)
   185 	local node, host = jid_split(from_bare);
   185 	local node, host = jid_split(from_bare);
   186 	if to_bare == origin.username.."@"..origin.host then return; end -- No self contacts
   186 	if to_bare == origin.username.."@"..origin.host then return; end -- No self contacts
   187 	local st_from, st_to = stanza.attr.from, stanza.attr.to;
   187 	local st_from, st_to = stanza.attr.from, stanza.attr.to;
   188 	stanza.attr.from, stanza.attr.to = from_bare, to_bare;
   188 	stanza.attr.from, stanza.attr.to = from_bare, to_bare;
   189 	log("debug", "outbound presence "..stanza.attr.type.." from "..from_bare.." for "..to_bare);
   189 	log("debug", "outbound presence "..stanza.attr.type.." from "..from_bare.." for "..to_bare);
   207 		-- 3. send_presence_of_available_resources
   207 		-- 3. send_presence_of_available_resources
   208 		if rostermanager.subscribed(node, host, to_bare) then
   208 		if rostermanager.subscribed(node, host, to_bare) then
   209 			rostermanager.roster_push(node, host, to_bare);
   209 			rostermanager.roster_push(node, host, to_bare);
   210 		end
   210 		end
   211 		core_route_stanza(origin, stanza);
   211 		core_route_stanza(origin, stanza);
   212 		send_presence_of_available_resources(node, host, to_bare, origin, core_route_stanza);
   212 		send_presence_of_available_resources(node, host, to_bare, origin);
   213 	elseif stanza.attr.type == "unsubscribed" then
   213 	elseif stanza.attr.type == "unsubscribed" then
   214 		-- 1. route stanza
   214 		-- 1. route stanza
   215 		-- 2. roster push (subscription = none or to)
   215 		-- 2. roster push (subscription = none or to)
   216 		if rostermanager.unsubscribed(node, host, to_bare) then
   216 		if rostermanager.unsubscribed(node, host, to_bare) then
   217 			rostermanager.roster_push(node, host, to_bare);
   217 			rostermanager.roster_push(node, host, to_bare);
   219 		core_route_stanza(origin, stanza);
   219 		core_route_stanza(origin, stanza);
   220 	end
   220 	end
   221 	stanza.attr.from, stanza.attr.to = st_from, st_to;
   221 	stanza.attr.from, stanza.attr.to = st_from, st_to;
   222 end
   222 end
   223 
   223 
   224 function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza)
   224 function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare)
   225 	local node, host = jid_split(to_bare);
   225 	local node, host = jid_split(to_bare);
   226 	local st_from, st_to = stanza.attr.from, stanza.attr.to;
   226 	local st_from, st_to = stanza.attr.from, stanza.attr.to;
   227 	stanza.attr.from, stanza.attr.to = from_bare, to_bare;
   227 	stanza.attr.from, stanza.attr.to = from_bare, to_bare;
   228 	log("debug", "inbound presence "..stanza.attr.type.." from "..from_bare.." for "..to_bare);
   228 	log("debug", "inbound presence "..stanza.attr.type.." from "..from_bare.." for "..to_bare);
   229 	
   229 	
   230 	if stanza.attr.type == "probe" then
   230 	if stanza.attr.type == "probe" then
   231 		local result, err = rostermanager.is_contact_subscribed(node, host, from_bare);
   231 		local result, err = rostermanager.is_contact_subscribed(node, host, from_bare);
   232 		if result then
   232 		if result then
   233 			if 0 == send_presence_of_available_resources(node, host, st_from, origin, core_route_stanza) then
   233 			if 0 == send_presence_of_available_resources(node, host, st_from, origin) then
   234 				core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"})); -- TODO send last activity
   234 				core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"})); -- TODO send last activity
   235 			end
   235 			end
   236 		elseif not err then
   236 		elseif not err then
   237 			core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unsubscribed"}));
   237 			core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unsubscribed"}));
   238 		end
   238 		end
   239 	elseif stanza.attr.type == "subscribe" then
   239 	elseif stanza.attr.type == "subscribe" then
   240 		if rostermanager.is_contact_subscribed(node, host, from_bare) then
   240 		if rostermanager.is_contact_subscribed(node, host, from_bare) then
   241 			core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="subscribed"})); -- already subscribed
   241 			core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="subscribed"})); -- already subscribed
   242 			-- Sending presence is not clearly stated in the RFC, but it seems appropriate
   242 			-- Sending presence is not clearly stated in the RFC, but it seems appropriate
   243 			if 0 == send_presence_of_available_resources(node, host, from_bare, origin, core_route_stanza) then
   243 			if 0 == send_presence_of_available_resources(node, host, from_bare, origin) then
   244 				core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"})); -- TODO send last activity
   244 				core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"})); -- TODO send last activity
   245 			end
   245 			end
   246 		else
   246 		else
   247 			core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"})); -- acknowledging receipt
   247 			core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"})); -- acknowledging receipt
   248 			if not rostermanager.is_contact_pending_in(node, host, from_bare) then
   248 			if not rostermanager.is_contact_pending_in(node, host, from_bare) then
   276 
   276 
   277 	local to = stanza.attr.to;
   277 	local to = stanza.attr.to;
   278 	if to then
   278 	if to then
   279 		local t = stanza.attr.type;
   279 		local t = stanza.attr.type;
   280 		if t ~= nil and t ~= "unavailable" and t ~= "error" then -- check for subscriptions and probes
   280 		if t ~= nil and t ~= "unavailable" and t ~= "error" then -- check for subscriptions and probes
   281 			handle_outbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to), core_route_stanza);
   281 			handle_outbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to));
   282 			return true;
   282 			return true;
   283 		end
   283 		end
   284 
   284 
   285 		local to_bare = jid_bare(to);
   285 		local to_bare = jid_bare(to);
   286 		if not(origin.roster[to_bare] and (origin.roster[to_bare].subscription == "both" or origin.roster[to_bare].subscription == "from")) then -- directed presence
   286 		if not(origin.roster[to_bare] and (origin.roster[to_bare].subscription == "both" or origin.roster[to_bare].subscription == "from")) then -- directed presence
   304 
   304 
   305 	local to = stanza.attr.to;
   305 	local to = stanza.attr.to;
   306 	local t = stanza.attr.type;
   306 	local t = stanza.attr.type;
   307 	if to then
   307 	if to then
   308 		if t ~= nil and t ~= "unavailable" and t ~= "error" then -- check for subscriptions and probes sent to bare JID
   308 		if t ~= nil and t ~= "unavailable" and t ~= "error" then -- check for subscriptions and probes sent to bare JID
   309 			handle_inbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to), core_route_stanza);
   309 			handle_inbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to));
   310 			return true;
   310 			return true;
   311 		end
   311 		end
   312 	
   312 	
   313 		local user = bare_sessions[to];
   313 		local user = bare_sessions[to];
   314 		if user then
   314 		if user then
   317 					session.send(stanza);
   317 					session.send(stanza);
   318 				end
   318 				end
   319 			end
   319 			end
   320 		end -- no resources not online, discard
   320 		end -- no resources not online, discard
   321 	elseif not t or t == "unavailable" then
   321 	elseif not t or t == "unavailable" then
   322 		handle_normal_presence(origin, stanza, core_route_stanza);
   322 		handle_normal_presence(origin, stanza);
   323 	end
   323 	end
   324 	return true;
   324 	return true;
   325 end);
   325 end);
   326 module:hook("presence/full", function(data)
   326 module:hook("presence/full", function(data)
   327 	-- inbound presence to full JID recieved
   327 	-- inbound presence to full JID recieved
   328 	local origin, stanza = data.origin, data.stanza;
   328 	local origin, stanza = data.origin, data.stanza;
   329 
   329 
   330 	local t = stanza.attr.type;
   330 	local t = stanza.attr.type;
   331 	if t ~= nil and t ~= "unavailable" and t ~= "error" then -- check for subscriptions and probes sent to full JID
   331 	if t ~= nil and t ~= "unavailable" and t ~= "error" then -- check for subscriptions and probes sent to full JID
   332 		handle_inbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to), core_route_stanza);
   332 		handle_inbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to));
   333 		return true;
   333 		return true;
   334 	end
   334 	end
   335 
   335 
   336 	local session = full_sessions[stanza.attr.to];
   336 	local session = full_sessions[stanza.attr.to];
   337 	if session then
   337 	if session then