3
Copyright (c) 2003, Arvid Norberg
6
Redistribution and use in source and binary forms, with or without
7
modification, are permitted provided that the following conditions
10
* Redistributions of source code must retain the above copyright
11
notice, this list of conditions and the following disclaimer.
12
* Redistributions in binary form must reproduce the above copyright
13
notice, this list of conditions and the following disclaimer in
14
the documentation and/or other materials provided with the distribution.
15
* Neither the name of the author nor the names of its
16
contributors may be used to endorse or promote products derived
17
from this software without specific prior written permission.
19
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
POSSIBILITY OF SUCH DAMAGE.
33
#include "libtorrent/pch.hpp"
44
#pragma warning(push, 1)
47
#include <boost/bind.hpp>
49
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
50
#include <boost/lexical_cast.hpp>
51
using boost::lexical_cast;
58
#include "libtorrent/tracker_manager.hpp"
59
#include "libtorrent/parse_url.hpp"
60
#include "libtorrent/udp_tracker_connection.hpp"
61
#include "libtorrent/io.hpp"
62
#include "libtorrent/escape_string.hpp"
68
udp_connection_retries = 4,
69
udp_announce_retries = 15,
70
udp_connect_timeout = 15,
71
udp_announce_timeout = 10
80
udp_tracker_connection::udp_tracker_connection(
82
, connection_queue& cc
83
, tracker_manager& man
84
, tracker_request const& req
86
, boost::weak_ptr<request_callback> c
87
, session_settings const& stn
88
, proxy_settings const& proxy)
89
: tracker_connection(man, req, ios, bind_infc, c)
92
, m_socket(ios, boost::bind(&udp_tracker_connection::on_receive, self(), _1, _2, _3, _4), cc)
97
, m_state(action_error)
99
m_socket.set_proxy_settings(proxy);
102
void udp_tracker_connection::start()
104
std::string hostname;
108
using boost::tuples::ignore;
109
boost::tie(ignore, ignore, hostname, port, ignore, error)
110
= parse_url_components(tracker_req().url);
118
udp::resolver::query q(hostname, to_string(port).elems);
119
m_name_lookup.async_resolve(q
121
&udp_tracker_connection::name_lookup, self(), _1, _2));
122
set_timeout(tracker_req().event == tracker_request::stopped
123
? m_settings.stop_tracker_timeout
124
: m_settings.tracker_completion_timeout
125
, m_settings.tracker_receive_timeout);
126
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
127
boost::shared_ptr<request_callback> cb = requester();
128
if (cb) cb->debug_log(("*** UDP_TRACKER [ initiating name lookup: " + hostname + " ]").c_str());
132
void udp_tracker_connection::name_lookup(error_code const& error
133
, udp::resolver::iterator i)
135
if (error == asio::error::operation_aborted) return;
136
if (error || i == udp::resolver::iterator())
138
fail(-1, error.message().c_str());
142
boost::shared_ptr<request_callback> cb = requester();
143
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
144
if (cb) cb->debug_log("*** UDP_TRACKER [ name lookup successful ]");
146
restart_read_timeout();
148
// look for an address that has the same kind as the one
149
// we're listening on. To make sure the tracker get our
150
// correct listening address.
151
udp::resolver::iterator target = i;
152
udp::resolver::iterator end;
153
udp::endpoint target_address = *i;
154
for (; target != end && target->endpoint().address().is_v4()
155
!= bind_interface().is_v4(); ++target);
158
TORRENT_ASSERT(target_address.address().is_v4() != bind_interface().is_v4());
161
std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6";
162
std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6";
163
cb->tracker_warning(tracker_req(), "the tracker only resolves to an "
164
+ tracker_address_type + " address, and you're listening on an "
165
+ bind_address_type + " socket. This may prevent you from receiving incoming connections.");
170
target_address = *target;
173
if (cb) cb->m_tracker_address = tcp::endpoint(target_address.address(), target_address.port());
174
m_target = target_address;
176
m_socket.bind(udp::endpoint(bind_interface(), 0), ec);
179
fail(-1, ec.message().c_str());
185
void udp_tracker_connection::on_timeout()
187
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
188
boost::shared_ptr<request_callback> cb = requester();
189
if (cb) cb->debug_log("*** UDP_TRACKER [ timed out ]");
192
m_name_lookup.cancel();
196
void udp_tracker_connection::close()
200
m_name_lookup.cancel();
201
tracker_connection::close();
204
void udp_tracker_connection::on_receive(error_code const& e
205
, udp::endpoint const& ep, char const* buf, int size)
207
// ignore resposes before we've sent any requests
208
if (m_state == action_error) return;
210
if (!m_socket.is_open()) return; // the operation was aborted
212
// ignore packet not sent from the tracker
213
if (m_target != ep) return;
215
if (e) fail(-1, e.message().c_str());
217
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
218
boost::shared_ptr<request_callback> cb = requester();
221
std::stringstream msg;
222
msg << "<== UDP_TRACKER_PACKET [ size: " << size << " ]";
223
cb->debug_log(msg.str());
227
// ignore packets smaller than 8 bytes
228
if (size < 8) return;
230
restart_read_timeout();
232
const char* ptr = buf;
233
int action = detail::read_int32(ptr);
234
int transaction = detail::read_int32(ptr);
236
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
239
std::stringstream msg;
240
msg << "*** UDP_TRACKER_PACKET [ acton: " << action << " ]";
241
cb->debug_log(msg.str());
245
// ignore packets with incorrect transaction id
246
if (m_transaction_id != transaction) return;
248
if (action == action_error)
250
fail(-1, std::string(ptr, size - 8).c_str());
254
// ignore packets that's not a response to our message
255
if (action != m_state) return;
257
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
260
std::stringstream msg;
261
msg << "*** UDP_TRACKER_RESPONSE [ cid: " << m_connection_id << " ]";
262
cb->debug_log(msg.str());
269
on_connect_response(buf, size);
271
case action_announce:
272
on_announce_response(buf, size);
275
on_scrape_response(buf, size);
281
void udp_tracker_connection::on_connect_response(char const* buf, int size)
283
// ignore packets smaller than 16 bytes
284
if (size < 16) return;
286
restart_read_timeout();
287
buf += 8; // skip header
290
m_transaction_id = 0;
292
m_connection_id = detail::read_int64(buf);
294
if (tracker_req().kind == tracker_request::announce_request)
296
else if (tracker_req().kind == tracker_request::scrape_request)
300
void udp_tracker_connection::send_udp_connect()
302
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
303
boost::shared_ptr<request_callback> cb = requester();
306
cb->debug_log("==> UDP_TRACKER_CONNECT ["
307
+ lexical_cast<std::string>(tracker_req().info_hash) + "]");
310
if (!m_socket.is_open()) return; // the operation was aborted
315
if (m_transaction_id == 0)
316
m_transaction_id = std::rand() ^ (std::rand() << 16);
318
detail::write_uint32(0x417, ptr);
319
detail::write_uint32(0x27101980, ptr); // connection_id
320
detail::write_int32(action_connect, ptr); // action (connect)
321
detail::write_int32(m_transaction_id, ptr); // transaction_id
322
TORRENT_ASSERT(ptr - buf == sizeof(buf));
325
m_socket.send(m_target, buf, 16, ec);
326
m_state = action_connect;
330
fail(-1, ec.message().c_str());
335
void udp_tracker_connection::send_udp_scrape()
337
if (m_transaction_id == 0)
338
m_transaction_id = std::rand() ^ (std::rand() << 16);
340
if (!m_socket.is_open()) return; // the operation was aborted
342
char buf[8 + 4 + 4 + 20];
345
detail::write_int64(m_connection_id, out); // connection_id
346
detail::write_int32(action_scrape, out); // action (scrape)
347
detail::write_int32(m_transaction_id, out); // transaction_id
349
std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end(), out);
351
TORRENT_ASSERT(out - buf == sizeof(buf));
354
m_socket.send(m_target, buf, sizeof(buf), ec);
355
m_state = action_scrape;
359
fail(-1, ec.message().c_str());
364
void udp_tracker_connection::on_announce_response(char const* buf, int size)
366
if (size < 20) return;
368
restart_read_timeout();
370
buf += 8; // skip header
371
restart_read_timeout();
372
int interval = detail::read_int32(buf);
373
int incomplete = detail::read_int32(buf);
374
int complete = detail::read_int32(buf);
375
int num_peers = (size - 20) / 6;
376
if ((size - 20) % 6 != 0)
378
fail(-1, "invalid udp tracker response length");
382
boost::shared_ptr<request_callback> cb = requester();
383
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
386
cb->debug_log("<== UDP_TRACKER_ANNOUNCE_RESPONSE");
392
m_man.remove_request(this);
396
std::vector<peer_entry> peer_list;
397
for (int i = 0; i < num_peers; ++i)
399
// TODO: don't use a string here
402
s << (int)detail::read_uint8(buf) << ".";
403
s << (int)detail::read_uint8(buf) << ".";
404
s << (int)detail::read_uint8(buf) << ".";
405
s << (int)detail::read_uint8(buf);
407
e.port = detail::read_uint16(buf);
409
peer_list.push_back(e);
412
cb->tracker_response(tracker_req(), peer_list, interval
413
, complete, incomplete, address());
415
m_man.remove_request(this);
419
void udp_tracker_connection::on_scrape_response(char const* buf, int size)
421
buf += 8; // skip header
423
restart_read_timeout();
424
int action = detail::read_int32(buf);
425
int transaction = detail::read_int32(buf);
427
if (transaction != m_transaction_id)
429
fail(-1, "incorrect transaction id");
433
if (action == action_error)
435
fail(-1, std::string(buf, size - 8).c_str());
439
if (action != action_scrape)
441
fail(-1, "invalid action in announce response");
447
fail(-1, "got a message with size < 20");
451
int complete = detail::read_int32(buf);
452
int downloaded = detail::read_int32(buf);
453
int incomplete = detail::read_int32(buf);
455
boost::shared_ptr<request_callback> cb = requester();
462
cb->tracker_scrape_response(tracker_req()
463
, complete, incomplete, downloaded);
465
m_man.remove_request(this);
469
void udp_tracker_connection::send_udp_announce()
471
if (m_transaction_id == 0)
472
m_transaction_id = std::rand() ^ (std::rand() << 16);
474
if (!m_socket.is_open()) return; // the operation was aborted
476
char buf[8 + 4 + 4 + 20 + 20 + 8 + 8 + 8 + 4 + 4 + 4 + 4 + 2 + 2];
479
tracker_request const& req = tracker_req();
481
detail::write_int64(m_connection_id, out); // connection_id
482
detail::write_int32(action_announce, out); // action (announce)
483
detail::write_int32(m_transaction_id, out); // transaction_id
484
std::copy(req.info_hash.begin(), req.info_hash.end(), out); // info_hash
486
std::copy(req.pid.begin(), req.pid.end(), out); // peer_id
488
detail::write_int64(req.downloaded, out); // downloaded
489
detail::write_int64(req.left, out); // left
490
detail::write_int64(req.uploaded, out); // uploaded
491
detail::write_int32(req.event, out); // event
493
if (m_settings.announce_ip != address() && m_settings.announce_ip.is_v4())
494
detail::write_uint32(m_settings.announce_ip.to_v4().to_ulong(), out);
496
detail::write_int32(0, out);
497
detail::write_int32(req.key, out); // key
498
detail::write_int32(req.num_want, out); // num_want
499
detail::write_uint16(req.listen_port, out); // port
500
detail::write_uint16(0, out); // extensions
502
TORRENT_ASSERT(out - buf == sizeof(buf));
504
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
505
boost::shared_ptr<request_callback> cb = requester();
508
cb->debug_log("==> UDP_TRACKER_ANNOUNCE ["
509
+ lexical_cast<std::string>(req.info_hash) + "]");
514
m_socket.send(m_target, buf, sizeof(buf), ec);
515
m_state = action_announce;
519
fail(-1, ec.message().c_str());