Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reenable subscribe message with security #6

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

vincentfretin
Copy link
Member

@vincentfretin vincentfretin commented Oct 22, 2022

Reenable subscribe message that was commented in #2 and add proper JWT check.
This closes mozilla#83 and mozilla#86

This is to support use case like 1-5 publishers and 100 listeners for some sort of webinar, see discussion in mozilla#76

This Subscribe message is currently only useful if:

  • you have your own backend using websocket for users presence in a room
  • you configured reliableTransport and unreliableTransport to use a function the send to your backend websocket for naf networked updates, chat, your own join/left messages.
  • you use a modified version naf-janus-adapter master with the syncOccupants api to sync subscriptions to publishers via the new createListener and to not create a publisher connection for you so that all participants don't subscribe automatically to you that make explode the number of connections the server needs to maintain. In the experiment add createListener with the subscribe message naf-janus-adapter#9 I only created the createListener function. Also be aware of Ghost avatar in the room after the user auto reconnect (master branch) naf-janus-adapter#21 that is not fixed yet.

Having written the above, rewritten the api documentation, reading again my comments on mozilla#76 and knowing that

  • datachannels reliable and unreliable are used in both direction send/receive on the main connection. The other subscriber connections don't have datachannels, only audio and video tracks.
  • the Subscribe message is exactly the same as Join with {media: UserId} except it doesn't has the listener user_id or room_id, and we don't maintain a list of them in the switchboard.

It would be more useful if we do the following changes instead:

  • remove this Subscribe message code completely
  • modify the Join message to add a kind field {kind: ["publisher"|"listener"|"subscriber"], data: true, notifications: true} (add JoinKind::Listener)
  • maintain a list of listeners in switchboard (add switchboard.join_listener)
  • in process_join, if listener, use switchboard.join_listener and send to all publishers and listeners { "event": "join", "kind": "listener", "user_id": user_id, "room_id": room_id }, if publisher, send with the event with "kind": "publisher". In naf janus adapter, you can subscribe to their audio/video if "kind": "publisher", otherwise just maintain a list of listeners or counter of listeners in the room.
  • in switchboard rename get_all_users to get_publishers, add a new get_listeners
  • in switchboard, new users_occupying similar to publishers_occupying but return publishers and listeners
  • in switchboard data_recipients_for, use users_occupying instead of publishers_occupying
  • in process_join response send the list of publishers in users array as today + listeners array: {"users:": ["publisherId1", "publisherId2"], "listeners": ["listenerId1", "listenerId2"]} (rename users to publishers if we don't care about backward compatibility, also modify the initialOccupants line in the adapter that add those publishers to the available occupants to subscribe)
  • stop using data:true to detect if the connection is a publisher and look at kind: "publisher" field (we can fallback to using data:true if kind is not defined if we care about backward compatibility)
  • in process_data and destroy_session (leave event), process_join (join event), instead of using switchboard.publishers_occupying use switchboard.users_occupying that returns both publishers and listeners. In destroy_session, add the kind: "publisher"|"listener" field to the leave event. Also probably fix sending the leave event if the main connection is closed and not all connections to fix Ghost avatar in the room after the user auto reconnect (master branch) naf-janus-adapter#21. This way naf adapter can unsubscribe if the participant was publisher, remove the participant for the users list if publisher or listener.
  • message Switch {kind: ["publisher"|"listener"]} to switch the main connection to publisher or back to listener, send a switch event to all publishers and listeners so they can subscribe if it became a publisher or unsubscribe if it became a listener. (switchboard.switch_to_publisher, switchboard.switch_to_listener)

Changes in naf adapter master branch that maintain a separate availableOccupants and occupants lists and syncOccupants api:

  • create the main connection (the one created currently with the this.createPublisher() call) with Join message kind: "listener" or kind: "publisher"
  • modify createSubscriber to add kind:subscriber
  • create a function sendSwitch with param kind: "publisher"|"listener" that send the switch event.
  • listener for the switch event, more or less treat it like a leave followed by a join
  • optional: option to not send unreliable data (networked updates) if kind listener so you can be a ghost avatar in a room and listen to publishers, you can still chat with the reliable transport (can be over datachannel or websocket)
  • modify availableOccupants to have the information of publisher or listener or two separate arrays.
  • in your project, instead of using adapter.requestedOccupants = adapter.availableOccupants;, use adapter.requestedOccupants = [] and maintain the list of occupants (publishers) you want to subscribe to, for example based on a private audio zone you are in.
  • in the join and leave event handlers, emit a similar event so we can add (if the user is in your private audio zone) or remove the occupant if kind publisher from the requestedOccupants array and call syncOccupants(). Note: the call syncOccupants() in the join handler in the adapter is not really useful here because we don't use an external users list backend and are not calling syncOccupants(newOccupants) when the users list change.

This way, you can use the plugin without any additional backend, you can also choose to keep reliableTransport/unreliableTransport to datachannel or websocket, and keep networked updates and chat on it.
Note: the server still maintain a WebRTC connection for the participant, even if the participant don't use datachannel, audio or video. We can probably remove creation of the datachannels if reliableTransport and unreliableTransport are not set to "datachannel" (this is the default, so meaning you set it to "websocket"), but we still keep a main WebRTC connection with an inactive audio track and an inactive video track.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant