Skip to content

Commit

Permalink
Properly propagating call id for call response handling.
Browse files Browse the repository at this point in the history
Previously a new call id was generated for INVITE and CANCEL.
Now the id generated during the initial INVITE will be used for
corresponding CANCEL events. Also, adding the ability to
trigger a call cancel via the poltergeist update api.
  • Loading branch information
Jacob MacElroy committed Jun 1, 2018
1 parent 6a1e9e2 commit e367490
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 36 deletions.
22 changes: 17 additions & 5 deletions resources/prosody-plugins/mod_muc_call.lua
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,29 @@ module:hook("muc-broadcast-presence", function (event)
return
end

local invite = function()
local url = assert(url_from_room_jid(event.stanza.attr.from))
ext_events.invite(event.stanza, url)
local call_id = event.stanza:get_child_text("call_id")
if not call_id then
module:log("info", "A call id was not provided in the status.")
return
end

local invite = function()
local url = assert(url_from_room_jid(event.stanza.attr.from))
ext_events.invite(event.stanza, url, call_id)
end

local cancel = function()
local cancel = function()
local url = assert(url_from_room_jid(event.stanza.attr.from))
local status = event.stanza:get_child_text("status")
ext_events.cancel(event.stanza, url, string.lower(status))
ext_events.cancel(event.stanza, url, string.lower(status), call_id)
end

local should_cancel = event.stanza:get_child_text("call_cancel")
if should_cancel == "true" then
cancel()
return
end

local switch = function(status)
case = {
[calling_status] = function() invite() end,
Expand Down
114 changes: 83 additions & 31 deletions resources/prosody-plugins/mod_muc_poltergeist.lua
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,27 @@ function remove_username(room, nick)
end
end

-- Provides a new presence stanza for a poltergeist.
-- @param room the room instance
-- @param nick the user nick
function generate_poltergeist_presence(room, nick, status)
local presence_stanza = st.presence({
to = room.jid.."/"..nick,
from = poltergeist_component.."/"..nick,
}):tag("x", { xmlns = MUC_NS }):up();

presence_stanza:tag("call_cancel"):text(nil):up();
presence_stanza:tag("call_id"):text(nil):up();

if status then
presence_stanza:tag("status"):text(status):up();
else
presence_stanza:tag("status"):text(nil):up();
end

return presence_stanza;
end

--- Verifies room name, domain name with the values in the token
-- @param token the token we received
-- @param room_name the room name
Expand Down Expand Up @@ -182,7 +203,7 @@ prosody.events.add_handler("pre-jitsi-authentication", function(session)
if (have_poltergeist_occupant(room, nick)) then
-- notify that user connected using the poltergeist
update_poltergeist_occupant_status(
room, nick, "connected");
room, nick, "connected");
remove_poltergeist_occupant(room, nick, true);
end

Expand All @@ -202,10 +223,7 @@ end);
function create_poltergeist_occupant(room, nick, name, avatar, status, context)
log("debug", "create_poltergeist_occupant %s", nick);
-- Join poltergeist occupant to room, with the invited JID as their nick
local join_presence = st.presence({
to = room.jid.."/"..nick,
from = poltergeist_component.."/"..nick
}):tag("x", { xmlns = MUC_NS }):up();
local join_presence = generate_poltergeist_presence(room, nick, status)

if (name) then
join_presence:tag(
Expand All @@ -215,9 +233,6 @@ function create_poltergeist_occupant(room, nick, name, avatar, status, context)
if (avatar) then
join_presence:tag("avatar-url"):text(avatar):up();
end
if (status) then
join_presence:tag("status"):text(status):up();
end

-- If the room has a password set, let the poltergeist enter using it
local room_password = room:get_password();
Expand All @@ -226,6 +241,9 @@ function create_poltergeist_occupant(room, nick, name, avatar, status, context)
join:tag("password", { xmlns = MUC_NS }):text(room_password);
end

local call_id = get_username(room, context.user.id);
join_presence:tag("call_id"):text(get_username(room, context.user.id)):up();

update_presence_identity(
join_presence,
context.user,
Expand Down Expand Up @@ -278,15 +296,13 @@ end
-- @param room the room instance where to remove the occupant
-- @param nick the nick of the occupant to remove
-- @param status the status to update
function update_poltergeist_occupant_status(room, nick, status)
-- @param call_details is a table of call flow details
function update_poltergeist_occupant_status(room, nick, status, call_details)
local update_presence = get_presence(room, nick);

if (not update_presence) then
-- no presence found for occupant, create one
update_presence = st.presence({
to = room.jid.."/"..nick,
from = poltergeist_component.."/"..nick
});
update_presence = generate_poltergeist_presence(room, nick)
else
-- update occupant presence with appropriate to and from
-- so we can send it again
Expand All @@ -295,29 +311,54 @@ function update_poltergeist_occupant_status(room, nick, status)
update_presence.attr.from = poltergeist_component.."/"..nick;
end

local once = false;
-- the status tag we will attach
local statusTag = st.stanza("status"):text(status);
update_presence = update_presence_tags(update_presence, status, call_details)

-- if there is already a status tag replace it
update_presence:maptags(function (tag)
if tag.name == statusTag.name then
if not once then
once = true;
return statusTag;
room:handle_normal_presence(
prosody.hosts[poltergeist_component], update_presence);
end

-- Updates the status tags and call flow tags of an existing poltergeist's
-- presence.
-- @param presence_stanza is the actual presence stanza for a poltergeist.
-- @param status is the new status to be updated in the stanza.
-- @param call_details is a table of call flow signal information.
function update_presence_tags(presence_stanza, status, call_details)
local call_cancel = false;
local call_id = nil;

-- Extract optional call flow signal information.
if call_details then
call_id = call_details["id"];

if call_details["cancel"] then
call_cancel = call_details["cancel"];
end
end

presence_stanza:maptags(function (tag)
if tag.name == "status" then
if call_cancel then
-- If call cancel is set then the status should not be changed.
return tag
end
return st.stanza("status"):text(status);
elseif tag.name == "call_id" then
if call_id then
return st.stanza("call_id"):text(call_id);
else
return nil;
-- If no call id is provided the re-use the existing id.
return tag;
end
elseif tag.name == "call_cancel" then
if call_cancel then
return st.stanza("call_cancel"):text("true");
else
return st.stanza("call_cancel"):text("false");
end
end
return tag;
end);
if (not once) then
-- no status tag was repleced, attach it
update_presence:add_child(statusTag);
end

room:handle_normal_presence(
prosody.hosts[poltergeist_component], update_presence);
return presence_stanza
end

-- Checks for existance of a poltergeist occupant
Expand Down Expand Up @@ -436,6 +477,12 @@ function handle_update_poltergeist (event)
local room_name = params["room"];
local group = params["group"];
local status = params["status"];
local call_id = params["callid"];

local call_cancel = false
if params["callcancel"] == "true" then
call_cancel = true;
end

if not verify_token(params["token"], room_name, group, {}) then
return 403;
Expand All @@ -452,9 +499,14 @@ function handle_update_poltergeist (event)
return 404;
end

local call_details = {
["cancel"] = call_cancel;
["id"] = call_id;
};

local nick = string.sub(username, 0, 8);
if (have_poltergeist_occupant(room, nick)) then
update_poltergeist_occupant_status(room, nick, status);
update_poltergeist_occupant_status(room, nick, status, call_details);
return 200;
else
return 404;
Expand Down

0 comments on commit e367490

Please sign in to comment.