/src/libtorrent/src/kademlia/find_data.cpp
Line | Count | Source |
1 | | /* |
2 | | |
3 | | Copyright (c) 2006, Daniel Wallin |
4 | | Copyright (c) 2006, 2008-2010, 2013-2017, 2019, Arvid Norberg |
5 | | Copyright (c) 2015, Thomas Yuan |
6 | | Copyright (c) 2016-2017, Alden Torres |
7 | | Copyright (c) 2017, Pavel Pimenov |
8 | | All rights reserved. |
9 | | |
10 | | Redistribution and use in source and binary forms, with or without |
11 | | modification, are permitted provided that the following conditions |
12 | | are met: |
13 | | |
14 | | * Redistributions of source code must retain the above copyright |
15 | | notice, this list of conditions and the following disclaimer. |
16 | | * Redistributions in binary form must reproduce the above copyright |
17 | | notice, this list of conditions and the following disclaimer in |
18 | | the documentation and/or other materials provided with the distribution. |
19 | | * Neither the name of the author nor the names of its |
20 | | contributors may be used to endorse or promote products derived |
21 | | from this software without specific prior written permission. |
22 | | |
23 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
24 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26 | | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
27 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
28 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
29 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
30 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
31 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
32 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
33 | | POSSIBILITY OF SUCH DAMAGE. |
34 | | |
35 | | */ |
36 | | |
37 | | #include <libtorrent/kademlia/find_data.hpp> |
38 | | #include <libtorrent/kademlia/node.hpp> |
39 | | #include <libtorrent/kademlia/dht_observer.hpp> |
40 | | #include <libtorrent/io.hpp> |
41 | | #include <libtorrent/socket.hpp> |
42 | | #include <libtorrent/socket_io.hpp> |
43 | | |
44 | | #ifndef TORRENT_DISABLE_LOGGING |
45 | | #include <libtorrent/hex.hpp> // to_hex |
46 | | #endif |
47 | | |
48 | | namespace libtorrent { namespace dht { |
49 | | |
50 | | void find_data_observer::reply(msg const& m) |
51 | 0 | { |
52 | 0 | bdecode_node const r = m.message.dict_find_dict("r"); |
53 | 0 | if (!r) |
54 | 0 | { |
55 | | #ifndef TORRENT_DISABLE_LOGGING |
56 | | get_observer()->log(dht_logger::traversal, "[%u] missing response dict" |
57 | | , algorithm()->id()); |
58 | | #endif |
59 | 0 | timeout(); |
60 | 0 | return; |
61 | 0 | } |
62 | | |
63 | 0 | bdecode_node const id = r.dict_find_string("id"); |
64 | 0 | if (!id || id.string_length() != 20) |
65 | 0 | { |
66 | | #ifndef TORRENT_DISABLE_LOGGING |
67 | | get_observer()->log(dht_logger::traversal, "[%u] invalid id in response" |
68 | | , algorithm()->id()); |
69 | | #endif |
70 | 0 | timeout(); |
71 | 0 | return; |
72 | 0 | } |
73 | 0 | bdecode_node const token = r.dict_find_string("token"); |
74 | 0 | if (token) |
75 | 0 | { |
76 | 0 | static_cast<find_data*>(algorithm())->got_write_token( |
77 | 0 | node_id(id.string_ptr()), token.string_value().to_string()); |
78 | 0 | } |
79 | |
|
80 | 0 | traversal_observer::reply(m); |
81 | 0 | done(); |
82 | 0 | } |
83 | | |
84 | | find_data::find_data( |
85 | | node& dht_node |
86 | | , node_id const& target |
87 | | , nodes_callback ncallback) |
88 | 0 | : traversal_algorithm(dht_node, target) |
89 | 0 | , m_nodes_callback(std::move(ncallback)) |
90 | 0 | , m_done(false) |
91 | 0 | { |
92 | 0 | } |
93 | | |
94 | | void find_data::start() |
95 | 0 | { |
96 | | // if the user didn't add seed-nodes manually, grab k (bucket size) |
97 | | // nodes from routing table. |
98 | 0 | if (m_results.empty()) |
99 | 0 | { |
100 | 0 | std::vector<node_entry> const nodes = m_node.m_table.find_node( |
101 | 0 | target(), routing_table::include_failed); |
102 | |
|
103 | 0 | for (auto const& n : nodes) |
104 | 0 | { |
105 | 0 | add_entry(n.id, n.ep(), observer::flag_initial); |
106 | 0 | } |
107 | 0 | } |
108 | |
|
109 | 0 | traversal_algorithm::start(); |
110 | 0 | } |
111 | | |
112 | | void find_data::got_write_token(node_id const& n, std::string write_token) |
113 | 0 | { |
114 | | #ifndef TORRENT_DISABLE_LOGGING |
115 | | auto logger = get_node().observer(); |
116 | | if (logger != nullptr && logger->should_log(dht_logger::traversal)) |
117 | | { |
118 | | logger->log(dht_logger::traversal |
119 | | , "[%u] adding write token '%s' under id '%s'" |
120 | | , id(), aux::to_hex(write_token).c_str() |
121 | | , aux::to_hex(n).c_str()); |
122 | | } |
123 | | #endif |
124 | 0 | m_write_tokens[n] = std::move(write_token); |
125 | 0 | } |
126 | | |
127 | | observer_ptr find_data::new_observer(udp::endpoint const& ep |
128 | | , node_id const& id) |
129 | 0 | { |
130 | 0 | auto o = m_node.m_rpc.allocate_observer<find_data_observer>(self(), ep, id); |
131 | 0 | #if TORRENT_USE_ASSERTS |
132 | 0 | if (o) o->m_in_constructor = false; |
133 | 0 | #endif |
134 | 0 | return o; |
135 | 0 | } |
136 | | |
137 | 0 | char const* find_data::name() const { return "find_data"; } |
138 | | |
139 | | void find_data::done() |
140 | 0 | { |
141 | 0 | m_done = true; |
142 | |
|
143 | | #ifndef TORRENT_DISABLE_LOGGING |
144 | | auto logger = get_node().observer(); |
145 | | if (logger != nullptr) |
146 | | { |
147 | | logger->log(dht_logger::traversal, "[%u] %s DONE" |
148 | | , id(), name()); |
149 | | } |
150 | | #endif |
151 | |
|
152 | 0 | std::vector<std::pair<node_entry, std::string>> results; |
153 | 0 | int num_results = m_node.m_table.bucket_size(); |
154 | 0 | for (auto i = m_results.begin() |
155 | 0 | , end(m_results.end()); i != end && num_results > 0; ++i) |
156 | 0 | { |
157 | 0 | observer_ptr const& o = *i; |
158 | 0 | if (!(o->flags & observer::flag_alive)) |
159 | 0 | { |
160 | | #ifndef TORRENT_DISABLE_LOGGING |
161 | | if (logger != nullptr && logger->should_log(dht_logger::traversal)) |
162 | | { |
163 | | logger->log(dht_logger::traversal, "[%u] not alive: %s" |
164 | | , id(), print_endpoint(o->target_ep()).c_str()); |
165 | | } |
166 | | #endif |
167 | 0 | continue; |
168 | 0 | } |
169 | 0 | auto j = m_write_tokens.find(o->id()); |
170 | 0 | if (j == m_write_tokens.end()) |
171 | 0 | { |
172 | | #ifndef TORRENT_DISABLE_LOGGING |
173 | | if (logger != nullptr && logger->should_log(dht_logger::traversal)) |
174 | | { |
175 | | logger->log(dht_logger::traversal, "[%u] no write token: %s" |
176 | | , id(), print_endpoint(o->target_ep()).c_str()); |
177 | | } |
178 | | #endif |
179 | 0 | continue; |
180 | 0 | } |
181 | 0 | results.emplace_back(node_entry(o->id(), o->target_ep()), j->second); |
182 | | #ifndef TORRENT_DISABLE_LOGGING |
183 | | if (logger != nullptr && logger->should_log(dht_logger::traversal)) |
184 | | { |
185 | | logger->log(dht_logger::traversal, "[%u] %s" |
186 | | , id(), print_endpoint(o->target_ep()).c_str()); |
187 | | } |
188 | | #endif |
189 | 0 | --num_results; |
190 | 0 | } |
191 | |
|
192 | 0 | if (m_nodes_callback) m_nodes_callback(results); |
193 | |
|
194 | 0 | traversal_algorithm::done(); |
195 | 0 | } |
196 | | |
197 | | } } // namespace libtorrent::dht |