2006-08-01 17:27:08 +02:00
|
|
|
/*
|
|
|
|
|
2015-06-03 07:18:48 +02:00
|
|
|
Copyright (c) 2006-2015, Arvid Norberg & Daniel Wallin
|
2006-08-01 17:27:08 +02:00
|
|
|
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.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <libtorrent/kademlia/find_data.hpp>
|
2008-09-20 19:42:25 +02:00
|
|
|
#include <libtorrent/kademlia/node.hpp>
|
2015-05-10 06:54:02 +02:00
|
|
|
#include <libtorrent/kademlia/dht_observer.hpp>
|
2006-08-01 17:27:08 +02:00
|
|
|
#include <libtorrent/io.hpp>
|
2008-05-03 18:05:42 +02:00
|
|
|
#include <libtorrent/socket.hpp>
|
2009-09-20 02:23:36 +02:00
|
|
|
#include <libtorrent/socket_io.hpp>
|
|
|
|
#include <vector>
|
2006-08-01 17:27:08 +02:00
|
|
|
|
|
|
|
namespace libtorrent { namespace dht
|
|
|
|
{
|
|
|
|
|
2009-10-19 04:43:50 +02:00
|
|
|
using detail::read_endpoint_list;
|
2009-09-20 02:23:36 +02:00
|
|
|
using detail::read_v4_endpoint;
|
2009-10-19 04:43:50 +02:00
|
|
|
#if TORRENT_USE_IPV6
|
2009-09-20 02:23:36 +02:00
|
|
|
using detail::read_v6_endpoint;
|
2009-10-19 04:43:50 +02:00
|
|
|
#endif
|
2009-09-20 02:23:36 +02:00
|
|
|
|
2006-08-01 17:27:08 +02:00
|
|
|
void find_data_observer::reply(msg const& m)
|
|
|
|
{
|
2015-03-12 06:20:12 +01:00
|
|
|
bdecode_node r = m.message.dict_find_dict("r");
|
2009-09-20 02:23:36 +02:00
|
|
|
if (!r)
|
|
|
|
{
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-05-22 04:42:26 +02:00
|
|
|
get_observer()->log(dht_logger::traversal, "[%p] missing response dict"
|
2015-08-20 01:33:20 +02:00
|
|
|
, static_cast<void*>(algorithm()));
|
2009-09-20 02:23:36 +02:00
|
|
|
#endif
|
2015-09-01 04:37:46 +02:00
|
|
|
timeout();
|
2009-09-20 02:23:36 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-12 06:20:12 +01:00
|
|
|
bdecode_node id = r.dict_find_string("id");
|
|
|
|
if (!id || id.string_length() != 20)
|
2009-09-20 02:23:36 +02:00
|
|
|
{
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-05-22 04:42:26 +02:00
|
|
|
get_observer()->log(dht_logger::traversal, "[%p] invalid id in response"
|
2015-08-20 01:33:20 +02:00
|
|
|
, static_cast<void*>(algorithm()));
|
2009-09-20 02:23:36 +02:00
|
|
|
#endif
|
2015-09-01 04:37:46 +02:00
|
|
|
timeout();
|
2009-09-20 02:23:36 +02:00
|
|
|
return;
|
|
|
|
}
|
2015-03-12 06:20:12 +01:00
|
|
|
bdecode_node token = r.dict_find_string("token");
|
2009-09-20 02:23:36 +02:00
|
|
|
if (token)
|
|
|
|
{
|
2015-05-22 04:42:26 +02:00
|
|
|
static_cast<find_data*>(algorithm())->got_write_token(
|
2015-03-12 06:20:12 +01:00
|
|
|
node_id(id.string_ptr()), token.string_value());
|
2009-09-20 02:23:36 +02:00
|
|
|
}
|
|
|
|
|
2013-12-15 00:25:38 +01:00
|
|
|
traversal_observer::reply(m);
|
2009-10-07 22:51:02 +02:00
|
|
|
done();
|
2006-08-01 17:27:08 +02:00
|
|
|
}
|
|
|
|
|
2015-04-20 06:52:49 +02:00
|
|
|
namespace {
|
|
|
|
|
2010-01-03 12:08:39 +01:00
|
|
|
void add_entry_fun(void* userdata, node_entry const& e)
|
|
|
|
{
|
2015-08-11 02:03:24 +02:00
|
|
|
traversal_algorithm* f = static_cast<traversal_algorithm*>(userdata);
|
2010-11-05 20:06:50 +01:00
|
|
|
f->add_entry(e.id, e.ep(), observer::flag_initial);
|
2010-01-03 12:08:39 +01:00
|
|
|
}
|
|
|
|
|
2015-04-20 06:52:49 +02:00
|
|
|
} // anonymous namespace
|
|
|
|
|
2006-08-01 17:27:08 +02:00
|
|
|
find_data::find_data(
|
2015-05-09 21:00:22 +02:00
|
|
|
node& dht_node
|
2008-09-20 19:42:25 +02:00
|
|
|
, node_id target
|
2013-12-27 05:28:25 +01:00
|
|
|
, nodes_callback const& ncallback)
|
2015-05-09 21:00:22 +02:00
|
|
|
: traversal_algorithm(dht_node, target)
|
2008-12-23 21:04:12 +01:00
|
|
|
, m_nodes_callback(ncallback)
|
2006-08-01 17:27:08 +02:00
|
|
|
, m_done(false)
|
|
|
|
{
|
2013-09-09 09:08:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void find_data::start()
|
|
|
|
{
|
|
|
|
// if the user didn't add seed-nodes manually, grab a bunch of nodes from the
|
|
|
|
// routing table
|
|
|
|
if (m_results.empty())
|
2015-08-11 02:03:24 +02:00
|
|
|
m_node.m_table.for_each_node(&add_entry_fun, 0, this);
|
2013-09-09 09:08:02 +02:00
|
|
|
|
|
|
|
traversal_algorithm::start();
|
2006-08-01 17:27:08 +02:00
|
|
|
}
|
|
|
|
|
2014-02-28 05:02:48 +01:00
|
|
|
void find_data::got_write_token(node_id const& n, std::string const& write_token)
|
|
|
|
{
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-08-20 01:33:20 +02:00
|
|
|
get_node().observer()->log(dht_logger::traversal
|
|
|
|
, "[%p] adding write token '%s' under id '%s'"
|
|
|
|
, static_cast<void*>(this), to_hex(write_token).c_str()
|
|
|
|
, to_hex(n.to_string()).c_str());
|
2014-02-28 05:02:48 +01:00
|
|
|
#endif
|
|
|
|
m_write_tokens[n] = write_token;
|
|
|
|
}
|
|
|
|
|
2010-11-05 20:06:50 +01:00
|
|
|
observer_ptr find_data::new_observer(void* ptr
|
|
|
|
, udp::endpoint const& ep, node_id const& id)
|
|
|
|
{
|
|
|
|
observer_ptr o(new (ptr) find_data_observer(this, ep, id));
|
2012-01-16 23:48:43 +01:00
|
|
|
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
|
2010-11-05 20:06:50 +01:00
|
|
|
o->m_in_constructor = false;
|
|
|
|
#endif
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
2013-12-27 05:28:25 +01:00
|
|
|
char const* find_data::name() const { return "find_data"; }
|
2006-08-01 17:27:08 +02:00
|
|
|
|
|
|
|
void find_data::done()
|
|
|
|
{
|
|
|
|
if (m_invoke_count != 0) return;
|
2008-12-23 21:04:12 +01:00
|
|
|
|
2009-10-07 22:51:02 +02:00
|
|
|
m_done = true;
|
|
|
|
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-05-10 06:54:02 +02:00
|
|
|
get_node().observer()->log(dht_logger::traversal, "[%p] %s DONE"
|
2015-08-20 01:33:20 +02:00
|
|
|
, static_cast<void*>(this), name());
|
2010-11-05 20:06:50 +01:00
|
|
|
#endif
|
|
|
|
|
2008-12-23 21:04:12 +01:00
|
|
|
std::vector<std::pair<node_entry, std::string> > results;
|
|
|
|
int num_results = m_node.m_table.bucket_size();
|
2010-11-05 20:06:50 +01:00
|
|
|
for (std::vector<observer_ptr>::iterator i = m_results.begin()
|
2008-12-23 21:04:12 +01:00
|
|
|
, end(m_results.end()); i != end && num_results > 0; ++i)
|
|
|
|
{
|
2010-11-05 20:06:50 +01:00
|
|
|
observer_ptr const& o = *i;
|
2014-02-28 05:02:48 +01:00
|
|
|
if ((o->flags & observer::flag_alive) == 0)
|
|
|
|
{
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-05-10 06:54:02 +02:00
|
|
|
get_node().observer()->log(dht_logger::traversal, "[%p] not alive: %s"
|
2015-08-20 01:33:20 +02:00
|
|
|
, static_cast<void*>(this), print_endpoint(o->target_ep()).c_str());
|
2014-02-28 05:02:48 +01:00
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
2010-11-05 20:06:50 +01:00
|
|
|
std::map<node_id, std::string>::iterator j = m_write_tokens.find(o->id());
|
2014-02-28 05:02:48 +01:00
|
|
|
if (j == m_write_tokens.end())
|
|
|
|
{
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-05-10 06:54:02 +02:00
|
|
|
get_node().observer()->log(dht_logger::traversal, "[%p] no write token: %s"
|
2015-08-20 01:33:20 +02:00
|
|
|
, static_cast<void*>(this), print_endpoint(o->target_ep()).c_str());
|
2014-02-28 05:02:48 +01:00
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
2010-11-05 20:06:50 +01:00
|
|
|
results.push_back(std::make_pair(node_entry(o->id(), o->target_ep()), j->second));
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-05-10 06:54:02 +02:00
|
|
|
get_node().observer()->log(dht_logger::traversal, "[%p] %s"
|
2015-08-20 01:33:20 +02:00
|
|
|
, static_cast<void*>(this), print_endpoint(o->target_ep()).c_str());
|
2014-02-28 05:02:48 +01:00
|
|
|
#endif
|
2008-12-23 21:04:12 +01:00
|
|
|
--num_results;
|
|
|
|
}
|
2014-02-28 05:02:48 +01:00
|
|
|
|
2013-12-27 05:28:25 +01:00
|
|
|
if (m_nodes_callback) m_nodes_callback(results);
|
2010-11-05 20:06:50 +01:00
|
|
|
|
|
|
|
traversal_algorithm::done();
|
2006-08-01 17:27:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} } // namespace libtorrent::dht
|
|
|
|
|