TCP/IP | Assignment 2 | --------------------------------------------------- Note: must be turned in on Wed Nov 29. no late assignments accepted. The 2nd assignment is to implement a FTP-like remote file system, using a client-server architecture. We will call this the "HomeBrew File System Service" (hbfs). The architecture must have the following clearly differentiated layers: 1. a client and server at the application layer. 2. a remote procedure call layer. 3. a transport mechanism. --------------------------------------------------------------- 1. the client/server layer: The client should have host and port parameters. % hbfs host|ip-addr port host should be the /etc/hosts name for remote host; an ip address should also be accepted. port - the remote port for the server. The client will talk to the remote hbfs server. The client should have the following commands: 1. ls - list the current directory of the server. The results should be roughly equivalent to a UNIX ls -l (long listing) command. List all of the files except . and ..; format as follows: 0744 jrb group size DATE filename Use ctime(3) for date, and print the permissions in octal. Each file should take a line of output. The information should include user, group, and size of the file in bytes. You get this information on the server side with the stat(2) system call. The server should use opendir(3), readdir(3), closedir(3) to walk the directory tree. You may *NOT* simply pipe the results of a "ls -l" command on the server back to the client. You must send the directory back as a stream of file records. More in class on this. 2. cp local_file remote_file - copy a file on the client system to the server system. 3. scp remote local - copy a file from the server to the local system. Use "s" as a prefix to indicate that the copy is to start from the server and treat the local file-system as the target. Note that both "cp" and "scp" are like UNIX cp and proceed from source to target in both cases. You will use open(2|3), close(2), read(2), and write(2), or higher level stdio routines (fopen(3), fread(3), fwrite(3)) to do the file i/o. Use whatever you think is convenient and makes sense. 4. !command - start a shell on the local client system and pass "command" to it for local execution. (Use system(3)). 5. cd dirname - cd to "dirname" on the server. (Server uses chdir(2)); If you want, implement "lcd dirname" on the client so that the client can change directory too. (Understand that the concept of working directory on UNIX is per-process, so that your client must call chdir(2) to change directories; !cd dir won't work.) 6. pwd - print working directory on the server. You can use pwd(1) on the server side to get the info. One way to do this is to use popen(3) and read the return value (the string) from pwd(1). (For the client, !pwd will work.) 7. help - print out a list of commands available on the client. 8. CTRL-D. terminate. You may have a "quit" or "exit" command if you choose. 9. rm file. The system must be able to remove a single file (but should not be able to remove directories). The client must be named hbfs. The server must be named hbfsd. % hbfsd port& The SERVER MUST BE ABLE TO HANDLE MULTIPLE CONNECTIONS. The server should be a master-slave server as discussed in the first few weeks of class. This means that the master server must fork a connected "slave" server for each new connection. The file system server. The port number should match the client port number. The server should terminate when sent a SIGHUP signal and should be started on background. --------------------------------------------------------------- 2. a remote procedure call level You must design and implement a remote procedure call (rpc) mechanism for implementing the client and server. This must take the form of a definite layer in the design. The rpc calls should be documented in your architecture plan. Suitable rpc calls should be designed and used for the "needs" specified above for the client; e.g., to implement a remote procedure call to change directory on the server, we need: int /* error */ rpc_chdir(char *dir) - tell the server to cd to dirname. Remote procedure calls should hide the details of byte order and compiler structure element order from the client and server. This is typically referred to as "marshalling" the data. This isn't hard for a char string since you don't have to do anything. Houwever the error return code must be "marshalled" because it is a long int. RPC calls should be synchronous; i.e., each call should go from the client, to the server and only return to the client when done. E.g., client: int error rpc_chdir(char *dir) msg.type = htonl(CHDIR); msg.buffer <--- dir writemsg(&msg, sizeof(msg)...); readmsg(&ackmsg, ...); return(ntohl(ackmsg.result)); server: readmsg(&msg...); type = ntohl(msg.type); switch(type) { case CHDIR: errno = 0; chdir(msg.buffer); ackmsg.result = htonl(errno); } writemsg(&ackmsg...); The flow here is that client writes to make the rpc request, and then blocks reading the return value or an ACK in the case of no return value. (The client/server pair must act synchronously to carry out the rpc call). The server reads, computes a result or carries out an action and finally writes an ACK or result back to the client. Notice the use of conversion macros to make sure machine byte-order is not a problem. You must specify the rpc interface in the architecture description. You *may* if you so desire, use Sun's rpc mechanism for this step. You do not have to use Sun's rpc mechanism. It could easily make your life needlessly complicated, but it wouldn't hurt to try and learn about it either. The choice is yours. If you use Sun RPC; you should use *rpcgen*, the xdr compiler. 3. a transport level You should use TCP as a transport in order to gain experience with TCP socket programming. (You wanted to use rup?). 4. Turn in at class (see syllabus for due date): 1. src listings 2. makefile 3. script output roughly show your test plan as captured with script via client side runs. 4. architecture description describe in ENGLISH the overall implementation of your protocol. This is an important part and will be the first thing the instructor/grader reads. Be sure and justify your decisions. 5. test plan This should consist of a set of test cases where you list each test, describe what it does, and describe what results you expect. Your script output should reflect a run of your test plan. You may put tests in the test plan, that you cannot execute. Justify them and clearly state that you cannot execute the test. ALSO turn in all of the above via e-mail to the instructor or grader as a shar listing. You turn in two things. 1. printed version at class. 2. email version using shar.