Programming Assignment 0
In this assignment, you will write both a TCP client and server. The client has a ﬁle and wants to obtain the hashes for various segments of the data inside the ﬁle. The client will send a message to the server for each segment, and the server will respond with the hash of the segment. The client converts each hash into a hexidecimal string representation, and prints it to the console. The server must be able to handle more than one client concurrently.
Figure 1: Example message sequence diagram for the assignment protocol.
An overview of the protocol is shown in Figure 1. The protocol between the client and server will use four types of messages: Initialization, Acknowledgement, HashRequest, and HashResponse. The client starts by sending an Initialization message to the server, which informs the server of the number of hashing requests that the client will make (denoted by the variable N). Afterwards, the client sends N HashRequest messages to the server, where each HashRequest contains the data segment to be hashed. The server responds to the Initialization message with an Acknowledgement, which informs the client of the total length of the response. The server responds to each HashRequest with a HashResponse that contains the hash of the corresponding data. The formats for four types of messages are shown in Figure 2. Additional details for each type of message are listed below.
ID Length Data
2 4 (Length)
i Hash i 4
(N = Number of Hash Requests)
(ID = 0x0417)
Figure 2: Format for messages used in the assignment protocol.
Initialization (Client ! Server) 1. N: A 4-byte integer value in network byte order that corresponds to the number of HashRequests that the client will send to the server.
Acknowledgement (Server ! Client) 1. Length: A 4-byte integer value in network byte order that denotes the total length of all HashResponses. This should be equal to 36*N.
HashRequest (Client ! Server) 1. ID: A 2-byte integer value in network byte order that is set to the value 0x0417.
2. Length: A 4-byte integer value in network byte order that denotes the length of the Data payload in number of bytes.
3. Data: A payload that holds the data segment to be hashed.
HashResponse (Server ! Client) 1. i: A 4-byte integer value in network byte order that denotes the zero-based index of the response. That is, the ﬁrst HashResponse should have this set to 0, while the last HashResponse should have this set to N – 1.
2. Hash i: A 32-byte (256-bit) value that corresponds to the hash of the data contained in the ith HashRequest sent by the client.
3 Server Implementation
The server will be a command line utility, which takes the following arguments:
1. -p <Number = Port that the server will bind to and listen on. Represented as a base-10 integer. Must be speciﬁed, with a value 1024.
2. -s <String = Salt that the server will use in computing the hash. Represented as an ASCII string. This is an optional argument.
An example usage is as follows:
server -p 41714 -s newsalt
The server listens for incoming connections on a TCP socket bound to the port speciﬁed in the command line arguments. The server should be capable of handling multiple concurrent client connections. Three ways of supporting concurrent connections are fork(), threading, or select()/poll() (see their manpages for more information). For each HashRequest that the server receives from the client, the server must compute the hash of the data using the SHA256 cryptographic message digest function. We provide code that wraps OpenSSL functionality in a Git repository that you can clone as follows:
git clone [email protected]:materials
The ﬁles are located in the ‘hash’ directory, and the header ﬁle contains information on the API. If the salt is speciﬁed, the server will pass the salt to the wrapper functions as the binary representation of the ASCII string, not including the NULL byte at the end of the string. Otherwise, if the salt is not speciﬁed, the server passes a NULL pointer (and 0 length) to the wrapper functions. The server is restricted to using at most 1 megabyte of memory for each client. Clients may request a hash for a source ﬁle that exceeds those bounds. Thus, hashes must be calculated without retaining the full message in memory. Additionally, the client may issue a large number of small hashing requests. Therefore, the server should start sending HashResponses without waiting until the Nth HashRequest has been received.
4 Client Implementation
The client will be a command line utility, which takes the following arguments:
1. -a <String = The IP address of the machine that the server is running on. Represented as a ASCII string (e.g., 220.127.116.11). Must be speciﬁed.
2. -p <Number = The port that the server is bound listening on. Represented as a base-10 integer. Must be speciﬁed.
3. -n <Number = The number of HashRequests (N) that the client will send to the server. Represented as a base-10 integer. Must be speciﬁed, and have a value 0. 4. –smin <Number = The minimum size for the data payload in each HashRequest. Represented as a base-10 integer. Must be speciﬁed, and have a value 1.
5. –smax <Number = The maximum size for the data payload in each HashRequest. Represented as a base-10 integer. Must be speciﬁed, and have a value 224. 6. -f <File = The ﬁle that the client reads data from for all HashRequests. Must be speciﬁed, and have enough data to support N requests at the maximum length (speciﬁed by -n and -smax respectively).
An example usage is as follows:
client -a 18.104.22.168 -p 41714 -n 100 –smin=128 –smax=512 -f /dev/zero
We provide code parses the options for you, located in a Git repository that you can clone as follows:
git clone [email protected]:materials
The ﬁles are located in the ‘assignment0’ directory. After reading in and parsing the command line arguments, the client will connect to the server and start the protocol by sending the server an Initialization message. For each one of the N HashRequests, the client must do the following:
1. Sample a random number L uniformly at random from the range [SMin,SMax].
2. Read in the next L bytes from the source ﬁle.
3. Construct and send the HashRequest message using the L bytes read as the data payload.
As the client receives each HashResponse, it must print out the index and thirty-two byte hash contained therein. The index must be in decimal format, while the hash must be in lowercase hexadecimal form. They should be separated by a colon and space (“: ”) and the hash must be preceded by “0x”. Each HashResponse should be on a new line. Here is an example of a correct line of output, corresponding to the 7th HashResponse received:
Your project grade will depend on the parts of the project that you implement. Assuming each part has a “good” implementation, the grades are as follows:
Grade Parts Completed A Client and Server (Handles 1+ Clients) B Client and Server (Handles 1 Client) C Client Only
6 Additional Requirements
1. Your code must be submitted as a series of commits that are pushed to the origin/master branch of your Git repository. We consider your latest commit prior to the due date/time to represent your submission.
2. The directory for your project must be called ‘assignment0’ and be located at the root of your Git repository.
3. You must provide a Makeﬁle that is included along with the code that you commit. We will run ‘make’ inside the ‘assignment0’ directory, which must produce two binaries ‘server’ and ’client’ also located in the ‘assignment0’ directory.
4. You must submit code that compiles in the provided VM, otherwise your assignment will not be graded.
5. Your code must be -Wall clean on gcc/g++ in the provided VM, otherwise your assignment will not be graded. Do not ask the TA for help on (or post to the forum) code that is not -Wall clean, unless getting rid of the warning is the actual problem.