worksheet 3 IoT - Ryan Morgan (20014885)
Implementation in udp.py
What's been completed:
Task 1 – Implemented a function that receives and decodes the welcome message from the UDP server. Data is picked out from the received packet and displayed in a specified format. Pieces of data is picked out using python slicing. Data such as: source port, destination port, data length, checksum, and payload.
Task 2 – Implemented a function that calculates the checksum for a UDP packet. The checksum is required to check if a packet is valid. This function starts by constructing a UDP packet to process and pre-processes the data if the length of the packet is uneven. It then loops through every two bytes in the packet and adds them together, which is then added onto the checksum for each loop iteration. Once all the bytes in the packet is processed, the checksum is bit shifted to the right by 16 and the one’s compliment of the checksum is calculated. The checksum is then returned for packet validation.
Task 3 – Implemented an infinite loop, which sends and a UDP packet with a payload of ‘1111’ and receives and the time back from the server. There’s a one second delay in each loop so a packet is sent/received every one second. The received packet is decoded and displayed.
How to run code:
Make sure the python environment is activated (Example command: “source /home/ryan5.morgan/projects/iot_env/bin/activate”). Then just run the python file “udp.py” and it should work on its own (Example command: “python -u "/home/ryan5.morgan/projects/worksheet3/udp.py"”)
I did not have to make unit tests for my implementation for worksheet 3. This is because the server essentially already tests the implementation. For each loop, the server would send back the correct packet, and send the wrong packet in the loop after.
Functions in udp.py:
udp()
This the main part of functionality for udp.py. It begins by connecting to the server. Then it sends, receive, and display packets to/from the server. Sending, receiving, and displaying packets are mainly done by calling other implemented functions such as display_packet, send_packet and recv_and_decode_packet. There are no parameters for this function. All that is needed is that the function is run with asyncio.
asyncio.run(udp())
Asyncio.run creates an event loop, then waits for the function to finish running, then closes the event loop. This is used to asynchronous tasks.
display_packet()
This function is for displaying the contents of a packet. The packet would be passed into the function as an argument.
E.g. display_packet(“\n\x00*\x00!\x00\xcb;Welcome to IoT UDP Server”)).
Each part of the packet is sliced up (using python slices) and decoded to bytes for it to be printed/displayed. The first 8 bytes of the packet are for the packet header. Bytes 1/2 are for the source port, 3/4 is for the destination port, 5/6 is for the length of the payload, and bytes 7/8 is for the checksum for the packet. Anything after 8 bytes is for the payload. The payload bytes is the payload length + 8, after the first 8 bytes (packet header).
send_packet()
This function constructs a UDP packet and sends it to the server. A UDP packet is made by getting all the parts of a packet in bytes and adding them together in a specific order (e.g. destination port + source port + length + checksum + message). The length is calculated from the length of a message. Once a packet is made, the bytes are encoded using the base64 library and sent off to the server using the websocket library. The websocket, destination port, source port, and message are passed into the function as parameters.
E.g. send_packet(websocket, dest_port, source_port, message))
recv_and_decode_packet()
This function is for receiving a packet from the server,
packet = await websocket.recv()
displaying the encoded packet,
print(f"Base64: {packet}")
and decoding it from base64 using the base64 library.
base64.b64decode(packet)
The websocket is the only argument needed for this function.
recv_and_decode_packet(websocket)
compute_checksum()
This function computes the checksum for a packet. It starts by constructing a packet (not with proper values because it’s not being sent to the server). the packet pre-processed in case the length of the packet is odd (uneven). If the length is odd, then add a 0 byte to the packet and increase the length by 1. The function then loops through each 2 bytes in the packet and adds them together. For each of the 2 bytes added, it is added onto the checksum. Finally, the final checksum is bit shifted by 16 bits and is converted to one’s compliment. Then the function can output the result The source port, destination port and payload are passed into this function as parameters.
E.g. compute_checksum(source, dest, payload)