From 1800e63c09f4ee9cd3a1ab69707a956795f2da61 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 23 Oct 2003 16:55:52 +0000 Subject: [PATCH] *** empty log message *** --- Jamfile | 20 +++--- docs/index.html | 13 ++++ include/libtorrent/piece_picker.hpp | 14 +++- include/libtorrent/storage.hpp | 3 - include/libtorrent/torrent.hpp | 13 ++-- src/peer_connection.cpp | 10 +-- src/piece_picker.cpp | 14 ++-- src/policy.cpp | 5 +- src/session.cpp | 19 +++-- src/torrent.cpp | 107 ++++++++++++++++------------ 10 files changed, 132 insertions(+), 86 deletions(-) diff --git a/Jamfile b/Jamfile index edb483992..dbfb67aa8 100755 --- a/Jamfile +++ b/Jamfile @@ -26,13 +26,15 @@ lib torrent ; -#exe torrent_test -# : src/main.cpp torrent -# $(BOOST_ROOT)/libs/filesystem/build//boost_filesystem -# : $(BOOST_ROOT) -# $(BOOST_ROOT) -# ./ -# multi -# : debug release -# ; +exe client_test + : examples/client_test.cpp + torrent +# $(BOOST_ROOT)/libs/filesystem/build/boost_filesystem +# $(BOOST_ROOT)/libs/thread/build/boost_thread + : $(BOOST_ROOT) + $(BOOST_ROOT) + ./include + multi + : debug release + ; diff --git a/docs/index.html b/docs/index.html index 9b92f4f26..c612b1c64 100755 --- a/docs/index.html +++ b/docs/index.html @@ -10,6 +10,19 @@

libtorrent

+ + + + + + +
+ sourceforge page + + mailing list +
+ +

