// Commented for the Learning branch
package com.limegroup.bittorrent;
import java.io.IOException;
import com.limegroup.gnutella.FileDesc;
import com.limegroup.gnutella.Uploader;
import com.limegroup.gnutella.http.HTTPRequestMethod;
/**
* A BTUploader object provides information about what we're uploading for this torrent.
*
* BTUploader implements LimeWire's Uploader interface.
* This lets LimeWire's GUI list this torrent in the same list as the Gnutella uploads.
*
* A ManagedTorrent makes and keeps a single BTUploader object.
*/
public class BTUploader implements Uploader {
/** A link back up to the ManagedTorrent object that made this BTDownloader. */
private ManagedTorrent _torrent;
/** A link to the BTMetaInfo object that represents the .torrent file for this torrent. */
private BTMetaInfo _info;
/** A BTUploader has a SimpleBandwidthTracker that measures how fast we're uploading the data of this torrent. */
private SimpleBandwidthTracker _tracker;
/**
* Make a new BTUploader object that the GUI can use to get information about what we're uploading for this torrent.
*
* @param torrent The ManagedTorrent that's making this BTUploader
* @param info A BTMetaInfo object we made from the bencoded data in the .torrent file
*/
public BTUploader(ManagedTorrent torrent, BTMetaInfo info) {
// Save the given objects
_torrent = torrent;
_info = info;
// Make a new SimpleBandwidthTracker to keep track of how fast we're uploading data
_tracker = new SimpleBandwidthTracker();
}
/**
* Stop this upload.
* Calls stop() on the ManagedTorrent.
*/
public void stop() {
// Stop Internet communications related to this torrent, and remove it from the program
_torrent.stop();
}
/**
* Get the file name of this torrent.
* If this is a multifile torrent, returns the folder name.
*
* @return The file or folder name as a String
*/
public String getFileName() {
// Ask the BTMetaInfo object, get the name from the bencoded data in the .torrent file
return _info.getName();
}
/**
* Get the total size in bytes of the files this .torrent file describes.
*
* If this is a single file torrent, _totalSize is the file size.
* If this is a multi-file torrent, _totalSize is the size of all the files totaled, and the size of the data block made by putting all the files together.
*
* @return The number of bytes of data of this .torrent file describes
*/
public long getFileSize() {
// Ask the BTMetaInfo object, get the total size from the bencoded data in the .torrent file
return _info.getTotalSize();
}
/**
* Get the length of the requested size for uploading.
* Not used in BitTorrent, returns 0.
*
* @return 0
*/
public long getAmountRequested() {
// Not used, return 0
return 0;
}
/**
* Make a FileDesc object with the save path, like "C:\Documents and Settings\Kevin\Shared\File Name.ext".
* This is the kind of object the GUI needs to be able to read the path and list the file.
*
* Returns a new FileDesc object that is actually a FakeFileDesc.
* FakeFileDesc is a nested class in this BTMetaInfo class.
*
* @return A FakeFileDesc object that has the path
*/
public FileDesc getFileDesc() {
// Have the BTMetaInfo object do this
return _info.getFileDesc();
}
/**
* Get the Gnutella file index for this upload.
* Returns Integer.MAX_VALUE because this is a torrent.
*
* @return Integer.MAX_VALUE
*/
public int getIndex() {
// Get the value the FakeFileDesc set, Integer.MAX_VALUE
return _info.getFileDesc().getIndex();
}
/**
* Find out how much data we've uploaded while sharing this torrent.
* amountUploaded() and getTotalAmountUploaded() both return the same answer.
*
* @return The amount we uploaded, in bytes
*/
public long amountUploaded() {
// Get the total distance our SimpleBandwidthTracker has recorded
return _tracker.getTotalAmount();
}
/**
* Find out how much data we've uploaded while sharing this torrent.
* amountUploaded() and getTotalAmountUploaded() both return the same answer.
*
* @return The amount we uploaded, in bytes
*/
public long getTotalAmountUploaded() {
// Get the total distance our SimpleBandwidthTracker has recorded
return _tracker.getTotalAmount();
}
/**
* Should return the IP address of the remote computer we're uploading data to, as a String.
* Returns "Multiple", because with BitTorrent, we're sending many of our connections pieces.
*
* @return The String "Multiple"
*/
public String getHost() {
// Return the word "Multiple" instead of an IP address
return "Multiple";
}
/**
* Determine what state this BitTorrent upload is in right now.
*
* The possible states are:
* INTERRUPTED
* UPLOADING
*
* @return The int code for the state
*/
public int getState() {
// If the ManagedTorrent is stopped, return INTERRUPTED
if (_torrent.hasStopped()) return Uploader.INTERRUPTED;
// Otherwise, we're sharing this torrent online, return UPLOADING
return Uploader.UPLOADING;
}
/**
* Get the previous state this uploader was in before it's current state.
*
* @return Uploader.UPLOADING
*/
public int getLastTransferState() {
// Alwasy return UPLOADING, since we can only change from that to INTERRUPTED
return Uploader.UPLOADING;
}
/**
* Does nothing.
*/
public void setState(int state) {}
/**
* Does nothing.
*/
public void writeResponse() throws IOException {}
/**
* Determine if the computer we're uploading to supports Gnutella chat.
*
* @return false, this is BitTorrent
*/
public boolean isChatEnabled() {
// This torrent can't do Gnutella chat
return false;
}
/**
* Determine if the computer we're uploading to supports the Gnutella browse host feature.
*
* @return false, this is BitTorrent
*/
public boolean isBrowseHostEnabled() {
// This torrent can't do Gnutella browse host
return false;
}
/**
* Return the port number the computer we're uploading to is listening on for new Gnutella connections.
*
* @return 0, this is BitTorrent
*/
public int getGnutellaPort() {
// Return 0, this is BitTorrent
return 0;
}
/**
* Get the "User-Agent" the computer we're uploading to told us in the Gnutella handshake.
*
* @return "BitTorrent"
*/
public String getUserAgent() {
// There is no Gnutella handshake
return "BitTorrent";
}
/**
* Determine if the headers have been parsed.
*
* @return true
*/
public boolean isHeaderParsed() {
// Just return true, even though this is BitTorrent
return true;
}
/**
* Determine if the computer we're uploading to supports Gnutella queuing.
*
* @return false
*/
public boolean supportsQueueing() {
// No, it doesn't, this is BitTorrent
return false;
}
/**
* Get the current request method.
* Returns "GET" even though BitTorrent doesn't use HTTP.
*
* @return HTTPRequestMethod.GET
*/
public HTTPRequestMethod getMethod() {
// Return the default "GET" method even though BitTorrent doesn't use it
return HTTPRequestMethod.GET;
}
/**
* Returns our current position in the remote computer's download queue.
*
* @return 0, BitTorrent doesn't have queues
*/
public int getQueuePosition() {
// Just return 0
return 0;
}
/**
* Determine if this upload is in an inactive state.
*
* @return false
*/
public boolean isInactive() {
// BitTorrent uploads never stop
return false;
}
/**
* Have the SimpleBandwidthTracker this BTUploader keeps update the speed it keeps current.
*/
public void measureBandwidth() {
// Have our SimpleBandwidthTracker do it
_tracker.measureBandwidth();
}
/**
* Find out how fast we are uploading data for this torrent right now.
*
* @return The speed, in KB/s
*/
public float getMeasuredBandwidth() {
// If we've stopped sharing this torrent, return 0
if (_torrent.hasStopped()) return 0.f;
// Have our SimpleBandwidthTracker update it's information, and return its saved value
measureBandwidth();
return _tracker.getMeasuredBandwidth();
}
/**
* Get the total average bandwidth, the number of bytes we've downloaded divided by the time since we started downloading this torrent.
*
* @return The total average bandwidth speed, in KB/s
*/
public float getAverageBandwidth() {
// Ask our SimpleBandwidthTracker
return _tracker.getAverageBandwidth();
}
/**
* Have our SimpleBandwidthTracker record that we've uploaded some bytes now.
*
* @param written The number of bytes we've uploaded
*/
void wroteBytes(int written) {
// Have our SimpleBandwidthTracker count them
_tracker.count(written);
}
}