use array_view more along the udp packet paths (#655)

This commit is contained in:
Arvid Norberg 2016-04-28 08:20:10 -04:00
parent 5576a01066
commit 5f5aa2361e
12 changed files with 347 additions and 144 deletions

View File

@ -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 \

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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)
{

View File

@ -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

View File

@ -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