forked from premiere/premiere-libtorrent
handle DHT error responses correctly
This commit is contained in:
parent
926cb44953
commit
db6a22d5c1
|
@ -1,3 +1,4 @@
|
||||||
|
* handle DHT error responses correctly
|
||||||
* allow force_announce to only affect a single tracker
|
* allow force_announce to only affect a single tracker
|
||||||
* add moving_storage field to torrent_status
|
* add moving_storage field to torrent_status
|
||||||
* expose UPnP and NAT-PMP mapping in session object
|
* expose UPnP and NAT-PMP mapping in session object
|
||||||
|
|
|
@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define RPC_MANAGER_HPP
|
#define RPC_MANAGER_HPP
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
#include <boost/pool/pool.hpp>
|
#include <boost/pool/pool.hpp>
|
||||||
|
@ -107,7 +108,7 @@ private:
|
||||||
|
|
||||||
mutable boost::pool<> m_pool_allocator;
|
mutable boost::pool<> m_pool_allocator;
|
||||||
|
|
||||||
typedef std::list<observer_ptr> transactions_t;
|
typedef std::deque<observer_ptr> transactions_t;
|
||||||
transactions_t m_transactions;
|
transactions_t m_transactions;
|
||||||
|
|
||||||
udp_socket_interface* m_sock;
|
udp_socket_interface* m_sock;
|
||||||
|
|
|
@ -218,9 +218,11 @@ void node_impl::incoming(msg const& m)
|
||||||
lazy_entry const* y_ent = m.message.dict_find_string("y");
|
lazy_entry const* y_ent = m.message.dict_find_string("y");
|
||||||
if (!y_ent || y_ent->string_length() == 0)
|
if (!y_ent || y_ent->string_length() == 0)
|
||||||
{
|
{
|
||||||
entry e;
|
// don't respond to this obviously broken messages. We don't
|
||||||
incoming_error(e, "missing 'y' entry");
|
// want to open up a magnification opportunity
|
||||||
m_sock->send_packet(e, m.addr, 0);
|
// entry e;
|
||||||
|
// incoming_error(e, "missing 'y' entry");
|
||||||
|
// m_sock->send_packet(e, m.addr, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,6 +284,8 @@ void node_impl::incoming(msg const& m)
|
||||||
TORRENT_LOG(node) << "INCOMING ERROR: " << err->list_string_value_at(1);
|
TORRENT_LOG(node) << "INCOMING ERROR: " << err->list_string_value_at(1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
node_id id;
|
||||||
|
m_rpc.incoming(m, &id, m_settings);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,7 +255,7 @@ void rpc_manager::unreachable(udp::endpoint const& ep)
|
||||||
observer_ptr const& o = *i;
|
observer_ptr const& o = *i;
|
||||||
if (o->target_ep() != ep) { ++i; continue; }
|
if (o->target_ep() != ep) { ++i; continue; }
|
||||||
observer_ptr ptr = *i;
|
observer_ptr ptr = *i;
|
||||||
m_transactions.erase(i++);
|
i = m_transactions.erase(i);
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(rpc) << " found transaction [ tid: " << ptr->transaction_id() << " ]";
|
TORRENT_LOG(rpc) << " found transaction [ tid: " << ptr->transaction_id() << " ]";
|
||||||
#endif
|
#endif
|
||||||
|
@ -273,13 +273,15 @@ bool rpc_manager::incoming(msg const& m, node_id* id, libtorrent::dht_settings c
|
||||||
|
|
||||||
if (m_destructing) return false;
|
if (m_destructing) return false;
|
||||||
|
|
||||||
// we only deal with replies, not queries
|
// we only deal with replies and errors, not queries
|
||||||
TORRENT_ASSERT(m.message.dict_find_string_value("y") == "r");
|
TORRENT_ASSERT(m.message.dict_find_string_value("y") == "r"
|
||||||
|
|| m.message.dict_find_string_value("y") == "e");
|
||||||
|
|
||||||
// if we don't have the transaction id in our
|
// if we don't have the transaction id in our
|
||||||
// request list, ignore the packet
|
// request list, ignore the packet
|
||||||
|
|
||||||
std::string transaction_id = m.message.dict_find_string_value("t");
|
std::string transaction_id = m.message.dict_find_string_value("t");
|
||||||
|
if (transaction_id.empty()) return false;
|
||||||
|
|
||||||
std::string::const_iterator i = transaction_id.begin();
|
std::string::const_iterator i = transaction_id.begin();
|
||||||
int tid = transaction_id.size() != 2 ? -1 : io::read_uint16(i);
|
int tid = transaction_id.size() != 2 ? -1 : io::read_uint16(i);
|
||||||
|
@ -287,25 +289,34 @@ bool rpc_manager::incoming(msg const& m, node_id* id, libtorrent::dht_settings c
|
||||||
observer_ptr o;
|
observer_ptr o;
|
||||||
|
|
||||||
for (transactions_t::iterator i = m_transactions.begin()
|
for (transactions_t::iterator i = m_transactions.begin()
|
||||||
, end(m_transactions.end()); i != end; ++i)
|
, end(m_transactions.end()); i != end;)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(*i);
|
TORRENT_ASSERT(*i);
|
||||||
if ((*i)->transaction_id() != tid) continue;
|
if ((*i)->transaction_id() != tid
|
||||||
if (m.addr.address() != (*i)->target_addr()) continue;
|
|| m.addr.address() != (*i)->target_addr())
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
o = *i;
|
o = *i;
|
||||||
m_transactions.erase(i);
|
i = m_transactions.erase(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!o)
|
if (!o)
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(rpc) << "Reply with invalid transaction id size: "
|
TORRENT_LOG(rpc) << "Reply with unknown transaction id size: "
|
||||||
<< transaction_id.size() << " from " << m.addr;
|
<< transaction_id.size() << " from " << m.addr;
|
||||||
#endif
|
#endif
|
||||||
entry e;
|
// this isn't necessarily because the other end is doing
|
||||||
incoming_error(e, "invalid transaction id");
|
// something wrong. This can also happen when we restart
|
||||||
m_sock->send_packet(e, m.addr, 0);
|
// the node, and we prematurely abort all outstanding
|
||||||
|
// requests. Also, this opens up a potential magnification
|
||||||
|
// attack.
|
||||||
|
// entry e;
|
||||||
|
// incoming_error(e, "invalid transaction id");
|
||||||
|
// m_sock->send_packet(e, m.addr, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,10 +331,15 @@ bool rpc_manager::incoming(msg const& m, node_id* id, libtorrent::dht_settings c
|
||||||
lazy_entry const* ret_ent = m.message.dict_find_dict("r");
|
lazy_entry const* ret_ent = m.message.dict_find_dict("r");
|
||||||
if (ret_ent == 0)
|
if (ret_ent == 0)
|
||||||
{
|
{
|
||||||
|
// it may be an error
|
||||||
|
ret_ent = m.message.dict_find_dict("e");
|
||||||
o->timeout();
|
o->timeout();
|
||||||
|
if (ret_ent == NULL)
|
||||||
|
{
|
||||||
entry e;
|
entry e;
|
||||||
incoming_error(e, "missing 'r' key");
|
incoming_error(e, "missing 'r' key");
|
||||||
m_sock->send_packet(e, m.addr, 0);
|
m_sock->send_packet(e, m.addr, 0);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +381,7 @@ time_duration rpc_manager::tick()
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
const static int short_timeout = 1;
|
const static int short_timeout = 1;
|
||||||
const static int timeout = 8;
|
const static int timeout = 15;
|
||||||
|
|
||||||
// look for observers that have timed out
|
// look for observers that have timed out
|
||||||
|
|
||||||
|
@ -405,7 +421,7 @@ time_duration rpc_manager::tick()
|
||||||
TORRENT_LOG(rpc) << "[" << o->m_algorithm.get() << "] Timing out transaction id: "
|
TORRENT_LOG(rpc) << "[" << o->m_algorithm.get() << "] Timing out transaction id: "
|
||||||
<< (*i)->transaction_id() << " from " << o->target_ep();
|
<< (*i)->transaction_id() << " from " << o->target_ep();
|
||||||
#endif
|
#endif
|
||||||
m_transactions.erase(i++);
|
i = m_transactions.erase(i);
|
||||||
timeouts.push_back(o);
|
timeouts.push_back(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue