From 43e9270363eb04ebeae7bc01b39e0401d5643007 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 23 Aug 2012 21:02:09 +0000 Subject: [PATCH] extend the UDP tracker protocol to include the request string from the tracker URL --- ChangeLog | 1 + docs/udp_tracker_protocol.rst | 35 ++++++++++++++++++++++++++++++++-- src/udp_tracker_connection.cpp | 28 ++++++++++++++++++++------- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3e8363e94..19a630237 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ * fix uTP edge case where udp socket buffer fills up * fix nagle implementation in uTP + * extend the UDP tracker protocol to include the request string from the tracker URL * fix mingw build for linux crosscompiler 0.16.3 release diff --git a/docs/udp_tracker_protocol.rst b/docs/udp_tracker_protocol.rst index d9fcbee82..07db7686d 100644 --- a/docs/udp_tracker_protocol.rst +++ b/docs/udp_tracker_protocol.rst @@ -255,8 +255,13 @@ The extensions field is a bitmask. The following bits are assigned: * 1 = authentication_. + * 2 = `request string`_. - +If multiple bits are present in the extension field, the extension +bodies are appended to the packet in the order of least significant +bit first. For instance, if both bit 1 and 2 are set, the extension +represented by bit 1 comes first, followed by the extension represented +by bit 2. authentication ~~~~~~~~~~~~~~ @@ -281,9 +286,35 @@ appended to it. It has the following format: | | | from the 20 bytes hash calculated. | +-------------+---------------------+----------------------------------------+ +request string +-------------- + +The request string extension is meant to allow torrent creators pass along +cookies back to the tracker. This can be useful for authenticating that a +torrent is allowed to be tracked by a tracker for instance. It could also +be used to authenticate users by generating torrents with unique tokens +in the tracker URL for each user. The extension body has the following format: + ++-------------+---------------------+----------------------------------------+ +| size | name | description | ++=============+=====================+========================================+ +| int16_t | request length | The number of bytes in the request | +| | | string. | ++-------------+---------------------+----------------------------------------+ +| int8_t[] | request string | The string that comes after the host- | +| | | name and port in the udp tracker URL. | +| | | Typically this starts with "/announce" | +| | | The bittorrent client is not expected | +| | | to append query string arguments for | +| | | stats reporting, like "uploaded" and | +| | | "downloaded" since this is already | +| | | reported in the udp tracker protocol. | +| | | However, the client is free to add | +| | | arguments as extensions. | ++-------------+---------------------+----------------------------------------+ credits ------- -Protocol designed by Olaf van der Spek +Protocol designed by Olaf van der Spek and extended by Arvid Norberg diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index 250904fdd..4c666be45 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include +#include #ifdef _MSC_VER #pragma warning(pop) @@ -599,7 +600,7 @@ namespace libtorrent if (m_abort) return; - char buf[8 + 4 + 4 + 20 + 20 + 8 + 8 + 8 + 4 + 4 + 4 + 4 + 2 + 2]; + char buf[800]; char* out = buf; tracker_request const& req = tracker_req(); @@ -636,9 +637,23 @@ namespace libtorrent detail::write_int32(req.key, out); // key detail::write_int32(req.num_want, out); // num_want detail::write_uint16(req.listen_port, out); // port - detail::write_uint16(0, out); // extensions - TORRENT_ASSERT(out - buf == sizeof(buf)); + std::string request_string; + error_code ec; + using boost::tuples::ignore; + boost::tie(ignore, ignore, ignore, ignore, request_string) = parse_url_components(req.url, ec); + if (ec) request_string.clear(); + + detail::write_uint16(request_string.empty() ? 0: 2, out); // extensions. 2 = request-string + + if (!request_string.empty()) + { + if (request_string.size() > 512) request_string.resize(512); + detail::write_uint16(request_string.size(), out); + detail::write_string(request_string, out); + } + + TORRENT_ASSERT(out - buf <= sizeof(buf)); #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING boost::shared_ptr cb = requester(); @@ -652,17 +667,16 @@ namespace libtorrent } #endif - error_code ec; if (!m_hostname.empty()) { - m_ses.m_udp_socket.send_hostname(m_hostname.c_str(), m_target.port(), buf, sizeof(buf), ec); + m_ses.m_udp_socket.send_hostname(m_hostname.c_str(), m_target.port(), buf, out - buf, ec); } else { - m_ses.m_udp_socket.send(m_target, buf, sizeof(buf), ec); + m_ses.m_udp_socket.send(m_target, buf, out - buf, ec); } m_state = action_announce; - sent_bytes(sizeof(buf) + 28); // assuming UDP/IP header + sent_bytes(out - buf + 28); // assuming UDP/IP header ++m_attempts; if (ec) {