diff --git a/Jamfile b/Jamfile index 781e627f0..d2eb4cb3a 100755 --- a/Jamfile +++ b/Jamfile @@ -20,6 +20,9 @@ project torrent $(BOOST_ROOT) release:NDEBUG BOOST_ALL_NO_LIB + /boost/thread//boost_thread + /boost/filesystem//boost_filesystem/static + /boost/date_time//boost_date_time/static # devstudio switches @@ -31,6 +34,10 @@ project torrent gcc:-Wno-unused-variable +# darwin switches + + darwin:-Wno-unused-variable + ; @@ -75,13 +82,11 @@ lib torrent : zlib//zlib src/$(SOURCES) - /boost/thread//boost_thread/shared - /boost/date_time//boost_date_time/static - /boost/filesystem//boost_filesystem/static $(LIBS) : multi static + debug:TORRENT_VERBOSE_LOGGING : debug release ; diff --git a/examples/Jamfile b/examples/Jamfile index 9ef4a85f4..e473c4def 100755 --- a/examples/Jamfile +++ b/examples/Jamfile @@ -22,4 +22,5 @@ exe dump_torrent : : debug release ; +stage bin : dump_torrent simple_client client_test ; diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 6cf0a7f19..0b8e4e1e7 100755 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -226,7 +226,7 @@ int main(int argc, char* argv[]) return 1; } - boost::filesystem::path::default_name_check(boost::filesystem::native); + boost::filesystem::path::default_name_check(boost::filesystem::no_check); http_settings settings; // settings.proxy_ip = "192.168.0.1"; diff --git a/examples/dump_torrent.cpp b/examples/dump_torrent.cpp index e9dc9bec2..d947d1ffa 100755 --- a/examples/dump_torrent.cpp +++ b/examples/dump_torrent.cpp @@ -50,6 +50,8 @@ int main(int argc, char* argv[]) return 1; } + boost::filesystem::path::default_name_check(boost::filesystem::no_check); + try { std::ifstream in(argv[1], std::ios_base::binary); diff --git a/include/libtorrent/entry.hpp b/include/libtorrent/entry.hpp index f7adbab25..c84b5dba6 100755 --- a/include/libtorrent/entry.hpp +++ b/include/libtorrent/entry.hpp @@ -107,7 +107,11 @@ namespace libtorrent { public: - typedef std::map dictionary_type; + // we need a vector here to maintain the order + // of elements. Since the info-hash is reconstructed + // from an entry, it's important that the order is + // preserved. + typedef std::vector > dictionary_type; typedef std::string string_type; typedef std::vector list_type; typedef size_type integer_type; @@ -192,32 +196,15 @@ namespace libtorrent return *reinterpret_cast(data); } - entry& operator[](const char* key) - { - return dict()[key]; - } - - entry& operator[](const std::string& key) - { - return dict()[key.c_str()]; - } - - const entry& operator[](const char* key) const - { - dictionary_type::const_iterator i = - dict().find(key); - if (i == dict().end()) throw type_error("key not found"); - return i->second; - } - - const entry& operator[](const std::string& key) const - { - dictionary_type::const_iterator i = - dict().find(key); - if (i == dict().end()) throw type_error("key not found"); - return i->second; - } - + // these functions requires that the entry + // is a dictionary, otherwise they will throw + entry& operator[](char const* key); + entry& operator[](std::string const& key); + const entry& operator[](char const* key) const; + const entry& operator[](std::string const& key) const; + entry* find_key(char const* key); + entry const* find_key(char const* key) const; + void print(std::ostream& os, int indent = 0) const; private: diff --git a/src/entry.cpp b/src/entry.cpp index bc34f82d6..2649197a8 100755 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. */ #include "libtorrent/entry.hpp" +#include #if defined(_MSC_VER) namespace std @@ -48,10 +49,79 @@ namespace assert(o); o->~T(); } + + struct compare_string + { + compare_string(char const* s): m_str(s) {} + + bool operator()( + std::pair const& e) const + { + return e.first == m_str; + } + char const* m_str; + }; } namespace libtorrent { + entry& entry::operator[](char const* key) + { + dictionary_type::iterator i = std::find_if( + dict().begin() + , dict().end() + , compare_string(key)); + if (i != dict().end()) return i->second; + dictionary_type::iterator ret = dict().insert( + dict().end() + , std::make_pair(std::string(key), entry())); + return ret->second; + } + + + entry& entry::operator[](std::string const& key) + { + return (*this)[key.c_str()]; + } + + entry* entry::find_key(char const* key) + { + dictionary_type::iterator i = std::find_if( + dict().begin() + , dict().end() + , compare_string(key)); + if (i == dict().end()) return 0; + return &i->second; + + } + + entry const* entry::find_key(char const* key) const + { + dictionary_type::const_iterator i = std::find_if( + dict().begin() + , dict().end() + , compare_string(key)); + if (i == dict().end()) return 0; + return &i->second; + + } + + + const entry& entry::operator[](char const* key) const + { + dictionary_type::const_iterator i = std::find_if( + dict().begin() + , dict().end() + , compare_string(key)); + if (i == dict().end()) throw type_error("key not found"); + return i->second; + } + + const entry& entry::operator[](std::string const& key) const + { + return (*this)[key.c_str()]; + } entry::entry(const dictionary_type& v) { diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index 1e9d07752..65a7815b0 100755 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -454,18 +454,17 @@ namespace libtorrent return false; } - peer_entry http_tracker_connection::extract_peer_info(const entry& e) + peer_entry http_tracker_connection::extract_peer_info(const entry& info) { peer_entry ret; - const entry::dictionary_type& info = e.dict(); - // extract peer id (if any) - entry::dictionary_type::const_iterator i = info.find("peer id"); - if (i != info.end()) + entry const* i = info.find_key("peer id"); + if (i != 0) { - if (i->second.string().length() != 20) throw std::runtime_error("invalid response from tracker"); - std::copy(i->second.string().begin(), i->second.string().end(), ret.id.begin()); + if (i->string().length() != 20) + throw std::runtime_error("invalid response from tracker"); + std::copy(i->string().begin(), i->string().end(), ret.id.begin()); } else { @@ -474,14 +473,14 @@ namespace libtorrent } // extract ip - i = info.find("ip"); - if (i == info.end()) throw std::runtime_error("invalid response from tracker"); - ret.ip = i->second.string(); + i = info.find_key("ip"); + if (i == 0) throw std::runtime_error("invalid response from tracker"); + ret.ip = i->string(); // extract port - i = info.find("port"); - if (i == info.end()) throw std::runtime_error("invalid response from tracker"); - ret.port = (unsigned short)i->second.integer(); + i = info.find_key("port"); + if (i == 0) throw std::runtime_error("invalid response from tracker"); + ret.port = (unsigned short)i->integer(); return ret; } diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index baeb44fab..c4fd80da6 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -886,11 +886,10 @@ namespace libtorrent for (int i = 0; i < num_supported_extensions; ++i) { - entry::dictionary_type::iterator f = - extensions.find(extension_names[i]); - if (f != extensions.end()) + entry* f = e.find_key(extension_names[i]); + if (f) { - m_extension_messages[i] = (int)f->second.integer(); + m_extension_messages[i] = (int)f->integer(); } } #ifndef NDEBUG @@ -1132,7 +1131,7 @@ namespace libtorrent if (m_extension_messages[extended_chat_message] == -1) return; entry e(entry::dictionary_t); - e.dict()["msg"] = msg; + e["msg"] = msg; std::vector message; bencode(std::back_inserter(message), e); @@ -1182,7 +1181,7 @@ namespace libtorrent for (int i = 0; i < num_supported_extensions; ++i) { - extension_list.dict()[extension_names[i]] = i; + extension_list[extension_names[i]] = i; } // make room for message size diff --git a/src/session.cpp b/src/session.cpp index e9f5508b9..e9607ce07 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -1069,13 +1069,13 @@ namespace libtorrent } - int num_blocks_per_piece = (int)rd.dict()["blocks per piece"].integer(); + int num_blocks_per_piece = (int)rd["blocks per piece"].integer(); if (num_blocks_per_piece != info.piece_length() / torrent_ptr->block_size()) return; // the unfinished pieces - entry::list_type& unfinished = rd.dict()["unfinished"].list(); + entry::list_type& unfinished = rd["unfinished"].list(); std::vector tmp_unfinished; tmp_unfinished.reserve(unfinished.size()); @@ -1085,11 +1085,11 @@ namespace libtorrent { piece_picker::downloading_piece p; - p.index = (int)i->dict()["piece"].integer(); + p.index = (int)(*i)["piece"].integer(); if (p.index < 0 || p.index >= info.num_pieces()) return; - const std::string& bitmask = i->dict()["bitmask"].string(); + const std::string& bitmask = (*i)["bitmask"].string(); const int num_bitmask_bytes = std::max(num_blocks_per_piece / 8, 1); if ((int)bitmask.size() != num_bitmask_bytes) return; diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index f8595af42..83f77589b 100755 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -310,7 +310,7 @@ namespace libtorrent ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end()); ret["slots"] = entry(entry::list_t); - entry::list_type& slots = ret.dict()["slots"].list(); + entry::list_type& slots = ret["slots"].list(); std::copy(piece_index.begin(), piece_index.end(), std::back_inserter(slots)); const piece_picker& p = t->picker(); @@ -321,7 +321,7 @@ namespace libtorrent // blocks per piece int num_blocks_per_piece = static_cast(t->torrent_file().piece_length()) / t->block_size(); - ret.dict()["blocks per piece"] = num_blocks_per_piece; + ret["blocks per piece"] = num_blocks_per_piece; // num unfinished pieces int num_unfinished = (int)q.size(); @@ -336,7 +336,7 @@ namespace libtorrent { if (i->finished_blocks.count() == 0) continue; - entry::dictionary_type piece_struct; + entry piece_struct(entry::dictionary_t); // the unfinished piece's index piece_struct["piece"] = i->index; @@ -381,7 +381,7 @@ namespace libtorrent if (!i->second->is_local()) continue; address ip = i->second->get_socket()->sender(); - entry::dictionary_type peer; + entry peer(entry::dictionary_t); peer["ip"] = ip.as_string(); peer["port"] = ip.port; peer_list.push_back(peer); diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index d0a80c5aa..c67e25478 100755 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -132,11 +132,11 @@ namespace libtorrent void torrent_info::read_torrent_info(const entry& torrent_file) { // extract the url of the tracker - const entry::dictionary_type& dict = torrent_file.dict(); - entry::dictionary_type::const_iterator i = dict.find("announce-list"); - if (i != dict.end()) +// const entry::dictionary_type& dict = torrent_file.dict(); + entry const* i = torrent_file.find_key("announce-list"); + if (i) { - const entry::list_type& l = i->second.list(); + const entry::list_type& l = i->list(); for (entry::list_type::const_iterator j = l.begin(); j != l.end(); ++j) { const entry::list_type& ll = j->list(); @@ -167,33 +167,33 @@ namespace libtorrent } else { - i = dict.find("announce"); - if (i == dict.end()) throw invalid_torrent_file(); + i = torrent_file.find_key("announce"); + if (i == 0) throw invalid_torrent_file(); announce_entry e; e.tier = 0; - e.url = i->second.string(); + e.url = i->string(); m_urls.push_back(e); } // extract creation date - i = dict.find("creation date"); - if (i != dict.end() && i->second.type() == entry::int_t) + i = torrent_file.find_key("creation date"); + if (i != 0 && i->type() == entry::int_t) { m_creation_date = ptime(date(1970, Jan, 1)) - + seconds((long)i->second.integer()); + + seconds((long)i->integer()); } // extract comment - i = dict.find("comment"); - if (i != dict.end() && i->second.type() == entry::string_t) + i = torrent_file.find_key("comment"); + if (i != 0 && i->type() == entry::string_t) { - m_comment = i->second.string(); + m_comment = i->string(); } - i = dict.find("info"); - if (i == dict.end()) throw invalid_torrent_file(); - entry info = i->second; + i = torrent_file.find_key("info"); + if (i == 0) throw invalid_torrent_file(); + entry const& info = *i; // encode the info-field in order to calculate it's sha1-hash std::vector buf; @@ -209,8 +209,8 @@ namespace libtorrent m_name = info["name"].string(); // extract file list - i = info.dict().find("files"); - if (i == info.dict().end()) + i = info.find_key("files"); + if (i == 0) { // if there's no list of files, there has to be a length // field. @@ -221,7 +221,7 @@ namespace libtorrent } else { - extract_files(i->second.list(), m_files); + extract_files(i->list(), m_files); } // calculate total size of all pieces @@ -241,7 +241,10 @@ namespace libtorrent throw invalid_torrent_file(); for (int i = 0; i < num_pieces; ++i) - std::copy(hash_string.begin() + i*20, hash_string.begin() + (i+1)*20, m_piece_hash[i].begin()); + std::copy( + hash_string.begin() + i*20 + , hash_string.begin() + (i+1)*20 + , m_piece_hash[i].begin()); } boost::optional