Electrical and Electronic EngineeringEG-351 / EG-M191 Internet of Things EG-351 / EG-M191 INTERNET OF THINGS LAB ASSIGNMENT 2 BRIEF Dr Jason Jones
[email protected] Aims The aim of this lab assignment is to show your understanding of: • Programming using the TCP protocol, • Writing a multi-threaded server, • Integrating security using SSL Description This assignment involves the implementation of a multi-user, text-based Instant Messaging system such as WhatsApp, Facebook Messenger, etc.. This involves writing two clients and one server program: • Display Client – Displays any messages entered by yourself or any other connected user. • Keyboard Client – Allows the user to enter a message to be sent to other users. • Server – Links all the clients (Display and Keyboard) together. When it receives a message from a Keyboard client it then sends it to each of the connected Display clients. Message Format A key part to any networked application is the definition of the message formats, i.e. the format of the data that is sent between programs. In this case, a message consists of 3 components: • The username (name) of the sender • The date and time the message was sent • The message text itself In order to ensure everyone’s programs interoperate, it is necessary to define the format explicitly. The format of each message is described in the table below. Field Datatype Size Length of Overall Message (including all the fields below but not this field) Integer 4 bytes Length of Username Integer 4 bytes Username Encoded string (bytes) Variable Year Integer 4 bytes Month Integer 4 bytes Date Integer 4 bytes Hour Integer 4 bytes Minute Integer 4 bytes Second Integer 4 bytes Length of Text Message Integer 4 bytes Text Message Encoded string (bytes) Variable A typical message, using the above format, would look like this. Here, the diagram is split across 4 lines but is, in fact, just one continuous stream of bytes. • The blue section represents the username and comprises: o 1integer storing the length of the username (4 bytes) o 5 characters for the username (5 bytes) • The green section represents the date of the message and comprises: o 3 integers storing year, month and date (3 * 4 bytes = 12 byes) • The pink section represents the time of the message and comprises: o 3 integers storing the hour, minute and second (3 * 4 bytes = 12 bytes) • The orange section represents the text message and comprises: o 1 integer storing the length of the text message (4 bytes) o 11 characters for the text message (11 bytes) If we add all these up, they total 48 bytes. This is stored in the first integer (the white box above) and is the first item to be sent and received. Architecture The architecture of this Lab Assignment is shown below: The server sits in the middle waiting for messages from any of the connected Keyboard Clients. Whenever a message arrives, it immediately sends it to every connected Display Client. The Keyboard Client’s task is to receive text input from the user and then send it to the server. The Display Client’s task is to wait for messages from the Server and display them on the screen. When a Display or Keyboard Client first connects to the server, it must identify itself to the Server as the Server needs to treat them differently – it listens for data from one and sends data to the other. The functions to do this have been provided to you in the ‘comms’ module. NOTE: Obviously, if we were producing an application with a graphical interface (such as the WhatsApp phone app) then each pair of Keyboard client and Display client would be integrated into one application both allowing the user to enter messages and display messages from any other user. However, the development of GUI applications are beyond the scope of this module. Approach Like Lab Assignment 1, this assignment has been designed to enable you to tackle it piece by piece. To do this, four Servers have been written and are available to you. Random Message Server This is a cut-down version of the Full Server that just sends out dummy messages at regular intervals (every 2 seconds). You may use this to test your Display Client before you have implemented your Keyboard Client. This is available at: 137.44.3.246 (engjjeee.swan.ac.uk) - Port number 55100 Full Server This is an implementation of the full server as described in the section below. You may use this to test the interaction with your Display Client and Keyboard Client. This is available at: 137.44.3.246 (engjjeee.swan.ac.uk) - Port number 55200 Random Message Secure Server This is the same as the “Random Message Server” (above) but uses SSL (Secure Sockets Layer) for security. This is available at: 137.44.3.246 (engjjeee.swan.ac.uk) - Port number 55300 Full Secure Server This is the same as the “Full Server” (above) but uses SSL (Secure Sockets Layer) for security. This is available at: 137.44.3.246 (engjjeee.swan.ac.uk) - Port number 55400 Starting Point On Canvas there is a zip file containing 5 Python files: • display_client.py – This can be used as the starting point for your Display Client program. • keyboard_client.py – This can be used as the starting point for your Keyboard Client program • chat_server.py – This can be used as the starting point for your Server program • eee_utils.py – This contains a number of boilerplate routines that you may use in your programs. The details of these can be found in Appendix 1. • comms.py – This is where you can implement your routines to pack/unpack and send/receive messages. Placing this in a separate module enables the same routines to be used in your client programs and your server program. Each of these is fully commented in order to guide you through the tasks. The Tasks This assignment has been broken down into a number of tasks to make it easier for you to implement. Task 1 – Display Client Implementation (15%) The implementation of the Display Client should follow these steps: 1. Connect to the server using a TCP socket 2. Send the server one integer – DISPLAY (defined in the comms module) 3. Loop forever a. Receive a message from the server b. Display the message in the form: Username YYYY-MM-DD HH:mm:ss Message where the date format is year-month-date hour:minute:second (See eee_utils.py and Appendix 1 for help on how to do this) It is advised to test this client against the “Random Message Server” before proceeding onto Task 2. Task 2 – Keyboard Client Implementation (15%) The implementation of the Keyboard Client should follow these steps: 1. Ask the user for their username. 2. Connect to the server using a TCP socket 3. Send the server one integer – KEYBOARD (defined in the comms module) 4. Loop forever a. Ask the user for a message b. Send the message to the server (in the format described above) It is advised to test this client, with your Display Client, against the “Full Server” before proceeding onto Task 3. Task 3 – Server Implementation (50%) For the Server, there is a skeleton of the code given to you as a starting point in file “chat_server.py”. The implementation of the Server should follow these steps: 1. Create a server socket 2. Listen for client connections 3. Loop forever a. Wait to accept a client connection b. Receive one integer from the client – this is the client identifying themself c. If the client identifies itself as a Display Client, add its socket to the global list of Display client sockets (display_client_list) d. If the client identifies itself as a Keyboard Client, create a Keyboard Monitoring Thread (using the function KeyboardClientThread) and pass it the socket for that client connection The implementation of the Keyboard Monitoring Thread should follow these steps: 1. Loop forever a. Wait for a message to be received If an error occurs then assume that Kayboard Client has disconnected so close the socket and end the thread. b. Loop through the global list of display sockets i. Send the message to each of the connected display clients If an error occurs sending the message then assume they have disconnected, so close that socket and remove it from the global list of display sockets. HINT: Since the global list of display client sockets is accessed (and altered) by multiple threads, it is important to use the Lock created for you (display_client_lock) to ensure only one thread can access the list at any given time. Task 4 – Security (20%) NOTE: This task can only be attempted after the lecture material on Security has been covered. The test servers for this Task will be made live at this time. HINT: Remember to keep a backup copy of Tasks 1 – 3 before altering your code to use SSL certificates. The implementation of this task is to use the SSL certificate given to you to ensure all communication is encrypted between the clients and the server. The Root Certificate Authority certificates and the Server certificates can be downloaded as a zip file from the “Lab Assignment 2” section on Canvas. In this zip file, there are 4 files: • “root_ca.crt” – This is the certificate of the “fake” Certificate Authority. Your clients and server must enable trust in this certificate. • “server.key” – This is the private key for your own server. It is linked to the hostname “localhost” or “127.0.0.1”. Like the tasks above, this can be attempted in stages: • Secure Display Client – The “Random Message Secure Server” can be used to ensure it connects and operates correctly. • Secure Kayboard Client – The “Full Secure Server” can be used to test this client along with the “Secure Display Client”. • Secure Server – This is the final part of this task which can be tested using the Secure Display and Keyboard clients (above). Appendix 1 – eee_utils.py There are 4 functions in this module recvall( sock, num_bytes ) This repeatedly calls sock.recv() until the required number of bytes have been received. On success, this returns the byte-string received On failure, this returns the value None sendall( sock, data ) This just calls the Python function sock.sendall() but without you having to understand ‘exceptions’ in order to detect any errors. On success, this returns True On failure, this returns False get_time_now() This function returns the current date and time as a tuple: (year, month, date, hour, minute, second) format_date_time( year, month, date, hour, minute, second ) This function formats the provided parameters in a standard format that meets the requirements of Task 1. Using this function ensures that the correct number of digits are used regardless of whether the numbers are single or double digits). Returns: a string containing the date and time formatted correctly