You will continue to add features to your app and pull from the repo to get the new front end features.
Sample Deployment: https://312demo.nico.engineer/
If you haven't already on HW3, please go to this line in your server.py: "socketserver.TCPServer.allow_reuse_address = True" and "server = socketserver.TCPServer((host, port), MyTCPHandler)". Change both of these lines from TCPServer to ThreadingTCPServer. This will make sure that your server can handle multiple requests at once, without blocking other requests.
In a file named websockets in the util package, write a function named compute_accept that takes a WebSocket key as a parameter (As a string) and returns the correct accept (As a string) according to the WebSocket handshake.
The output must be character for character exactly what is expected. Make sure you don't have any extra characters in your output (Not even white space).
You may use libraries to compute the SHA1 hash and Base64 encoding.
Add a function named parse_ws_frame to the util.websockets file that takes bytes as a parameter that represents the bytes of a WebSocket frame and parses all the values of the frame. The function returns an object containing the following fields (You have some freedom in how you design the class for this object as long as it has the required fields).
Add a function named generate_ws_frame to the util.websockets file that takes bytes as a parameter and returns a properly formatted WebSocket frame (As bytes) with the input bytes as its payload. Use a fin bit of 1, an op code of bx0001 for text, and no mask. You need to handle all 3 payload length modes.
With your 3 helper methods ready, you will now add WebSocket features to your app. First, add the following HTML paths to your server:
The front end will initiate a WebSocket connection using the "/websocket" path. When you receive a request on this path, you should go through the WS handshake to upgrade the connection.
When the connection is established, all WS message will be in the form of JSON objects and will all contain a field named "messageType". This messageType will determine how to handle the message.
Implement an echo feature that will be used on the Test WebSocket page. For this feature, whenever you receive a WS message of type "echo_client", read the message from the "text" field which is what the user typed and sent. In response, send a WS message back to only the sender of type "echo_server" with a field named "text" containing the exact message that was sent to your server.
For example, if your server receives a WS frame containing the payload:
{"messageType":"echo_client","text":"WebSockets are for winners"}
You will send a WS frame back to the sender containing the payload:
{"messageType":"echo_server","text":"WebSockets are for winners"}
These message can, and will during testing, be large enough to test all 3 payload length modes. This also implies that you must implement buffering for the WebSocket frames you receive. Continuation frames are not required for this objective.
Implement the shared drawing board from the Drawing Board page. When a user draws, the client will send WS messages of type "drawing" to your server. When you receive a message of this type, you will:
When a user first creates a WS connection, send them the drawings that have already been made (It is ok if you always send this even when the user is not on the Drawing Board page). This should be sent in a WS message of type "init_strokes" containing a field "strokes" that is an array of all the drawing messages received by your server. This feature will allow users to see all the drawings that have been made before they loaded the page since only the new drawings are broadcast. You should now be able to refresh the page and still see all the drawings.
Example Message: {"messageType": "init_strokes", "strokes": [{"startX": 283.1, "startY": 232.7, "endX": 287.5, "endY": 152.2, "color": "#000000"}, ... ]}
Note that you will need a way to store all WS connections in a way that can be accessed from all connections to enable broadcasting.
Send a message of type "active_users_list" containing a field named "users" with an array containing all the authenticated users who have an active WS connection. Each user is represented as an object with a field "username"
Example Message: {"messageType": "active_users_list", "users": [{"username": "admin"}, {"username": "cse312"}]}
Broadcast this message to all WS users whenever this list changes. This includes whenever you finish a WS handshake (adding a user), and whenever you see a disconnect opcode (removing a user).
Expand your WebSocket code to support the processing of multiple frames under the following two conditions:
To complete this objective, your server must handle the case where multiple messages requiring continuation frames are sent back-to-back.
Implement DMs on the Direct Messaging page. To accomplish this, add the following functionality to your server:
Security: Do not send DMs to anyone other than the 2 users who are part of the conversation.
Build a Zoom clone. This feature will allow users to create video call "rooms" that can be joined by other users. Each room can contain any subset of users, and they can all share audio and video in peer-to-peer connections using WebRTC.
Add a POST endpoint at the path "/api/video-calls" that will create a new video call. The body of the request will be a JSON object with a field named "name" that should be stored as the name of the room. Your app will respond with the id of the room (Generated by you) in a JSON object (eg. {"id":"67e42b3b0cb5bda054049243"}).
To enable this feature, you'll need to support the following WS messages:
Each objective will be scored on a 0-3 scale as follows:
3 (Complete) | Clearly correct |
2 (Complete) | Mostly correct, but with some minor issues |
1 (Incomplete) | Not all features outlined in this document are functional, but an honest attempt was made to complete the objective |
0.3 (Incomplete) | The objective would earn a 3, but a security risk was found while testing |
0.2 (Incomplete) | The objective would earn a 2, but a security risk was found while testing |
0.1 (Incomplete) | The objective would earn a 1, but a security risk was found while testing |
0 (Incomplete) | No attempt to complete the objective or violation of the assignment (Ex. Using an HTTP library) |
Note that for your final grade there is no difference between a 2 and 3, or a 0 and a 1. The numeric score is meant to give you more feedback on your work.
3 | Objective Complete |
2 | Objective Complete |
1 | Objective Not Complete |
0 | Objective Not Complete |
Autograded objectives are graded on a pass/fail basis with grades of 3.0 or 0.0.
For each objective for which you earned a 0.3 or 0.2, you will still have an opportunity to earn credit for the objective by submitting an essay about the security issue you exposed. These essays must:
Any submission that does not meet all these criteria will be rejected and your objective will remain incomplete.
Due Date: Security essays are due 1-week after grades are released.
Any essay may be subject to an interview with the course staff to verify that you understand the importance of the security issue that you exposed. If an interview is required, you will be contacted by the course staff for scheduling. Decisions of whether or not an interview is required will be made at the discretion of the course staff.
When you don't have to write an essay: