Commit Graph

55 Commits

Author SHA1 Message Date
Paulo Lanzarin
14c92a3843
feat: add experimental support for ICE restart (#21208)
We currently use full renegotiation for audio, video, and screen sharing
reconnections, which involves re-creating transports and signaling channels
from scratch. While effective in some scenarios, this approach is slow and,
especially with outbound cameras and screen sharing, prone to failures.

To counter that, WebRTC provides a mechanism to restart ICE without needing
to re-create the peer connection. This allows us to avoid full renegotiation
and bypass some server-side signaling limitations. Implementing ICE restart
should make outbound camera/screen sharing reconnections more reliable and
faster.

This commit implements the ICE restart procedure for all WebRTC components'
*outbound* peers. It is based on bbb-webrtc-sfu >= v2.15.0-beta.0, which
added support for ICE restart requests. This feature is *off by default*.
To enable it, adjust the following flags:
- `/etc/bigbluebutton/bbb-webrtc-sfu/production.yml`: `allowIceRestart: true`
- `/etc/bigbluebutton/bbb-html5.yml`: `public.kurento.restartIce`
  * Refer to the inline documentation; this can be enabled on the client side
    per media type.
  * Note: The default max retries for audio is lower than for cameras/screen
    sharing (1 vs 3). This is because the full renegotiation process for audio
    is more reliable, so ICE restart is attempted first, followed by full
    renegotiation if necessary. This approach is less suitable for cameras/
    screen sharing, where longer retry periods for ICE restart make sense
    since full renegotation there is... iffy.

Endpoints that are inbound/`recvonly` only (client's perspective) do *not*
support ICE restart yet. There are two main reasons:
  - Server-side changes are required to support `recvonly` endpoints,
    particularly the proper handling of the server’s `setup` role in the
    its SDPs during an ICE restart. These changes are too broad for now,
    so they are deferred to future releases (SFU@v2.16).
  - Full reconnections for `recvonly` endpoints are currently reliable,
    unlike for `send*` endpoints. ICE restarts could still provide benefits
    for `recvonly` endpoints, but we need the server updates first.
2024-09-20 06:35:32 -04:00
prlanzarin
325887e325 feat(audio): rework audio join without listen only
This is a rework of the audio join procedure whithout the explict listen
only separation in mind. It's supposed to be used in conjunction with
the transparent listen only feature so that the distinction between
modes is seamless with minimal server-side impact. An abridged list of
changes:
  - Let the user pick no input device when joining microphone while
    allowing them to set an input device on the fly later on
  - Give the user the option to join audio with no input device whenever
    we fail to obtain input devices, with the option to try re-enabling
    them on the fly later on
  - Add the option to open the audio settings modal (echo test et al)
    via the in-call device selection chevron
  - Rework the SFU audio bridge and its services to support
    adding/removing tracks on the fly without renegotiation
  - Rework the SFU audio bridge and its services to support a new peer
    role called "passive-sendrecv". That role is used by dupled peers
    that have no active input source on start, but might have one later
    on.
  - Remove stale PermissionsOverlay component from the audio modal
  - Rework how permission errors are detected using the Permissions API
  - Rework the local echo test so that it uses a separate media tag
    rather than the remote
  - Add new, separate dialplans that mute/hold FreeSWITCH channels on
    hold based on UA strings. This is orchestrated server-side via
    webrtc-sfu and akka-apps. The basic difference here is that channels
    now join in their desired state rather than waiting for client side
    observers to sync the state up. It also mitigates transparent listen
    only performance edge cases on multiple audio channels joining at
    the same time.

The old, decoupled listen only mode is still present in code while we
validate this new approach. To test this, transparentListenOnly
must be enabled and listen only mode must be disable on audio join so
that the user skips straight through microphone join.
2024-08-15 00:43:28 +00:00
Ramón Souza
7514066fc3
fix: Client can't load in certain cases (#20336)
* move settings

* remove meteor cache files
2024-05-29 09:26:11 -04:00
Anton Georgiev
70e4ab1f66
Merge pull request #20159 from prlanzarin/u30/fix/onconnectionstatechange-crash-rc
fix(bbb-html5): crash when stopping WebRTC peers
2024-05-03 08:52:28 -04:00
prlanzarin
85cdc7cc2a fix(bbb-html5): crash when stopping WebRTC peers
There's a race condition that may cause a client crash whenever a
connectionstatechange callback is cleaned up in a peer without a
valid peer connection present in our custom RTCPeerConnection wrapper.

Check for peerConnection availability in the WebRtcPeer wrapper before
trying to clean up its connectionstatechange callback.
2024-05-02 22:59:39 +00:00
prlanzarin
00a2ab52a5 fix(audio): acquire streams before negotiation when peer is answerer
When a sendrecv peer acts as the answerer, gUM is only called _after_
the remote offer is received. This is fine, but the error handling runs
different in that scenario in a way that eventual gUM errors are treated
as negotiation errors, leading to inconsistencies when surfacing the
error to end users.

If a peer is acting as answerer and is a transceiver, acquire the local
streams _before_ actual negotiation so that gUM errors are surfaced
correctly (and we spare uneeded negotiation steps).
2024-05-02 22:27:16 +00:00
André Castro
58a0efe708
Migrate auth and settings to graphQL (#19507) 2024-03-06 14:28:18 -03:00
prlanzarin
8feb934169 feat(audio): add experimental transparent listen only mode
This is an initial, experimental implementation of the feature proposed in
https://github.com/bigbluebutton/bigbluebutton/issues/14021.

The intention is to phase out the explicit listen only mode with two
overarching goals:
  - Reduce UX friction and increase familiarity: the existence of a separate
  listen only mode is a source of confusion for the majority of users
  Reduce average server-side CPU usage while also making it possible for
  having full audio-only meetings.

The proof-of-concept works based on the assumption that a "many
concurrent active talkers" scenario is both rare and not useful. With
that in mind, this including two server-side triggers:
 - On microphone inactivity (currently mute action that is sustained for
   4 seconds, configurable): FreeSWITCH channels are held (which translates
   to much lower CPU usage, virtually 0%). Receiving channels are switched,
   server side, to a listening mode (SFU, mediasoup).
   * This required an extension to mediasoup two allow re-assigning producers
     to already established consumers. No re-negotiation is done.
 - On microphone activity (currently unmute action, immediate):
   FreeSWITCH channels are unheld, listening mode is deactivated and the
   mute state is updated accordingly (in this order).

This is *off by default*. It needs to be enabled in two places:
  - `/etc/bigbluebutton/bbb-webrtc-sfu/production.yml` ->
    `transparentListenOnly: true`
  - End users:
    * Server wide: `/etc/bigbluebutton/bbb-html5.yml` ->
      `public.media.transparentListenOnly: true`
    * Per user: `userdata-bbb_transparent_listen_only=true`
2023-08-07 19:43:18 -03:00
Arthurk12
e902f2ee27 feat(screenshare): add contentType field
This commit adds a contentType field in the back-end components of the
screenshare feature in order to accomodate the new 'camera as content'
feature.
2023-05-09 17:21:47 -03:00
Anton Georgiev
e2dc7da98a
Merge pull request #16828 from prlanzarin/u27/fix/ss-cam-reconn
fix: re-connection improvements for cameras and screen sharing
2023-04-05 16:13:01 -04:00
prlanzarin
be6a23a003 feat: add option to force/extend gathering window in SFU components
There's an edge case in finnicky networks where ALG-like firewalls
tamper with USE-CANDIDATE STUN packets and, consequently, bork ICE-lite
connectivity establishment. The odd part is that client-side gathering
seems to complete if intermediate STUN bindings work (before the final
USE-CANDIDATE), which may cause the peer not to generate relay
candidates == connectivity fails.

This adds the `public.kurento.gatheringTimeout` option to forcefully extend
the candidate gathering window in peers that act as offerers. The
behavior is as follows: if the flag is set (ms), the peer will wait
either the gathering completed stage or, _at most_,
public.kurento.gatheringTimeout ms before proceeding with calls chained
to setLocalDescription.

This option is disabled by default and intentionally ommited from the
base settings.yml file as to not encourage its use. Don't use it unless
you know what you're doing :).
2023-04-05 13:22:38 -03:00
prlanzarin
5ee0ff9af2 fix(screenshare): add proper signaling heartbeat, +
Same rationale as in video-provider's commit
(34fa37ae4f092af4a5aef0cf01d96c033d97473c).

This commit does the following:
  - Implement actual heartbeat checks to trigger reconnects when
    necessary
  - Properly catch and log WebSocket.send errors
2023-03-08 15:46:55 -03:00
Daniel Schreiber
4347ff2e3b Re-add option to disable enforce relay webrtc traffic for Firefox
There may be other bridges may not need to force relay traffic on
firefox as @prlanzarin pointed out. So set the default to a
configuration that works out of the box but leave other choices for the
operator.

The option is moved from kurento namespace to media next to the general
forceRelay option.
2023-01-03 23:21:25 +01:00
Daniel Schreiber
74f37db4fa Get rid of forceRelayOnFirefox
Firefox has a buggy ICE implementation and needs WebRTC media traffic to
be routed through a turn server to work reliably with mediasoup.

Use the information fetched by the STUN API to determine if the operator
has configured a turn server. If there is one force firefox to use it.

Closes #16164
2022-12-18 23:17:14 +01:00
prlanzarin
0f24e5634d fix(audio): bypass overconstrained errors in SFU-based audio 2022-09-15 20:42:43 +00:00
prlanzarin
0e162f1cda feat: configurable DSCP marking for WebRTC media
RTCRTPSender exposes DSCP marking via `networkPriority` in the encodings
configuration dictionaries. That should allow us to control
QoS priorities for different media streams, eg audio with higher network
priority than video. The only browser that implements that right
now is Chromium.

To use this, the public.app.media.networkPriorities configuration in
settings.yml. Audio, camera and screenshare priorities can be controlled
separately. For further info on the possible values, see:
  - https://www.w3.org/TR/webrtc-priority/
  - https://datatracker.ietf.org/doc/html/rfc8837#section-5
2022-08-15 21:24:05 +00:00
prlanzarin
45049cbd65 refactor: swap kurento-utils for new peer wrapper in screen sharing and audio 2022-07-15 14:00:12 +00:00
prlanzarin
602238b84e refactor(audio): remove caller ID from fullaudio bridge start request
The callerId is assembled server-side as of bbb-webrtc-sfu
v2.9.0-alpha.3 based on the work done in commit
d940bff541b6fe3c4976428ca471457bc67ac97e.
2022-06-28 20:33:36 +00:00
prlanzarin
1d860d64d0 fix(audio): remove deprecated getLocalStreams usage
Use the built-in getLocalStream from the peer wrapper instead (which
relies on getSenders - the proper, spec-compliant way).

Two different issues are addressed:
  - RTCPeerConnection.getLocalStreams is a pre-1.0 WebRTC spec which is
    deprecated and not recommended.
  - Fixed an issue where a switch from full audio to listen only could
  cause the latter to be rejected with an error 1004 in rare scenarios.
2022-05-27 14:02:10 +00:00
prlanzarin
83e26b7f63 fix(screenshare): race condition - local stream ends while broker stars
There could be a race condition where the local getDisplayMedia stream ends
(eg via Chrome`s stop sharing toast) while the broker hasn't finished starting.
That would lead to a scenario where the broker wouldn't emit an end event,
causing screen sharing to be flagged as started with a blank/invalid stream.
2022-05-09 18:00:30 +00:00
prlanzarin
6a0e0a87c2 fix(audio): abide to signalCandidates configuration flag 2022-05-02 13:49:47 +00:00
prlanzarin
459e1a9514 refactor(audio): remove old listen only bridge (kurento.js)
- Remove the old listen only bridge (kurento.js), superseded by the equivalent
  and equally stable (AS FAR AS LISTEN ONLY IS CONCERNED) sfu-audio-bridge
  - Rename FullAudioBridge.js -> sfu-audio-bridge.js
    * A more generic name that better represents the capabilities and
      the nature of the bridge
    * The bridge name identifier in configuration is still the same
      ('fullaudio')
  - Remove the FreeSWITCH listen only fallback
  - Temporarily disable the "trickle ICE" pair gathering feature used
    in SIP.js (which was always experimental, nonstandard and disabled
    by default)
  - Updates to settings.yml keys in places where relevant
2022-04-20 20:46:32 +00:00
prlanzarin
6fd6a52d47 fix(audio): prevent uncaught rejections in the experimental audio bridge startup 2022-04-20 17:40:06 +00:00
prlanzarin
1e80d050b7 refactor(audio): generic use of sfu audio broker to cover mic and listen only 2022-04-20 17:26:52 +00:00
prlanzarin
2eaf96ae95 refactor(audio): address linter warnings in fullaudio-broker.js 2022-04-20 13:52:16 +00:00
prlanzarin
f4ba6dd9a2 refactor(audio): use preloaded audio stream if provided
Avoids a surplus gUM with local echo test et al
2022-04-11 22:29:20 +00:00
Paulo Lanzarin
5fa7c18b43
Merge pull request #14621 from prlanzarin/u25-victorio-fuzz
fix(audio): clean up sfu broker, guarantee peer exists in getLocalStream
2022-03-17 14:39:41 -03:00
prlanzarin
13c6b12f89 fix(audio): clean up sfu broker, guarantee peer exists in getLocalStream 2022-03-17 11:20:19 -03:00
Paulo Lanzarin
e9c400e61b
Merge pull request #14211 from prlanzarin/u25-victorio-fuzz
feat(fullaudio): implement echo test, device change and audio filters (new bridge)
2022-03-16 12:36:50 -03:00
prlanzarin
d9c329df27 refactor(fullaudio): remove server-provided RPC parameters 2022-03-10 14:59:43 -03:00
prlanzarin
b9f9043d9c feat(fullaudio): handle forceRelayOnFirefox flag 2022-03-10 14:31:42 -03:00
prlanzarin
53115ccaa2 fix: missing import in load-play util script (webrtc) 2022-03-03 19:49:53 -03:00
prlanzarin
ed89f6e4a5 feat(fullaudio): implement input/output device change in new bridge 2022-02-01 17:19:50 -03:00
prlanzarin
cb84e34833 feat(fullaudio): implement echo test in new full audio bridge
Partially addresses https://github.com/bigbluebutton/bigbluebutton/issues/14191
2022-01-26 11:03:27 -03:00
prlanzarin
93b5f4c93d feat(bbb-html5): add a general forceRelay flag
public.media.forceRelay forces relay usage on all browsers, environments and media modules

If true, overrides public.kurento.[4~forceRelayOnFirefox
2021-12-09 11:35:56 +00:00
prlanzarin
da6ab02122 chore: add forceRelayOnFirefox option (false by default)
- forceRelayOnFirefox: whether TURN/relay usage should be forced to work
around Firefox's lack of support for regular nomination when dealing with
ICE-litee peers (e.g.: mediasoup).
  * See: https://bugzilla.mozilla.org/show_bug.cgi?id=1034964
- iOS endpoints are ignored from the trigger because _all_ iOS browsers
  are either native WebKit or WKWebView based (so they shouldn't be affected)
2021-11-30 20:31:12 +00:00
Mario Jr
a719f8f5e4 fix(audio): update fullaudio bridge according to sonar's checks 2021-11-09 12:10:44 -03:00
Mario Jr
f9dbefe764 feat(audio): basic funcionality for fullaudio bridge
This commit allows user to join/leave audio using the fullaudio bridge.
This is still under development, but to use this now we must set values of
skipCheck to false, and defaultFullAudioBridge to fullaudio. This
depends on newest version of bbb-webrtc-sfu
2021-11-09 12:09:18 -03:00
Mario Jr
42778adeaf feat(audio): add base code for fullaudio bridge
This bridge will work with bbb-webrtc-sfu to handle microphone audio.
2021-11-09 12:08:45 -03:00
prlanzarin
1cb412529d feat(webrtc): add EXPERIMENTAL option to disable ICE candidate signaling
ICE lite servers (eg mediasoup) dont need candidates signaled out-of-band; neither does KMS in certain scenarios

Disable their signaling saves us some ticks in bbb-webrtc-sfu and some bandwidth all around
2021-09-24 17:24:06 +00:00
prlanzarin
c57fb0b388 feat(audio): add media server adapter config for listen only in bbb-html5
Allows configuring, via bbb-html5, which media server adapter will be used by listen only; server wide
2021-08-31 00:24:41 +00:00
prlanzarin
86a715dc15 feat(screenshare): add media server adapter config in bbb-html5
Allows configuring, via bbb-html5, which media server adapter will be used by screen sharing; server wide
2021-08-31 00:19:51 +00:00
prlanzarin
54d04fdb77 refactor(listen-only): let the server generate subscriber offers 2021-08-12 13:45:18 +00:00
prlanzarin
387c453076 refactor(screnshare): let the server generate subscriber offers 2021-08-12 13:45:04 +00:00
prlanzarin
455fb8426f feat(sfu): add both ways negotiation to SFU broker 2021-08-11 19:35:16 +00:00
prlanzarin
84cbda75a3 feat(screenshare): add screen bitrate config in bbb-html5 2021-04-24 19:12:59 +00:00
prlanzarin
e0e22733dd video-provider,screenshare: consider a stream unhealthy only when the peer fails
Done to avoid false positives where the stream would transition to the unhealthy UI state (or flicker between states) due to disconnected also triggering it, which is not fatal. Disconnected has to be used alongside getStats heuristics, which I removed due to issues with it, so I´m hardening the transition to fatal states only
2021-02-05 19:54:05 -03:00
prlanzarin
9a916878f9 sfu: split broker errors into different classes
Will be used in subsequent changes to allow us to compose them into error normalization procedures
2021-01-13 09:05:12 -03:00
prlanzarin
6f16154035 screenshare: logging/trailing lines cleanup 2021-01-13 09:04:46 -03:00
prlanzarin
569ace358b screenshare: improve reconnection procedures and error logging in kurento/sfu bridge 2020-12-15 17:45:20 +00:00