package org.limewire.libtorrent; import org.limewire.bittorrent.TorrentState; import org.limewire.bittorrent.TorrentStatus; import org.limewire.util.StringUtils; import com.sun.jna.Structure; /** * Structure used to pass data from the native code regarding a torrents state * back to java. */ public class LibTorrentStatus extends Structure implements TorrentStatus { /** * long containing the total amount of the torrent downloaded and verified. */ public long total_done; /** * String containing the total amount of wanted bytes of the torrent * downloaded and verified. */ public long total_wanted_done; /** * long containing the total amount of wanted bytes of the torrent. */ public long total_wanted; /** * long containing the total amount of the torrent downloaded, this session. */ public long total_download; /** * long containing the total amount of the torrent uploaded, this session. */ public long total_upload; /** * long containing the total amount of the torrent payload downloaded, this * session. */ public long total_payload_download; /** * long containing the total amount of the torrent payload uploaded, this * session. */ public long total_payload_upload; /** * long containing the total amount of the torrent payload downloaded over * all time. */ public long all_time_payload_download; /** * long containing the total amount of the torrent payload uploaded over all * time. */ public long all_time_payload_upload; /** * The current rate of the torrent download in bytes/second */ public float download_rate; /** * The current rate of the torrent upload in bytes/second */ public float upload_rate; /** * The current rate of the torrent payload download in bytes/second */ public float download_payload_rate; /** * The current rate of the torrent payload upload in bytes/second */ public float upload_payload_rate; /** * The number of peers this torrent has. */ public int num_peers; /** * The number of uplaod peers this torrent has. */ public int num_uploads; /** * The number of seeds this torrent has. */ public int num_seeds; /** * The number of connections this torrent has. */ public int num_connections; /** * The state of this torrent, aligning with LibTorrentState. */ public int state; /** * The progress of this torrents download, from 0 to 1.0. */ public float progress; /** * boolean of whether this torrent is paused. */ public int paused; /** * boolean of whether this torrent is finished. */ public int finished; /** * boolean of whether this torrent is valid. */ public int valid; /** * boolean of whether this torrent is auto managed. */ public int auto_managed; /** * int for the amount of time this torrent has been seeding in seconds. */ public int seeding_time; /** * int for the amount of time this torrent has been seeding in seconds. */ public int active_time; /** * String containing the error message for the torrent. Null/empty if there * is no error. */ public String error; /** * Represents the current tracker for this torrent. Null/empty if there was * never a successful tracker connect. */ public String current_tracker; /** * Total number of peers that are seeding (complete). * <p> -1 if no data from tracker */ public int num_complete; /** * Total number of peers that are downloading (incomplete). * <p> -1 if no data from tracker */ public int num_incomplete; /** * Amount of download data that has been discarded due to error. */ public long total_failed_bytes; @Override public float getDownloadPayloadRate() { return download_payload_rate; } @Override public float getUploadPayloadRate() { return upload_payload_rate; } @Override public int getNumPeers() { return num_peers; } @Override public int getNumUploads() { return num_uploads; } @Override public int getNumSeeds() { return num_seeds; } @Override public int getNumConnections() { return num_connections; } @Override public float getProgress() { return progress; } @Override public long getTotalDone() { return total_done; } @Override public long getAllTimePayloadDownload() { return all_time_payload_download; } @Override public long getAllTimePayloadUpload() { return all_time_payload_upload; } @Override public long getTotalFailedDownload() { return total_failed_bytes; } @Override public boolean isPaused() { return paused != 0; } @Override public boolean isFinished() { return finished != 0; } @Override public boolean isError() { return !StringUtils.isEmpty(error); } @Override public String getError() { return error; } @Override public TorrentState getState() { LibTorrentState libTorrentState = LibTorrentState.forId(state); switch (libTorrentState) { case ALLOCATING: return TorrentState.ALLOCATING; case CHECKING_FILES: return TorrentState.CHECKING_FILES; case DOWNLOADING: return TorrentState.DOWNLOADING; case DOWNLOADING_METADATA: return TorrentState.DOWNLOADING_METADATA; case FINISHED: return TorrentState.FINISHED; case QUEUED_FOR_CHECKING: return TorrentState.QUEUED_FOR_CHECKING; case SEEDING: return TorrentState.SEEDING; default: throw new UnsupportedOperationException("No known state for id: " + state + " and libtorrent state: " + libTorrentState); } } @Override public float getSeedRatio() { if (getAllTimePayloadDownload() <= 0 || getAllTimePayloadUpload() <= 0) { return 0; } float seedRatio = getAllTimePayloadUpload() / (float) getAllTimePayloadDownload(); return seedRatio; } @Override public float getDownloadRate() { return download_rate; } @Override public float getUploadRate() { return upload_rate; } @Override public boolean isAutoManaged() { return false; } @Override public int getSeedingTime() { // Partial downloads have no notion of seeding time since they never // fully // enter the seeding state. Instead use the active time in this case for // comparison. // TODO: Update when something better becomes available. This will cause // partial torrent download seeds to become stale comparatively sooner // than their normal peers. //TODO after talking with arvid, he will add a finished_time variable for this extraneous case. //it will be a part of 0.15.0 when it is released. if (seeding_time == 0 && LibTorrentState.forId(state) == LibTorrentState.FINISHED) { return active_time; } else { return seeding_time; } } @Override public int getActiveTime() { return active_time; } @Override public long getTotalWanted() { return total_wanted; } @Override public long getTotalWantedDone() { return total_wanted_done; } @Override public String getCurrentTracker() { return current_tracker != null && current_tracker.isEmpty() ? null : current_tracker; } @Override public int getNumComplete() { return num_complete; } @Override public int getNumIncomplete() { return num_incomplete; } }