Greenlight: Ability to have a static voicebridge PIN from within reenlight.

Created on 20 May 2020  路  21Comments  路  Source: bigbluebutton/greenlight

Since all issues I am aware of about getting a static telephone PIN in greenlight are closed now, but someone mentioned an idea of how to achieve this without problems with the load balancer, I (re)open the request here, referencing back to issues #1412 and #1572

Here is the idea on how to achieve this, posted originally here in #1572:

Another approach could be creating the 5 digit numeric PIN as a hash of the 9 digit alphanumeric room name. This would be predictable and should be unique across loadbalanced instances, right?

feature request

Most helpful comment

We are using our fork to set the static pin. It works for us, but only in a non-scalelite setup. You can also adjust the range of pin numbers that bbb assigns (manually) and then reserve a chunk outside of those for static pins. This way there isn't a collision.

I'd be interested to hear more about your setup using fsconfregger.

All 21 comments

This issue is not with the pin number creation, but rather the actual phone number. It is possible, but not without some pretty big changes to Scalelite

See https://github.com/bigbluebutton/greenlight/issues/1412#issuecomment-622579506

This issue is not with the pin number creation, but rather the actual phone number. It is possible, but not without some pretty big changes to Scalelite

But the PIN-issue is _also_ there. And originally the issue #1412 was about the PIN.

We use a server without scalelite and already tried the greenligt-fork which has the static PIN functionality -- but it seemed not to work (I amnot the admin, and the admin has not much time and gave up on a failing docker compose).

And we have a static phone number (defined already by our phone-network-provider) but a dynamic PIN.

And a static PIN would be much more barrier-free to those who cannot have internet at the time of conference start.

I wanted to open a new issue, but it seems there are more than enough issues covering the voiceBridge topic so i will add my thought here..

Situation

It is not possible to use VoIP-dialin via telephone when running bbb in a clustered environment.
Reason is that the voiceBridge is not predictable.
This is because voiceBridge is not set by greenlight and gets shuffled by the bbb-node everytime the room is created.
The dialNumber cant be predicted because it is more or less bound to the node at the moment and cant effectively be assigned via API.
But it could be set to the same number on every node. So it would be predictable.

I want to show a scenario how you can route SIP-calls into your bbb cluster.

Using static dialNumber(s) and predictable voiceBridge solves this problem!

All you need is a static voiceBridge set by Greenlight..

Approach

For a cluster, lets assume we have a central SIP router for the bbb cluster with one (ore more) dialNumbers.
From a nodes perspective lets think of the dialNumber only as a placeholder for the welcome message.
Because you cant just assign a number, if you would want this to work, you would have to assign a whole set of SIP-credentials...

Single Node with greenlight.

When using a single BBB host, you would setup the dialNumber in bigbluebutton.properties.
You setup SIP routing of the dialNumber to your BBB node and enter the voiceBridge directly on the right node.

-> This works in theory and practice but you cant send EMail invitations because greenlight does not allow to set a predictable voiceBridge.

BBB Cluster with greenlight

When running a BBB cluster with scalelite and greenlight you dont know on which node the room will be created.
So it is hard to route incoming SIP-calls to the correct node.

This is where https://github.com/denzs/fsconfregger jumps in.
It watches FreeSWITCHs eventsocket and creates a SIP registration when a conference is created.

This registration is done against a central SIP-Server which then knows where SIP-calls should be routed.

Et voila you can route incoming calls into your cluster!

-> This works in theory and practice but you cant send EMail invitations because greenlight does not allow to set a predictable voiceBridge.

While playing with greenlight (not a ruby dev at all!) it was possible to set a static voiceBridge.
There is branch from @davidpesce which seems to allow exaclty that! But at the moment there are issues with his version (see https://github.com/bigbluebutton/greenlight/issues/1572#issuecomment-627521345).

See attached image for a better unstanding...

To be clear, this works in my dev environment! Without the greenlight part obviously.
I am willing to share an example setup of fsconfregger including the SIP-Server configuration.
So basically everything to make phone calls into your cluster work!

All i would need is to set predictable voiceBridges via Greenlight!
...no need to worry about the dialNumber at all... ;)

example

TLDR:

  • it is mandatory to have a predictable voiceBridge anyway to be able to send invitations
  • lets ignore the idea of setting a dialNumber via API because it would require you to provide SIP-credentials and not just a number
  • just use the predictable voiceBridge as parameter to solve the problem of sip-credentials outside of bbb with fsconfregger (or something like that) and a dedicated sipserver as gateway for the cluster

Maybe i should add:

  • you could easily have more than one dialNumber to scale inbound call traffic among various SIP trunks.
    Just let them all terminate on the Gateway and use invitations (and/or bigbluebutton.properties on the nodes) to announce different dialin numbers and balance the calls among various incoming SIP trunks. On the gateway the calls from different trunks can be treated identically.
  • it would be very easy to have more than one gateway for balancing or HA scenarios
  • the gateway can let the callers wait for the conference to be created

