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
Write a "how it works" documentation #409
Comments
Information about the connection/handshake would be nice, so people can easily write adapters :) |
The connection to a signaling server and connecting to other participants depends on the WebRTC server tech you use, but I know what you mean. To create an adapter you need to implement a set of methods, you have the list on the interface NoOpAdapter |
True, I've just created a slimline WebSocket server as I was finding easyrtc too opaque as an easy "get to grips" solution. What helped me to understand everything in the end was putting a console.log in each of the existing wseasyrtc adapter's methods to see the exact flow and expected callbacks. For example, I didn't really understand when a client would be sent an individual message vs a broadcast, and if they should be handled separately (the answer is no, they should both be fed to the messageListener callback in setDataChannelListeners). Another issue I had was the setRoom function, it seems like the connection and setRoom are independent, but with wseasyrtc at least, the adapter expects the room to be joined on connection, before it returns the clientid - that's not obvious unless you debug quite closely. I hope this is useful feedback! |
This is useful feedback. Putting console.log is something I did a lot too. You're correct about the clientId of wseasyrtc adapter, you know it only after you're connected to the room, and that's an issue actually, make it hard to fix this issue #320. The janus adapter in comparison you set the clientId before connecting. individual message: Depending on the adapter the implementation can be different, sending over reliable datachannel of each participant (mesh typology, the easyrtc adapter) or via websocket (wseasyrtc adapter). For janus adapter, broadcast can be on reliable datachannel or websocket, sending a private message you need to use the websocket transport ( |
I also find it quite hard to get a good understanding of the whole flow, when is which method called from the adapters. Also when is information broadcasted to the channel, i.e. in a client-server kind of way, and what information is sent p2p. I will also try to understand better adding a console.log to all the different methods in the adapter. A visual overview/ diagram as you proposed would be much appreciated, whenever you find time. |
Alright I'll focus first on the transfer logic for the entities data, I won't go in details on the signaling part in this post.
When you connect, each networked component will take care of sending the entity to all participants if you're the owner of the entity. When you create an entity, at first you're the creator and owner of it, creator won't change, owner can change during the lifetime of the entity. networked-aframe/src/components/networked.js Line 277 in 3299622
onConnected callback registered for the the connected event that is triggered herenetworked-aframe/src/NetworkConnection.js Lines 70 to 76 in 3299622
This call networked-aframe/src/components/networked.js Line 342 in 3299622
When a user join, all the participants are notified, if those other participants own some entities, they will send their owned entities to the joined user with networked-aframe/src/components/networked.js Line 340 in 3299622
This is actually when the user opens a connection to the new user that we do the firstSync to this user only networked-aframe/src/NetworkConnection.js Lines 130 to 137 in 3299622
that calls networked-aframe/src/NetworkEntities.js Lines 141 to 147 in 3299622
Later, if you take ownership of an entity (with the networked-aframe/src/components/networked.js Line 342 in 3299622
but this time with isFirstSync: false on the data.
When an entity is removed by the owner, it broadcasts a remove message to all participants: networked-aframe/src/components/networked.js Line 581 in 3299622
All the above use the reliable transport. Depending of the adapter it can be the websocket or a WebRTC datachannel configured with When you do some changes to a owned entity (like position and rotation or other components defined in the networked schema), it uses networked-aframe/src/components/networked.js Line 104 in 3299622
to broadcast to all participants using the unreliable transport, see no Guaranteed in the name of this api. Depending of the adapter it can be websocket or WebRTC datachannel configured with { ordered: false, maxRetransmits: 0 } .The data are sent 15 times per sec (NAF.options.updateRate=15) so every 66ms if something changed. networked-aframe/src/components/networked.js Line 112 in 3299622
When you receive a notification that a user disconnected, all non persistent entities he created even if owned by someone else are removed. If there are persistent entities that the user created, each participant will try to get ownership of those persistent entities. networked-aframe/src/NetworkConnection.js Lines 139 to 146 in 3299622
that calls networked-aframe/src/NetworkEntities.js Lines 155 to 172 in 3299622
The last participant that took ownership wins. networked-aframe/src/components/networked.js Lines 467 to 472 in 3299622
Feel free to contribute a diagram from the above explanation. :) You can start one with https://excalidraw.com and share it here if you want. |
Thanks a lot Vincent, that does clarify already a lot of things. Do I understand correctly that with the WsEasyRtcAdapter and EasyRtcAdapter all the data is sent peer-to-peer, even if it is broadcasted to everyone? I read the following doc, is it correct that there is no adapter in place which which sends the data from a client to a server, which then broadcasts the messages through websockets to each client? We are looking for a solution that we can scale with many users, by using a commercial solution like Ably, so we do not need to maintain our own server. It is not quite clear to us how we would implement such an adapter. |
Indeed with the Only EasyRTCAdapter is peer-to-peer (audio/video/data with WebRTC), mesh topology. |
That makes sense, thanks. I will implement an Ably adapter and see if I find time to create a diagram along the way. That was all very helpful! |
I created an AblyAdapter today which seems to work but I still have a few questions:
networked-aframe/src/adapters/naf-socketio-adapter.js Lines 170 to 183 in 3299622
|
For easyrtc, the check is done in the open-easyrtc library There is a similar check in janus adapter for publisher WebRTC connection In theory you should never see those warnings, If you see them, there is probably something wrong. As we saw above, the initial networked-aframe/src/NetworkConnection.js Lines 46 to 49 in 3299622
In the case of the janus adapter, the socket is opened, the publisher WebRTC is created and then the connectSuccess callback is called. So you definitely should do something like that if your reliable transport is via WebRTC datachannel https://github.com/networked-aframe/naf-janus-adapter/blob/fed7925cd1f4f771980f63a845edcfd606ae3544/src/index.js#L246-L252 The broadcast for the first sync via the WebRTC datachannel initially is probably useless for janus sfu, because nobody is connected to us yet, so the real first sync will happen when we're connecting to each participant and when the onOccupantConnected callback is calledhttps://github.com/networked-aframe/naf-janus-adapter/blob/fed7925cd1f4f771980f63a845edcfd606ae3544/src/index.js#L344 For the easyrtc adapter, the networked-aframe/src/adapters/EasyRtcAdapter.js Lines 166 to 175 in 7d7b1ab
It will actually send the first sync via websocket if the WebRTC datachannel is not yet ready. https://github.com/open-easyrtc/open-easyrtc/blob/221f6439a083aa6e47b0e508d155723b60bdec4e/api/easyrtc_int.js#L3273-L3280 |
For the networked-aframe/src/NetworkConnection.js Lines 82 to 108 in 3299622
The easyrtc adapter uses those methods: networked-aframe/src/adapters/EasyRtcAdapter.js Lines 127 to 150 in 7d7b1ab
janus adapter doesn't use those methods and do the logic internally: Those methods are used to subscribe to a participant for naf updates, audio, video.
|
Write an overview of how it works “internally”, regarding data-flow, serialization, send interval, if it's send at all (ownership), deserialization on the receiving end. A diagram would be nice.
What do you folks want to know?
The text was updated successfully, but these errors were encountered: