Gatekeeping room creation from prosody module

How do I go about rejecting room creation from a prosody plugin based on the result of an API call?

I’m new to jitsi/prosody and could use some pointers on the right way to go about this.

I’ve played around with adding a handler for muc-room-pre-create and can reject room creation, but since the focus user is the one that creates the room this results in an error in Jicofo and users just see an “Unfortunately, something went wrong” page which retries and keeps failing.

I’m aware that this could be done using Jicofo’s Reservation system – this is how I’m doing it now; but I’m exploring the possibility of doing this from prosody because:

  1. I do not need other features provided by the Reservation system e.g. enforcing conference duration
  2. I gather from this PR that there isn’t much love for the resevation system and there was mention that this could all be done from a prosody module
  3. I already have a custom module to push meeting participation events to my app (on user join/leave) and would be nice to consolidation my integration point to once module.

Any help greatly appreciated. Thanks.

Check token/util you can skip logic based on is_admin, as jicofo is always set to be admin.

Will you try porting reservation system to a prosody module?

Check token/util you can skip logic based on is_admin, as jicofo is always set to be admin.

I did try that, but since jicofo is the one that handles room creation before users join, the muc-room-pre-create handler would always pass and won’t conditionally block room creation?

Will you try porting reservation system to a prosody module?

Perhaps partially at first, since I don’t need the feature to automatically terminate meetings that are past allocated duration.

So, you need to query the reservation like service to decide whether the room can be created …

I’m not very familiar with the reservation system in jicofo, but what I can see is when jicofo receives the conference IQ, first contacts the reservation system can the room be created and if not returns an error.
What you can do is get that conferenceIQ and store it and do not reply but contact your service, if it is not allowed return a response error, if it is ok pass it through and the normal flow will continue.

Here comes the fun part :slight_smile: That IQ is sent to the focus component at the moment and you need to listen for stanzas on global level or hook the listeners to that component, but … we are currently trying to get rid of it and those iqs will be converted and forwarded to the user connection used by jicofo … so you should add a global hook for now …

That’s fine, but if you contribute it the community may help evolve it in the new reservation system.

Many thanks. That has given me a good start.

To better understand what’s involved, I hooked into the pre-iq/host and iq/full events and logged out all conference IQs. Indeed I see the client sending one or more conferenceIQs to the focus component, and jicofo responding to each IQ with ready=false/true (depending on whether room has been created), or with an error IQ with reservation-error body if room creation is denied.

I’ve also been able to intercept the conferenceIQ before it gets routed to the focus component and immediately respond to client with a reservation error. Useless, but a nice start to see the expected message on the UI.

What you can do is get that conferenceIQ and store it and do not reply but contact your service, if it is not allowed return a response error

Just so I am interpreting this right, is your suggestion to intercept conference IQ with a pre-iq/host hook and only allow it through to focus component when reservation system confirms room is valid? (This makes sense since if I let the event through, Jicofo could create the room and respond before call to reservation system returns.)

If that’s the case, there’s probably a bit more to be done e.g.

  • skip the checks if room already exists, and allow normal flow
  • track pending reservation API calls so we don’t duplicate reservation API calls if client (or another user joins) sends further conference IQs for same room

Also, do I need to emulate Jicofo’s ready=false responses while API calls are pending? I presume client would time out eventually and fail if it does not get a response?

That’s fine, but if you contribute it the community may help evolve it in the new reservation system.

Happy to contribute back if I can get something working sensibly :slight_smile:

Yep.

Easy jitsi-meet/mod_muc_size.lua at 80d789879ca999f89a4ca9be8528963b7bc8abb7 · jitsi/jitsi-meet · GitHub

Yeah you can keep a list of room with pending http responses once it timeouts or ok is received, clear that …

Thank you, if we can call it reservation system with options :slight_smile: and start with the limited option of what you need :slight_smile:

Thanks for the update and quick reply. I’ll be sure to keep an eye on this thread.

Hi @damencho

I have an initial implementation of the plugin here:

This is my first attempt at Lua so I won’t be surprised if it is scattered with rookie mistakes.

Would you like me to raise a PR? or do you want to take a look first and see if it is worth the bother :slight_smile:

A few things to note:

  1. I ended up implementing all features of the Jicofo version, including enforcing meeting duration, and kept the API interface as is so we can use it as a drop-in replacement. There is a small difference in behaviour which I have commented on in the source.
  2. :warning: There’s still something missing in how I terminate an expired room. I used room:clear() and room:delete() which does kick everyone and destroy the meeting, but it does not offer a very nice experience to users (everyone appears to just drop off and no message).
  3. I have not implemented retries on HTTP failures.
  4. There are a few spots that could use mutexes, but couldn’t find a easy way to do it so I just made sure impact of (very rare) race conditions are negligible.
  5. I’ve tested it on my deployment and appears to work in standard scenarios (will be doing more thorough testing today). I only use JWT for auth, so not sure how this works with other setups.

Also added a few additional configs so users can configure custom headers (e.g. for auth) and api timeouts.

The flow turned out slightly more complex than I anticipated, so hopefully the following diagram helps clarify the design:

We can work on that in the UI, by adding some special reason for destroying the room or something … I can take it later and look at it.

Hum… What about using this: jitsi-meet/util.lib.lua at 69c6463476e776761fe548c636c3298fe7d91df0 · jitsi/jitsi-meet · GitHub
Can you reuse some of the functions around the HTTP requests from that util?

Why you need mutexes? I mean, prosody is single threaded … you don’t need to worry about that …

Nice work! Maybe create a PR and I will try to look at it and we can discuss it there … I can’t promise it will be immediately … but will try to squeeze it in the following two weeks (too busy sorry).

We can work on that in the UI, by adding some special reason for destroying the room or something … I can take it later and look at it.

Thanks!

Can you reuse some of the functions around the HTTP requests from that util?

Can’t use that method directly since I need a non-blocking call. I can probably borrow some of the approaches from it.

To be honest, I intentionally skipped retries to keep complexity down on my first attempt (and I don’t need retries in my deploy since my calls go via a local proxy app than handles retries for me).

Why you need mutexes? I mean, prosody is single threaded … you don’t need to worry about that …

Ah, I didn’t know that. No mutex needed then :slight_smile: Will remove those comments.

I can’t promise it will be immediately … but will try to squeeze it in the following two weeks (too busy sorry).

Not a problem. Thanks.

Will do a quick clean-up later today and raise a PR. Will link it in here once it’s submitted.

Once you create the PR I will ask and the other people that complain about removing that from jicofo to test it, so we can have more eyes on it and improve it.

Nice job! Thank you.

1 Like

PR raised:

1 Like

Just pushed changes to handle multi-tenant (subdomains).

Also added option (disabled by default) to include the tenant name in the room name when posting to reservation API, so /TenantX/RoomName → “[tenantx]roomname”.

I considered sending tenant name as a separate field in API payload, but decided to keep it consistent with how muc_domain_mapper works (easier to match reservation room names to internal room jids).