libtorrent is a C++ library that aims to be a good alternative to all the other bittorrent implementations around. It is a diff --git a/include/libtorrent/piece_picker.hpp b/include/libtorrent/piece_picker.hpp index 378b67092..294014072 100755 --- a/include/libtorrent/piece_picker.hpp +++ b/include/libtorrent/piece_picker.hpp @@ -150,6 +150,14 @@ namespace libtorrent int index; std::bitset requested_blocks; std::bitset finished_blocks; + // TODO: store a hash and a peer_connection reference + // for each block. Then if the hash test fails on the + // piece, redownload one block from another peer + // then the first time, and check the hash again. + // also maintain a counter how many times a piece-hash + // has been confirmed. Download blocks that hasn't + // been confirmed (since they are most probably the + // invalid blocks) }; struct has_index @@ -172,8 +180,12 @@ namespace libtorrent // that no peer have, the vector at index 1 contains // all pieces that exactly one peer have, index 2 contains // all pieces exactly two peers have and so on. - std::vector > m_piece_info; + + // this vector has the same structure as m_piece_info + // but only contains pieces we are currently downloading + // they have higher priority than pieces we aren't downloading + // during piece picking std::vector > m_downloading_piece_info; // this maps indices to number of peers that has this piece and diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index a3f68d28d..c16db9b5a 100755 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -72,9 +72,6 @@ namespace libtorrent }; // wraps access to pieces with a file-like interface - // TODO: add functionality for switching piece - // that's optimized not to closing the file if the - // new piece is in the same file class piece_file { friend class storage; diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index ce025117c..3fd0e8861 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -61,7 +61,7 @@ namespace libtorrent struct session_impl; } - // TODO: each torrent should have a status string that + // TODO: each torrent should have a status value that // reflects what's happening to it // TODO: There should be a maximum number of peers that // is maintained (if someone disconnects, try to connect to @@ -70,6 +70,7 @@ namespace libtorrent // speed than one of the peers currently connected, it will be // replaced to maximize bandwidth usage. It wil also have to // depend on how many and which pieces the peers have. + // TODO: In debug mode all pieces that are sent should be checked. // a torrent is a class that holds information @@ -119,7 +120,8 @@ namespace libtorrent int bytes_left() const { return m_storage.bytes_left(); } // TODO: temporary implementation. Should count the actually - // verified pieces + // verified pieces and should support the different states + // a torrent can be in. float progress() const { return bytes_downloaded() / static_cast(m_torrent_file.total_size()); @@ -238,11 +240,13 @@ namespace libtorrent // blocks when requested int m_block_size; + // is set to true when the torrent has + // been aborted. bool m_abort; event_id m_event; - void parse_response(const entry& e); + void parse_response(const entry& e, std::vector& peer_list); // total amount of bytes uploaded, downloaded and // the number of bytes left to be downloaded @@ -266,9 +270,6 @@ namespace libtorrent std::string m_failed; std::vector m_connections; - // TODO: move to a local function? - std::vector m_peer_list; - // ----------------------------- boost::shared_ptr m_policy; diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 2100d48e8..b4fa91c11 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -402,9 +402,12 @@ bool libtorrent::peer_connection::dispatch_message() } else { - // TODO: we have to let the piece_picker know that - // this piece failed the check os it can restore it + // we have to let the piece_picker know that + // this piece failed the check as it can restore it // and mark it as being interesting for download + // TODO: do this more intelligently! and keep track + // of how much crap (data that failed hash-check) and + // how much redundant data we have downloaded picker.restore_piece(index); } m_torrent->get_policy().piece_finished(*this, index, verified); @@ -464,8 +467,6 @@ void libtorrent::peer_connection::request_block(piece_block block) // TODO: add a timeout to disconnect peer if we don't get any piece messages when // we have requested. - // TODO: there must be a way to ask the storage if a given - // piece already has some data (and how much). To avoid requesting std::copy(buf, buf + 5, m_send_buffer.begin()+start_offset); start_offset +=5; @@ -685,6 +686,7 @@ void libtorrent::peer_connection::receive_data() { // verify peer_id // TODO: It seems like the original client ignores to check the peer id + // can this be correct? if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.begin() + 20, (const char*)m_peer_id.begin())) { #ifndef NDEBUG diff --git a/src/piece_picker.cpp b/src/piece_picker.cpp index 97cb15a59..9b226714f 100755 --- a/src/piece_picker.cpp +++ b/src/piece_picker.cpp @@ -90,7 +90,6 @@ namespace libtorrent // TODO: random_shuffle } - // TODO: add a check to make sure m_downloads is intact #ifndef NDEBUG void piece_picker::integrity_check(const torrent* t) const @@ -304,6 +303,13 @@ namespace libtorrent #endif } + // TODO: since inc_refcount is called + // with sequential indices when peers + // connect, it will sort the pieces + // that is not good. one solution is + // to insert the element at a random + // index when moving it to another + // vector. bool piece_picker::inc_refcount(int i) { assert(i >= 0); @@ -337,10 +343,6 @@ namespace libtorrent if (index == 0xffffff) return; move(m_piece_map[i].downloading, peer_count, index); - -#ifndef NDEBUG - integrity_check(); -#endif } void piece_picker::we_have(int index) @@ -360,10 +362,8 @@ namespace libtorrent void piece_picker::pick_pieces(const std::vector& pieces, std::vector& interesting_pieces) const { - // TODO: modify this! assert(pieces.size() == m_piece_map.size()); - // free refers to pieces that are free to download, noone else // is downloading them. // partial is pieces that are partially being downloaded, and diff --git a/src/policy.cpp b/src/policy.cpp index 116a8b043..fe3789a31 100755 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -71,9 +71,8 @@ namespace return; } - // TODO: - // compare this peer's bandwidth against the ones downloading - // these pieces (busy_pieces) + // TODO: compare this peer's bandwidth against the + // ones downloading these pieces (busy_pieces) } } diff --git a/src/session.cpp b/src/session.cpp index 4f1266c4a..73e4886eb 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -82,8 +82,9 @@ namespace { peer_id ret; std::srand(std::time(0)); -// unsigned char fingerprint[] = "h\0\0\0\0\0\0\0\0\0"; - unsigned char fingerprint[] = "h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + // TODO: add ability to control fingerprint +// unsigned char fingerprint[] = "lt.\0\0\0\0\0\0\0"; + unsigned char fingerprint[] = "lt.\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; const int len = sizeof(fingerprint)-1; std::copy(fingerprint, fingerprint+len, ret.begin()); for (unsigned char* i = ret.begin()+len; i != ret.end(); ++i) *i = rand(); @@ -181,7 +182,9 @@ namespace libtorrent // that has been closed. Otherwise we have to wait 2 minutes for their timeout // let the readable clients receive data - for (std::vector >::iterator i = readable_clients.begin(); i != readable_clients.end(); ++i) + for (std::vector >::iterator i = readable_clients.begin(); + i != readable_clients.end(); + ++i) { // special case for listener socket @@ -236,7 +239,9 @@ namespace libtorrent // ************************ // let the writable clients send data - for (std::vector >::iterator i = writable_clients.begin(); i != writable_clients.end(); ++i) + for (std::vector >::iterator i = writable_clients.begin(); + i != writable_clients.end(); + ++i) { connection_map::iterator p = m_connections.find(*i); // the connection may have been disconnected in the receive phase @@ -269,7 +274,9 @@ namespace libtorrent // disconnect the one we couldn't connect to - for (std::vector >::iterator i = error_clients.begin(); i != error_clients.end(); ++i) + for (std::vector >::iterator i = error_clients.begin(); + i != error_clients.end(); + ++i) { connection_map::iterator p = m_connections.find(*i); @@ -439,7 +446,7 @@ namespace libtorrent boost::mutex::scoped_lock l(m_impl.m_mutex); // is the torrent already active? - // TODO: Maybe this should throw? + // TODO: this should throw if (m_impl.m_torrents.find(ti.info_hash()) != m_impl.m_torrents.end()) return torrent_handle(&m_impl, ti.info_hash()); diff --git a/src/torrent.cpp b/src/torrent.cpp index 54edf77d1..b7346375e 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -71,7 +71,7 @@ namespace int calculate_block_size(const torrent_info& i) { - // TODO: if blocks_per_piece > 64 increase block-size + // TODO: if blocks_per_piece > 128 increase block-size return 16*1024; } @@ -154,10 +154,63 @@ namespace libtorrent void torrent::tracker_response(const entry& e) { + std::vector peer_list; try { // parse the response - parse_response(e); + parse_response(e, peer_list); + + m_last_working_tracker + = m_torrent_file.prioritize_tracker(m_currently_trying_tracker); + m_next_request = boost::posix_time::second_clock::local_time() + + boost::posix_time::seconds(m_duration); + m_currently_trying_tracker = 0; + + // connect to random peers from the list + std::random_shuffle(peer_list.begin(), peer_list.end()); + + std::cout << "interval: " << m_duration << "\n"; + std::cout << "peers:\n"; + for (std::vector::const_iterator i = peer_list.begin(); + i != peer_list.end(); + ++i) + { + std::cout << " " << std::setfill(' ') << std::setw(16) << i->ip + << " " << std::setw(5) << std::dec << i->port << " "; + for (const unsigned char* j = i->id.begin(); + j != i->id.end(); + ++j) + { + std::cout << std::hex << std::setw(2) << std::setfill('0') + << static_cast(*j); + } + std::cout << "\n"; + } + std::cout << std::dec << std::setfill(' '); + + + // for each of the peers we got from the tracker + for (std::vector::iterator i = peer_list.begin(); + i != peer_list.end(); + ++i) + { + // don't make connections to ourself + if (i->id == m_ses->get_peer_id()) + continue; + + address a(i->ip, i->port); + + // if we aleady have a connection to the person, don't make another one + if (std::find_if(m_ses->m_connections.begin(), + m_ses->m_connections.end(), + find_peer(i->id, this)) != m_ses->m_connections.end()) + { + continue; + } + + m_policy->peer_from_tracker(a, i->id); + } + } catch(type_error& e) { @@ -168,30 +221,6 @@ namespace libtorrent tracker_request_error(e.what()); } - m_last_working_tracker = m_torrent_file.prioritize_tracker(m_currently_trying_tracker); - m_next_request = boost::posix_time::second_clock::local_time() + boost::posix_time::seconds(m_duration); - m_currently_trying_tracker = 0; - - // connect to random peers from the list - std::random_shuffle(m_peer_list.begin(), m_peer_list.end()); - - print(std::cout); - - // for each of the peers we got from the tracker - for (std::vector::iterator i = m_peer_list.begin(); i != m_peer_list.end(); ++i) - { - // don't make connections to ourself - if (i->id == m_ses->get_peer_id()) - continue; - - address a(i->ip, i->port); - - // if we aleady have a connection to the person, don't make another one - if (std::find_if(m_ses->m_connections.begin(), m_ses->m_connections.end(), find_peer(i->id, this)) != m_ses->m_connections.end()) - continue; - - m_policy->peer_from_tracker(a, i->id); - } } int torrent::num_connections(const peer_id& id) const @@ -223,7 +252,6 @@ namespace libtorrent m_next_request = boost::posix_time::second_clock::local_time() + boost::posix_time::seconds(m_duration); std::vector buffer; - // TODO: temporary! support multi-tracker std::string request = m_torrent_file.trackers()[m_currently_trying_tracker].url; request += "?info_hash="; @@ -255,7 +283,7 @@ namespace libtorrent return request; } - void torrent::parse_response(const entry& e) + void torrent::parse_response(const entry& e, std::vector& peer_list) { entry::dictionary_type::const_iterator i = e.dict().find("failure reason"); if (i != e.dict().end()) @@ -272,15 +300,14 @@ namespace libtorrent i = msg.find("peers"); if (i == msg.end()) throw std::runtime_error("invalid response from tracker"); - m_peer_list.clear(); + peer_list.clear(); - const entry::list_type& peer_list = i->second.list(); - for(entry::list_type::const_iterator i = peer_list.begin(); i != peer_list.end(); ++i) + const entry::list_type& l = i->second.list(); + for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i) { peer p = extract_peer_info(*i); - m_peer_list.push_back(p); + peer_list.push_back(p); } - } void torrent::remove_peer(peer_connection* p) @@ -328,20 +355,6 @@ namespace libtorrent std::cout << "connecting to: " << a.as_string() << ":" << a.port() << "\n"; } - void torrent::print(std::ostream& os) const - { - os << "interval: " << m_duration << "\n"; - os << "peers:\n"; - for (std::vector::const_iterator i = m_peer_list.begin(); i != m_peer_list.end(); ++i) - { - os << " " << std::setfill(' ') << std::setw(16) << i->ip << " " << std::setw(5) << std::dec << i->port << " "; - for (const unsigned char* j = i->id.begin(); j != i->id.end(); ++j) - os << std::hex << std::setw(2) << std::setfill('0') << static_cast(*j); - os << "\n"; - } - os << std::dec << std::setfill(' '); - } - #ifndef NDEBUG logger* torrent::spawn_logger(const char* title) {