2020-06-29 23:11:41 +00:00
|
|
|
local st = require "util.stanza";
|
|
|
|
local jid = require "util.jid";
|
|
|
|
local http = require "net.http";
|
|
|
|
local json = require "cjson";
|
|
|
|
local inspect = require('inspect');
|
|
|
|
local socket = require "socket";
|
|
|
|
local uuid_gen = require "util.uuid".generate;
|
|
|
|
local jwt = require "luajwtjitsi";
|
|
|
|
local it = require "util.iterators";
|
2020-06-29 23:20:04 +00:00
|
|
|
local neturl = require "net.url";
|
|
|
|
local parse = neturl.parseQuery;
|
2020-06-29 23:11:41 +00:00
|
|
|
|
|
|
|
local get_room_from_jid = module:require "util".get_room_from_jid;
|
|
|
|
local room_jid_match_rewrite = module:require "util".room_jid_match_rewrite;
|
|
|
|
local is_healthcheck_room = module:require "util".is_healthcheck_room;
|
2020-07-14 20:50:34 +00:00
|
|
|
local room_jid_split_subdomain = module:require "util".room_jid_split_subdomain;
|
|
|
|
local internal_room_jid_match_rewrite = module:require "util".internal_room_jid_match_rewrite;
|
2020-06-29 23:20:04 +00:00
|
|
|
local async_handler_wrapper = module:require "util".async_handler_wrapper;
|
|
|
|
|
|
|
|
-- this basically strips the domain from the conference.domain address
|
|
|
|
local parentHostName = string.gmatch(tostring(module.host), "%w+.(%w.+)")();
|
|
|
|
if parentHostName == nil then
|
|
|
|
log("error", "Failed to start - unable to get parent hostname");
|
|
|
|
return;
|
|
|
|
end
|
|
|
|
|
|
|
|
local parentCtx = module:context(parentHostName);
|
|
|
|
if parentCtx == nil then
|
|
|
|
log("error",
|
|
|
|
"Failed to start - unable to get parent context for host: %s",
|
|
|
|
tostring(parentHostName));
|
|
|
|
return;
|
|
|
|
end
|
|
|
|
local token_util = module:require "token/util".new(parentCtx);
|
|
|
|
|
2020-06-29 23:11:41 +00:00
|
|
|
|
|
|
|
local ASAPKeyPath
|
|
|
|
= module:get_option_string("asap_key_path", '/etc/prosody/certs/asap.key');
|
|
|
|
|
|
|
|
local ASAPKeyId
|
|
|
|
= module:get_option_string("asap_key_id", 'jitsi');
|
|
|
|
|
|
|
|
local ASAPIssuer
|
|
|
|
= module:get_option_string("asap_issuer", 'jitsi');
|
|
|
|
|
|
|
|
local ASAPAudience
|
|
|
|
= module:get_option_string("asap_audience", 'jibriqueue');
|
|
|
|
|
|
|
|
local ASAPTTL
|
|
|
|
= module:get_option_number("asap_ttl", 3600);
|
|
|
|
|
|
|
|
local ASAPTTL_THRESHOLD
|
|
|
|
= module:get_option_number("asap_ttl_threshold", 600);
|
|
|
|
|
|
|
|
local ASAPKey;
|
|
|
|
|
2020-06-29 23:20:04 +00:00
|
|
|
local queueServiceURL
|
|
|
|
= module:get_option_string("jibri_queue_url");
|
|
|
|
|
|
|
|
if queueServiceURL == nil then
|
|
|
|
log("error", "No jibri_queue_url specified. No service to contact!");
|
|
|
|
return;
|
|
|
|
end
|
|
|
|
|
2020-06-29 23:46:15 +00:00
|
|
|
-- option to enable/disable token verifications
|
|
|
|
local disableTokenVerification
|
|
|
|
= module:get_option_boolean("disable_jibri_queue_token_verification", false);
|
2020-06-29 23:20:04 +00:00
|
|
|
|
2020-06-29 23:11:41 +00:00
|
|
|
local http_headers = {
|
|
|
|
["User-Agent"] = "Prosody ("..prosody.version.."; "..prosody.platform..")",
|
|
|
|
["Content-Type"] = "application/json"
|
|
|
|
};
|
|
|
|
|
|
|
|
-- we use async to detect Prosody 0.10 and earlier
|
|
|
|
local have_async = pcall(require, "util.async");
|
|
|
|
if not have_async then
|
|
|
|
module:log("warn", "conference duration will not work with Prosody version 0.10 or less.");
|
|
|
|
return;
|
|
|
|
end
|
|
|
|
|
|
|
|
local muc_component_host = module:get_option_string("muc_component");
|
|
|
|
if muc_component_host == nil then
|
|
|
|
log("error", "No muc_component specified. No muc to operate on for jibri queue!");
|
|
|
|
return;
|
|
|
|
end
|
|
|
|
|
|
|
|
log("info", "Starting jibri queue handling for %s", muc_component_host);
|
|
|
|
|
2020-07-17 02:48:52 +00:00
|
|
|
local external_api_url = module:get_option_string("external_api_url",tostring(parentHostName));
|
|
|
|
module:log("info", "External advertised API URL", external_api_url);
|
|
|
|
|
2020-06-29 23:11:41 +00:00
|
|
|
-- Read ASAP key once on module startup
|
|
|
|
local f = io.open(ASAPKeyPath, "r");
|
|
|
|
if f then
|
|
|
|
ASAPKey = f:read("*all");
|
|
|
|
f:close();
|
|
|
|
if not ASAPKey then
|
|
|
|
module:log("warn", "No ASAP Key read, disabling muc_events plugin");
|
|
|
|
return
|
|
|
|
end
|
|
|
|
else
|
|
|
|
module:log("warn", "Error reading ASAP Key, disabling muc_events plugin");
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- TODO: Figure out a less arbitrary default cache size.
|
|
|
|
local jwtKeyCacheSize = module:get_option_number("jwt_pubkey_cache_size", 128);
|
|
|
|
local jwtKeyCache = require"util.cache".new(jwtKeyCacheSize);
|
|
|
|
|
|
|
|
local function round(num, numDecimalPlaces)
|
|
|
|
local mult = 10^(numDecimalPlaces or 0)
|
|
|
|
return math.floor(num * mult + 0.5) / mult
|
|
|
|
end
|
|
|
|
|
|
|
|
local function generateToken(audience)
|
|
|
|
audience = audience or ASAPAudience
|
|
|
|
local t = os.time()
|
|
|
|
local err
|
|
|
|
local exp_key = 'asap_exp.'..audience
|
|
|
|
local token_key = 'asap_token.'..audience
|
|
|
|
local exp = jwtKeyCache:get(exp_key)
|
|
|
|
local token = jwtKeyCache:get(token_key)
|
|
|
|
|
|
|
|
--if we find a token and it isn't too far from expiry, then use it
|
|
|
|
if token ~= nil and exp ~= nil then
|
|
|
|
exp = tonumber(exp)
|
|
|
|
if (exp - t) > ASAPTTL_THRESHOLD then
|
|
|
|
return token
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
--expiry is the current time plus TTL
|
|
|
|
exp = t + ASAPTTL
|
|
|
|
local payload = {
|
|
|
|
iss = ASAPIssuer,
|
|
|
|
aud = audience,
|
|
|
|
nbf = t,
|
|
|
|
exp = exp,
|
|
|
|
}
|
|
|
|
|
|
|
|
-- encode
|
|
|
|
local alg = "RS256"
|
|
|
|
token, err = jwt.encode(payload, ASAPKey, alg, {kid = ASAPKeyId})
|
|
|
|
if not err then
|
|
|
|
token = 'Bearer '..token
|
|
|
|
jwtKeyCache:set(exp_key,exp)
|
|
|
|
jwtKeyCache:set(token_key,token)
|
|
|
|
return token
|
|
|
|
else
|
|
|
|
return ''
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-07-17 20:19:25 +00:00
|
|
|
local function sendIq(participant,action,participant,time,position,token)
|
|
|
|
local outStanza = st.iq({type = 'set', to = participant}):tag("jibri-queue",
|
|
|
|
{ xmlns = 'http://jitsi.org/protocol/jibri-queue', requestId = requestId, action = action }):
|
|
|
|
|
|
|
|
module:send(outStanza);
|
|
|
|
end
|
2020-06-29 23:11:41 +00:00
|
|
|
|
|
|
|
local function cb(content_, code_, response_, request_)
|
|
|
|
if code_ == 200 or code_ == 204 then
|
|
|
|
module:log("debug", "URL Callback: Code %s, Content %s, Request (host %s, path %s, body %s), Response: %s",
|
|
|
|
code_, content_, request_.host, request_.path, inspect(request_.body), inspect(response_));
|
|
|
|
else
|
|
|
|
module:log("warn", "URL Callback non successful: Code %s, Content %s, Request (%s), Response: %s",
|
|
|
|
code_, content_, inspect(request_), inspect(response_));
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-07-17 20:19:25 +00:00
|
|
|
local function sendEvent(type,room_address,participant,requestId,replyIq,replyError)
|
2020-06-29 23:11:41 +00:00
|
|
|
local event_ts = round(socket.gettime()*1000);
|
2020-07-14 20:50:34 +00:00
|
|
|
local node, host, resource, target_subdomain = room_jid_split_subdomain(room_address);
|
|
|
|
local room_param = '';
|
|
|
|
if target_subdomain then
|
|
|
|
room_param = target_subdomain..'/'..node;
|
|
|
|
else
|
|
|
|
room_param = node;
|
|
|
|
end
|
|
|
|
|
2020-06-29 23:11:41 +00:00
|
|
|
local out_event = {
|
|
|
|
["conference"] = room_address,
|
2020-07-17 20:19:25 +00:00
|
|
|
["roomParam"] = room_param,
|
|
|
|
["eventType"] = type,
|
2020-06-29 23:11:41 +00:00
|
|
|
["participant"] = participant,
|
2020-07-17 20:19:25 +00:00
|
|
|
["externalApiUrl"] = external_api_url.."/jibriqueue/update",
|
|
|
|
["requestId"] = requestId,
|
2020-06-29 23:11:41 +00:00
|
|
|
}
|
|
|
|
module:log("debug","Sending event %s",inspect(out_event));
|
|
|
|
|
|
|
|
local headers = http_headers or {}
|
|
|
|
headers['Authorization'] = generateToken()
|
|
|
|
|
|
|
|
module:log("debug","Sending headers %s",inspect(headers));
|
|
|
|
local request = http.request(queueServiceURL, {
|
|
|
|
headers = headers,
|
|
|
|
method = "POST",
|
|
|
|
body = json.encode(out_event)
|
2020-07-17 20:19:25 +00:00
|
|
|
}, function (content_, code_, response_, request_)
|
|
|
|
if code_ == 200 or code_ == 204 then
|
|
|
|
module:log("debug", "URL Callback: Code %s, Content %s, Request (host %s, path %s, body %s), Response: %s",
|
|
|
|
code_, content_, request_.host, request_.path, inspect(request_.body), inspect(response_));
|
|
|
|
module:log("info", "sending reply IQ %s",inspect(replyIq));
|
|
|
|
module:send(replyIq);
|
|
|
|
else
|
|
|
|
module:log("warn", "URL Callback non successful: Code %s, Content %s, Request (%s), Response: %s",
|
|
|
|
code_, content_, inspect(request_), inspect(response_));
|
|
|
|
module:log("warn", "sending reply error IQ %s",inspect(replyError));
|
|
|
|
module:send(replyError);
|
|
|
|
end
|
|
|
|
end);
|
2020-06-29 23:11:41 +00:00
|
|
|
end
|
|
|
|
|
2020-07-13 22:04:48 +00:00
|
|
|
-- receives iq from client currently connected to the room
|
|
|
|
function on_iq(event)
|
2020-07-17 20:19:25 +00:00
|
|
|
local requestId;
|
2020-06-29 23:11:41 +00:00
|
|
|
-- Check the type of the incoming stanza to avoid loops:
|
|
|
|
if event.stanza.attr.type == "error" then
|
|
|
|
return; -- We do not want to reply to these, so leave.
|
|
|
|
end
|
2020-07-13 22:04:48 +00:00
|
|
|
if event.stanza.attr.to == module:get_host() then
|
|
|
|
if event.stanza.attr.type == "set" then
|
|
|
|
log("info", "Jibri Queue Messsage Event found: %s ",inspect(event.stanza));
|
2020-07-17 20:19:25 +00:00
|
|
|
local reply = st.reply(event.stanza);
|
|
|
|
local replyError = st.error_reply(event.stanza,'cancel','internal-server-error',"Queue Server Error");
|
|
|
|
module:log("info","Reply stanza %s",inspect(reply));
|
2020-07-13 22:04:48 +00:00
|
|
|
|
|
|
|
local jibriQueue
|
2020-07-14 20:50:34 +00:00
|
|
|
= event.stanza:get_child('jibri-queue', 'http://jitsi.org/protocol/jibri-queue');
|
2020-07-13 22:04:48 +00:00
|
|
|
if jibriQueue then
|
2020-07-17 20:19:25 +00:00
|
|
|
module:log("info", "Jibri Queue Request: %s ",inspect(jibriQueue));
|
|
|
|
|
2020-07-13 22:04:48 +00:00
|
|
|
local roomAddress = jibriQueue.attr.room;
|
|
|
|
local room = get_room_from_jid(room_jid_match_rewrite(roomAddress));
|
|
|
|
|
|
|
|
if not room then
|
2020-07-14 20:50:34 +00:00
|
|
|
module:log("warn", "No room found %s", roomAddress);
|
2020-07-13 22:04:48 +00:00
|
|
|
return false;
|
|
|
|
end
|
|
|
|
|
|
|
|
local from = event.stanza.attr.from;
|
|
|
|
|
|
|
|
local occupant = room:get_occupant_by_real_jid(from);
|
|
|
|
if not occupant then
|
2020-07-14 20:50:34 +00:00
|
|
|
module:log("warn", "No occupant %s found for %s", from, roomAddress);
|
2020-07-13 22:04:48 +00:00
|
|
|
return false;
|
|
|
|
end
|
2020-07-14 20:50:34 +00:00
|
|
|
|
2020-07-17 20:19:25 +00:00
|
|
|
local action = jibriQueue.attr.action;
|
|
|
|
if action == 'join' then
|
|
|
|
-- join action, so send event out
|
|
|
|
requestId = uuid_gen();
|
2020-07-14 20:50:34 +00:00
|
|
|
|
2020-07-17 20:19:25 +00:00
|
|
|
-- now handle new jibri queue message
|
|
|
|
room.jibriQueue[occupant.jid] = requestId;
|
|
|
|
reply:add_child(st.stanza("jibri-queue", { xmlns = 'http://jitsi.org/protocol/jibri-queue', requestId = requestId})):up()
|
|
|
|
replyError:add_child(st.stanza("jibri-queue", { xmlns = 'http://jitsi.org/protocol/jibri-queue', requestId = requestId})):up()
|
|
|
|
|
|
|
|
module:log("info","Sending JoinQueue event for jid %s occupant %s reply %s",roomAddress,occupant.jid,inspect(reply));
|
|
|
|
sendEvent('JoinQueue',roomAddress,occupant.jid,requestId,reply,replyError);
|
|
|
|
end
|
|
|
|
if action == 'leave' then
|
|
|
|
requestId = jibriQueue.attr.requestId;
|
|
|
|
-- TODO: check that requestId is the same as cached value
|
|
|
|
room.jibriQueue[occupant.jid] = nil;
|
|
|
|
reply:add_child(st.stanza("jibri-queue", { xmlns = 'http://jitsi.org/protocol/jibri-queue', requestId = requestId})):up()
|
|
|
|
replyError:add_child(st.stanza("jibri-queue", { xmlns = 'http://jitsi.org/protocol/jibri-queue', requestId = requestId})):up()
|
|
|
|
sendEvent('LeaveQueue',roomAddress,occupant.jid,requestId,reply,replyError);
|
|
|
|
end
|
2020-07-14 20:50:34 +00:00
|
|
|
else
|
2020-07-17 20:19:25 +00:00
|
|
|
module:log("warn","Jibri Queue Stanza missing child %s",inspect(event.stanza))
|
2020-07-13 22:04:48 +00:00
|
|
|
end
|
2020-06-29 23:11:41 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2020-07-14 20:50:34 +00:00
|
|
|
-- create recorder queue cache for the room
|
|
|
|
function room_created(event)
|
2020-06-29 23:11:41 +00:00
|
|
|
local room = event.room;
|
|
|
|
|
|
|
|
if is_healthcheck_room(room.jid) then
|
|
|
|
return;
|
|
|
|
end
|
|
|
|
|
2020-07-14 20:50:34 +00:00
|
|
|
room.jibriQueue = {};
|
|
|
|
end
|
2020-06-29 23:11:41 +00:00
|
|
|
|
2020-07-14 20:50:34 +00:00
|
|
|
-- Conference ended, clear all queue cache jids
|
|
|
|
function room_destroyed(event)
|
|
|
|
local room = event.room;
|
|
|
|
|
|
|
|
if is_healthcheck_room(room.jid) then
|
|
|
|
return;
|
|
|
|
end
|
|
|
|
for jid, x in pairs(room.jibriQueue) do
|
|
|
|
if x then
|
2020-07-17 20:19:25 +00:00
|
|
|
sendEvent('LeaveQueue',internal_room_jid_match_rewrite(room.jid),jid,x);
|
2020-07-14 20:50:34 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Occupant left remove it from the queue if it joined the queue
|
|
|
|
function occupant_leaving(event)
|
|
|
|
local room = event.room;
|
|
|
|
|
|
|
|
if is_healthcheck_room(room.jid) then
|
|
|
|
return;
|
|
|
|
end
|
|
|
|
|
|
|
|
local occupant = event.occupant;
|
2020-07-17 20:19:25 +00:00
|
|
|
local requestId = room.jibriQueue[occupant.jid];
|
2020-07-14 20:50:34 +00:00
|
|
|
-- check if user has cached queue request
|
2020-07-17 20:19:25 +00:00
|
|
|
if requestId then
|
2020-07-14 20:50:34 +00:00
|
|
|
-- remove occupant from queue cache, signal backend
|
|
|
|
room.jibriQueue[occupant.jid] = nil;
|
2020-07-17 20:19:25 +00:00
|
|
|
sendEvent('LeaveQueue',internal_room_jid_match_rewrite(room.jid),occupant.jid,requestId);
|
2020-07-14 20:50:34 +00:00
|
|
|
end
|
2020-06-29 23:11:41 +00:00
|
|
|
end
|
|
|
|
|
2020-07-13 22:04:48 +00:00
|
|
|
module:hook("iq/host", on_iq);
|
2020-06-29 23:11:41 +00:00
|
|
|
|
|
|
|
-- executed on every host added internally in prosody, including components
|
|
|
|
function process_host(host)
|
|
|
|
if host == muc_component_host then -- the conference muc component
|
|
|
|
module:log("info","Hook to muc events on %s", host);
|
|
|
|
|
|
|
|
local muc_module = module:context(host);
|
2020-07-14 20:50:34 +00:00
|
|
|
muc_module:hook("muc-room-created", room_created, -1);
|
|
|
|
-- muc_module:hook("muc-occupant-joined", occupant_joined, -1);
|
|
|
|
muc_module:hook("muc-occupant-pre-leave", occupant_leaving, -1);
|
|
|
|
muc_module:hook("muc-room-destroyed", room_destroyed, -1);
|
2020-06-29 23:11:41 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if prosody.hosts[muc_component_host] == nil then
|
|
|
|
module:log("info","No muc component found, will listen for it: %s", muc_component_host)
|
|
|
|
|
|
|
|
-- when a host or component is added
|
|
|
|
prosody.events.add_handler("host-activated", process_host);
|
|
|
|
else
|
|
|
|
process_host(muc_component_host);
|
|
|
|
end
|
|
|
|
|
|
|
|
module:log("info", "Loading jibri_queue_component");
|
2020-06-29 23:20:04 +00:00
|
|
|
|
|
|
|
--- Verifies room name, domain name with the values in the token
|
|
|
|
-- @param token the token we received
|
|
|
|
-- @param room_name the room name
|
|
|
|
-- @param group name of the group (optional)
|
|
|
|
-- @param session the session to use for storing token specific fields
|
|
|
|
-- @return true if values are ok or false otherwise
|
2020-06-29 23:46:15 +00:00
|
|
|
function verify_token(token, room_name, session)
|
2020-06-29 23:20:04 +00:00
|
|
|
if disableTokenVerification then
|
|
|
|
return true;
|
|
|
|
end
|
|
|
|
|
|
|
|
-- if not disableTokenVerification and we do not have token
|
|
|
|
-- stop here, cause the main virtual host can have guest access enabled
|
|
|
|
-- (allowEmptyToken = true) and we will allow access to rooms info without
|
|
|
|
-- a token
|
|
|
|
if token == nil then
|
|
|
|
log("warn", "no token provided");
|
|
|
|
return false;
|
|
|
|
end
|
|
|
|
|
|
|
|
session.auth_token = token;
|
|
|
|
local verified, reason = token_util:process_and_verify_token(session);
|
|
|
|
if not verified then
|
|
|
|
log("warn", "not a valid token %s", tostring(reason));
|
|
|
|
return false;
|
|
|
|
end
|
|
|
|
|
|
|
|
local room_address = jid.join(room_name, module:get_host());
|
|
|
|
-- if there is a group we are in multidomain mode and that group is not
|
|
|
|
-- our parent host
|
|
|
|
if group and group ~= "" and group ~= parentHostName then
|
|
|
|
room_address = "["..group.."]"..room_address;
|
|
|
|
end
|
|
|
|
|
|
|
|
if not token_util:verify_room(session, room_address) then
|
|
|
|
log("warn", "Token %s not allowed to join: %s",
|
|
|
|
tostring(token), tostring(room_address));
|
|
|
|
return false;
|
|
|
|
end
|
|
|
|
|
|
|
|
return true;
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Handles request for updating jibri queue status
|
|
|
|
-- @param event the http event, holds the request query
|
|
|
|
-- @return GET response, containing a json with response details
|
2020-06-29 23:46:15 +00:00
|
|
|
function handle_update_jibri_queue(event)
|
2020-06-29 23:20:04 +00:00
|
|
|
if (not event.request.url.query) then
|
|
|
|
return { status_code = 400; };
|
|
|
|
end
|
|
|
|
|
2020-07-17 02:48:52 +00:00
|
|
|
local body = json.decode(event.request.body);
|
2020-06-29 23:20:04 +00:00
|
|
|
local params = parse(event.request.url.query);
|
|
|
|
|
2020-07-17 02:48:52 +00:00
|
|
|
local token = params["token"];
|
|
|
|
if not token then
|
|
|
|
token = event.request.headers["authorization"];
|
|
|
|
local prefixStart, prefixEnd = token:find("Bearer ");
|
|
|
|
if prefixStart ~= 1 then
|
|
|
|
module:log("error", "Invalid authorization header format. The header must start with the string 'Bearer '");
|
|
|
|
return 403
|
|
|
|
end
|
|
|
|
token = token:sub(prefixEnd + 1);
|
|
|
|
end
|
|
|
|
|
|
|
|
local user_jid = body["participant"];
|
|
|
|
local roomAddress = body["conference"];
|
|
|
|
local userJWT = body["token"];
|
|
|
|
|
|
|
|
if not verify_token(token, roomAddress, {}) then
|
2020-06-29 23:20:04 +00:00
|
|
|
return { status_code = 403; };
|
|
|
|
end
|
|
|
|
|
2020-06-29 23:46:15 +00:00
|
|
|
local room = get_room_from_jid(room_jid_match_rewrite(roomAddress));
|
2020-06-29 23:20:04 +00:00
|
|
|
if (not room) then
|
2020-06-29 23:46:15 +00:00
|
|
|
log("error", "no room found %s", roomAddress);
|
2020-06-29 23:20:04 +00:00
|
|
|
return { status_code = 404; };
|
|
|
|
end
|
|
|
|
|
2020-06-29 23:46:15 +00:00
|
|
|
local occupant = room:get_occupant_by_real_jid(user_jid);
|
|
|
|
if not occupant then
|
|
|
|
log("warn", "No occupant %s found for %s", user_jid, roomAddress);
|
2020-06-29 23:20:04 +00:00
|
|
|
return { status_code = 404; };
|
|
|
|
end
|
|
|
|
|
2020-06-29 23:46:15 +00:00
|
|
|
-- TODO: actually implement udpate code here
|
2020-06-29 23:20:04 +00:00
|
|
|
|
|
|
|
return { status_code = 200; };
|
|
|
|
end
|
|
|
|
|
|
|
|
module:depends("http");
|
|
|
|
module:provides("http", {
|
|
|
|
default_path = "/";
|
|
|
|
name = "jibriqueue";
|
|
|
|
route = {
|
|
|
|
["GET /jibriqueue/update"] = function (event) return async_handler_wrapper(event,handle_update_jibri_queue) end;
|
|
|
|
};
|
|
|
|
});
|