Project 1: a P2P client for sharing images


In this project, you'll integrate the tools you've developed in the labs for this course to build a simple peer-to-peer client for sharing images.

Due date: Thursday April 12 at the start of class. No late assignments will be accepted.

Points: 100 points total (breakdown below)

In this project, you'll build a simple p2p client. It will need to be able to do the following tasks:

In addition, there is some additional functionality that can be built in if you want to get a good grade on the project. (more details below).

Note also: You are welcome to use as much or as little of the code from the labs as you like. There are many places where it could be helpful, but if integration will make your life more difficult, feel free to start from scratch. Also, there are places where your code from CS 601 may be useful. You are also welcome to reuse as much of that as you wish. All code that is written must be your own.

Grading


Grades will be assigned as follows:

To turn in: Place a copy of your client in your submit directory. No hardcopy needed. Also, please be prepared to demo your client on April 12.

Building the peer

Your peer should maintain its list of songs in an XML database. It will communicate with other peers by using RESTful URL requests and replies.

Your client will also need to have some sort of GUI that users can use to interact with it. You should build this using HTML and use a web browser to control the peer.

the GUI should provide the user with:

In building the peer, you will want to construct your own HTTP server that can process requests from a browser and return HTML. If you were careful in how you built your labs, you can probably reuse almost all of this, along with Python's CGIHTTPServer class. If you woud prefer to work in Java, you may reuse the HTTP server you built in CS 601.

Messages

Much of the new code you will write will involve the messages that your peer will send and receive. It is essential that you follow this protocol exactly; in grading your project, I will ask you to run it with other students' projects.

Communicating with the name server

When your client starts up, the first thing it should do is register itself with the name server. For this project, we'll keep things simple and use a single centralized name server. To register itself, your client should use the following RESTful request:
http://scorpio.cs.usfca.edu/~brooks/682/peerdb.cgi/?requestType=register&name=username&address=ipnumber:port