So from my point of view this approach would perfectly match a cluster scenario...

We are using our fork to set the static pin. It works for us, but only in a non-scalelite setup. You can also adjust the range of pin numbers that bbb assigns (manually) and then reserve a chunk outside of those for static pins. This way there isn't a collision.

I'd be interested to hear more about your setup using fsconfregger.

A. Number of digits
When setting static voicebridge pin in Greenlight you have to be able to adjust the length of the pin to the settings in bigbluebutton.properties and Freeswitch. So there should be a setting in .env (default: 5 digits). (see https://github.com/bigbluebutton/bigbluebutton/issues/9581#issuecomment-629868997)

B. PIN as hash of room name

Here is the idea on how to achieve this, posted originally here in #1572:

Another approach could be creating the 5 digit numeric PIN as a hash of the 9 digit alphanumeric room name. This would be predictable and should be unique across loadbalanced instances, right?

BigBluebutton doesn't mind the greenlight alphanumeric room name. There is a long meeting id that is used for communication between Greenlight and BBB.
Further more you don't always want that voicebridge pin can be determinded with only the knowledge of the room name. The room name can be secured with a room pin. So dial-in should't be able when only knowning room name.

We are using our fork to set the static pin. It works for us, but only in a non-scalelite setup. You can also adjust the range of pin numbers that bbb assigns (manually) and then reserve a chunk outside of those for static pins. This way there isn't a collision.

From what i've seen in the webinterface, your branch looks very promising! :+1:

I'd be interested to hear more about your setup using fsconfregger.

On the BBB node it is as simple as mentioned in the repo right now..

I am using Asterisk as gateway. It is registered at a pbx and has one dialNumber at the moment. It takes incoming registration from the nodes. There is a small dialplan which lets the caller enter the voiceBridge he wants to join. This is working as a proof of concept.. In the next days i'll play around with it to improve and stabilize everything.

I would really like to test your branch to have stable voiceBridges during testing, but i would need it to work with scalelite.. Do you see a chance to look into the problem i referenced above?

We are using our fork to set the static pin. It works for us, but only in a non-scalelite setup.

@davidpesce: I tested your latest greenlight fork but when a user starts a conference there is a internal server error (code 500) and the conference does not start. I used a clean bbb install with ssl config and phone number added to freeswitch. Log:

Error during failsafe response: Couldn't find Room with [WHERE "rooms"."deleted" = $1 AND "rooms"."uid" = $2]
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/activerecord-5.2.3/lib/active_record/relation/finder_methods.rb:343:in raise_record_not_found_exception!' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/activerecord-5.2.3/lib/active_record/relation/finder_methods.rb:109:in take!'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/activerecord-5.2.3/lib/active_record/relation/finder_methods.rb:89:in find_by!' /usr/src/app/app/controllers/rooms_controller.rb:303:in find_room'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:426:in block in make_lambda' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:179:in block (2 levels) in halting_and_conditional'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/abstract_controller/callbacks.rb:34:in block (2 levels) in ' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:180:in block in halting_and_conditional'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:513:in block in invoke_before' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:513:in each'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:513:in invoke_before' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:131:in run_callbacks'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/abstract_controller/callbacks.rb:41:in process_action' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal/rescue.rb:22:in process_action'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal/instrumentation.rb:34:in block in process_action' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/notifications.rb:168:in block in instrument'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/notifications/instrumenter.rb:23:in instrument' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/notifications.rb:168:in instrument'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal/instrumentation.rb:32:in process_action' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal/params_wrapper.rb:256:in process_action'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/activerecord-5.2.3/lib/active_record/railties/controller_runtime.rb:24:in process_action' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/abstract_controller/base.rb:134:in process'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionview-5.2.3/lib/action_view/rendering.rb:32:in process' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal.rb:191:in dispatch'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_controller/metal.rb:252:in dispatch' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:52:in dispatch'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:34:in serve' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:52:in block in serve'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:35:in each' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:35:in serve'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:840:in call' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/show_exceptions.rb:51:in render_exception'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/show_exceptions.rb:36:in rescue in call' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/show_exceptions.rb:31:in call'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/lograge-0.11.2/lib/lograge/rails_ext/rack/logger.rb:15:in call_app' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:26:in block in call'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/tagged_logging.rb:71:in block in tagged' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/tagged_logging.rb:28:in tagged'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.3/lib/active_support/tagged_logging.rb:71:in tagged' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:26:in call'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/remote_ip.rb:81:in call' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/request_store-1.4.1/lib/request_store/middleware.rb:19:in call'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/request_id.rb:27:in call' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/rack-2.2.2/lib/rack/method_override.rb:24:in call'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/rack-2.2.2/lib/rack/runtime.rb:22:in call' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/executor.rb:14:in call'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/static.rb:127:in call' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/rack-2.2.2/lib/rack/sendfile.rb:110:in call'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/railties-5.2.3/lib/rails/engine.rb:524:in call' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/rack-2.2.2/lib/rack/urlmap.rb:74:in block in call'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/rack-2.2.2/lib/rack/urlmap.rb:58:in each' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/rack-2.2.2/lib/rack/urlmap.rb:58:in call'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/puma-3.12.4/lib/puma/configuration.rb:227:in call' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/puma-3.12.4/lib/puma/server.rb:675:in handle_request'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/puma-3.12.4/lib/puma/server.rb:476:in process_client' /usr/src/app/vendor/bundle/ruby/2.5.0/gems/puma-3.12.4/lib/puma/server.rb:334:in block in run'
/usr/src/app/vendor/bundle/ruby/2.5.0/gems/puma-3.12.4/lib/puma/thread_pool.rb:135:in `block in spawn_thread'

I'm also interested in the "static" pin and I'm looking a workaround to still have a dinamic pin BUT have the ability to retrieve that PIN and send some sms/email/etc via some script as soon as the conference is created. So I ask here if there is some script that is triggered when the conference start and if the value of the pin is available to use in some custom script. Thank you. I really love BBB!

@almoondsllc have a look at https://github.com/denzs/fsconfregger
it does exactly what you described :)

@denzs thank you for your reply. I had a look at fsconfregger but I didn't get how to retrieve the pin of conference number that is what I need to have after the conference is create

fsconregger calls an external script with the conference name as parameter.
And the conference name is identical to the voiceBridge...

Oh so you mean conference name is also the conference pin number the user have to enter. If so then all is clear now :) Thanks!

I'd be cool to have this feature in greenlight. Providing a static PIN (e.g. same as the access code) would be very helpful.

In general, a PIN identifies a conference uniquely, hence routing a call in cluster is possible - both with or without a node having a coordinator role.Having SIP-stations register numbers (e.g. PIN numbers) for reachbility is basic stuff. This boils down to registering a PIN based endpoint at a SIP-router. Let's ignore dialplan issues for greenlight.

IMHO the actual challange is to coordinate PINs among different frontends or even multiple instances of greenlight accessing the same BBB server. A PIN cannot be used twice. Some ideas to think of:

  • Generate long PINs with negligible collision probability (secure, but not that usable)
  • Make BBB (not greenlight) hand out nonces
  • Establish a numberspace (e.g. configure an prefix "123") for each pin generated by a greenlight instance.

I published my tools and configs at https://github.com/gonicus/bbb-clustersip
Be aware that this is a proof-of-concept and not for use in production. ;)
So if anybody wants to play with it, feel free...

@davidpesce Do you see a chance to have a look at the issue which is described above?

I made a patch for static conference numbers that seems to work in a test environment. This is using the first 9 decimal digits of the sha1 hash of the room uid (the one visible in the room url) as the conference pin. Don't forget to change the backend settings to support 9 digit pins.

diff --git a/app/controllers/concerns/bbb_server.rb b/app/controllers/concerns/bbb_server.rb
index ee70ed7..17614b8 100644
--- a/app/controllers/concerns/bbb_server.rb
+++ b/app/controllers/concerns/bbb_server.rb
@@ -17,6 +17,7 @@
 # with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.

 require 'bigbluebutton_api'
+require 'digest/sha1'

 module BbbServer
   extend ActiveSupport::Concern
@@ -61,6 +62,7 @@ module BbbServer

   # Creates a meeting on the BigBlueButton server.
   def start_session(room, options = {})
+    voiceBridge = Digest::SHA1.hexdigest(room.uid).to_i(16).to_s[0..8]
     create_options = {
       record: options[:meeting_recorded].to_s,
       logoutURL: options[:meeting_logout_url] || '',
@@ -68,6 +70,7 @@ module BbbServer
       attendeePW: room.attendee_pw,
       moderatorOnlyMessage: options[:moderator_message],
       muteOnStart: options[:mute_on_start] || false,
+      voiceBridge: voiceBridge,
       "meta_#{META_LISTED}": options[:recording_default_visibility] || false,
       "meta_bbb-origin-version": Greenlight::Application::VERSION,
       "meta_bbb-origin": "Greenlight",

Inspired by this thread, I created a branch for our instance to generate static pin in room settings.
https://github.com/miztaka/greenlight/tree/contrib-static-pin

This may not be adopted in cluster environment though.

@miztaka What is the reason you think it can not be adopted in a cluster environment?

@denzs Hi, as we just use single instance and single phone number, it shows a single phone number in room settings with my branch version, that might not be useful for a cluster environment.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tarunb999 picture tarunb999  路  5Comments

bixmatech picture bixmatech  路  3Comments

lakano picture lakano  路  4Comments

mrkeksi picture mrkeksi  路  5Comments

ffdixon picture ffdixon  路  4Comments