From b897315abb146877bfb46ee563d5d3d332dada5a Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 21 Jan 2004 13:16:11 +0000 Subject: [PATCH] implemented completely untested support for udp-trackers. --- docs/manual.html | 2 +- docs/manual.rst | 2 +- examples/client_test.cpp | 2 +- include/libtorrent/peer_connection.hpp | 16 +++ include/libtorrent/peer_id.hpp | 2 +- include/libtorrent/torrent.hpp | 20 ++- src/peer_connection.cpp | 9 +- src/torrent.cpp | 165 ++++++++----------------- 8 files changed, 80 insertions(+), 138 deletions(-) diff --git a/docs/manual.html b/docs/manual.html index 58f5896e5..4ed7e59bc 100755 --- a/docs/manual.html +++ b/docs/manual.html @@ -205,7 +205,7 @@ class session: public boost::noncopyable torrent_handle add_torrent( const torrent_info& t - , const std::string& save_path + , const boost::filesystem::path& save_path , const entry& resume_data = entry()); void remove_torrent(const torrent_handle& h); diff --git a/docs/manual.rst b/docs/manual.rst index 64038f49c..8c5143a45 100755 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -153,7 +153,7 @@ The ``session`` class has the following synopsis:: torrent_handle add_torrent( const torrent_info& t - , const std::string& save_path + , const boost::filesystem::path& save_path , const entry& resume_data = entry()); void remove_torrent(const torrent_handle& h); diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 459fe0624..7851418e4 100755 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -259,7 +259,7 @@ int main(int argc, char* argv[]) {} handles.push_back(ses.add_torrent(t, save_path, resume_data)); - handles.back().set_max_connections(5); + handles.back().set_max_connections(60); handles.back().set_max_uploads(-1); handles.back().set_ratio(1.02); } diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 33994daa0..018b5bb58 100755 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -96,6 +96,15 @@ namespace libtorrent return ret; } + template + inline unsigned short read_ushort(InIt& start) + { + unsigned short val = 0; + val |= static_cast(*start) << 8; ++start; + val |= static_cast(*start); ++start; + return val; + } + // reads an integer to a byte stream // and converts it from native endianess template @@ -113,6 +122,13 @@ namespace libtorrent write_uint(static_cast(val), start); } + template + void write_ushort(unsigned short val, OutIt& start) + { + *start = static_cast((val >> 8) & 0xff); ++start; + *start = static_cast((val) & 0xff); ++start; + } + template inline void write_uchar(unsigned char val, OutIt& start) { diff --git a/include/libtorrent/peer_id.hpp b/include/libtorrent/peer_id.hpp index 691b6ff15..b1deb1027 100755 --- a/include/libtorrent/peer_id.hpp +++ b/include/libtorrent/peer_id.hpp @@ -46,7 +46,7 @@ namespace libtorrent enum { number_size = 20 }; public: - void set_to_all_zero() + void clear() { std::fill(m_number,m_number+number_size,0); } diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 1fa72d566..5aaa41f37 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -82,7 +82,7 @@ namespace libtorrent ~torrent(); - void abort() { m_abort = true; m_event = event_stopped; } + void abort() { m_abort = true; m_event = tracker_request::stopped; } bool is_aborted() const { return m_abort; } // is called every second by session. @@ -172,7 +172,7 @@ namespace libtorrent // this is a callback called by the tracker_connection class // when this torrent got a response from its tracker request - virtual void tracker_response(const entry& e); + virtual void tracker_response(std::vector& e, int interval); virtual void tracker_request_timed_out(); virtual void tracker_request_error(int response_code, const char* str); @@ -210,7 +210,11 @@ namespace libtorrent void announce_piece(int index); void disconnect_all(); - void disconnect_seeds(); + + // this is called wheh the torrent has completed + // the download. It will post an event, disconnect + // all seeds and let the tracker know we're finished. + void completed(); piece_picker& picker() { return m_picker; } @@ -254,14 +258,6 @@ namespace libtorrent void try_next_tracker(); - enum event_id - { - event_started = 0, - event_stopped, - event_completed, - event_none - }; - // the size of a request block // each piece is divided into these // blocks when requested @@ -271,7 +267,7 @@ namespace libtorrent // been aborted. bool m_abort; - event_id m_event; + tracker_request::event_t m_event; void parse_response(const entry& e, std::vector& peer_list); diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 353fe4c45..7f4491544 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -705,14 +705,7 @@ namespace libtorrent if (!was_seed && m_torrent->is_seed()) { assert(verified); - if (m_torrent->alerts().should_post(alert::info)) - { - m_torrent->alerts().post_alert(torrent_finished_alert( - m_torrent->get_handle() - , "torrent is finished downloading")); - } - - m_torrent->disconnect_seeds(); + m_torrent->completed(); } } diff --git a/src/torrent.cpp b/src/torrent.cpp index 4848e7840..c79cf35d5 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -94,39 +94,6 @@ namespace return default_block_size; } - - peer_entry extract_peer_info(const entry& e) - { - 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()) - { - 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()); - } - else - { - // if there's no peer_id, just initialize it to a bunch of zeroes - std::fill_n(ret.id.begin(), 20, 0); - } - - // extract ip - i = info.find("ip"); - if (i == info.end()) throw std::runtime_error("invalid response from tracker"); - ret.ip = i->second.string(); - - // extract port - i = info.find("port"); - if (i == info.end()) throw std::runtime_error("invalid response from tracker"); - ret.port = i->second.integer(); - - return ret; - } - /* struct find_peer_by_id { @@ -242,7 +209,7 @@ namespace libtorrent , const boost::filesystem::path& save_path) : m_block_size(calculate_block_size(torrent_file)) , m_abort(false) - , m_event(event_started) + , m_event(tracker_request::started) , m_torrent_file(torrent_file) , m_storage(m_torrent_file, save_path) , m_next_request(boost::posix_time::second_clock::local_time()) @@ -268,60 +235,48 @@ namespace libtorrent if (m_ses.m_abort) m_abort = true; } - void torrent::tracker_response(const entry& e) + void torrent::tracker_response( + std::vector& peer_list + , int interval) { - std::vector peer_list; - try - { - // parse the response - 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; - 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; + m_duration = interval; - // connect to random peers from the list - std::random_shuffle(peer_list.begin(), peer_list.end()); + // connect to random peers from the list + std::random_shuffle(peer_list.begin(), peer_list.end()); #ifndef NDEBUG - std::stringstream s; - s << "interval: " << m_duration << "\n"; - s << "peers:\n"; - for (std::vector::const_iterator i = peer_list.begin(); - i != peer_list.end(); - ++i) - { - s << " " << std::setfill(' ') << std::setw(16) << i->ip - << " " << std::setw(5) << std::dec << i->port << " " - << i->id << " " << identify_client(i->id) << "\n"; - } - debug_log(s.str()); + std::stringstream s; + s << "interval: " << m_duration << "\n"; + s << "peers:\n"; + for (std::vector::const_iterator i = peer_list.begin(); + i != peer_list.end(); + ++i) + { + s << " " << std::setfill(' ') << std::setw(16) << i->ip + << " " << std::setw(5) << std::dec << i->port << " " + << i->id << " " << identify_client(i->id) << "\n"; + } + debug_log(s.str()); #endif - // 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); - - m_policy->peer_from_tracker(a, i->id); - } - - } - catch(type_error& e) + // for each of the peers we got from the tracker + for (std::vector::iterator i = peer_list.begin(); + i != peer_list.end(); + ++i) { - tracker_request_error(-1, e.what()); - } - catch(std::runtime_error& e) - { - tracker_request_error(-1, e.what()); + // don't make connections to ourself + if (i->id == m_ses.get_peer_id()) + continue; + + address a(i->ip, i->port); + + m_policy->peer_from_tracker(a, i->id); } m_got_tracker_response = true; @@ -494,43 +449,11 @@ namespace libtorrent req.uploaded = m_stat.total_payload_upload(); req.left = bytes_left(); req.listen_port = port; - if (m_event != event_none) - { - const char* event_string[] = {"started", "stopped", "completed"}; - req.event += event_string[m_event]; - m_event = event_none; - } + req.event = m_event; req.url = m_torrent_file.trackers()[m_currently_trying_tracker].url; return req; } - 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()) - { - throw std::runtime_error(i->second.string().c_str()); - } - - const entry::dictionary_type& msg = e.dict(); - i = msg.find("interval"); - if (i == msg.end()) throw std::runtime_error("invalid response from tracker (no interval)"); - - m_duration = i->second.integer(); - - i = msg.find("peers"); - if (i == msg.end()) throw std::runtime_error("invalid response from tracker (no peers)"); - - peer_list.clear(); - - const entry::list_type& l = i->second.list(); - for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i) - { - peer_entry p = extract_peer_info(*i); - peer_list.push_back(p); - } - } - void torrent::remove_peer(peer_connection* p) { peer_iterator i = m_connections.find(p->get_socket()->sender()); @@ -626,8 +549,17 @@ namespace libtorrent } } - void torrent::disconnect_seeds() + void torrent::completed() { + if (alerts().should_post(alert::info)) + { + alerts().post_alert(torrent_finished_alert( + get_handle() + , "torrent is finished downloading")); + } + + + // disconnect all seeds for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) @@ -636,6 +568,11 @@ namespace libtorrent if (i->second->is_seed()) i->second->disconnect(); } + + // make the next tracker request + // be a completed-event + m_event = tracker_request::completed; + force_tracker_request(); }