CS 352 Spring 2006

Programming Assignment 1

Due Date: 5 Mar, 2006 5:00pm

Sections

Updates

Before jumping into the project I would like to mention one thing. Most of the time your first attempt at a software project is either too slow, too buggy, or is difficult to maintain/expand. Be prepared to throw away the first versions of most of your code. You can even plan to have them as throw-aways. You don't waste time doing this because you learn where you can make improvements in your final version.

Theory of Operation

In this project, you will build a simple BitTorrent(BT) client which will serve as the foundation for a fully-featured BT client you will build in later assignments. For project 1, your client will load a .torrent file , interface with a tracker and a single peer and will download a single file(Jpeg) from that peer. When the file is finished downloading, you will save it to the hard disk. All communication will be done over TCP.

The file your program will read in is a .torrent file containing metadata for the file to be downloaded. You will be supplied with a class that will take in a String containing the file name (in the local directory) or the complete file path and will return a TorrentFile object containing all the necessary information. An example of usage will be included with the class.

Assignment Specifics

Your assignment should basically do the following:

  1. Take as a command-line argument the name of the .torrent file to be loaded and the name of the file to save the data to. For example:
    			java mybtclient somefile.torrent picture.jpg
    		
  2. Pass the name of the .torrent file to the TorrentFileHandler class as a String and store the returned TorrentFile object.
  3. Open a TCP socket on the local machine and send an HTTP_GET request to the tracker at the IP address and port specified by the TorrentFile object.
  4. Capture the response from the tracker and decode it in order to get the list of peers. From this list of peers, use only the peer at IP address 172.23.26.98 . You must extract this IP from the list, hard-coding it is not acceptable.
  5. Open a TCP socket on the local machine and contact the peer using the BT peer protocol and request a piece of the file.
  6. Download the piece of the file and verify its SHA-1 hash against the hash stored in the TorrentFile object. The first time you begin the download, you need to contact the tracker and let it know you are starting download.
  7. After a piece is downloaded and verified, the peer is notified that you have completed the piece.
  8. Repeat steps 5-7 (using the same TCP connection) for the rest of the file.
  9. When the file is finished, you must contact the tracker and send it the completed event and properly close all TCP connections
  10. Save the file to the hard disk according to the second command-line argument.

Files Available

The files below are intended to help you concentrate on the networking portion of the project and not have to worry about how to bencode or "unbencode" the torrent file and some of the communication.

Programming Style

Writing maintainable code is just as important as writing correct code. Consequently, you will be graded on your style. Below is a list of suggestions to make your code easier to understand and maintain:

Bencoding (Pronounced "Bee Encoding")

Bencoding a method of encoding binary data. Tracker responses, and interpeer communication will be bencoded. Below is how data types are bencoded according to the BT protocol. [The following list is taken from http://www.bittorrent.com/protocol.html ]

Communication With the Tracker

Your client must take the information supplied by the TorrentFile object and use it to communicate with the tracker. The tracker's IP address and port number will be given to you by the TorrentFile object, and your program must then contact the tracker. Your program will send an HTTP_GET request to the tracker with the following key/value pairs. Note that these are NOT bencoded, but must be properly escaped [this list is taken from http://www.bittorrent.com/protocol.html ]:

The response from the tracker is a bencoded dictionary and contains two keys:

Communicating With the Peer

Handshaking between peers begins with character nineteen (decimal) followed by the string 'BitTorrent protocol'. After the fixed headers are 8 reserved bytes which are set to 0. Next is the 20-byte SHA-1 hash of the bencoded form of the info value from the metainfo (.torrent) file. The next 20-bytes are the peer id generated by the client. The info_hash should be the same as sent to the tracker, and the peer_id is the same as sent to the tracker. If the info_hash is different between two peers, then the connection is dropped.

After the handshake, messages between peers take the form of <length prefix><message ID><payload> , where length prefix is a 4-byte big-endian value and message ID is a single decimal character. The payload depends on the message. Please consult either of the BT-related resources for detailed information describing these messages. Below is a list of messages that need to be implemented in the project.

The Write-Up

Submitting the Project

The project should be submitted through the Computer Science Handin Server.

Grading

Resources

It is strongly recommended that you bookmark or download the Sun Java 1.5.0 API , as well as read the following pages:

Please email romoore _at_ cs _dot_ rutgers _dot_ edu concerning any questions or problems with this page. Please visit the Sakai website for questions concerning this project.

Frequently Asked Questions

I've been getting a lot of similar questions lately, so I'll post general forms of them as well as advice on how to solve the underlying problems. As a bit of general advice, if you aren't sure what a packet is supposed to look like, you can always fire up a working client (the mainline BitTorrent client, for example) and then use a network packet sniffing tool like Ethereal to capture the traffic and analyze it.

  1. I can't connect to the tracker. I've tried creating a Socket and sending the bytes through myself by grabbing the InputStream and OutputStream from the Socket, but I can't get a response from the tracker.
    Contacting the tracker is a simple HTTP GET request. This type of operation is done by every web browser today and even some smaller programs. As a result, there exists a class java.net.URL that can easily handle this type of request. As I mentioned in the presentation - whatever you're trying to do in Java has probably already been done a thousand times, so it's usually faster to find an existing implementation than to write one yourself.