Properly propagating call id for call response handling.

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.
This commit is contained in:
Jacob MacElroy 2018-05-24 15:20:52 +00:00
parent 6a1e9e256d
commit e367490839
2 changed files with 103 additions and 39 deletions

View File

@ -67,17 +67,29 @@ module:hook("muc-broadcast-presence", function (event)
return return
end end
local invite = function() local call_id = event.stanza:get_child_text("call_id")
local url = assert(url_from_room_jid(event.stanza.attr.from)) if not call_id then
ext_events.invite(event.stanza, url) module:log("info", "A call id was not provided in the status.")
return
end end
local cancel = function() 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 url = assert(url_from_room_jid(event.stanza.attr.from)) local url = assert(url_from_room_jid(event.stanza.attr.from))
local status = event.stanza:get_child_text("status") 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 end
local should_cancel = event.stanza:get_child_text("call_cancel")
if should_cancel == "true" then
cancel()
return
end
local switch = function(status) local switch = function(status)
case = { case = {
[calling_status] = function() invite() end, [calling_status] = function() invite() end,

View File

@ -108,6 +108,27 @@ function remove_username(room, nick)
end end
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 --- Verifies room name, domain name with the values in the token
-- @param token the token we received -- @param token the token we received
-- @param room_name the room name -- @param room_name the room name
@ -182,7 +203,7 @@ prosody.events.add_handler("pre-jitsi-authentication", function(session)
if (have_poltergeist_occupant(room, nick)) then if (have_poltergeist_occupant(room, nick)) then
-- notify that user connected using the poltergeist -- notify that user connected using the poltergeist
update_poltergeist_occupant_status( update_poltergeist_occupant_status(
room, nick, "connected"); room, nick, "connected");
remove_poltergeist_occupant(room, nick, true); remove_poltergeist_occupant(room, nick, true);
end end
@ -202,10 +223,7 @@ end);
function create_poltergeist_occupant(room, nick, name, avatar, status, context) function create_poltergeist_occupant(room, nick, name, avatar, status, context)
log("debug", "create_poltergeist_occupant %s", nick); log("debug", "create_poltergeist_occupant %s", nick);
-- Join poltergeist occupant to room, with the invited JID as their nick -- Join poltergeist occupant to room, with the invited JID as their nick
local join_presence = st.presence({ local join_presence = generate_poltergeist_presence(room, nick, status)
to = room.jid.."/"..nick,
from = poltergeist_component.."/"..nick
}):tag("x", { xmlns = MUC_NS }):up();
if (name) then if (name) then
join_presence:tag( join_presence:tag(
@ -215,9 +233,6 @@ function create_poltergeist_occupant(room, nick, name, avatar, status, context)
if (avatar) then if (avatar) then
join_presence:tag("avatar-url"):text(avatar):up(); join_presence:tag("avatar-url"):text(avatar):up();
end 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 -- If the room has a password set, let the poltergeist enter using it
local room_password = room:get_password(); local room_password = room:get_password();
@ -226,6 +241,9 @@ function create_poltergeist_occupant(room, nick, name, avatar, status, context)
join:tag("password", { xmlns = MUC_NS }):text(room_password); join:tag("password", { xmlns = MUC_NS }):text(room_password);
end 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( update_presence_identity(
join_presence, join_presence,
context.user, context.user,
@ -278,15 +296,13 @@ end
-- @param room the room instance where to remove the occupant -- @param room the room instance where to remove the occupant
-- @param nick the nick of the occupant to remove -- @param nick the nick of the occupant to remove
-- @param status the status to update -- @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); local update_presence = get_presence(room, nick);
if (not update_presence) then if (not update_presence) then
-- no presence found for occupant, create one -- no presence found for occupant, create one
update_presence = st.presence({ update_presence = generate_poltergeist_presence(room, nick)
to = room.jid.."/"..nick,
from = poltergeist_component.."/"..nick
});
else else
-- update occupant presence with appropriate to and from -- update occupant presence with appropriate to and from
-- so we can send it again -- so we can send it again
@ -295,31 +311,56 @@ function update_poltergeist_occupant_status(room, nick, status)
update_presence.attr.from = poltergeist_component.."/"..nick; update_presence.attr.from = poltergeist_component.."/"..nick;
end end
local once = false; update_presence = update_presence_tags(update_presence, status, call_details)
-- the status tag we will attach
local statusTag = st.stanza("status"):text(status);
-- 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;
else
return nil;
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( room:handle_normal_presence(
prosody.hosts[poltergeist_component], update_presence); prosody.hosts[poltergeist_component], update_presence);
end 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
-- 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
end);
return presence_stanza
end
-- Checks for existance of a poltergeist occupant -- Checks for existance of a poltergeist occupant
-- @param room the room instance where to check for occupant -- @param room the room instance where to check for occupant
-- @param nick the nick of the occupant -- @param nick the nick of the occupant
@ -436,6 +477,12 @@ function handle_update_poltergeist (event)
local room_name = params["room"]; local room_name = params["room"];
local group = params["group"]; local group = params["group"];
local status = params["status"]; 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 if not verify_token(params["token"], room_name, group, {}) then
return 403; return 403;
@ -452,9 +499,14 @@ function handle_update_poltergeist (event)
return 404; return 404;
end end
local call_details = {
["cancel"] = call_cancel;
["id"] = call_id;
};
local nick = string.sub(username, 0, 8); local nick = string.sub(username, 0, 8);
if (have_poltergeist_occupant(room, nick)) then 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; return 200;
else else
return 404; return 404;