From 61e8d3dd49b2bd29f1271b6dd0361b2a9c44a53a Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 4 Jan 2012 20:49:54 +0000 Subject: [PATCH] improved peer exchange performance by sharing incoming connections which advertize listen port --- ChangeLog | 1 + include/libtorrent/peer_connection.hpp | 8 +++++++ src/bt_peer_connection.cpp | 2 ++ src/peer_connection.cpp | 2 ++ src/ut_pex.cpp | 33 ++++++++++++++++++++++---- 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 18e90249a..fc5f5d0e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * improved peer exchange performance by sharing incoming connections which advertize listen port * deprecate set_ratio(), and per-peer rate limits * add web seed support for torrents with pad files * introduced a more scalable API for torrent status updates (post_torrent_updates()) and updated client_test to use it diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index c0395ec21..00836fb57 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -402,6 +402,10 @@ namespace libtorrent // if it was an incoming connection, it is remote bool is_local() const { return m_active; } + bool received_listen_port() const { return m_received_listen_port; } + void received_listen_port() + { m_received_listen_port = true; } + bool on_local_network() const; bool ignore_bandwidth_limits() const { return m_ignore_bandwidth_limits; } @@ -1053,6 +1057,10 @@ namespace libtorrent // could be considered: true = local, false = remote bool m_active:1; + // is true if we learn the incoming connections listening + // during the extended handshake + bool m_received_listen_port:1; + // other side says that it's interested in downloading // from us. bool m_peer_interested:1; diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index 5f74165c6..408d4751d 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -1777,8 +1777,10 @@ namespace libtorrent { t->get_policy().update_peer_port(listen_port , peer_info_struct(), peer_info::incoming); + received_listen_port(); if (is_disconnecting()) return; } + // there should be a version too // but where do we put that info? diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 7400ea9ba..825bbc372 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -170,6 +170,7 @@ namespace libtorrent , m_choke_rejects(0) , m_fast_reconnect(false) , m_active(outgoing) + , m_received_listen_port(false) , m_peer_interested(false) , m_peer_choked(true) , m_interesting(false) @@ -320,6 +321,7 @@ namespace libtorrent , m_choke_rejects(0) , m_fast_reconnect(false) , m_active(outgoing) + , m_received_listen_port(false) , m_peer_interested(false) , m_peer_choked(true) , m_interesting(false) diff --git a/src/ut_pex.cpp b/src/ut_pex.cpp index 90a98fe4b..6f1a27877 100644 --- a/src/ut_pex.cpp +++ b/src/ut_pex.cpp @@ -72,9 +72,10 @@ namespace libtorrent { namespace bool send_peer(peer_connection const& p) { - // don't send out peers that we haven't connected to - // (that have connected to us) - if (!p.is_local()) return false; + // don't send out those peers that we haven't connected to + // (that have connected to us) and that aren't sharing their + // listening port + if (!p.is_local() && !p.received_listen_port()) return false; // don't send out peers that we haven't successfully connected to if (p.is_connecting()) return false; return true; @@ -136,7 +137,7 @@ namespace libtorrent { namespace peer_connection* peer = *i; if (!send_peer(*peer)) continue; - tcp::endpoint const& remote = peer->remote(); + tcp::endpoint remote = peer->remote(); m_old_peers.insert(remote); std::set::iterator di = dropped.find(remote); @@ -151,6 +152,13 @@ namespace libtorrent { namespace bt_peer_connection* p = static_cast(peer); + // if the peer has told us which port its listening on, + // use that port. But only if we didn't connect to the peer. + // if we connected to it, use the port we know works + policy::peer *pi = 0; + if (!p->is_local() && (pi = peer->peer_info_struct()) && pi->port > 0) + remote.port(pi->port); + // no supported flags to set yet // 0x01 - peer supports encryption // 0x02 - peer is a seed @@ -502,11 +510,26 @@ namespace libtorrent { namespace // no supported flags to set yet // 0x01 - peer supports encryption // 0x02 - peer is a seed + // 0x04 - supports uTP. This is only a positive flags + // passing 0 doesn't mean the peer doesn't + // support uTP + // 0x08 - supports holepunching protocol. If this + // flag is received from a peer, it can be + // used as a rendezvous point in case direct + // connections to the peer fail int flags = p->is_seed() ? 2 : 0; #ifndef TORRENT_DISABLE_ENCRYPTION flags |= p->supports_encryption() ? 1 : 0; #endif - tcp::endpoint const& remote = peer->remote(); + flags |= p->get_socket()->get() ? 4 : 0; + flags |= p->supports_holepunch() ? 8 : 0; + + tcp::endpoint remote = peer->remote(); + + policy::peer *pi = 0; + if (!p->is_local() && (pi = peer->peer_info_struct()) && pi->port > 0) + remote.port(pi->port); + // i->first was added since the last time if (remote.address().is_v4()) {