# HG changeset patch # User Waqas Hussain # Date 1224951368 -18000 # Node ID e5cd2a03891dc4487e0160a110706c44921e9bd8 # Parent 5f71d290bb442a02dddf5b0ef6ae041a86eaa4b6 Outbound presence subscription diff -r 5f71d290bb44 -r e5cd2a03891d core/rostermanager.lua --- a/core/rostermanager.lua Sat Oct 25 06:49:48 2008 +0500 +++ b/core/rostermanager.lua Sat Oct 25 21:16:08 2008 +0500 @@ -96,10 +96,10 @@ function process_inbound_subscription_approval(username, host, jid) local roster = load_roster(username, host); local item = roster[jid]; - if item and item.ask and (item.subscription == "none" or item.subscription == "from") then + if item and item.ask then if item.subscription == "none" then item.subscription = "to"; - else + else -- subscription == from item.subscription = "both"; end item.ask = nil; @@ -110,13 +110,21 @@ function process_inbound_subscription_cancellation(username, host, jid) local roster = load_roster(username, host); local item = roster[jid]; - if item and (item.subscription == "to" or item.subscription == "both") then + local changed = nil; + if is_contact_pending_out(username, host, jid) then + item.ask = nil; + changed = true; + end + if item then if item.subscription == "to" then item.subscription = "none"; - else + changed = true; + elseif item.subscription == "both" then item.subscription = "from"; + changed = true; end - -- FIXME do we need to item.ask = nil;? + end + if changed then return datamanager.store(username, host, "roster", roster); end end @@ -124,13 +132,21 @@ function process_inbound_unsubscribe(username, host, jid) local roster = load_roster(username, host); local item = roster[jid]; - if item and (item.subscription == "from" or item.subscription == "both") then + local changed = nil; + if is_contact_pending_in(username, host, jid) then + roster.pending[jid] = nil; -- TODO maybe delete roster.pending if empty? + changed = true; + end + if item then if item.subscription == "from" then item.subscription = "none"; - else + changed = true; + elseif item.subscription == "both" then item.subscription = "to"; + changed = true; end - item.ask = nil; + end + if changed then return datamanager.store(username, host, "roster", roster); end end @@ -141,4 +157,108 @@ return item and (item.subscription == "from" or item.subscription == "both"); end +function is_contact_pending_in(username, host, jid) + local roster = load_roster(username, host); + return roster.pending or roster.pending[jid]; +end +function set_contact_pending_in(username, host, jid, pending) + local roster = load_roster(username, host); + local item = roster[jid]; + if item and (item.subscription == "from" or item.subscription == "both") then + return; -- false + end + if not roster.pending then roster.pending = {}; end + roster.pending[jid] = true; + return datamanager.store(username, host, "roster", roster); +end +function is_contact_pending_out(username, host, jid) + local roster = load_roster(username, host); + local item = roster[jid]; + return item and item.ask; +end +function set_contact_pending_out(username, host, jid) -- subscribe + local roster = load_roster(username, host); + local item = roster[jid]; + if item and (item.ask or item.subscription == "to" or item.subscription == "both") then + return true; + end + if not item then + item = {subscription = "none"}; + roster[jid] = item; + end + item.ask = "subscribe"; + return datamanager.store(username, host, "roster", roster); +end +function unsubscribe(username, host, jid) + local roster = load_roster(username, host); + local item = roster[jid]; + if not item then return false; end + if (item.subscription == "from" or item.subscription == "none") and not item.ask then + return true; + end + item.ask = nil; + if item.subscription == "both" then + item.subscription = "from"; + elseif item.subscription == "to" then + item.subscription = "none"; + end + return datamanager.store(username, host, "roster", roster); +end +function subscribed(username, host, jid) + if is_contact_pending_in(username, host, jid) then + local roster = load_roster(username, host); + local item = roster[jid]; + if item.subscription == "none" then + item.subscription = "from"; + else -- subscription == to + item.subsctiption = "both"; + end + roster.pending[jid] = nil; + -- TODO maybe remove roster.pending if empty + return datamanager.store(username, host, "roster", roster); + end -- TODO else implement optional feature pre-approval (ask = subscribed) +end +function unsubscribed(username, host, jid) + local roster = load_roster(username, host); + local item = roster[jid]; + local pending = is_contact_pending_in(username, host, jid); + local changed = nil; + if is_contact_pending_in(username, host, jid) then + roster.pending[jid] = nil; -- TODO maybe delete roster.pending if empty? + changed = true; + end + if item then + if item.subscription == "from" then + item.subscription = "none"; + changed = true; + elseif item.subscription == both then + item.subscription = "to"; + changed = true; + end + end + if changed then + return datamanager.store(username, host, "roster", roster); + end +end + +function process_outbound_subscription_request(username, host, jid) + local roster = load_roster(username, host); + local item = roster[jid]; + if item and (item.subscription == "none" or item.subscription == "from") then + item.ask = "subscribe"; + return datamanager.store(username, host, "roster", roster); + end +end + +--[[function process_outbound_subscription_approval(username, host, jid) + local roster = load_roster(username, host); + local item = roster[jid]; + if item and (item.subscription == "none" or item.subscription == "from" then + item.ask = "subscribe"; + return datamanager.store(username, host, "roster", roster); + end +end]] + + + return _M; \ No newline at end of file diff -r 5f71d290bb44 -r e5cd2a03891d core/sessionmanager.lua --- a/core/sessionmanager.lua Sat Oct 25 06:49:48 2008 +0500 +++ b/core/sessionmanager.lua Sat Oct 25 21:16:08 2008 +0500 @@ -116,6 +116,7 @@ end function send_to_available_resources(user, host, stanza) + local count = 0; local to = stanza.attr.to; stanza.attr.to = nil; local h = hosts[host]; @@ -125,11 +126,13 @@ for k, session in pairs(u.sessions) do if session.presence then session.send(stanza); + count = count + 1; end end end end stanza.attr.to = to; + return count; end return _M; \ No newline at end of file diff -r 5f71d290bb44 -r e5cd2a03891d core/stanza_router.lua --- a/core/stanza_router.lua Sat Oct 25 06:49:48 2008 +0500 +++ b/core/stanza_router.lua Sat Oct 25 21:16:08 2008 +0500 @@ -196,6 +196,41 @@ return count; end +function handle_outbound_presence_subscriptions(origin, stanza, from_bare, to_bare) + local node, host = jid_split(to_bare); + if stanza.attr.type == "subscribe" then + -- 1. route stanza + -- 2. roster push (subscription = none, ask = subscribe) + if rostermanager.set_contact_pending_out(node, host, from_bare) then + rostermanager.roster_push(node, host, from_bare); + end -- else file error + core_route_stanza(origin, st.presence({from=from_bare, to=to_bare, type="subscribe"})); + elseif stanza.attr.type == "unsubscribe" then + -- 1. route stanza + -- 2. roster push (subscription = none or from) + if rostermanager.unsubscribe(node, host, from_bare) then + rostermanager.roster_push(node, host, from_bare); -- FIXME do roster push when roster has in fact not changed? + end -- else file error + core_route_stanza(origin, st.presence({from=from_bare, to=to_bare, type="unsubscribe"})); + elseif stanza.attr.type == "subscribed" then + -- 1. route stanza + -- 2. roster_push () + -- 3. send_presence_of_available_resources + if rostermanager.subscribed(node, host, from_bare) then + rostermanager.roster_push(node, host, from_bare); + core_route_stanza(origin, st.presence({from=from_bare, to=to_bare, type="subscribed"})); + send_presence_of_available_resources(user, host, from_bare, origin); + end + elseif stanza.attr.type == "unsubscribed" then + -- 1. route stanza + -- 2. roster push (subscription = none or to) + if rostermanager.unsubscribed(node, host, from_bare) then + rostermanager.roster_push(node, host, from_bare); + core_route_stanza(origin, st.presence({from=from_bare, to=to_bare, type="unsubscribed"})); + end + end +end + function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare) local node, host = jid_split(to_bare); if stanza.attr.type == "probe" then @@ -210,8 +245,11 @@ if rostermanager.is_contact_subscribed(node, host, from_bare) then send(origin, st.presence({from=to_bare, to=from_bare, type="subscribed"})); -- already subscribed else - sessionmanager.send_to_available_resources(node, host, st.presence({from=from_bare, type="subscribe"})); - -- TODO store when no resources online + if not rostermanager.is_contact_pending(node, host, from_bare) then + if rostermanager.set_contact_pending(node, host, from_bare) then + sessionmanager.send_to_available_resources(node, host, st.presence({from=from_bare, type="subscribe"})); + end -- TODO else return error, unable to save + end end elseif stanza.attr.type == "unsubscribe" then if rostermanager.process_inbound_unsubscribe(node, host, from_bare) then