added uTorrent Peer exchange support, implemented by MassaRoddel
This commit is contained in:
parent
f56cd20a1e
commit
b63c155c0d
|
@ -1,3 +1,4 @@
|
|||
* Added support for uT peer exchange extension, implemented by Massaroddel.
|
||||
* Modified the quota management to offer better bandwidth balancing
|
||||
between peers.
|
||||
* added XCode project files (maintained by Gregor Riepl)
|
||||
|
|
1
Jamfile
1
Jamfile
|
@ -54,6 +54,7 @@ SOURCES =
|
|||
udp_tracker_connection.cpp
|
||||
sha1.cpp
|
||||
metadata_transfer.cpp
|
||||
ut_pex.cpp
|
||||
logger.cpp
|
||||
file_pool.cpp
|
||||
;
|
||||
|
|
|
@ -52,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#endif
|
||||
|
||||
#include "libtorrent/extensions/metadata_transfer.hpp"
|
||||
#include "libtorrent/extensions/ut_pex.hpp"
|
||||
|
||||
#include "libtorrent/entry.hpp"
|
||||
#include "libtorrent/bencode.hpp"
|
||||
|
@ -570,6 +571,7 @@ int main(int ac, char* av[])
|
|||
handles_t handles;
|
||||
session ses;
|
||||
ses.add_extension(&create_metadata_plugin);
|
||||
ses.add_extension(&create_ut_pex_plugin);
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
dht_settings s;
|
||||
|
|
|
@ -46,6 +46,7 @@ libtorrent/version.hpp \
|
|||
libtorrent/aux_/allocate_resources_impl.hpp \
|
||||
libtorrent/aux_/session_impl.hpp \
|
||||
libtorrent/extensions/metadata_transfer.hpp \
|
||||
libtorrent/extensions/ut_pex.hpp \
|
||||
libtorrent/extensions/logger.hpp \
|
||||
\
|
||||
libtorrent/kademlia/closest_nodes.hpp \
|
||||
|
|
|
@ -238,7 +238,7 @@ namespace libtorrent
|
|||
{
|
||||
assert(num_saturated > 0);
|
||||
target = div_round_up(saturated_sum, num_saturated);
|
||||
target += div_round_up(target, 6);
|
||||
target += div_round_up(target, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2006, MassaRoddel
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED
|
||||
#define TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 1)
|
||||
#endif
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
struct torrent_plugin;
|
||||
class torrent;
|
||||
boost::shared_ptr<torrent_plugin> create_ut_pex_plugin(torrent*);
|
||||
}
|
||||
|
||||
#endif // TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED
|
|
@ -8,8 +8,7 @@ storage.cpp torrent.cpp torrent_handle.cpp \
|
|||
torrent_info.cpp tracker_manager.cpp \
|
||||
http_tracker_connection.cpp udp_tracker_connection.cpp \
|
||||
alert.cpp identify_client.cpp ip_filter.cpp file.cpp metadata_transfer.cpp \
|
||||
logger.cpp \
|
||||
file_pool.cpp \
|
||||
logger.cpp file_pool.cpp ut_pex.cpp \
|
||||
\
|
||||
kademlia/closest_nodes.cpp \
|
||||
kademlia/dht_tracker.cpp \
|
||||
|
@ -35,6 +34,7 @@ $(top_srcdir)/include/libtorrent/escape_string.hpp \
|
|||
$(top_srcdir)/include/libtorrent/extensions.hpp \
|
||||
$(top_srcdir)/include/libtorrent/extensions/metadata_transfer.hpp \
|
||||
$(top_srcdir)/include/libtorrent/extensions/logger.hpp \
|
||||
$(top_srcdir)/include/libtorrent/extensions/ut_pex.hpp \
|
||||
$(top_srcdir)/include/libtorrent/file.hpp \
|
||||
$(top_srcdir)/include/libtorrent/file_pool.hpp \
|
||||
$(top_srcdir)/include/libtorrent/fingerprint.hpp \
|
||||
|
@ -75,3 +75,4 @@ libtorrent_la_LIBADD = @ZLIB@ -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -
|
|||
|
||||
AM_CXXFLAGS= -ftemplate-depth-50 -I$(top_srcdir)/include -I$(top_srcdir)/include/libtorrent @ZLIBINCL@ @DEBUGFLAGS@ @PTHREAD_CFLAGS@
|
||||
AM_LDFLAGS= $(LDFLAGS) -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@
|
||||
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2006, MassaRoddel, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 1)
|
||||
#endif
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include "libtorrent/peer_connection.hpp"
|
||||
#include "libtorrent/bt_peer_connection.hpp"
|
||||
#include "libtorrent/bencode.hpp"
|
||||
#include "libtorrent/torrent.hpp"
|
||||
#include "libtorrent/extensions.hpp"
|
||||
|
||||
#include "libtorrent/extensions/ut_pex.hpp"
|
||||
|
||||
namespace libtorrent { namespace
|
||||
{
|
||||
const char extension_name[] = "ut_pex";
|
||||
|
||||
enum
|
||||
{
|
||||
extension_index = 1,
|
||||
max_peer_entries = 100
|
||||
};
|
||||
|
||||
struct ut_pex_plugin: torrent_plugin
|
||||
{
|
||||
ut_pex_plugin(torrent& t): m_torrent(t), m_1_minute(0) {}
|
||||
|
||||
virtual boost::shared_ptr<peer_plugin> new_connection(peer_connection* pc);
|
||||
|
||||
std::vector<char>& get_ut_pex_msg()
|
||||
{
|
||||
return m_ut_pex_msg;
|
||||
}
|
||||
|
||||
// the second tick of the torrent
|
||||
// each minute the new lists of "added" + "added.f" and "dropped"
|
||||
// are calculated here and the pex message is created
|
||||
// each peer connection will use this message
|
||||
// max_peer_entries limits the packet size
|
||||
virtual void tick()
|
||||
{
|
||||
if (++m_1_minute < 60) return;
|
||||
|
||||
m_1_minute = 0;
|
||||
std::list<tcp::endpoint> cs;
|
||||
for (torrent::peer_iterator i = m_torrent.m_connections.begin()
|
||||
, end(m_torrent.m_connections.end()); i != end; ++i)
|
||||
{
|
||||
if (!i->second->is_local()) continue;
|
||||
cs.push_back(i->first);
|
||||
}
|
||||
std::list<tcp::endpoint> added_peers, dropped_peers;
|
||||
|
||||
std::set_difference(cs.begin(), cs.end(), m_old_peers.begin()
|
||||
, m_old_peers.end(), std::back_inserter(added_peers));
|
||||
std::set_difference(m_old_peers.begin(), m_old_peers.end()
|
||||
, cs.begin(), cs.end(), std::back_inserter(dropped_peers));
|
||||
m_old_peers = cs;
|
||||
|
||||
unsigned int num_peers = max_peer_entries;
|
||||
|
||||
std::string pla, pld, plf;
|
||||
std::back_insert_iterator<std::string> pla_out(pla);
|
||||
std::back_insert_iterator<std::string> pld_out(pld);
|
||||
std::back_insert_iterator<std::string> plf_out(plf);
|
||||
|
||||
for (std::list<tcp::endpoint>::const_iterator i = added_peers.begin()
|
||||
, end(added_peers.end());i != end; ++i)
|
||||
{
|
||||
if (!i->address().is_v4()) continue;
|
||||
detail::write_endpoint(*i, pla_out);
|
||||
// no supported flags to set yet
|
||||
// 0x01 - peer supports encryption
|
||||
detail::write_uint8(0, plf_out);
|
||||
|
||||
if (--num_peers == 0) break;
|
||||
}
|
||||
|
||||
num_peers = max_peer_entries;
|
||||
for (std::list<tcp::endpoint>::const_iterator i = dropped_peers.begin()
|
||||
, end(dropped_peers.end());i != end; ++i)
|
||||
{
|
||||
if (!i->address().is_v4()) continue;
|
||||
detail::write_endpoint(*i, pld_out);
|
||||
|
||||
if (--num_peers == 0) break;
|
||||
}
|
||||
|
||||
entry pex(entry::dictionary_t);
|
||||
pex["added"] = pla;
|
||||
pex["dropped"] = pld;
|
||||
pex["added.f"] = plf;
|
||||
|
||||
m_ut_pex_msg.clear();
|
||||
bencode(std::back_inserter(m_ut_pex_msg), pex);
|
||||
}
|
||||
|
||||
private:
|
||||
torrent& m_torrent;
|
||||
|
||||
std::list<tcp::endpoint> m_old_peers;
|
||||
int m_1_minute;
|
||||
std::vector<char> m_ut_pex_msg;
|
||||
};
|
||||
|
||||
|
||||
struct ut_pex_peer_plugin : peer_plugin
|
||||
{
|
||||
ut_pex_peer_plugin(torrent& t, peer_connection& pc, ut_pex_plugin& tp)
|
||||
: m_torrent(t)
|
||||
, m_pc(pc)
|
||||
, m_tp(tp)
|
||||
, m_1_minute(0)
|
||||
, m_message_index(0)
|
||||
{}
|
||||
|
||||
virtual void add_handshake(entry& h)
|
||||
{
|
||||
entry& messages = h["m"];
|
||||
messages[extension_name] = extension_index;
|
||||
}
|
||||
|
||||
virtual bool on_extension_handshake(entry const& h)
|
||||
{
|
||||
entry const& messages = h["m"];
|
||||
|
||||
if (entry const* index = messages.find_key(extension_name))
|
||||
{
|
||||
m_message_index = index->integer();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_message_index = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool on_extended(int length, int msg, buffer::const_interval body)
|
||||
{
|
||||
if (msg != extension_index) return false;
|
||||
if (m_message_index == 0) return false;
|
||||
|
||||
if (length > 500 * 1024)
|
||||
throw protocol_error("ut peer exchange message larger than 500 kB");
|
||||
|
||||
if (body.left() < length) return true;
|
||||
|
||||
// in case we are a seed we do not use the peers
|
||||
// from the pex message to prevent us from
|
||||
// overloading ourself
|
||||
if (m_torrent.is_seed()) return true;
|
||||
|
||||
entry Pex = bdecode(body.begin, body.end);
|
||||
entry* PeerList = Pex.find_key("added");
|
||||
|
||||
if (!PeerList) return true;
|
||||
std::string const& peers = PeerList->string();
|
||||
int num_peers = peers.length() / 6;
|
||||
char const* in = peers.c_str();
|
||||
|
||||
peer_id pid;
|
||||
pid.clear();
|
||||
policy& p = m_torrent.get_policy();
|
||||
for (int i = 0; i < num_peers; ++i)
|
||||
{
|
||||
tcp::endpoint adr = detail::read_v4_endpoint<tcp::endpoint>(in);
|
||||
if (!m_torrent.connection_for(adr)) p.peer_from_tracker(adr, pid);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// the peers second tick
|
||||
// every minute we send a pex message
|
||||
virtual void tick()
|
||||
{
|
||||
if (!m_message_index) return; // no handshake yet
|
||||
if (++m_1_minute <= 60) return;
|
||||
|
||||
send_ut_peer_list();
|
||||
m_1_minute = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void send_ut_peer_list()
|
||||
{
|
||||
std::vector<char>& pex_msg = m_tp.get_ut_pex_msg();
|
||||
|
||||
buffer::interval i = m_pc.allocate_send_buffer(6 + pex_msg.size());
|
||||
|
||||
detail::write_uint32(1 + 1 + pex_msg.size(), i.begin);
|
||||
detail::write_uint8(bt_peer_connection::msg_extended, i.begin);
|
||||
detail::write_uint8(m_message_index, i.begin);
|
||||
std::copy(pex_msg.begin(), pex_msg.end(), i.begin);
|
||||
i.begin += pex_msg.size();
|
||||
|
||||
assert(i.begin == i.end);
|
||||
m_pc.setup_send();
|
||||
}
|
||||
|
||||
torrent& m_torrent;
|
||||
peer_connection& m_pc;
|
||||
ut_pex_plugin& m_tp;
|
||||
int m_1_minute;
|
||||
int m_message_index;
|
||||
};
|
||||
|
||||
boost::shared_ptr<peer_plugin> ut_pex_plugin::new_connection(peer_connection* pc)
|
||||
{
|
||||
return boost::shared_ptr<peer_plugin>(new ut_pex_peer_plugin(m_torrent
|
||||
, *pc, *this));
|
||||
}
|
||||
}}
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
boost::shared_ptr<torrent_plugin> create_ut_pex_plugin(torrent* t)
|
||||
{
|
||||
if (t->torrent_file().priv())
|
||||
{
|
||||
return boost::shared_ptr<torrent_plugin>();
|
||||
}
|
||||
return boost::shared_ptr<torrent_plugin>(new ut_pex_plugin(*t));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue