# Design for WebRTC Part 2 ## Constraints 1. At any time, a client can be in at most 1 room 2. Once a username has been negotiated, it will be used until the websocket is torn down 3. The websocket is only torn down when the client leaves the page (not torn down when the client leaves a room) 4. The username has to be unique among all the currently registered users. (if the client requests for a username that is already taken, the server responds with an error). ## Websocket message format Client-server communication through the websocket will be done through JSON objects. ### Client to server 1. registering a username ```jsonld= { "type": "register", "username": "alice" } ``` 2. request to join a room ```jsonld= { "type": "join_room", "sender_username": "alice", "room": "room1", } ``` 3. WebRTC-related messages ```jsonld= { "type": "video_offer", "sender_username": "alice", "receiver_username": "bob", "payload": "..." } { "type": "video_answer", "sender_username": "alice", "receiver_username": "bob", "payload": "..." } { "type": "ice_candidate", "sender_username": "alice", "receiver_username": "bob", "payload": "..." } ``` 4. Leaving room (hanging up) ```jsonld= { "type": "hang_up", "sender_username": "alice", "room": "room1" } ``` 5. Reconnecting to the server ```jsonld= { "type": "reconnect", "sender_username": "alice" } ``` ### Server to Client ```jsonld= { "type": "register_response", "error": "username taken", "rooms": ["room1", "room2", ...], } ``` Either "error" or "rooms" must be present. 2. responding to request to join a room ```jsonld= { "type": "join_room_response", "room_name": "room1", "error": "room does not exist", "members": ["alice", "bob"] } ``` Either "error" or "members" must be present. 3. WebRTC-related messages Same as the messages sent by client 4. responding to reconnection attempts ```jsonld= { "type": "reconnect_response", "sender_username": "alice", "error": "unknown client", "room": "room1", "members": ["bob", "charlie", ...] } ``` If the client does not have a previous connection with the server, "error" field should be present. Otherwise, if the client was in a room before being disconnected, the server will inform the client of the room's current members. 5. new member joins a room Sent when a new member joins the client's room. ```jsonld= { "type": "new_member", "room": "room1", "username": "bob" } ``` 6. member left room Sent when a member leaves the room (either due to disconnection, or hangup) ```jsonld= { "type": "member_left", "room": "room1", "username": "", "reason": "disconnected | hung_up" } ``` ### Intentionally missing features 1. unregistering (for now, just refresh the page) 2. creating rooms (for now, there will be a single default room) ## Event order ### Bootstrapping 1. client establishes a websocket with the server 2. client requests for username by sending "register" 3. server responds whether the username is acceptable 4. if not acceptable, client informs user, otherwise proceed 5. the client displays the list of rooms to the user ### Joining a room 1. client sends "join_room" 2. server responds (also sends 'new_member' message to the existing members, who should prepare to establish a new p2p connection with the new member) 3. if response contains error, display error and abort 4. otherwise, the client establishes p2p connection with each other member in the room. ### Hanging up 1. client sends "hang_up" 2. server sends member_left to every other member in the room 3. other clients should clean up their p2p connection. ### Reconnecting (or more precisely, re-joining the previous room after temporary network disruption) 1. client sends "reconnect" 2. server checks whether its record shows the client was in a room 3. if not, respons with error 4. otherwise, send the current list of participants in the room ### Client times out 1. server periodically sends pings to the client 2. if a pong is not received within the specified deadline, the server will kill the websocket and send "member_left" to the other members in the room. NB. the browser's implementation of WebSocket responds to pings by sending pongs automatically. ### Clients closes/refreshes the tab 1. the client websocket will be closed with status code 1001 2. the server cleans up the resources and inform the other members in the room (by sending a "member_left"). ## Discussion Corner ### what happens when the client never comes back? l: hmm i don't know l: maybe the server removes the client after a set timeout (>5 mins), and sends the clientHangup message l: do you have any ideas for this? g: not really l: maybe we avoid handling this case for now g: good idea g: I'm planning to implement this with ping/pongs (see above). any thoughts? --- g: I think channel based communication would be cleaner here. I'm still reading up on the topic. Websocket seems to support virtual channels on the same TCP connection. l: socket.io certainly does, but default websocket library requires a lot more work to do so and it's similar to what we have set up (e.g. an additional `channelID` parameter) g: yea, basically that g: But there are native ways to do that let me research more before coming to conclusion g: i think's it's a protocol extension g: socket.io is a websocket wrapper. g: websocket has it's own native extensions to do this g: have you read the book chapter? g: the link in trello g: hmmm? g: the hbpn chapter on websockets g: wait g: hmm? l: I guess I'll try to find it on node then l: most likely using a combination of node/react l: which book chapter l: for webrtc or websocket l: no i haven't read it yet l: all of the methods I've seen use socket.io, which we cannot use here because we're using a go signaling server l: I think what you're referring to is this https://www.npmjs.com/package/websocket-multiplexer l: which is basically an implementation of the idea in the book l: I need to eat dinner now, see you tomorrow ## Original plan ### Message format Original: - `senderID`: Contains the sender ID, or in the event `clientDisconnect`, contains the disconnected user. - `receiverID`: Contains the receive - `messageType`: The type of the message. Can take (not limited to) `videoOffer`, `videoAnswer`, `iceCandidate`, `newClient`, `clientReconnect`, `clientDisconnect`, `clientHangup` - `content`: The content of the message ### Event orders When a new client start a websocket, the server should tell the client the current list of rooms. When a new client connects to a room, - The client and server negotiate an ID to use. - The server informs the client about the list of currently connected clients in the room. - The server updates the client's room info for potential disconnections later. (Server-side stuff) - The server sends a `newClient` message to the other clients in the room. - The new client creates a PeerConnection for each user in the room, and send an offer to each with their ID. - Negotiation proceeds normally. When a client leaves a room, - The client sends a `clientHangup` message to the server, which is forwarded to the other clients. - The client cleans up and closes all connections. - The other clients clean up and close the PeerConnection for the leaving client. When a client disconnects from a room, via socket timeout, - The server sends a `clientDisconnect` message with `senderID` as the disconnected client's ID to the other clients in the room. - The other clients update the stream accordingly (e.g., display status message). When a client reconnects to a room, - The server sends the client the list of current connected clients in the room. - The client closes old streams and creates new ones for the missing clients (who have joined since they disconnected). - The server sends a `clientReconnect` message to the other clients in the room. - The other clients update the stream accordingly. - Clients who have not seen the disconnected client will treat the disconnected client as a new peer. [//] other clients must know about the reconnecting client, because the reconnecting client should still be within the member list of the room when other clients joined. if a client tries to reconnects to a room to which it is not a member, the server will send and error and not proceed with reconnection.