package org.limewire.libtorrent; import java.util.concurrent.atomic.AtomicBoolean; import org.limewire.bittorrent.TorrentException; import org.limewire.bittorrent.TorrentManagerSettings; import org.limewire.bittorrent.TorrentStatus; import org.limewire.libtorrent.callback.AlertCallback; import org.limewire.logging.Log; import org.limewire.logging.LogFactory; import org.limewire.util.ExceptionUtils; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.WString; import com.sun.jna.ptr.IntByReference; /** * Wrapper class for the LibTorrent c interface. Provides library loading logic, * and handles rethrowing c++ exceptions as java exceptions. */ class LibTorrentWrapper { private static final Log LOG = LogFactory.getLog(LibTorrentWrapper.class); private final AtomicBoolean loaded = new AtomicBoolean(false); private LibTorrent libTorrent; /** * Initializes the LibTorrent library. Finding necessary dependencies first, * then loading the libtorrent library as a jna lib. */ void initialize(TorrentManagerSettings torrentSettings) { try { this.libTorrent = (LibTorrent) Native.loadLibrary("torrent-wrapper", LibTorrent.class); init(torrentSettings); loaded.set(true); } catch (Throwable e) { LOG.error("Failure loading the libtorrent libraries.", e); if (torrentSettings.isReportingLibraryLoadFailture()) { ExceptionUtils.reportOrReturn(e); } } } public boolean isLoaded() { return loaded.get(); } private void init(TorrentManagerSettings torrentSettings) { LOG.debugf("before init"); catchWrapperException(libTorrent.init(new LibTorrentSettings(torrentSettings))); LOG.debugf("after init"); } public void add_torrent(String sha1, String trackerURI, String torrentPath, String savePath, String fastResumePath) { LOG.debugf("before add_torrent: {0}", sha1); catchWrapperException(libTorrent.add_torrent(sha1, trackerURI, new WString(torrentPath), new WString(savePath), new WString(fastResumePath))); LOG.debugf("after add_torrent: {0}", sha1); } public void freeze_and_save_all_fast_resume_data(AlertCallback alertCallback) { LOG.debug("before get_alerts"); catchWrapperException(libTorrent.freeze_and_save_all_fast_resume_data(alertCallback)); LOG.debug("after get_alerts"); } public void get_alerts(AlertCallback alertCallback) { LOG.debug("before get_alerts"); catchWrapperException(libTorrent.get_alerts(alertCallback)); LOG.debug("after get_alerts"); } public void pause_torrent(String id) { LOG.debugf("before pause_torrent: {0}", id); catchWrapperException(libTorrent.pause_torrent(id)); LOG.debugf("after pause_torrent: {0}", id); } public void resume_torrent(String id) { LOG.debugf("before resume_torrent: {0}", id); catchWrapperException(libTorrent.resume_torrent(id)); LOG.debugf("after resume_torrent: {0}", id); } public void get_torrent_status(String id, TorrentStatus status) { LOG.debugf("before get_torrent_status: {0}", id); catchWrapperException(libTorrent.get_torrent_status(id, status)); LOG.debugf("after get_torrent_status: {0}", id); } public void remove_torrent(String id) { LOG.debugf("before remove_torrent: {0}", id); catchWrapperException(libTorrent.remove_torrent(id)); LOG.debugf("after remove_torrent: {0}", id); } public LibTorrentPeer[] get_peers(String id) { LOG.debugf("before get_num_peers: {0}", id); IntByReference numPeersReference = new IntByReference(); catchWrapperException(libTorrent.get_num_peers(id, numPeersReference)); LOG.debugf("after get_num_peers: {0} - {1}", id, numPeersReference); int numPeers = numPeersReference.getValue(); if (numPeers == 0) { return new LibTorrentPeer[0]; } LibTorrentPeer[] torrentPeers = new LibTorrentPeer[numPeers]; Pointer[] torrentPeersPointers = new Pointer[numPeers]; for (int i = 0; i < torrentPeersPointers.length; i++) { LibTorrentPeer torrentPeer = new LibTorrentPeer(); torrentPeers[i] = torrentPeer; torrentPeersPointers[i] = torrentPeer.getPointer(); } LOG.debugf("before get_peers: {0}", id); catchWrapperException(libTorrent.get_peers(id, torrentPeersPointers, torrentPeersPointers.length)); for (int i = 0; i < torrentPeers.length; i++) { torrentPeers[i].read(); } free_peers(id, torrentPeersPointers, torrentPeersPointers.length); LOG.debugf("after get_peers: {0}", id); return torrentPeers; } private void free_peers(String id, Pointer[] torrentPeersPointers, int length) { LOG.debugf("before free_peers: {0}", id); catchWrapperException(libTorrent.free_peers(torrentPeersPointers, torrentPeersPointers.length)); LOG.debugf("after free_peers: {0}", id); } public void signal_fast_resume_data_request(String id) { LOG.debugf("before print signal_fast_resume_data_request: {0}", id); catchWrapperException(libTorrent.signal_fast_resume_data_request(id)); LOG.debugf("after print signal_fast_resume_data_request: {0}", id); } public void clear_error_and_retry(String id) { LOG.debugf("before print clear_error_and_retry: {0}", id); catchWrapperException(libTorrent.clear_error_and_retry(id)); LOG.debugf("after print clear_error_and_retry: {0}", id); } public void move_torrent(String id, String absolutePath) { LOG.debugf("before move_torrent: {0} - {1}", id, absolutePath); catchWrapperException(libTorrent.move_torrent(id, new WString(absolutePath))); LOG.debugf("after move_torrent: {0} - {1}", id, absolutePath); } public void abort_torrents() { LOG.debug("before abort"); catchWrapperException(libTorrent.abort_torrents()); LOG.debug("after abort"); } public void free_torrent_status(LibTorrentStatus status) { LOG.debugf("before free_torrent_status: {0}", status); catchWrapperException(libTorrent.free_torrent_status(status.getPointer())); LOG.debugf("after free_torrent_status: {0}", status); } private void catchWrapperException(WrapperStatus status) { if (status != null) { throw new TorrentException(status.message, status.type); } } public void update_settings(TorrentManagerSettings torrentSettings) { LOG.debugf("before update_settings: {0}", torrentSettings); catchWrapperException(libTorrent.update_settings(new LibTorrentSettings(torrentSettings))); LOG.debugf("after update_settings: {0}", torrentSettings); } public void start_dht() { LOG.debugf("before start_dht"); catchWrapperException(libTorrent.start_dht()); LOG.debugf("after start_dht"); } public void stop_dht() { LOG.debugf("before stop_dht"); catchWrapperException(libTorrent.stop_dht()); LOG.debugf("after stop_dht"); } public void start_upnp() { LOG.debugf("before start_upnp"); catchWrapperException(libTorrent.start_upnp()); LOG.debugf("after start_upnp"); } public void stop_upnp() { LOG.debugf("before stop_upnp"); catchWrapperException(libTorrent.stop_upnp()); LOG.debugf("after stop_upnp"); } public void start_lsd() { LOG.debugf("before start_lsd"); catchWrapperException(libTorrent.start_lsd()); LOG.debugf("after start_lsd"); } public void stop_lsd() { LOG.debugf("before stop_lsd"); catchWrapperException(libTorrent.stop_lsd()); LOG.debugf("after stop_lsd"); } public void start_natpmp() { LOG.debugf("before start_natpmp"); catchWrapperException(libTorrent.start_natpmp()); LOG.debugf("after start_natpmp"); } public void stop_natpmp() { LOG.debugf("before stop_natpmp"); catchWrapperException(libTorrent.stop_natpmp()); LOG.debugf("after stop_natpmp"); } /** * Set the target seed ratio for this torrent. */ public void set_seed_ratio(String id, float seed_ratio) { LOG.debugf("before set_seed_ratio"); catchWrapperException(libTorrent.set_seed_ratio(id, seed_ratio)); LOG.debugf("after set_seed_ratio"); } /** * Returns the file priority for the given index. */ public int get_file_priority(String id, int fileIndex) { LOG.debugf("before get_file_priority"); IntByReference priority = new IntByReference(); catchWrapperException(libTorrent.get_file_priority(id, fileIndex, priority)); LOG.debugf("after get_file_priority"); return priority.getValue(); } /** * Sets the file priority for the given index. */ public void set_file_priorities(String id, int[] priorities) { LOG.debugf("before set_file_priorities"); catchWrapperException(libTorrent.set_file_priorities(id, priorities, priorities.length)); LOG.debugf("after set_file_priorities"); } /** * Returns the number of files for the given torrent. */ public int get_num_files(String id) { LOG.debugf("before get_num_files"); IntByReference numFiles = new IntByReference(); catchWrapperException(libTorrent.get_num_files(id, numFiles)); LOG.debugf("after get_num_files"); return numFiles.getValue(); } /** * Returns the files for the given torrent. */ public LibTorrentFileEntry[] get_files(String id) { LOG.debugf("before get_files"); int numFiles = get_num_files(id); LibTorrentFileEntry[] fileEntries = new LibTorrentFileEntry[numFiles]; Pointer[] filePointers = new Pointer[numFiles]; for (int i = 0; i < fileEntries.length; i++) { LibTorrentFileEntry fileEntry = new LibTorrentFileEntry(); fileEntries[i] = fileEntry; filePointers[i] = fileEntry.getPointer(); } catchWrapperException(libTorrent.get_files(id, filePointers)); for (int i = 0; i < fileEntries.length; i++) { fileEntries[i].read(); } LOG.debugf("after get_files"); return fileEntries; } public void set_auto_managed_torrent(String sha1, boolean auto_managed) { LOG.debugf("before set_auto_managed_torrent: {0} - {1}", sha1, auto_managed); catchWrapperException(libTorrent.set_auto_managed_torrent(sha1, auto_managed)); LOG.debugf("after set_auto_managed_torrent: {0} - {1}", sha1, auto_managed); } public void set_file_priority(String sha1, int index, int priority) { LOG.debugf("before set_file_priority: {0} - index: {1} - priority: {2}", sha1, index, priority); catchWrapperException(libTorrent.set_file_priority(sha1, index, priority)); LOG.debugf("after set_file_priority: {0} - index: {1} - priority: {2}", sha1, index, priority); } }