I am working on adding the password header so asterisk can connect the user to a password protected room.
Is there any way to query a room to see if there is a password set or not ? I am trying to avoid asking a user through the phone to enter a password if there is not really one.
I was able to figure this out with help of several posts from this forum⌠its not as straight forward as you think. Even https://meet.jit.si/ doesnât handle incoming calls with passwords in a good way. So I would say, there is no official solution out there.
Here is my tweak/hackie way of handling incoming calls with password, or calls to meetings that havenât started yet.
First need to modify prosodyâs /yourdomain.cfg.lua and add the muc_size module
VirtualHost "meet.jitsi"
authentication = "anonymous"
ssl = {
key = "/config/certs/meet.jitsi.key";
certificate = "/config/certs/meet.jitsi.crt";
}
modules_enabled = {
"bosh";
"pubsub";
"ping";
"muc_size";
}
c2s_require_encryption = false
Then add the following block of code to mod_muc_size.lua inside prosodyâs plugin folder: This code will allow you to curl http://your.jitsi.url:5280/all-rooms?domain=your.jitsi.domain. and get back number of rooms, room names, participants and which room has a password set or not. (you might have to expose port 5280 to make this work.
function handle_get_all_rooms(event)
if (not event.request.url.query) then
return { status_code = 400; };
end
local params = parse(event.request.url.query);
local domain_name = params["domain"];
local raw_rooms = get_raw_rooms(domain_name);
local rooms_json = array();
for room in raw_rooms do
local room_jid = room.jid;
-- local room_everything = room;
local participant_count = 0;
local occupants_json = array();
local occupants = room._occupants;
local data = room._data;
if occupants then
for _, occupant in room:each_occupant() do
-- filter focus as we keep it as hidden participant
if string.sub(occupant.nick,-string.len("/focus"))~="/focus" then
for _, pr in occupant:each_session() do
participant_count = participant_count + 1;
local nick = pr:get_child_text("nick", "http://jabber.org/protocol/nick") or "";
local email = pr:get_child_text("email") or "";
occupants_json:push({
jid = tostring(occupant.nick),
email = tostring(email),
display_name = tostring(nick)});
end
end
end
end
rooms_json:push({
jid = room_jid,
password = data.password,
participant_count = participant_count,
participants = occupants_json
});
end
local result_json={
rooms = rooms_json;
};
-- create json response
return { status_code = 200; body = json.encode(result_json); };
end
function module.load()
module:depends("http");
module:provides("http", {
default_path = "/";
route = {
["GET room-size"] = function (event) return async_handler_wrapper(event,handle_get_room_size) end;
["GET sessions"] = function () return tostring(it.count(it.keys(prosody.full_sessions))); end;
["GET room"] = function (event) return async_handler_wrapper(event,handle_get_room) end;
["GET all-rooms"] = function (event) return async_handler_wrapper(event,handle_get_all_rooms) end;
};
});
end
I am also using a docker version of jitsi & jigasi. I had to add the following lines to the jigasiâs sip-communicator.properties file
#This will prevent call to drop after 32 seconds and avoid calls that keep rining and never connect
net.java.sip.communicator.impl.protocol.sip.SKIP_REINVITE_ON_FOCUS_CHANGE_PROP=true
net.java.sip.communicator.impl.protocol.sip.acc1.JITSI_MEET_ROOM_PASS_HEADER_NAME=X-Room-Name-Pass
org.jitsi.jigasi.MUC_SERVICE_ADDRESS=your.jitsi.domain
To be able to add the dial in numbers and pin system to the meeting rooms, you have to add these lines to webâs config.js file
//you have to come up with your own list of numbers (json format and place it in your webserver under /var/www/html/...here is a json file example https://api.jitsi.net/phoneNumberList
dialInNumbersUrl: 'https://your.jitsi.url/phoneNumberList',
dialInConfCodeUrl: 'https://api.jitsi.net/conferenceMapper',
I am using asterisk 17 (PJSIP conf) in my company with the following architecture
Client cellphone -> PSTN -> Cisco unified callmanager - (trunk) -> asterisk - (sip client) -> jigasi
in your Asterisk server, place the following 2 scripts inside /var/lib/asterisk/agi-bin/
jitsi_curling.sh
#!/bin/bash
jit_rm=$(curl -x http://webproxy.ext.ti.com:80 -v https://Jitsi-api.jitsi.net/conferenceMapper?id=$1 | cut -d \, -f 3 | cut -d \: -f 2 | cut -d \" -f 2 | cut -d \@ -f 1)
echo "SET VARIABLE JITSI \"$jit_rm\" "
jitsi_haspassword.sh
#!/bin/bash
jsonResponse=$(curl --silent --noproxy "*" http://your.jitsi.url:5280/all-rooms?domain=muc.meet.jitsi | jq -r '.rooms[]')
for row in $(echo "${jsonResponse}" | jq -r '. | @base64' ); do
_jq() {
echo ${row} | base64 --decode | jq -r ${1}
}
entry=$(echo $(_jq '.'))
for variable in $(echo "${entry}" | jq -r '. | @base64' ); do
_jq() {
echo ${variable} | base64 --decode | jq -r ${1}
}
roomName=$(echo $(_jq '.jid'))
if [ ${roomName} == $1"@muc.meet.jitsi" ]; then
roomPassword=$(echo $(_jq '.password'))
fi
done
done
if [ -z "${roomPassword}" ]; then
roomPassword="ConfDidNotStartYet"
else
if [ ${roomPassword} == "null" ]; then
roomPassword="NoPassword"
fi
fi
echo "SET VARIABLE JITSIPassword ${roomPassword}"
This is how my extensions.conf file looks like. I am using from-external context because calls are coming from call manager, if you only have asterisk, you context will be from-internal and you will have just an extension instead of _[0-9].
extensions.conf
[handler]
exten => addheader,1,Set(PJSIP_HEADER(add,X-Room-Name)=${ARG1})
exten => addheader,n,Set(PJSIP_HEADER(add,X-Room-Name-Pass)=${ARG2})
[from-external]
exten => _[0-9].,1,Set(__RINGTIMER={IF([${DB(AMPUSER/6000/ringtimer)} > 0]?{DB(AMPUSER/6000/ringtimer)}:{RINGTIMER_DEFAULT})})
exten => _[0-9].,n,Playback(conf-getconfno)
;get conference pin
exten => _[0-9].,n(getmeeting),Read(Pin,beep,20)
exten => _[0-9].,n,Verbose(result is: ${Pin})
;Run meeting pin cript
exten => _[0-9].,n,AGI(jitsi_curling.sh,${Pin})
exten => _[0-9].,n,Verbose(Meeting Name: ${JITSI})
exten => _[0-9].,n,GotoIf($[${JITSI} = false}]?invalidnum:checkForPassword)
exten => _[0-9].,n(invalidnum),Playback(conf-invalid)
exten => _[0-9].,n,Goto(getmeeting)
;Run password script
exten => _[0-9].,n(checkForPassword),AGI(jitsi_haspassword.sh,${JITSI})
exten => _[0-9].,n,Verbose(Jitsi Password return: ${JITSIPassword})
exten => _[0-9].,n,GotoIf($[${JITSIPassword} = ConfDidNotStartYet]?hangUpandTryAgain:checkforPassword)
;meeting has a password, check if password matches
exten => _[0-9].,n(checkforPassword),GotoIf($[${JITSIPassword} = NoPassword]?joinmeeting:askForPassword)
exten => _[0-9].,n(askForPassword),Playback(agent-pass)
exten => _[0-9].,n,Read(Password,beep,20)
exten => _[0-9].,n,Verbose(Meeting password: ${Password})
exten => _[0-9].,n,GotoIf($[${JITSIPassword} = ${Password}]?joinmeeting:invalidPassword)
exten => _[0-9].,n(invalidPassword),Playback(vm-invalidpassword)
exten => _[0-9].,n,Goto(askForPassword)
;everything is good, join meeting
exten => _[0-9].,n(joinmeeting),Playback(auth-thankyou)
exten => _[0-9].,n,playback(conf-placeintoconf)
exten => _[0-9].,n,Dial(PJSIP/9729956000,,b(handler^addheader^1(${JITSI},${Password})))
exten => _[0-9].,n(hangUpandTryAgain),Playback(conf-onlyperson)
exten => _[0-9].,n,Playback(hangup-try-again)
Thank you for sharing
Iâm trying to set up this (docker-container). Configs are written/modified. (Sip is already running)
But i get no answer on port 5280.
Is there a another trick to enable it in prosody-container?
Greetings, Peter
have you mapped the ports in docker-compose.yml?
prosody:
#image: jitsi/prosody
build: ./prosody
expose:
- '5222'
- '5347'
- '5280'
ports:
- '5222:5222'
- '5347:5347'
- '5280:5280'
volumes:
- ${CONFIG}/prosody:/config
Ok. in default config (git docker image) the mapping ports missing.
Thank you, Iâll test it
# XMPP server
prosody:
image: jitsi/prosody
restart: ${RESTART_POLICY}
expose:
- '5222'
- '5347'
- '5280'
volumes:
- ${CONFIG}/prosody:/config
Thank you, now the port 5280 answers.
Now i can call the url, but there is a error. Is this a missing modul?
startup warn Attempt to read a non-existent global âget_raw_roomsâ
stack traceback:
/prosody-plugins/mod_muc_size.lua:209: in function âhandlerâ
/prosody-plugins/util.lib.lua:75: in function âfuncâ
/usr/lib/prosody/util/async.lua:127: in function </usr/lib/prosody/util/async.lua:125>
runnernDo1PMGs error Encountered error: /prosody-plugins/mod_muc_size.lua:209: attempt to call global âget_raw_roomsâ (a nil value)
stack traceback:
/prosody-plugins/mod_muc_size.lua:209: in function âhandlerâ
/prosody-plugins/util.lib.lua:75: in function âfuncâ
/usr/lib/prosody/util/async.lua:127: in function </usr/lib/prosody/util/async.lua:125>
http.server error Traceback[httpserver]: /usr/lib/prosody/util/async.lua:137: /prosody-plugins/mod_muc_size.lua:209: attempt to call global âget_raw_roomsâ (a nil value)
stack traceback:
/prosody-plugins/mod_muc_size.lua:209: in function âhandlerâ
/prosody-plugins/util.lib.lua:75: in function âfuncâ
/usr/lib/prosody/util/async.lua:127: in function </usr/lib/prosody/util/async.lua:125>
stack traceback:
[C]: in function âerrorâ
/usr/lib/prosody/util/async.lua:137: in function âhandlerâ
/usr/lib/prosody/util/async.lua:211: in function ârunâ
/prosody-plugins/util.lib.lua:98: in function </prosody-plugins/util.lib.lua:62>
(âŚtail callsâŚ)
/usr/lib/prosody/util/events.lua:79: in function </usr/lib/prosody/util/events.lua:75>
(âŚtail callsâŚ)
/usr/lib/prosody/net/http/server.lua:248: in function </usr/lib/prosody/net/http/server.lua:176>
[C]: in function âxpcallâ
/usr/lib/prosody/net/http/server.lua:108: in function âprocess_nextâ
/usr/lib/prosody/net/http/server.lua:124: in function âsuccess_cbâ
/usr/lib/prosody/net/http/parser.lua:177: in function âfeedâ
/usr/lib/prosody/net/http/server.lua:155: in function </usr/lib/prosody/net/http/server.lua:154>
[C]: in function âpcallâ
/usr/lib/prosody/net/server_epoll.lua:159: in function âonâ
/usr/lib/prosody/net/server_epoll.lua:348: in function âonreadableâ
/usr/lib/prosody/net/server_epoll.lua:734: in function </usr/lib/prosody/net/server_epoll.lua:726>
[C]: in function âxpcallâ
/usr/bin/prosody:76: in function âloopâ
/usr/bin/prosody:86: in main chunk
[C]: in ?
Did you add the module âmuc_sizeâ to meet.jitsi.cfg.lua?
Did you copy the block of code inside mod_muc_size.lua?
If you did all this, please share your meet.jitsi.cfg.lua, mod_muc_lua and docker-compose files
A good test to see if your code deployed correctly is running this command.
docker-compose exec prosody bash -c "cat /prosody-plugins/mod_muc_size.lua"
if you are able to see your custom code inside that file, then it made it to the container. Otherwise, you will have to tweak your docker-compose file
I see that your image is getting build remotely every time.
try changing these lines in your docker-compose file, remove jitsi-meet-cfg/ folder and try again.
XMPP server
prosody:
# image: jitsi/prosody
build: ./prosody
restart: ${RESTART_POLICY}
To set the build option is no good idea. So i lost a part my configuration and bosh take errors (Iâve test it and now i test my vmware-snapshot ) The configuration-files of prosodoy lies partly outside the Docker-Container. In the /prosody-plugin path is already a plugin mod-muc_size. I can overide it when i connect the bash in container. This works well.
Now i do the muc_size setup again.