DUE DATE 1/23/2007 11:59pm
Note 1: to reset your password, please use the '-r' option.Note: It is possible that there may be bugs in our code. Please let us know ASAP if you suspect a bug.
For this homework, you are to write the client side and modify the server side of a turnin program that you will use to turn your homeworks and/or programming assignments in for the rest of the semester. This project is to be done individually.
The server side code (turnind.c and _turnind.c) and a skeleton of the client side code (turnin.c) is available from the link above. The missing client code will also be available in object form (_turnin.o for Sun Solaris and _turnin-linux.o for Linux). The Makefile in that directory makes both the client and server side binaries. Copy all the files and subdirectories in the assignment directories to your own hw1 directory. To make the binaries for Sun Solaris do:
% make sunwhich generates the binaries named turnin and turnind. To make the binaries for Linux do:
% make linuxwhich generates the binaries named turnin-linux and turnind-linux.
If you are new to network programming, check here for a tutorial on sockets programming.
To run turnin, which authenticates you via a shared secret in the form of a password known to both you and the server, you must set your password. You can run the client with the -r (for reset) option to set your password. We will issue you a starting password which you may change to whatever you like. You are advised not to use any password you use for any other account (especially any umich login), as the server will store the plaintext version of your password. Make sure that no one else knows your password, even members of your own group. Finally, read all the contents of this page CAREFULLY before you start your programming.
The first part of your mission is to replace the following functions in turnin.c: tin_setup_conn(), tin_send_hdr(), tin_send_fhdr(), tin_send_file(), and tin_recv_ack() with ones that do not make a call to their associated functions in _turnin.o.
(That is, you are to REPLACE the call to _tin_setup_conn() in tin_setup_conn() with your code. You DO NOT write a function named _tin_setup_conn(). Similarly for tind_recv() in the server code, you are to put your code, in that function and not write a separate function named _tind_recv().)
Your client code takes the following command line arguments:
% turnin [-r] [-l] [-s servername] [-p port#] -a assignment [files...]
where -s servername and -p port# are optional arguments (that's what the brackets mean) to help you in debugging. (We will discuss these options further in the debugging section below.)
The -r option causes the client to let you reset your password. When using this option, only the -s servername and -p port options apply (i.e., others are ignored). It is only when using this option that -a assignment is not required.
The argument -a assignment is required, where assignment is one of hwX and paX, X a single digit. For this homework, use hw1. The files... are the files you want to turn in. These files must be in the directory where you're running the turnin client, i.e. the filenames cannot have a path name component to them.The option -l may be used with the client to get a list of turned in files for the specified assignment. A list of turned in files is automatically returned whenever you actually turn some files in.
You can turn in a file as many times as you want. The server overwrites any existing file with the same name with the new copy. Always keep a copy of all the files you turn in.
When your client connects to the server, it first must authenticate the server, as well as prove your identity to the server. To do this, it uses a shared secret (a password) known to both parties. The authentication protocol works as follows:
1. Upon connecting, the client C sends the server your uniqname and a random two-letter string NC chosen from [a-zA-Z0-9./] as a challenge. This message must be exactly 11 bytes long. See Fig. 1.
Figure 1: The client challenge.
2. Upon receiving the client challenge, the server S first computes RS = crypt(password,NC), where password is the password it has on file for the given user (uniqname). RS is always exactly 13 printable ASCII characters long (see the crypt() man page for more info). It also selects its own random 2-byte nonce, NS. It sends the client the concatenation of RS and NS, a 15-byte message.
3. Upon receiving the server response, the client checks that RS = crypt(password,NC). If not, it closes the connection and aborts. Otherwise, it then computes RC = crypt(password,NS), and sends these 13 bytes back to the server.
4. When the server receives RC, it checks that RC = crypt(password,NS). If so, the user is authenticated and we may proceed; otherwise, the server closes the connection.
Figure 2: The turnin header _tin_head.
Once authentication is complete, the server expects to receive the following in order: First, a turnin header that tells the server four things: (1) the version number of the turnin protocol you're running (for this homework, use TIN_VERS as defined in turnin.h), (2) the operation you want, this is either TIN_PUT or TIN_LST; the former if you didn't specify -l on the command line, the latter otherwise, (3) the assignment for which you are turning in files, and (4) the number of files you are turning in, 0 if operation is TIN_LST. Fig. 2 shows this header in pictorial form. It is defined in turnin.h as the _tin_head structure.
Figure 3: The file header _tif_head.
Next, for each file you turn in, you must first send a file header depicted in Fig. 3 (and found in turnin.h as the _tif_head structure) to tell the server what to expect. After you send the file header, you can send the file in chunk(s) of TIN_DLEN bytes, as defined in turnin.h.
When you're done sending, the server will reply with either an error message (of maximum size TIN_MLEN bytes--again, as defined in turnin.h) if there was an error, or it will send you a list of all the files turned in for the specified assignment (with size NOT limited by TIN_MLEN or TIN_DLEN). Your client must be prepared to receive the whole extent of this message and print it out.
As specified, turnin can send and receive both plain text and binary files correctly, make sure yours can too. Also make sure that yours does not truncate large files.
To prevent the server from getting hung by a misbehaving client, the server socket is put into non-blocking mode in tind_waitfor_conn(). Thus in tind_recv() the server polls the socket for data every TIND_SLEEPUSEC, for a maximum of TIND_MAXTRIES times so that buggy client won't cause an infinite loop. This could be better implemented using select(). The second part of your mission is to rewrite the tind_recv() function in turnind.c with a version that uses select() instead of calling _tind_recv(). In writing your function, you should ``protect'' every call to recv() by a select(), which should wait for a maximum of TIND_SLEEPUSEC. If select() times out and you still haven't received all the data you're expecting, you may try again for TIND_MAXTRIES times. TIND_SLEEPUSEC and TIND_MAXTRIES are defined in turnin.h
To test your server, the directory from which you run your server should have a sub-directory named hw1.
You can tell the server to listen on a different port number than the default one by using the -p option. For example, the command:
% turnind -p 4891fires up the server listening on port 4891.
Recall that the server must know the password for your uniqname in order to perform authentication with the client. To set a password, change to the passwds directory below your hw1 directory. You will see that there is already a file named uniqname containing the string password. To set a password for your uniqname, simply create a new file of the same name as your uniqname, and put your password in it (be sure not to include any extra characters!). You can do this easily with the following command (replace "password" with your desired password):
echo "password" > $USERFirst get your turnin client working on CAEN's Solaris machines. Run our turnind and then your turnin client, on the same machine. By default, the turnin client assumes the server runs on the same machine and is listening on the default port. If there is already someone else running turnind on your machine, your attempt to run turnind will fail with the error message:
bind: Address already in use Abort (core dumped)In which case, you simply run turnind again with a different port number, for example:
% turnind -p 4891You will then need to also tell your turnin client to talk to the server listening on that port:
% turnin -p 4891Otherwise you will be sending your file to whomever is running the other turnind server! (Don't get any ideas now . . . .) Once you get your turnin and our turnind working on the same Solaris machine, try them on different Solaris machines. You use the -s option to tell your turnin client which machine your server is running on, for example:
% turnin -s cputo talk to a turnind running on cpu.engin.umich.edu, listening on the default port number.
Next, run your turnin client on a CAEN linux machine (using an Intel processor; use uname -n to find out what architecture you're on), and our turnind on a Solaris machine. (You can find a list of Sun or Linux machines using hostinfo -sun and hostinfo -linux, respectively, on any CAEN machine)
Using your turnin client, turn in all the files you modified. DO NOT TURN IN FILES YOU DO NOT MODIFY. DO NOT TURN IN OBJECT AND BINARY FILES. The ``official'' EECS 489 turnind server runs on the machine koala.eecs.umich.edu. It listens for connections on the default port, 4891. To turn your files in, you do, for example:
% turnin -s koala.eecs.umich.edu -a hw1 turnin.c turnind.cThe server name koala.eecs.umich.edu MUST be given in full, i.e. you cannot just type koala. To list the files you have turned in:
% turnin -l -s koala.eecs.umich.edu -a hw1
Note that the server on koala.eecs.umich.edu will not be running until the day before the project is due. You MUST test your client against a turnind server running on your localhost when testing your code, as described in the debugging section above. DO NOT USE THE turnind SERVER ON koala FOR TESTING!