forked from premiere/premiere-libtorrent
implemented completely untested support for udp-trackers.
This commit is contained in:
parent
8b286d84a6
commit
b897315abb
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -96,6 +96,15 @@ namespace libtorrent
|
|||
return ret;
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
inline unsigned short read_ushort(InIt& start)
|
||||
{
|
||||
unsigned short val = 0;
|
||||
val |= static_cast<unsigned char>(*start) << 8; ++start;
|
||||
val |= static_cast<unsigned char>(*start); ++start;
|
||||
return val;
|
||||
}
|
||||
|
||||
// reads an integer to a byte stream
|
||||
// and converts it from native endianess
|
||||
template <class OutIt>
|
||||
|
@ -113,6 +122,13 @@ namespace libtorrent
|
|||
write_uint(static_cast<unsigned int>(val), start);
|
||||
}
|
||||
|
||||
template <class OutIt>
|
||||
void write_ushort(unsigned short val, OutIt& start)
|
||||
{
|
||||
*start = static_cast<unsigned char>((val >> 8) & 0xff); ++start;
|
||||
*start = static_cast<unsigned char>((val) & 0xff); ++start;
|
||||
}
|
||||
|
||||
template <class OutIt>
|
||||
inline void write_uchar(unsigned char val, OutIt& start)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<peer_entry>& 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_entry>& peer_list);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
165
src/torrent.cpp
165
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_entry>& peer_list
|
||||
, int interval)
|
||||
{
|
||||
std::vector<peer_entry> 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<peer_entry>::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<peer_entry>::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<peer_entry>::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<peer_entry>::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_entry>& 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();
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue