CS4513 Project 4

Nutella - A P2P Streaming Movie System

                        _,''"`.      ,~     
        ("`-''-/").___.- (     )_    \ |    
         `6_ 6  )   `-.   `_   ).`--.' /    
         (_Y_.)'  ._   )    ', . ``-..'     
          `--' _.- _/ /--'_.' ,'            
           (il) (li),'  ((!.-'              

The term is nearly over. Your Distributed Systems course has been brutal and you need some R&R this term break. What you want to do is kick back, relax and watch a flick from the comfort of your home. You make a plan to make this happen, using the magic of the some text-based video, your computer and, of course, some slick distributed systems programming!

Due date: Thursday, December 18th by 11:59pm

Note, positively the last day this project can be turned in is Friday, December 18th by 11:59pm! We need to have time to grade them before assigning final grades. Please plan accordingly.


Index


Search

You will use a non-centralized system for your document searching. Users will input a text-based query, which the local Nutella client will multicast to other Nutella peers. Any Nutella peer with a match on the content will respond. At that time, the local Nutella client will contact the remote peer and request the movie. The remote peer will then stream the movie to the local Nutella client.

From the viewpoint of an active Nutella client looking for a movie, the steps of the search process are as follows:

  1. Get query (ie- movie name) from user
  2. Multicast query to well-known address
  3. Listen at a different well-known multicast address for peers with match to query to respond. The response will providing IP and port for contact to initiate streaming.
  4. Contact remote peer at IP and port, requesting streaming of the movie.
  5. If there is no response to the initial multicast query, assume movie is not located on any Nutella peer.

From the viewpoint of a passive Nutella client, the process is:

  1. Listen on well-known multicast address for query.
  2. If query matches local movie list, multicast response back, providing IP address and port for streaming.
  3. If request comes to IP address and port, stream movie.


Stream

When contacted, a Nutella peer will stream a requested movie. Whereas downloading and playing a movie means the entire movie file is transferred to a client before it is played out, streaming has a client play out the movie as it receives the frames over the network. The server, then, sends the movie frames at the frame playout rate.

You should only stream at no more than 10 frames per second. Streaming at 1-3 frames per second is fine, too (and it means you have fewer movie frames to make :-)). You can achieve a delay between sending each frame by using sleep() or usleep() (see the man pages for more details). The idea is to get a "animated" effect.

From the viewpoint of a Nutella client wanting to stream, the steps in the streaming process are:

  1. Send (unicast) request for movie to IP address and port of Nutella peer that responded to query.
  2. Receive frames on (unicast) socket, playing each frame as it arrives.

From the viewpoint of a passive Nutella client, the streamiing process is:

  1. Listen for movie request at (unicast) IP address and port.
  2. Parse request for movie name.
  3. Stream movie to IP address and port of client.
  4. Repeat movie once done, if desired.

You can assume a Nutella peer only sends one movie at a time. Thus, while sending a stream, your Nutella peer can either ignore any subsequent multicast searches for movies, or ignore any additional requests for streaming movies. If you want to add the capability of simultaneously streaming more than one movie (to different Nutella peers), that if fine, however.

A user should be able to play a movie (ie- request a stream from a different Nutella peer) while sending a movie to someone else. Note, you can handle this requirement by actually having a multi-process/threaded Nutella client or by having the Nutella player being a separate program (and then process) from the Nutella streamer.


Movies

Each Nutella peer will have a number of movies they are willing to share by streaming to other Nutella peers. For convenience, the list of movies a peer has can be keep in a configuration file (say, ".nutella") which should also contain information on the file location of each movie.

The movie files themselves are human-readable text containing the animation frames and a frame separator. The format of a movie file is:

picture 1, arbitrarily long
end
picture 2, arbitrarily long
...
stop

For example, the start of the walk.mov file is:

o
|
|
end
 o
 |
/ \
end
  o
  |
  |
end
   o
   |
  / \
    o
    |
    |
end
...

Earlier creative creations include:

Feel free to be creative with the movies. If you stick to the movie format given above, others in the class can share your creations. Have fun!


Multicast

You will use IP multicast sockets for your query communications. IP multicast allows a message sent to reach several receivers simultaneously. An end-point of a multicast socket is the same as that of a unicast socket and specified by an IP address and a port. The valid range of multicast addresses are are: 239.0.0.1 to 239.255.255.255. Valid ports are roughly integers above 6000.

To simplify the use of multicast sockets, you may use some code wrappers (think of them as middleware) written especially for projects like this. The source file containing these wrappers is msock.c and a header file containing prototype definitions is msock.h. The routines provided in msock.h are:

/* msockcreate -- Create socket from which to read.
   return socket descriptor if ok, -1 if not ok.  */
int msockcreate(int type, char *address, int port);

/* msockdestroy -- Destroy socket by closing.
   return socket descriptor if ok, -1 if not ok.  */
int msockdestroy(int sock);

/* msend -- Send multicast message to given address. 
   return number of bytes sent, -1 if error. */
int msend(int sock, char *message, int len);

/* mrecv -- Receive message on given mcast address. Will block.
   return bytes received, -1 if error. */
int mrecv(int sock, char *message, int max_len);

To use the msock wrappers, you must compile the file msock.c yourself. Do this by downloading both the msock.c and msock.h files to your directory and using the command gcc -c msock.c. Better still, use a Makefile.

See mcast.tar for an example of how these wrappers might be used (extract with tar xvf and then type "make".

You may only need one multicast address for your Nutella system, since both queries and responses can be to the same address. However, conceptually it may be cleaner to have a multicast address for queries and a multicast address for responses. For example:

Use       IP             Port  
Query     239.xxx.xxx.1  7000 
Response  239.xxx.xxx.2  7001 

Warning! Be careful of errant multicast code. Below is an example of what might happen due to multicast program that sends too much data (this one due to yours, truely):

From: "Charles R. Anderson" <cra@WPI.EDU>
To: system@cs.wpi.edu, mvoorhis@WPI.EDU, jbanning@WPI.EDU
Cc: netops@WPI.EDU
Subject: cs.wpi.edu flooding network
Date: Mon, 25 Nov 2002 00:29:35 -0500

cs.wpi.edu is flooding the network with multicast traffic, causing
network outages in Fuller Labs.  I have disabled the port.

-- 
Charles R. Anderson			cra@wpi.edu
Network Engineer			(508) 831-6110
Computing and Communications Center	X2220 on-campus
Worcester Polytechnic Institute	    Fax (508) 831-5483
In general, you should be ok if you only send one multicast packet request for each query the user types in but be sure to debug carefully before you run multicast code and monitor the code performance as your do so.


Hints

For displaying the movies, use the Curses information from your project 3.

For your streaming sockets, use the information on UDP sockets from your project 3. In particular, see the sample code talk.udp.c and listen.udp.c, and the class slides on sockets.

Remember, if you read from a socket that has no data, your process will block. You can poll a non-blocking socket for data (use MSG_DONTWAIT with recvfrom() or use fcntl() on the socket). But perhaps better is to use select() to see if any socket has information. See select.c for a sample and do a man 2 select for more information.


Hand In

You must hand in the following:

You will turn in your assignment online using the turn-in program. Before you use turnin tar up (with gzip) your files. For example:

        mkdir proj4
        cp * proj4 /* copy all your files to submit to proj2 directory */
        tar -czf proj4.tgz proj4

then copy your files from your Fossil client to your CCC account:

        scp proj4.tgz login_name@ccc:~/  /* will ask your ccc passwd */
        ssh login_name@ccc               /* will ask your ccc passwd */
        /cs/bin/turnin submit cs4513 proj4 proj4.tgz


Return to 4513 Home Page

Send all questions to the TA mailing list (cs4513-ta at cs.wpi.edu).