(it's just a simple cgi script, so please be nice to it ...)

You will receive back the following message:
<reply>
  <type>RegisterReply</type>
  <success>true</success>
  <dateTime>Tue 8 Mar, 2007 11:01:02 </dateTime>
 </reply>

Similarly, to unregister, do:
http://scorpio.cs.usfca.edu/~brooks/682/peerdb.cgi/?requestType=unregister&name=username

You will receive back an unregisterReply in return.
To find out what other peers are currently active, send the following request to the address server:
http://scorpio.cs.usfca.edu/~brooks/682/peerdb.cgi/?requestType=findAllPeers
The address server will return XML representing the peer database:
<reply>
  <type>UserListReply</type>
  <success>true</success>
  <dateTime>Tue 8 Mar, 2005 11:01:02</dateTime>
<users>
  <user>
    <name> Joe Smith </name>
    <address> 192.3.55.6:8000 </address>
  </user>
  <user>
    <name> Malcolm X </name>
    <address> 133.66.197.2:8000 </address>
  </user>

<user>
<name>bob jones</name>
<address>132.6.55.1:8000</address>
</user> 
</users>
 </reply>

Communicating with other peers

Your peer should be able to send and respond to the following messages. Note: this protocol is the one that everyone will use. No exceptions or changes.

Request photos that meet certain criteria

A peer should be able to send a RESTful request to another peer asking for photos with particular characteristics. The peer should be able to specify filename, tag, picture type, or date taken, as well as combinations of these (either AND or OR). The receiving peer should return a document containing all movie that match the necessary criteria. For example:
http://valis.cs.usfca.edu:8000/?requestType=GetPhoto&tag=cats&dateTaken=2007-03-21&mode=all&address=123.122.0.1:8000

http://valis.cs.usfca.edu:8000?requestType=GetPhoto&dateTaken=2007-03-21&type=jpeg&mode=any&address=123.122.0.1:8000
The peer receiving the request must repond with an XML message in the following format:
<reply>
<type> getPhotoReply < /type>
  <success> true</success>
  <dateTime> Tue 8 Mar, 2005 11:01:02</dateTime>
  <photos>
    <photo>
    < username> brooks < /username>
      <filename> 123.jpg</filename>
      <dateTaken> 2007-03-21</dateTaken>
      <url> http://www.cs.usfca.edu/~brooks/123.jpg</url>
      <thumburl> http://www.cs.usfca.edu/~brooks/123_thumb.jpg</thumburl>
      <tags>
        <tag> cat </tag>
        <tag> dog </tag>
        </tags>
      </photo>
    <photo>
    < username> joe < /username>
      <filename> abc.jpg</filename>
      <dateTaken> 2007-03-21</dateTaken>
      <url> http://www.cs.usfca.edu/~brooks/abc.jpg</url>
      <thumburl> http://www.cs.usfca.edu/~brooks/123_thumb.jpg</thumburl>
      <tags>
        <tag> bunny </tag>
        <tag> fish </tag>
        </tags>
      </photo>
      ...
</photos>
</reply>

Some notes on this:

Transforms

Your peer should be able to request transformations from other peers. These will correspond to the methods you implemented for Lab 6, although we'll use REST as a protocol instead of SOAP.
The format for transformations is as follows:
http://valis.cs.usfca.edu:8000/?requestType=transform&requestID=123&type=rotate°rees=90&url=http://www.cs.usfca.edu/%20brooks/123.jpg&address=123.122.0.1:8000
Each transformation will have different parameters. Here is a list of all required transforms and their parameters:
  1. rotate: type=rotate°rees=X - rotate X degrees clockwise
  2. resize: type=resize&newX=x&newY=y - resizes image to be newX x newY pixels.
  3. scale: type=scale&percentage=Z - scales the image by Z percent.
  4. thumbnail: type=thumbnail&width=w&height=h - returns a thumbnail of the image of dimension w x h.
  5. blur: type=blur - apply standard blur filter.
  6. sharpen: type=sharpen- apply standard sharpen filter.
  7. normalize: type=normalize - apply autocontrast.
  8. equalize: type=equalize - Apply equalization to uniformly distribute grayscale.
  9. crop: type=crop&left=l&right=r&top=t&bottom=b - crop image according to the dimensions provided.
  10. grayscale: type=grayscale - convert image to grayscale
The receiving peer should return a TransformReply indicating that the picture was processed successfully, along with a URL indicating where the new picture is located. It should have the following format:
< reply> 
<type> transformReply < /type>
  <success> true </success> 
  <dateTime> Tue 8 Mar, 2005 11:01:02 </dateTime>
  <requestID> 123 </requestID>
  <url> http://www.cs.usfca.edu/%20brooks/newPic.jpg </url>
</reply>

Unknown messages


Your peer should also reqpond nicely to malformed or otherwise incorrect messages. The following XML should be returned to a requestor with an invalid URL:
<reply>
  <type>UnknownReply</type>
  <success>false</success>
  <dateTime>Tue 8 Mar, 2005 11:01:02</dateTime>
  <receivedRequest> args here </receivedRequest>

</reply>

receivedRequest should contain whatever arguments were sent to you.

Advanced stuff

Picture of other peers: Currently, the only time your peer finds out about other peers in when it first registers and calls findAllPeers. For this step, you will add to your peer the ability to dynamically keep track of other peers .When another peer does a search of your peer, send it an identifySelf message afterward: http://name.of.host/?requestType=identifySelf&requesterAddress=ip:port

The remote peer should then respond to the address and port indicated in the request with:

<reply>
  <type>IdentifySelfReply</type>
  <success>true</success>
  <dateTime>Tue 8 Mar, 2005 11:01:02</dateTime>
  <user>
    <name> Joe Smith </name>
    <address> 192.3.55.6:8000 </address>
  </user>

<reply>

Your peer should be able to send and respond to identifySelf requests. (note: querying the name server repeatedly is not a suitable way to solve this problem)

Forwarding search: When your peer receives a getPhoto request that contains the getOthers=true parameter, it should try forward this search to at least three peers. It should then retrieve the XML returned by those peers and add it to its reply, so that it sends back a single reply to the original requestor.

Culling peer list. If your client tries to contact a peer that is no longer alive, it should remove that peer from its list. (note: querying the name server repeatedly is not a suitable way to solve this problem)

More expressive queries. Your peer should be able to send and respond to queries representing any logical formulation. For example, to find all jpegs tagged "cat" or tiffs tagged "dog" or "bunny", your request would look like: http://name.of.host/?requestType=logicalPicQuery&query=(type(jpeg)ANDtag(cat))OR(type(tiff)AND(tag(bunny)OR(tag(dog))))

We'll use the following representation:



Forwarding transform. If your peer receives a transform request which contains the getOthers=true parameter, it should forward this request to another peer. The response should then be returned to the original requestor. This is most interesting when combined with the following function.

Discovery of additional transforms: A peer should be able to send the following getTransform request:
 
http://valis.cs.usfca.edu:8000/?requestType=getTransforms
The receiving peer should respond with an XML document describing all of the transforms it has available, in the following format:
< reply>
< type> TransformDescriptionReply < /type>
<transforms>
  <transform>
    <name> rotate </name>
    <parameters> 
      <parameter> 
        <name> degrees</name>
        <type> integer </type>
        </parameter>
      </parameters>
    </transform>
  ...
< /reply>

Resources


Serving HTTP:

Back in the days of 601, you built an HTTP server as a project. You may find this useful. If you've forgotten how it worked, the project spec is here. If you're working in Java, you should be able to reuse a fair amount of your 601 code. The C# solution should look very much like the Java solution. (you only need to be able to handle HTTP GET).

If you're working in Python, here are some notes on HTTP serving with Python's CGIHTTPServer class.

Finding out your IP address and dealing with firewall issues:

If you're planning to work from home and you are using NAT and/or a firewall, you may need to do a little playing around to make sure that other processes can correctly find your peer, and that messages are not blocked by your firewall.

Also, please feel free to use the cs682 mailing list to discuss interoperation or clarification issues with each other - you shouldn't share code or solutions, but you're more than welcome to use the list to discuss things such as useful external resources, additional messages you plan to support, or techniques for dealing with NAT.