📄 torrent.cc
字号:
// libTorrent - BitTorrent library// Copyright (C) 2005-2006, Jari Sundell//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//// In addition, as a special exception, the copyright holders give// permission to link the code of portions of this program with the// OpenSSL library under certain conditions as described in each// individual source file, and distribute linked combinations// including the two.//// You must obey the GNU General Public License in all respects for// all of the code used other than OpenSSL. If you modify file(s)// with this exception, you may extend this exception to your version// of the file(s), but you are not obligated to do so. If you do not// wish to do so, delete this exception statement from your version.// If you delete this exception statement from all source files in the// program, then also delete it here.//// Contact: Jari Sundell <jaris@ifi.uio.no>//// Skomakerveien 33// 3185 Skoppum, NORWAY#include "config.h"#include <rak/address_info.h>#include <rak/functional.h>#include <rak/string_manip.h>#include "exceptions.h"#include "torrent.h"#include "object.h"#include "object_stream.h"#include "connection_manager.h"#include "poll.h"#include "manager.h"#include "resource_manager.h"#include "net/throttle_list.h"#include "net/throttle_manager.h"#include "protocol/handshake_manager.h"#include "protocol/peer_factory.h"#include "data/file_manager.h"#include "data/hash_queue.h"#include "data/hash_torrent.h"#include "download/download_constructor.h"#include "download/download_manager.h"#include "download/download_wrapper.h"namespace torrent {uint32_tcalculate_max_open_files(uint32_t openMax) { if (openMax >= 8096) return 256; else if (openMax >= 1024) return 128; else if (openMax >= 512) return 64; else if (openMax >= 128) return 16; else // Assumes we don't try less than 64. return 4;}uint32_tcalculate_reserved(uint32_t openMax) { if (openMax >= 8096) return 256; else if (openMax >= 1024) return 128; else if (openMax >= 512) return 64; else if (openMax >= 128) return 32; else // Assumes we don't try less than 64. return 16;} voidinitialize(Poll* poll) { if (manager != NULL) throw client_error("torrent::initialize(...) called but the library has already been initialized"); if (poll->open_max() < 64) throw client_error("Could not initialize libtorrent, Poll::open_max() < 64."); cachedTime = rak::timer::current(); manager = new Manager; manager->set_poll(poll); uint32_t maxFiles = calculate_max_open_files(poll->open_max()); manager->connection_manager()->set_max_size(poll->open_max() - maxFiles - calculate_reserved(poll->open_max())); manager->file_manager()->set_max_size(maxFiles);}// Clean up and close stuff. Stopping all torrents and waiting for// them to finish is not required, but recommended.voidcleanup() { if (manager == NULL) throw client_error("torrent::cleanup() called but the library is not initialized."); delete manager; manager = NULL;}voidperform() { cachedTime = rak::timer::current(); // Ensure we don't call rak::timer::current() twice if there was no // scheduled tasks called. if (taskScheduler.empty() || taskScheduler.top()->time() > cachedTime) return; while (!taskScheduler.empty() && taskScheduler.top()->time() <= cachedTime) { rak::priority_item* v = taskScheduler.top(); taskScheduler.pop(); v->clear_time(); v->call(); } // Update the timer again to ensure we get accurate triggering of // msec timers. cachedTime = rak::timer::current();}boolis_inactive() { return manager == NULL || std::find_if(manager->download_manager()->begin(), manager->download_manager()->end(), std::not1(std::mem_fun(&DownloadWrapper::is_stopped))) == manager->download_manager()->end();}ChunkManager*chunk_manager() { return manager->chunk_manager();}ConnectionManager*connection_manager() { return manager->connection_manager();}uint32_ttotal_handshakes() { return manager->handshake_manager()->size();}int64_tnext_timeout() { cachedTime = rak::timer::current(); if (!taskScheduler.empty()) return std::max(taskScheduler.top()->time() - cachedTime, rak::timer()).usec(); else return rak::timer::from_seconds(60).usec();}int32_tdown_throttle() { return manager->download_throttle()->max_rate();}voidset_down_throttle(int32_t bytes) { if (bytes < 0 || bytes > (1 << 30)) throw input_error("Download throttle must be between 0 and 2^30."); return manager->download_throttle()->set_max_rate(bytes);}int32_tup_throttle() { return manager->upload_throttle()->max_rate();}voidset_up_throttle(int32_t bytes) { if (bytes < 0 || bytes > (1 << 30)) throw input_error("Upload throttle must be between 0 and 2^30."); return manager->upload_throttle()->set_max_rate(bytes);}uint32_tcurrently_unchoked() { return manager->resource_manager()->currently_unchoked();}uint32_tmax_unchoked() { return manager->resource_manager()->max_unchoked();}voidset_max_unchoked(uint32_t count) { if (count > (1 << 16)) throw input_error("Max unchoked must be between 0 and 2^16."); manager->resource_manager()->set_max_unchoked(count);}const Rate*down_rate() { return manager->download_throttle()->throttle_list()->rate_slow();}const Rate*up_rate() { return manager->upload_throttle()->throttle_list()->rate_slow();}const char*version() { return VERSION;}uint32_thash_read_ahead() { return manager->hash_queue()->read_ahead();}voidset_hash_read_ahead(uint32_t bytes) { if (bytes < (1 << 20) || bytes > (64 << 20)) throw input_error("Hash read ahead must be between 1 and 64 MB."); manager->hash_queue()->set_read_ahead(bytes);}uint32_thash_interval() { return manager->hash_queue()->interval();}voidset_hash_interval(uint32_t usec) { if (usec < (1 * 1000) || usec > (1000 * 1000)) throw input_error("Hash interval must be between 1 and 1000 ms."); manager->hash_queue()->set_interval(usec);}uint32_thash_max_tries() { return manager->hash_queue()->max_tries();}voidset_hash_max_tries(uint32_t tries) { if (tries > 100) throw input_error("Hash max tries must be between 0 and 100."); manager->hash_queue()->set_max_tries(tries);} uint32_topen_files() { return manager->file_manager()->open_size();}uint32_tmax_open_files() { return manager->file_manager()->max_size();}voidset_max_open_files(uint32_t size) { if (size < 4 || size > (1 << 16)) throw input_error("Max open files must be between 4 and 2^16."); manager->file_manager()->set_max_size(size);}uint32_topen_sockets() { return manager->connection_manager()->size();}uint32_tmax_open_sockets() { return manager->connection_manager()->max_size();}voidset_max_open_sockets(uint32_t size) { if (size < 4 || size > (1 << 16)) throw input_error("Max open sockets must be between 4 and 2^16."); manager->connection_manager()->set_max_size(size);}EncodingList*encoding_list() { return manager->encoding_list();}Downloaddownload_add(Object* object) { std::auto_ptr<DownloadWrapper> download(new DownloadWrapper); DownloadConstructor ctor; ctor.set_download(download.get()); ctor.set_encoding_list(manager->encoding_list()); ctor.initialize(*object); std::string infoHash = object_sha1(&object->get_key("info")); if (manager->download_manager()->find(infoHash) != manager->download_manager()->end()) throw input_error("Info hash already used by another torrent."); download->initialize(infoHash, PEER_NAME + rak::generate_random<std::string>(20 - std::string(PEER_NAME).size())); // Default PeerConnection factory functions. download->main()->connection_list()->slot_new_connection(&createPeerConnectionDefault); // Consider move as much as possible into this function // call. Anything that won't cause possible torrent creation errors // go in there. manager->initialize_download(download.get()); download->set_bencode(object); return Download(download.release());}voiddownload_remove(Download d) { manager->cleanup_download(d.ptr());}// Add all downloads to dlist. Make sure it's cleared.voiddownload_list(DList& dlist) { for (DownloadManager::const_iterator itr = manager->download_manager()->begin(); itr != manager->download_manager()->end(); ++itr) dlist.push_back(Download(*itr));}// Make sure you check that it's valid.Downloaddownload_find(const std::string& infohash) { return *manager->download_manager()->find(infohash);}uint32_tdownload_priority(Download d) { ResourceManager::iterator itr = manager->resource_manager()->find(d.ptr()->main()); if (itr == manager->resource_manager()->end()) throw client_error("torrent::download_priority(...) could not find the download in the resource manager."); return itr->first;}voiddownload_set_priority(Download d, uint32_t pri) { ResourceManager::iterator itr = manager->resource_manager()->find(d.ptr()->main()); if (itr == manager->resource_manager()->end()) throw client_error("torrent::download_set_priority(...) could not find the download in the resource manager."); if (pri > 1024) throw client_error("torrent::download_set_priority(...) received an invalid priority."); manager->resource_manager()->set_priority(itr, pri);}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -