use array_view more along the udp packet paths (#655)
This commit is contained in:
parent
5576a01066
commit
5f5aa2361e
|
@ -167,6 +167,7 @@ nobase_include_HEADERS = \
|
|||
aux_/disable_warnings_push.hpp \
|
||||
aux_/disable_warnings_pop.hpp \
|
||||
aux_/escape_string.hpp \
|
||||
aux_/io.hpp \
|
||||
aux_/merkle.hpp \
|
||||
aux_/session_call.hpp \
|
||||
aux_/session_impl.hpp \
|
||||
|
|
|
@ -34,6 +34,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define TORRENT_ARRAY_VIEW_HPP_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
#include <type_traits> // for std::is_convertible
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent { namespace aux {
|
||||
|
||||
|
@ -41,17 +43,28 @@ namespace libtorrent { namespace aux {
|
|||
struct array_view
|
||||
{
|
||||
array_view() : m_ptr(NULL), m_len(0) {}
|
||||
array_view(T* p, int l) : m_ptr(p), m_len(l) {}
|
||||
|
||||
// T -> const T conversion constructor
|
||||
template <typename U, typename
|
||||
= std::enable_if<std::is_convertible<U, T>::value>
|
||||
>
|
||||
array_view(array_view<U> const& v)
|
||||
: m_ptr(v.data()), m_len(v.size()) {}
|
||||
|
||||
array_view(T* p, int l) : m_ptr(p), m_len(l)
|
||||
{
|
||||
TORRENT_ASSERT(l >= 0);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
explicit array_view(boost::array<T, N>& arr)
|
||||
array_view(boost::array<T, N>& arr)
|
||||
: m_ptr(arr.data()), m_len(arr.size()) {}
|
||||
|
||||
template <size_t N>
|
||||
explicit array_view(T (&arr)[N])
|
||||
array_view(T (&arr)[N])
|
||||
: m_ptr(&arr[0]), m_len(N) {}
|
||||
|
||||
explicit array_view(std::vector<T>& vec)
|
||||
array_view(std::vector<T>& vec)
|
||||
: m_ptr(vec.data()), m_len(vec.size()) {}
|
||||
|
||||
size_t size() const { return m_len; }
|
||||
|
@ -59,7 +72,31 @@ namespace libtorrent { namespace aux {
|
|||
T* begin() const { return m_ptr; }
|
||||
T* end() const { return m_ptr + m_len; }
|
||||
|
||||
T& operator[](int idx)
|
||||
T& front() const { TORRENT_ASSERT(m_len > 0); return m_ptr[0]; }
|
||||
T& back() const { TORRENT_ASSERT(m_len > 0); return m_ptr[m_len-1]; }
|
||||
|
||||
array_view<T> first(int const n) const
|
||||
{
|
||||
TORRENT_ASSERT(size() >= n);
|
||||
TORRENT_ASSERT(n >= 0);
|
||||
return { data(), size() - n };
|
||||
}
|
||||
|
||||
array_view<T> last(int const n) const
|
||||
{
|
||||
TORRENT_ASSERT(size() >= n);
|
||||
TORRENT_ASSERT(n >= 0);
|
||||
return { data() + size() - n, n };
|
||||
}
|
||||
|
||||
array_view<T> cut_first(int const n) const
|
||||
{
|
||||
TORRENT_ASSERT(size() >= n);
|
||||
TORRENT_ASSERT(n >= 0);
|
||||
return { data() + n, int(size()) - n };
|
||||
}
|
||||
|
||||
T& operator[](int const idx)
|
||||
{
|
||||
TORRENT_ASSERT(idx >= 0);
|
||||
TORRENT_ASSERT(idx < m_len);
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2016, Arvid Norberg
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_AUX_IO_HPP_INCLUDED
|
||||
#define TORRENT_AUX_IO_HPP_INCLUDED
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
#include <boost/cstdint.hpp>
|
||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <algorithm> // for copy
|
||||
#include "libtorrent/aux_/array_view.hpp"
|
||||
|
||||
namespace libtorrent { namespace aux
|
||||
{
|
||||
template <class T> struct type {};
|
||||
|
||||
// reads an integer from a byte stream
|
||||
// in big endian byte order and converts
|
||||
// it to native endianess
|
||||
template <class T, class Byte>
|
||||
inline typename std::enable_if<sizeof(Byte)==1, T>::type
|
||||
read_impl(array_view<Byte>& view, type<T>)
|
||||
{
|
||||
T ret = 0;
|
||||
for (int i = 0; i < int(sizeof(T)); ++i)
|
||||
{
|
||||
ret <<= 8;
|
||||
ret |= static_cast<boost::uint8_t>(view[i]);
|
||||
}
|
||||
view = view.cut_first(sizeof(T));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class T, class Byte>
|
||||
inline typename std::enable_if<sizeof(Byte)==1, void>::type
|
||||
write_impl(T val, array_view<Byte>& view)
|
||||
{
|
||||
int shift = int(sizeof(T)) * 8;
|
||||
for (int i = 0; i < int(sizeof(T)); ++i)
|
||||
{
|
||||
shift -= 8;
|
||||
view[i] = static_cast<unsigned char>((val >> shift) & 0xff);
|
||||
}
|
||||
view = view.cut_first(sizeof(T));
|
||||
}
|
||||
|
||||
// -- adaptors
|
||||
|
||||
template <typename Byte>
|
||||
boost::int64_t read_int64(array_view<Byte>& view)
|
||||
{ return read_impl(view, type<boost::int64_t>()); }
|
||||
|
||||
template <typename Byte>
|
||||
boost::uint64_t read_uint64(array_view<Byte>& view)
|
||||
{ return read_impl(view, type<boost::uint64_t>()); }
|
||||
|
||||
template <typename Byte>
|
||||
boost::uint32_t read_uint32(array_view<Byte>& view)
|
||||
{ return read_impl(view, type<boost::uint32_t>()); }
|
||||
|
||||
template <typename Byte>
|
||||
boost::int32_t read_int32(array_view<Byte>& view)
|
||||
{ return read_impl(view, type<boost::int32_t>()); }
|
||||
|
||||
template <typename Byte>
|
||||
boost::int16_t read_int16(array_view<Byte>& view)
|
||||
{ return read_impl(view, type<boost::int16_t>()); }
|
||||
|
||||
template <typename Byte>
|
||||
boost::uint16_t read_uint16(array_view<Byte>& view)
|
||||
{ return read_impl(view, type<boost::uint16_t>()); }
|
||||
|
||||
template <typename Byte>
|
||||
boost::int8_t read_int8(array_view<Byte>& view)
|
||||
{ return read_impl(view, type<boost::int8_t>()); }
|
||||
|
||||
template <typename Byte>
|
||||
boost::uint8_t read_uint8(array_view<Byte>& view)
|
||||
{ return read_impl(view, type<boost::uint8_t>()); }
|
||||
|
||||
|
||||
template <typename Byte>
|
||||
void write_uint64(boost::uint64_t val, array_view<Byte>& view)
|
||||
{ write_impl(val, view); }
|
||||
|
||||
template <typename Byte>
|
||||
void write_int64(boost::int64_t val, array_view<Byte>& view)
|
||||
{ write_impl(val, view); }
|
||||
|
||||
template <typename Byte>
|
||||
void write_uint32(boost::uint32_t val, array_view<Byte>& view)
|
||||
{ write_impl(val, view); }
|
||||
|
||||
template <typename Byte>
|
||||
void write_int32(boost::int32_t val, array_view<Byte>& view)
|
||||
{ write_impl(val, view); }
|
||||
|
||||
template <typename Byte>
|
||||
void write_uint16(boost::uint16_t val, array_view<Byte>& view)
|
||||
{ write_impl(val, view); }
|
||||
|
||||
template <typename Byte>
|
||||
void write_int16(boost::int16_t val, array_view<Byte>& view)
|
||||
{ write_impl(val, view); }
|
||||
|
||||
template <typename Byte>
|
||||
void write_uint8(boost::uint8_t val, array_view<Byte>& view)
|
||||
{ write_impl(val, view); }
|
||||
|
||||
template <typename Byte>
|
||||
void write_int8(boost::int8_t val, array_view<Byte>& view)
|
||||
{ write_impl(val, view); }
|
||||
|
||||
template<typename Byte>
|
||||
inline int write_string(std::string const& str, array_view<Byte>& view)
|
||||
{
|
||||
int const len = int(str.size());
|
||||
for (int i = 0; i < len; ++i)
|
||||
view[i] = str[i];
|
||||
|
||||
view = array_view<Byte>(view.data() + len, view.size() - len);
|
||||
return len;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // TORRENT_AUX_IO_HPP_INCLUDED
|
||||
|
|
@ -315,10 +315,6 @@ namespace libtorrent
|
|||
address const& bind_interface() const { return m_req.bind_ip; }
|
||||
void sent_bytes(int bytes);
|
||||
void received_bytes(int bytes);
|
||||
virtual bool on_receive(udp::endpoint const&
|
||||
, char const* /* buf */, int /* size */) { return false; }
|
||||
virtual bool on_receive_hostname(char const* /* hostname */
|
||||
, char const* /* buf */, int /* size */) { return false; }
|
||||
|
||||
boost::shared_ptr<tracker_connection> shared_from_this()
|
||||
{
|
||||
|
@ -378,13 +374,13 @@ namespace libtorrent
|
|||
void received_bytes(int bytes);
|
||||
|
||||
void incoming_error(error_code const& ec, udp::endpoint const& ep);
|
||||
bool incoming_packet(udp::endpoint const& ep, char const* buf, int size);
|
||||
bool incoming_packet(udp::endpoint const& ep, aux::array_view<char const> buf);
|
||||
|
||||
// this is only used for SOCKS packets, since
|
||||
// they may be addressed to hostname
|
||||
// TODO: 3 make sure the udp_socket supports passing on string-hostnames
|
||||
// too, and that this function is used
|
||||
bool incoming_packet(char const* hostname, char const* buf, int size);
|
||||
bool incoming_packet(char const* hostname, aux::array_view<char const> buf);
|
||||
|
||||
void update_transaction_id(
|
||||
boost::shared_ptr<udp_tracker_connection> c
|
||||
|
|
|
@ -94,11 +94,11 @@ namespace libtorrent
|
|||
void timeout(error_code const& error);
|
||||
void start_announce();
|
||||
|
||||
bool on_receive(udp::endpoint const& ep, char const* buf, int size);
|
||||
bool on_receive_hostname(char const* hostname, char const* buf, int size);
|
||||
bool on_connect_response(char const* buf, int size);
|
||||
bool on_announce_response(char const* buf, int size);
|
||||
bool on_scrape_response(char const* buf, int size);
|
||||
bool on_receive(udp::endpoint const& ep, aux::array_view<char const> buf);
|
||||
bool on_receive_hostname(char const* hostname, aux::array_view<char const> buf);
|
||||
bool on_connect_response(aux::array_view<char const> buf);
|
||||
bool on_announce_response(aux::array_view<char const> buf);
|
||||
bool on_scrape_response(aux::array_view<char const> buf);
|
||||
|
||||
// wraps tracker_connection::fail
|
||||
void fail(error_code const& ec, int code = -1
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace libtorrent
|
|||
~utp_socket_manager();
|
||||
|
||||
// return false if this is not a uTP packet
|
||||
bool incoming_packet(udp::endpoint const& ep, char const* p, int size);
|
||||
bool incoming_packet(udp::endpoint const& ep, aux::array_view<char const> p);
|
||||
|
||||
// if the UDP socket failed with an EAGAIN or EWOULDBLOCK, this will be
|
||||
// called once the socket is writeable again
|
||||
|
|
|
@ -173,8 +173,8 @@ void delete_utp_impl(utp_socket_impl* s);
|
|||
bool should_delete(utp_socket_impl* s);
|
||||
void tick_utp_impl(utp_socket_impl* s, time_point now);
|
||||
void utp_init_mtu(utp_socket_impl* s, int link_mtu, int utp_mtu);
|
||||
bool utp_incoming_packet(utp_socket_impl* s, char const* p
|
||||
, int size, udp::endpoint const& ep, time_point receive_time);
|
||||
bool utp_incoming_packet(utp_socket_impl* s, aux::array_view<char const> p
|
||||
, udp::endpoint const& ep, time_point receive_time);
|
||||
bool utp_match(utp_socket_impl* s, udp::endpoint const& ep, boost::uint16_t id);
|
||||
udp::endpoint utp_remote_endpoint(utp_socket_impl* s);
|
||||
boost::uint16_t utp_receive_id(utp_socket_impl* s);
|
||||
|
|
|
@ -2398,7 +2398,7 @@ namespace aux {
|
|||
{
|
||||
boost::array<udp_socket::packet, 50> p;
|
||||
error_code err;
|
||||
int const num_packets = s->read(array_view<udp_socket::packet>(p), err);
|
||||
int const num_packets = s->read(p, err);
|
||||
|
||||
for (int i = 0; i < num_packets; ++i)
|
||||
{
|
||||
|
@ -2418,26 +2418,25 @@ namespace aux {
|
|||
continue;
|
||||
}
|
||||
|
||||
char* buf = packet.data.data();
|
||||
int const len = packet.data.size();
|
||||
aux::array_view<char const> const buf = packet.data;
|
||||
|
||||
// give the uTP socket manager first dis on the packet. Presumably
|
||||
// the majority of packets are uTP packets.
|
||||
if (!mgr.incoming_packet(packet.from, buf, len))
|
||||
if (!mgr.incoming_packet(packet.from, buf))
|
||||
{
|
||||
// if it wasn't a uTP packet, try the other users of the UDP
|
||||
// socket
|
||||
bool handled = false;
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
if (m_dht && len > 20 && buf[0] == 'd' && buf[len-1] == 'e')
|
||||
if (m_dht && buf.size() > 20 && buf.front() == 'd' && buf.back() == 'e')
|
||||
{
|
||||
handled = m_dht->incoming_packet(packet.from, buf, len);
|
||||
handled = m_dht->incoming_packet(packet.from, buf.data(), buf.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
m_tracker_manager.incoming_packet(packet.from, buf, len);
|
||||
m_tracker_manager.incoming_packet(packet.from, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/http_tracker_connection.hpp"
|
||||
#include "libtorrent/udp_tracker_connection.hpp"
|
||||
#include "libtorrent/aux_/session_impl.hpp"
|
||||
#include "libtorrent/aux_/io.hpp"
|
||||
#include "libtorrent/aux_/array_view.hpp"
|
||||
|
||||
using boost::tuples::make_tuple;
|
||||
using boost::tuples::tuple;
|
||||
|
@ -118,7 +120,7 @@ namespace libtorrent
|
|||
time_point now = clock_type::now();
|
||||
time_duration receive_timeout = now - m_read_time;
|
||||
time_duration completion_timeout = now - m_start_time;
|
||||
|
||||
|
||||
if ((m_read_timeout
|
||||
&& m_read_timeout <= total_seconds(receive_timeout))
|
||||
|| (m_completion_timeout
|
||||
|
@ -312,40 +314,40 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
bool tracker_manager::incoming_packet(udp::endpoint const& ep
|
||||
, char const* buf, int size)
|
||||
, aux::array_view<char const> const buf)
|
||||
{
|
||||
// ignore packets smaller than 8 bytes
|
||||
if (size < 8)
|
||||
if (buf.size() < 8)
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
m_ses.session_log("incoming packet from %s, not a UDP tracker message "
|
||||
"(%d Bytes)", print_endpoint(ep).c_str(), size);
|
||||
"(%d Bytes)", print_endpoint(ep).c_str(), int(buf.size()));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// the first word is the action, if it's not [0, 3]
|
||||
// it's not a valid udp tracker response
|
||||
const char* ptr = buf;
|
||||
boost::uint32_t action = detail::read_uint32(ptr);
|
||||
aux::array_view<const char> ptr = buf;
|
||||
boost::uint32_t const action = aux::read_uint32(ptr);
|
||||
if (action > 3) return false;
|
||||
|
||||
boost::uint32_t transaction = detail::read_uint32(ptr);
|
||||
udp_conns_t::iterator i = m_udp_conns.find(transaction);
|
||||
boost::uint32_t const transaction = aux::read_uint32(ptr);
|
||||
udp_conns_t::iterator const i = m_udp_conns.find(transaction);
|
||||
|
||||
if (i == m_udp_conns.end())
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
m_ses.session_log("incoming UDP tracker packet from %s has invalid "
|
||||
"transaction ID (%" PRIu32 ")", print_endpoint(ep).c_str()
|
||||
"transaction ID (%x)", print_endpoint(ep).c_str()
|
||||
, transaction);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::shared_ptr<tracker_connection> p = i->second;
|
||||
boost::shared_ptr<udp_tracker_connection> const p = i->second;
|
||||
// on_receive() may remove the tracker connection from the list
|
||||
return p->on_receive(ep, buf, size);
|
||||
return p->on_receive(ep, buf);
|
||||
}
|
||||
|
||||
void tracker_manager::incoming_error(error_code const& ec
|
||||
|
@ -357,19 +359,19 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
bool tracker_manager::incoming_packet(char const* hostname
|
||||
, char const* buf, int size)
|
||||
, aux::array_view<char const> const buf)
|
||||
{
|
||||
// ignore packets smaller than 8 bytes
|
||||
if (size < 16) return false;
|
||||
if (buf.size() < 16) return false;
|
||||
|
||||
// the first word is the action, if it's not [0, 3]
|
||||
// it's not a valid udp tracker response
|
||||
const char* ptr = buf;
|
||||
boost::uint32_t action = detail::read_uint32(ptr);
|
||||
aux::array_view<const char> ptr = buf;
|
||||
boost::uint32_t const action = aux::read_uint32(ptr);
|
||||
if (action > 3) return false;
|
||||
|
||||
boost::uint32_t transaction = detail::read_uint32(ptr);
|
||||
udp_conns_t::iterator i = m_udp_conns.find(transaction);
|
||||
boost::uint32_t const transaction = aux::read_uint32(ptr);
|
||||
udp_conns_t::iterator const i = m_udp_conns.find(transaction);
|
||||
|
||||
if (i == m_udp_conns.end())
|
||||
{
|
||||
|
@ -382,9 +384,9 @@ namespace libtorrent
|
|||
return false;
|
||||
}
|
||||
|
||||
boost::shared_ptr<tracker_connection> p = i->second;
|
||||
boost::shared_ptr<udp_tracker_connection> const p = i->second;
|
||||
// on_receive() may remove the tracker connection from the list
|
||||
return p->on_receive_hostname(hostname, buf, size);
|
||||
return p->on_receive_hostname(hostname, buf);
|
||||
}
|
||||
|
||||
void tracker_manager::send_hostname(char const* hostname, int const port
|
||||
|
@ -454,7 +456,7 @@ namespace libtorrent
|
|||
(*i)->close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool tracker_manager::empty() const
|
||||
{
|
||||
mutex::scoped_lock l(m_mutex);
|
||||
|
|
|
@ -51,6 +51,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/resolver_interface.hpp"
|
||||
#include "libtorrent/ip_filter.hpp"
|
||||
#include "libtorrent/aux_/time.hpp"
|
||||
#include "libtorrent/aux_/io.hpp"
|
||||
#include "libtorrent/aux_/array_view.hpp"
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
#include "libtorrent/socket_io.hpp"
|
||||
|
@ -96,7 +98,7 @@ namespace libtorrent
|
|||
tracker_connection::fail(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
aux::session_settings const& settings = m_man.settings();
|
||||
|
||||
if (settings.get_bool(settings_pack::proxy_hostnames)
|
||||
|
@ -320,18 +322,18 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
bool udp_tracker_connection::on_receive_hostname(char const* hostname
|
||||
, char const* buf, int size)
|
||||
, aux::array_view<char const> buf)
|
||||
{
|
||||
TORRENT_UNUSED(hostname);
|
||||
// just ignore the hostname this came from, pretend that
|
||||
// it's from the same endpoint we sent it to (i.e. the same
|
||||
// port). We have so many other ways of confirming this packet
|
||||
// comes from the tracker anyway, so it's not a big deal
|
||||
return on_receive(m_target, buf, size);
|
||||
return on_receive(m_target, buf);
|
||||
}
|
||||
|
||||
bool udp_tracker_connection::on_receive(udp::endpoint const& ep
|
||||
, char const* buf, int const size)
|
||||
, aux::array_view<char const> const buf)
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
|
@ -370,15 +372,16 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (cb) cb->debug_log("<== UDP_TRACKER_PACKET [ size: %d ]", size);
|
||||
if (cb) cb->debug_log("<== UDP_TRACKER_PACKET [ size: %d ]"
|
||||
, int(buf.size()));
|
||||
#endif
|
||||
|
||||
// ignore packets smaller than 8 bytes
|
||||
if (size < 8) return false;
|
||||
if (buf.size() < 8) return false;
|
||||
|
||||
const char* ptr = buf;
|
||||
int action = detail::read_int32(ptr);
|
||||
boost::uint32_t transaction = detail::read_uint32(ptr);
|
||||
aux::array_view<const char> ptr = buf;
|
||||
int const action = read_int32(ptr);
|
||||
boost::uint32_t const transaction = read_uint32(ptr);
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (cb) cb->debug_log("*** UDP_TRACKER_PACKET [ action: %d ]", action);
|
||||
|
@ -396,7 +399,8 @@ namespace libtorrent
|
|||
|
||||
if (action == action_error)
|
||||
{
|
||||
fail(error_code(errors::tracker_failure), -1, std::string(ptr, size - 8).c_str());
|
||||
fail(error_code(errors::tracker_failure), -1
|
||||
, std::string(buf.data(), buf.size()).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -421,11 +425,11 @@ namespace libtorrent
|
|||
switch (m_state)
|
||||
{
|
||||
case action_connect:
|
||||
return on_connect_response(buf, size);
|
||||
return on_connect_response(buf);
|
||||
case action_announce:
|
||||
return on_announce_response(buf, size);
|
||||
return on_announce_response(buf);
|
||||
case action_scrape:
|
||||
return on_scrape_response(buf, size);
|
||||
return on_scrape_response(buf);
|
||||
default: break;
|
||||
}
|
||||
return false;
|
||||
|
@ -445,17 +449,19 @@ namespace libtorrent
|
|||
m_transaction_id = new_tid;
|
||||
}
|
||||
|
||||
bool udp_tracker_connection::on_connect_response(char const* buf, int size)
|
||||
bool udp_tracker_connection::on_connect_response(aux::array_view<char const> buf)
|
||||
{
|
||||
// ignore packets smaller than 16 bytes
|
||||
if (size < 16) return false;
|
||||
if (buf.size() < 16) return false;
|
||||
|
||||
restart_read_timeout();
|
||||
buf += 8; // skip header
|
||||
|
||||
// skip header
|
||||
buf = buf.cut_first(8);
|
||||
|
||||
// reset transaction
|
||||
update_transaction_id();
|
||||
boost::uint64_t connection_id = detail::read_int64(buf);
|
||||
boost::uint64_t const connection_id = read_int64(buf);
|
||||
|
||||
mutex::scoped_lock l(m_cache_mutex);
|
||||
connection_cache_entry& cce = m_connection_cache[m_target.address()];
|
||||
|
@ -484,26 +490,26 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
char buf[16];
|
||||
char* ptr = buf;
|
||||
aux::array_view<char> view = buf;
|
||||
|
||||
TORRENT_ASSERT(m_transaction_id != 0);
|
||||
|
||||
detail::write_uint32(0x417, ptr);
|
||||
detail::write_uint32(0x27101980, ptr); // connection_id
|
||||
detail::write_int32(action_connect, ptr); // action (connect)
|
||||
detail::write_int32(m_transaction_id, ptr); // transaction_id
|
||||
TORRENT_ASSERT(ptr - buf == sizeof(buf));
|
||||
aux::write_uint32(0x417, view);
|
||||
aux::write_uint32(0x27101980, view); // connection_id
|
||||
aux::write_int32(action_connect, view); // action (connect)
|
||||
aux::write_int32(m_transaction_id, view); // transaction_id
|
||||
TORRENT_ASSERT(view.size() == 0);
|
||||
|
||||
error_code ec;
|
||||
if (!m_hostname.empty())
|
||||
{
|
||||
m_man.send_hostname(m_hostname.c_str()
|
||||
, m_target.port(), aux::array_view<char const>(buf, 16), ec
|
||||
, m_target.port(), buf, ec
|
||||
, udp_socket::tracker_connection);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_man.send(m_target, aux::array_view<char const>(buf, 16), ec
|
||||
m_man.send(m_target, buf, ec
|
||||
, udp_socket::tracker_connection);
|
||||
}
|
||||
|
||||
|
@ -546,27 +552,27 @@ namespace libtorrent
|
|||
if (i == m_connection_cache.end()) return;
|
||||
|
||||
char buf[8 + 4 + 4 + 20];
|
||||
char* out = buf;
|
||||
aux::array_view<char> view = buf;
|
||||
|
||||
detail::write_int64(i->second.connection_id, out); // connection_id
|
||||
detail::write_int32(action_scrape, out); // action (scrape)
|
||||
detail::write_int32(m_transaction_id, out); // transaction_id
|
||||
aux::write_int64(i->second.connection_id, view); // connection_id
|
||||
aux::write_int32(action_scrape, view); // action (scrape)
|
||||
aux::write_int32(m_transaction_id, view); // transaction_id
|
||||
// info_hash
|
||||
std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end(), out);
|
||||
std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end()
|
||||
, view.data());
|
||||
#if defined TORRENT_DEBUG || defined TORRENT_RELEASE_ASSERTS
|
||||
out += 20;
|
||||
TORRENT_ASSERT(out - buf == sizeof(buf));
|
||||
TORRENT_ASSERT(view.size() == 20);
|
||||
#endif
|
||||
|
||||
error_code ec;
|
||||
if (!m_hostname.empty())
|
||||
{
|
||||
m_man.send_hostname(m_hostname.c_str(), m_target.port()
|
||||
, aux::array_view<char const>(buf), ec, udp_socket::tracker_connection);
|
||||
, buf, ec, udp_socket::tracker_connection);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_man.send(m_target, aux::array_view<char const>(buf), ec
|
||||
m_man.send(m_target, buf, ec
|
||||
, udp_socket::tracker_connection);
|
||||
}
|
||||
m_state = action_scrape;
|
||||
|
@ -579,21 +585,21 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
bool udp_tracker_connection::on_announce_response(char const* buf, int size)
|
||||
bool udp_tracker_connection::on_announce_response(aux::array_view<char const> buf)
|
||||
{
|
||||
if (size < 20) return false;
|
||||
if (buf.size() < 20) return false;
|
||||
|
||||
buf += 8; // skip header
|
||||
buf = buf.cut_first(8);
|
||||
restart_read_timeout();
|
||||
|
||||
tracker_response resp;
|
||||
|
||||
resp.interval = detail::read_int32(buf);
|
||||
resp.interval = aux::read_int32(buf);
|
||||
resp.min_interval = 60;
|
||||
resp.incomplete = detail::read_int32(buf);
|
||||
resp.complete = detail::read_int32(buf);
|
||||
int num_peers = (size - 20) / 6;
|
||||
if ((size - 20) % 6 != 0)
|
||||
resp.incomplete = aux::read_int32(buf);
|
||||
resp.complete = aux::read_int32(buf);
|
||||
int const num_peers = buf.size() / 6;
|
||||
if ((buf.size() % 6) != 0)
|
||||
{
|
||||
fail(error_code(errors::invalid_tracker_response_length));
|
||||
return false;
|
||||
|
@ -618,9 +624,9 @@ namespace libtorrent
|
|||
for (int i = 0; i < num_peers; ++i)
|
||||
{
|
||||
ipv4_peer_entry e;
|
||||
memcpy(&e.ip[0], buf, 4);
|
||||
buf += 4;
|
||||
e.port = detail::read_uint16(buf);
|
||||
memcpy(&e.ip[0], buf.data(), 4);
|
||||
buf = buf.cut_first(4);
|
||||
e.port = aux::read_uint16(buf);
|
||||
resp.peers4.push_back(e);
|
||||
}
|
||||
|
||||
|
@ -638,11 +644,13 @@ namespace libtorrent
|
|||
return true;
|
||||
}
|
||||
|
||||
bool udp_tracker_connection::on_scrape_response(char const* buf, int size)
|
||||
bool udp_tracker_connection::on_scrape_response(aux::array_view<char const> buf)
|
||||
{
|
||||
using namespace libtorrent::aux;
|
||||
|
||||
restart_read_timeout();
|
||||
int action = detail::read_int32(buf);
|
||||
boost::uint32_t transaction = detail::read_uint32(buf);
|
||||
int const action = aux::read_int32(buf);
|
||||
boost::uint32_t const transaction = read_uint32(buf);
|
||||
|
||||
if (transaction != m_transaction_id)
|
||||
{
|
||||
|
@ -652,7 +660,8 @@ namespace libtorrent
|
|||
|
||||
if (action == action_error)
|
||||
{
|
||||
fail(error_code(errors::tracker_failure), -1, std::string(buf, size - 8).c_str());
|
||||
fail(error_code(errors::tracker_failure), -1
|
||||
, std::string(buf.data(), buf.size()).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -662,15 +671,15 @@ namespace libtorrent
|
|||
return true;
|
||||
}
|
||||
|
||||
if (size < 20)
|
||||
if (buf.size() < 12)
|
||||
{
|
||||
fail(error_code(errors::invalid_tracker_response_length));
|
||||
return true;
|
||||
}
|
||||
|
||||
int complete = detail::read_int32(buf);
|
||||
int downloaded = detail::read_int32(buf);
|
||||
int incomplete = detail::read_int32(buf);
|
||||
int const complete = aux::read_int32(buf);
|
||||
int const downloaded = aux::read_int32(buf);
|
||||
int const incomplete = aux::read_int32(buf);
|
||||
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
if (!cb)
|
||||
|
@ -678,7 +687,7 @@ namespace libtorrent
|
|||
close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
cb->tracker_scrape_response(tracker_req()
|
||||
, complete, incomplete, downloaded, -1);
|
||||
|
||||
|
@ -691,10 +700,10 @@ namespace libtorrent
|
|||
if (m_abort) return;
|
||||
|
||||
char buf[800];
|
||||
char* out = buf;
|
||||
aux::array_view<char> out = buf;
|
||||
|
||||
tracker_request const& req = tracker_req();
|
||||
const bool stats = req.send_stats;
|
||||
bool const stats = req.send_stats;
|
||||
aux::session_settings const& settings = m_man.settings();
|
||||
|
||||
std::map<address, connection_cache_entry>::iterator i
|
||||
|
@ -703,17 +712,17 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(i != m_connection_cache.end());
|
||||
if (i == m_connection_cache.end()) return;
|
||||
|
||||
detail::write_int64(i->second.connection_id, out); // connection_id
|
||||
detail::write_int32(action_announce, out); // action (announce)
|
||||
detail::write_int32(m_transaction_id, out); // transaction_id
|
||||
std::copy(req.info_hash.begin(), req.info_hash.end(), out); // info_hash
|
||||
out += 20;
|
||||
std::copy(req.pid.begin(), req.pid.end(), out); // peer_id
|
||||
out += 20;
|
||||
detail::write_int64(stats ? req.downloaded : 0, out); // downloaded
|
||||
detail::write_int64(stats ? req.left : 0, out); // left
|
||||
detail::write_int64(stats ? req.uploaded : 0, out); // uploaded
|
||||
detail::write_int32(req.event, out); // event
|
||||
aux::write_int64(i->second.connection_id, out); // connection_id
|
||||
aux::write_int32(action_announce, out); // action (announce)
|
||||
aux::write_int32(m_transaction_id, out); // transaction_id
|
||||
std::copy(req.info_hash.begin(), req.info_hash.end(), out.data()); // info_hash
|
||||
out.cut_first(20);
|
||||
std::copy(req.pid.begin(), req.pid.end(), out.data()); // peer_id
|
||||
out.cut_first(20);
|
||||
aux::write_int64(stats ? req.downloaded : 0, out); // downloaded
|
||||
aux::write_int64(stats ? req.left : 0, out); // left
|
||||
aux::write_int64(stats ? req.uploaded : 0, out); // uploaded
|
||||
aux::write_int32(req.event, out); // event
|
||||
// ip address
|
||||
address_v4 announce_ip;
|
||||
|
||||
|
@ -724,10 +733,10 @@ namespace libtorrent
|
|||
address ip = address::from_string(settings.get_str(settings_pack::announce_ip).c_str(), ec);
|
||||
if (!ec && ip.is_v4()) announce_ip = ip.to_v4();
|
||||
}
|
||||
detail::write_uint32(announce_ip.to_ulong(), out);
|
||||
detail::write_int32(req.key, out); // key
|
||||
detail::write_int32(req.num_want, out); // num_want
|
||||
detail::write_uint16(req.listen_port, out); // port
|
||||
aux::write_uint32(announce_ip.to_ulong(), out);
|
||||
aux::write_int32(req.key, out); // key
|
||||
aux::write_int32(req.num_want, out); // num_want
|
||||
aux::write_uint16(req.listen_port, out); // port
|
||||
|
||||
std::string request_string;
|
||||
error_code ec;
|
||||
|
@ -741,13 +750,11 @@ namespace libtorrent
|
|||
int str_len = (std::min)(int(request_string.size()), 255);
|
||||
request_string.resize(str_len);
|
||||
|
||||
detail::write_uint8(2, out);
|
||||
detail::write_uint8(str_len, out);
|
||||
detail::write_string(request_string, out);
|
||||
aux::write_uint8(2, out);
|
||||
aux::write_uint8(str_len, out);
|
||||
aux::write_string(request_string, out);
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(out - buf <= int(sizeof(buf)));
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
if (cb)
|
||||
|
@ -761,16 +768,16 @@ namespace libtorrent
|
|||
if (!m_hostname.empty())
|
||||
{
|
||||
m_man.send_hostname(m_hostname.c_str()
|
||||
, m_target.port(), aux::array_view<char const>(buf, out - buf), ec
|
||||
, m_target.port(), aux::array_view<char const>(buf, sizeof(buf) - out.size()), ec
|
||||
, udp_socket::tracker_connection);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_man.send(m_target, aux::array_view<char const>(buf, out - buf), ec
|
||||
m_man.send(m_target, aux::array_view<char const>(buf, sizeof(buf) - out.size()), ec
|
||||
, udp_socket::tracker_connection);
|
||||
}
|
||||
m_state = action_announce;
|
||||
sent_bytes(out - buf + 28); // assuming UDP/IP header
|
||||
sent_bytes(sizeof(buf) - out.size() + 28); // assuming UDP/IP header
|
||||
++m_attempts;
|
||||
if (ec)
|
||||
{
|
||||
|
|
|
@ -163,13 +163,13 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
bool utp_socket_manager::incoming_packet(udp::endpoint const& ep
|
||||
, char const* p, int const size)
|
||||
, aux::array_view<char const> p)
|
||||
{
|
||||
// UTP_LOGV("incoming packet size:%d\n", size);
|
||||
|
||||
if (size < int(sizeof(utp_header))) return false;
|
||||
if (p.size() < int(sizeof(utp_header))) return false;
|
||||
|
||||
utp_header const* ph = reinterpret_cast<utp_header const*>(p);
|
||||
utp_header const* ph = reinterpret_cast<utp_header const*>(p.data());
|
||||
|
||||
// UTP_LOGV("incoming packet version:%d\n", int(ph->get_version()));
|
||||
|
||||
|
@ -186,7 +186,7 @@ namespace libtorrent
|
|||
if (m_last_socket
|
||||
&& utp_match(m_last_socket, ep, id))
|
||||
{
|
||||
return utp_incoming_packet(m_last_socket, p, size, ep, receive_time);
|
||||
return utp_incoming_packet(m_last_socket, p, ep, receive_time);
|
||||
}
|
||||
|
||||
std::pair<socket_map_t::iterator, socket_map_t::iterator> r =
|
||||
|
@ -195,7 +195,7 @@ namespace libtorrent
|
|||
for (; r.first != r.second; ++r.first)
|
||||
{
|
||||
if (!utp_match(r.first->second, ep, id)) continue;
|
||||
bool ret = utp_incoming_packet(r.first->second, p, size, ep, receive_time);
|
||||
bool ret = utp_incoming_packet(r.first->second, p, ep, receive_time);
|
||||
if (ret) m_last_socket = r.first->second;
|
||||
return ret;
|
||||
}
|
||||
|
@ -225,7 +225,6 @@ namespace libtorrent
|
|||
instantiate_connection(m_ios, aux::proxy_settings(), *c
|
||||
, m_ssl_context, this, true, false);
|
||||
|
||||
|
||||
utp_stream* str = NULL;
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
if (is_ssl(*c))
|
||||
|
@ -238,7 +237,7 @@ namespace libtorrent
|
|||
int link_mtu, utp_mtu;
|
||||
mtu_for_dest(ep.address(), link_mtu, utp_mtu);
|
||||
utp_init_mtu(str->get_impl(), link_mtu, utp_mtu);
|
||||
bool ret = utp_incoming_packet(str->get_impl(), p, size, ep, receive_time);
|
||||
bool ret = utp_incoming_packet(str->get_impl(), p, ep, receive_time);
|
||||
if (!ret) return false;
|
||||
m_cb(c);
|
||||
// the connection most likely changed its connection ID here
|
||||
|
|
|
@ -325,7 +325,7 @@ struct utp_socket_impl
|
|||
|
||||
void tick(time_point now);
|
||||
void init_mtu(int link_mtu, int utp_mtu);
|
||||
bool incoming_packet(boost::uint8_t const* buf, int size
|
||||
bool incoming_packet(aux::array_view<boost::uint8_t const> buf
|
||||
, udp::endpoint const& ep, time_point receive_time);
|
||||
void writable();
|
||||
|
||||
|
@ -745,10 +745,12 @@ void utp_init_mtu(utp_socket_impl* s, int link_mtu, int utp_mtu)
|
|||
s->init_mtu(link_mtu, utp_mtu);
|
||||
}
|
||||
|
||||
bool utp_incoming_packet(utp_socket_impl* s, char const* p
|
||||
, int size, udp::endpoint const& ep, time_point receive_time)
|
||||
bool utp_incoming_packet(utp_socket_impl* s
|
||||
, aux::array_view<char const> p
|
||||
, udp::endpoint const& ep, time_point receive_time)
|
||||
{
|
||||
return s->incoming_packet(reinterpret_cast<boost::uint8_t const*>(p), size
|
||||
return s->incoming_packet(
|
||||
aux::array_view<boost::uint8_t const>(reinterpret_cast<boost::uint8_t const*>(p.data()), p.size())
|
||||
, ep, receive_time);
|
||||
}
|
||||
|
||||
|
@ -2697,12 +2699,12 @@ void utp_socket_impl::init_mtu(int link_mtu, int utp_mtu)
|
|||
}
|
||||
|
||||
// return false if this is an invalid packet
|
||||
bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||
bool utp_socket_impl::incoming_packet(aux::array_view<boost::uint8_t const> buf
|
||||
, udp::endpoint const& ep, time_point receive_time)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
utp_header const* ph = reinterpret_cast<utp_header const*>(buf);
|
||||
utp_header const* ph = reinterpret_cast<utp_header const*>(buf.data());
|
||||
|
||||
m_sm->inc_stats_counter(counters::utp_packets_in);
|
||||
|
||||
|
@ -2944,7 +2946,8 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||
}
|
||||
|
||||
// look for extended headers
|
||||
boost::uint8_t const* ptr = buf;
|
||||
boost::uint8_t const* ptr = buf.data();
|
||||
int const size = buf.size();
|
||||
ptr += sizeof(utp_header);
|
||||
|
||||
unsigned int extension = ph->extension;
|
||||
|
@ -2952,7 +2955,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||
{
|
||||
// invalid packet. It says it has an extension header
|
||||
// but the packet is too short
|
||||
if (ptr - buf + 2 > size)
|
||||
if (ptr - buf.data() + 2 > size)
|
||||
{
|
||||
UTP_LOG("%8p: ERROR: invalid extension header\n", static_cast<void*>(this));
|
||||
m_sm->inc_stats_counter(counters::utp_invalid_pkts_in);
|
||||
|
@ -2963,14 +2966,14 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||
if (len < 0)
|
||||
{
|
||||
UTP_LOGV("%8p: invalid extension length:%d packet:%d\n"
|
||||
, static_cast<void*>(this), len, int(ptr - buf));
|
||||
, static_cast<void*>(this), len, int(ptr - buf.data()));
|
||||
m_sm->inc_stats_counter(counters::utp_invalid_pkts_in);
|
||||
return true;
|
||||
}
|
||||
if (ptr - buf + len > ptrdiff_t(size))
|
||||
if (ptr - buf.data() + len > ptrdiff_t(size))
|
||||
{
|
||||
UTP_LOG("%8p: ERROR: invalid extension header size:%d packet:%d\n"
|
||||
, static_cast<void*>(this), len, int(ptr - buf));
|
||||
, static_cast<void*>(this), len, int(ptr - buf.data()));
|
||||
m_sm->inc_stats_counter(counters::utp_invalid_pkts_in);
|
||||
return true;
|
||||
}
|
||||
|
@ -3017,7 +3020,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||
// ptr points to the payload of the packet
|
||||
// size is the packet size, payload is the
|
||||
// number of payload bytes are in this packet
|
||||
const int header_size = ptr - buf;
|
||||
const int header_size = ptr - buf.data();
|
||||
const int payload_size = size - header_size;
|
||||
|
||||
#if TORRENT_UTP_LOG
|
||||
|
|
Loading…
Reference in New Issue