Learnings from 100ms Dive
These are my learnings while looking into the 100ms repos, inspecting devtools and trying to bind all these into something that make sense.
I might be horribly wrong at understanding these but either way I get to learn something. So here we go.
Repos
- ion-sfu: pion sfu
- ion-avp: audio video processing
- islb: intelligent server load balancing server
- biz: websocket server?
My starting point was from the web-app, opened up devtools
-> network tab
.
Preview
Initial log
# Socket Connection Journey
[HMSTransport]: connect: started ⏰
InitService fetchInitConfig: initEndpoint=https://prod-init.100ms.live/init
[HMSTransport]: ⏳ internal connect: connecting to ws endpoint
[HMSTransport]: ✅ internal connect: connected to ws endpoint
Opening a Websocket connection: Code
Preview establishes a Websocket connection and keeps sending ping ⇄ pong messages.
Upon opening WS
panel
initially you can see on-role-change
& on-policy-change
Looks like info around roles but why do both exist? what is the difference?
on-role-change message
{
"method": "on-role-change",
"params": {
"role": {
"name": "host",
"publishParams": {
"allowed": ["audio", "video", "screen"],
"audio": { "bitRate": 32, "codec": "opus" },
"video": {
"bitRate": 1000,
"codec": "vp8",
"frameRate": 30,
"width": 960,
"height": 720
},
"screen": {
"codec": "vp8",
"frameRate": 10,
"width": 1920,
"height": 1080
},
"videoSimulcastLayers": {},
"screenSimulcastLayers": {}
},
"subscribeParams": {
"subscribeToRoles": ["host", "guest"],
"maxSubsBitRate": 8000,
"subscribeDegradation": {}
},
"permissions": {
"endRoom": true,
"removeOthers": true,
"mute": true,
"unmute": true,
"changeRole": true
},
"priority": 1
}
},
"jsonrpc": "2.0"
}
on-policy-change message
{
"method": "on-policy-change",
"params": {
"name": "host",
"known_roles": {
"guest": {
"name": "guest",
"publishParams": {
"allowed": ["audio", "video"],
"audio": { "bitRate": 32, "codec": "opus" },
"video": {
"bitRate": 400,
"codec": "vp8",
"frameRate": 30,
"width": 640,
"height": 480
},
"screen": {
"codec": "vp8",
"frameRate": 10,
"width": 1920,
"height": 1080
},
"videoSimulcastLayers": {},
"screenSimulcastLayers": {}
},
"subscribeParams": {
"subscribeToRoles": ["host", "guest"],
"maxSubsBitRate": 5200,
"subscribeDegradation": {}
},
"permissions": {},
"priority": 1
},
"host": {
"name": "host",
"publishParams": {
"allowed": ["audio", "video", "screen"],
"audio": { "bitRate": 32, "codec": "opus" },
"video": {
"bitRate": 1000,
"codec": "vp8",
"frameRate": 30,
"width": 960,
"height": 720
},
"screen": {
"codec": "vp8",
"frameRate": 10,
"width": 1920,
"height": 1080
},
"videoSimulcastLayers": {},
"screenSimulcastLayers": {}
},
"subscribeParams": {
"subscribeToRoles": ["host", "guest"],
"maxSubsBitRate": 8000,
"subscribeDegradation": {}
},
"permissions": {
"endRoom": true,
"removeOthers": true,
"mute": true,
"unmute": true,
"changeRole": true
},
"priority": 1
}
}
},
"jsonrpc": "2.0"
}
Every 1 second this happens:
- JSON object with method
ping
is sent withtimestamp
as param - JSON object with
timestamp
asresult
is recieved
Observation: method ping
is an action (call) and the response is the timestamp
this is how jsonrpc 2.0
is standardized. jsonprc is also one of the interface provided by Pion SFU.
The call function that sends JSONRPC request -> Code
This is where ping
is called Code
On the "Backend" pingHandler function handles the results sent to the client.
This is where all methods enums reside.
I disconnect my internet then connect in preview and then join, i don't see any messages/pings in WS why? logs do say my Window and Transport has connected. (nvm new connection is established)
Join
upon clicking join we now send a new method: join
with SDP offer as params.
join message
{
"method": "join",
"params": {
"name": "Deep",
"disableVidAutoSub": true,
"data": "",
"offer": {
"type": "offer",
"sdp": "v=0\r\no=- 997832987756044998 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0\r\na=extmap-allow-mixed\r\na=msid-semantic: WMS\r\nm=application 9 UDP/DTLS/SCTP webrtc-datachannel\r\nc=IN IP4 0.0.0.0\r\na=ice-ufrag:QNrR\r\na=ice-pwd:YLb9lH802wEeI8Y4PbCLFr2O\r\na=ice-options:trickle\r\na=fingerprint:sha-256 75:CE:1E:6B:72:1E:CB:21:6B:1C:EB:AE:03:FF:C9:79:36:9F:24:61:5B:2C:7A:D7:B7:CE:47:7F:90:6F:00:C7\r\na=setup:actpass\r\na=mid:0\r\na=sctp-port:5000\r\na=max-message-size:262144\r\n"
}
},
"id": "142530e9-ff3f-4db1-8fa9-0217915309ba",
"jsonrpc": "2.0"
}
Then the join method sends these params (SDP) to "biz" via the call
method.
Now I am seeing some messages of method trickle
looks like ICE candidate.
trickle message
{
"method": "trickle",
"params": {
"target": 0,
"candidate": {
"candidate": "candidate:3350409123 1 udp 2113937151 ebbcc4b9-7270-4ec2-abac-a7e9766ada98.local 61016 typ host generation 0 ufrag QNrR network-cost 999",
"sdpMid": "0",
"sdpMLineIndex": 0
}
}
}
Then an offer comes from "biz" , peer-list
method with peers, trickle, trickle, trickle, "answer" method (need to learn more).
Now that I know the enum method JOIN = 'join'
finding this in biz should be easy. On the "biz" side it's called PeerJoin
.
Add peer in local room Code
Joining in the SFU client: Code
Then Delete from local room Code
Why local room?