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:
- Register and unregister itself with an address server.
- Query the address server for other peers.
- Send an information request to another client.
- Respond to an information request.
- Request processing from another client
- Respond to a processing request from another client.
- Gracefully handle unknown messages.
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:
- 50 points: basic functionality: register/unregister,
findAllPeers, info request/reply, processing request/reply, basic GUI.
- 30 points: advanced features: dynamic peer discovery, forwarding
search, forwarding transform, transform discovery, peer culling,
logical query.
- 20 points: style. This includes: good software engineering
principles, well-built or stylish interface, and cool or extra
features. (note: I reserve the right to assign more than 20 points in
this category to projects whose design particularly impresses me.)
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:
- The ability to view his/her own photos
- The ability to search and display a subset of photos
- The ability to add tags to photos
- The ability to see the photos of other users, and tell what photo
belongs to a particular user.
- The ability to apply basic transformations to a picture, such as
scale, rotate, and so on (see below).
- The ability to conduct searches of other peers and view results.
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:
- mode=any means that a picture satisfies the search if ANY of the
search criteria are satisfied (for example, if it is tagged 'cats'
OR it was taken on 2007-03-21) mode=all means that ALL of the
criteria must be met in order to be a match.
- Please do NOT change your XML database to fit this format. (I
might decide to change it again without warning) Instead, use XSLT
to transform from your internal representation to this one.
- 'type' should indicate the file type. Allowable values are
'jpeg', 'gif', and 'tiff' (spelled exactly like that).
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:
- rotate: type=rotate°rees=X - rotate X degrees clockwise
- resize: type=resize&newX=x&newY=y - resizes image to be newX
x newY pixels.
- scale: type=scale&percentage=Z - scales the image by Z percent.
- thumbnail: type=thumbnail&width=w&height=h - returns a
thumbnail of the image of dimension w x h.
- blur: type=blur - apply standard blur filter.
- sharpen: type=sharpen- apply standard sharpen filter.
- normalize: type=normalize - apply autocontrast.
- equalize: type=equalize - Apply equalization to uniformly distribute
grayscale.
- crop: type=crop&left=l&right=r&top=t&bottom=b - crop image
according to the dimensions provided.
- 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:
- AND will be denoted with AND
- OR will be denoted with OR
- We'll use a predicate representation to indicate
attribute/value pairs. In other words, rather than writing
tag=dog, we'll use tag(dog).
- Expressions may be nested using parentheses.
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.