lt tracker request url ampersand fix, endpoint to string conversion fix. 1602

This commit is contained in:
Marcos Pinto 2007-09-23 23:45:41 +00:00
commit 44240b194e
6 changed files with 172 additions and 415 deletions

View file

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2003 - 2005, Arvid Norberg, Daniel Wallin Copyright (c) 2007, Arvid Norberg
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -32,9 +32,8 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef LIBTORRENT_BUFFER_HPP #ifndef LIBTORRENT_BUFFER_HPP
#define LIBTORRENT_BUFFER_HPP #define LIBTORRENT_BUFFER_HPP
//#define TORRENT_BUFFER_DEBUG
#include <memory> #include <memory>
#include <cstring>
#include "libtorrent/invariant_check.hpp" #include "libtorrent/invariant_check.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
@ -43,410 +42,157 @@ namespace libtorrent {
class buffer class buffer
{ {
public: public:
struct interval struct interval
{ {
interval(char* begin, char* end) interval(char* begin, char* end)
: begin(begin) : begin(begin)
, end(end) , end(end)
{} {}
char operator[](int index) const char operator[](int index) const
{ {
assert(begin + index < end); assert(begin + index < end);
return begin[index]; return begin[index];
} }
int left() const { assert(end >= begin); return end - begin; } int left() const { assert(end >= begin); return end - begin; }
char* begin; char* begin;
char* end; char* end;
}; };
struct const_interval struct const_interval
{ {
const_interval(char const* begin, char const* end) const_interval(char const* begin, char const* end)
: begin(begin) : begin(begin)
, end(end) , end(end)
{} {}
char operator[](int index) const char operator[](int index) const
{ {
assert(begin + index < end); assert(begin + index < end);
return begin[index]; return begin[index];
} }
bool operator==(const const_interval& p_interval) bool operator==(const const_interval& p_interval)
{ {
return (begin == p_interval.begin return (begin == p_interval.begin
&& end == p_interval.end); && end == p_interval.end);
} }
int left() const { assert(end >= begin); return end - begin; } int left() const { assert(end >= begin); return end - begin; }
char const* begin; char const* begin;
char const* end; char const* end;
}; };
typedef std::pair<const_interval, const_interval> interval_type; buffer(std::size_t n = 0)
: m_begin(0)
, m_end(0)
, m_last(0)
{
if (n) resize(n);
}
buffer(std::size_t n = 0); buffer(buffer const& b)
~buffer(); : m_begin(0)
, m_end(0)
, m_last(0)
{
if (b.size() == 0) return;
resize(b.size());
std::memcpy(m_begin, b.begin(), b.size());
}
interval allocate(std::size_t n); buffer& operator=(buffer const& b)
void insert(char const* first, char const* last); {
void erase(std::size_t n); resize(b.size());
std::size_t size() const; std::memcpy(m_begin, b.begin(), b.size());
std::size_t capacity() const; return *this;
void reserve(std::size_t n); }
interval_type data() const;
bool empty() const;
std::size_t space_left() const; ~buffer()
{
::operator delete (m_begin);
}
char const* raw_data() const buffer::interval data() { return interval(m_begin, m_end); }
{ buffer::const_interval data() const { return const_interval(m_begin, m_end); }
return m_first;
} void resize(std::size_t n)
{
reserve(n);
m_end = m_begin + n;
}
#ifndef NDEBUG void insert(char* point, char const* first, char const* last)
void check_invariant() const; {
#endif std::size_t p = point - m_begin;
if (point == m_end)
{
resize(size() + last - first);
std::memcpy(m_begin + p, first, last - first);
return;
}
resize(size() + last - first);
std::memmove(m_begin + p + (last - first), m_begin + p, last - first);
std::memcpy(m_begin + p, first, last - first);
}
void erase(char* begin, char* end)
{
assert(end <= m_end);
assert(begin >= m_begin);
assert(begin <= end);
if (end == m_end)
{
resize(begin - m_begin);
return;
}
std::memmove(begin, end, m_end - end);
m_end = begin + (m_end - end);
}
void clear() { m_end = m_begin; }
std::size_t size() const { return m_end - m_begin; }
std::size_t capacity() const { return m_last - m_begin; }
void reserve(std::size_t n)
{
if (n <= capacity()) return;
assert(n > 0);
char* buf = (char*)::operator new(n);
std::size_t s = size();
std::memcpy(buf, m_begin, s);
::operator delete (m_begin);
m_begin = buf;
m_end = buf + s;
m_last = m_begin + n;
}
bool empty() const { return m_begin == m_end; }
char& operator[](std::size_t i) { assert(i >= 0 && i < size()); return m_begin[i]; }
char const& operator[](std::size_t i) const { assert(i >= 0 && i < size()); return m_begin[i]; }
char* begin() { return m_begin; }
char const* begin() const { return m_begin; }
char* end() { return m_end; }
char const* end() const { return m_end; }
void swap(buffer& b)
{
using std::swap;
swap(m_begin, b.m_begin);
swap(m_end, b.m_end);
swap(m_last, b.m_last);
}
private: private:
char* m_first; char* m_begin; // first
char* m_last; char* m_end; // one passed end of size
char* m_write_cursor; char* m_last; // one passed end of allocation
char* m_read_cursor;
char* m_read_end;
bool m_empty;
#ifdef TORRENT_BUFFER_DEBUG
mutable std::vector<char> m_debug;
mutable int m_pending_copy;
#endif
}; };
inline buffer::buffer(std::size_t n)
: m_first((char*)::operator new(n))
, m_last(m_first + n)
, m_write_cursor(m_first)
, m_read_cursor(m_first)
, m_read_end(m_last)
, m_empty(true)
{
#ifdef TORRENT_BUFFER_DEBUG
m_pending_copy = 0;
#endif
}
inline buffer::~buffer()
{
::operator delete (m_first);
}
inline buffer::interval buffer::allocate(std::size_t n)
{
assert(m_read_cursor <= m_read_end || m_empty);
INVARIANT_CHECK;
#ifdef TORRENT_BUFFER_DEBUG
if (m_pending_copy)
{
std::copy(m_write_cursor - m_pending_copy, m_write_cursor
, m_debug.end() - m_pending_copy);
m_pending_copy = 0;
}
m_debug.resize(m_debug.size() + n);
m_pending_copy = n;
#endif
if (m_read_cursor < m_write_cursor || m_empty)
{
// ..R***W..
if (m_last - m_write_cursor >= (std::ptrdiff_t)n)
{
interval ret(m_write_cursor, m_write_cursor + n);
m_write_cursor += n;
m_read_end = m_write_cursor;
assert(m_read_cursor <= m_read_end);
if (n) m_empty = false;
return ret;
}
if (m_read_cursor - m_first >= (std::ptrdiff_t)n)
{
m_read_end = m_write_cursor;
interval ret(m_first, m_first + n);
m_write_cursor = m_first + n;
assert(m_read_cursor <= m_read_end);
if (n) m_empty = false;
return ret;
}
reserve(capacity() + n - (m_last - m_write_cursor));
assert(m_last - m_write_cursor >= (std::ptrdiff_t)n);
interval ret(m_write_cursor, m_write_cursor + n);
m_write_cursor += n;
m_read_end = m_write_cursor;
if (n) m_empty = false;
assert(m_read_cursor <= m_read_end);
return ret;
}
//**W...R**
if (m_read_cursor - m_write_cursor >= (std::ptrdiff_t)n)
{
interval ret(m_write_cursor, m_write_cursor + n);
m_write_cursor += n;
if (n) m_empty = false;
return ret;
}
reserve(capacity() + n - (m_read_cursor - m_write_cursor));
assert(m_read_cursor - m_write_cursor >= (std::ptrdiff_t)n);
interval ret(m_write_cursor, m_write_cursor + n);
m_write_cursor += n;
if (n) m_empty = false;
return ret;
}
inline void buffer::insert(char const* first, char const* last)
{
INVARIANT_CHECK;
std::size_t n = last - first;
#ifdef TORRENT_BUFFER_DEBUG
if (m_pending_copy)
{
std::copy(m_write_cursor - m_pending_copy, m_write_cursor
, m_debug.end() - m_pending_copy);
m_pending_copy = 0;
}
m_debug.insert(m_debug.end(), first, last);
#endif
if (space_left() < n)
{
reserve(capacity() + n);
}
m_empty = false;
char const* end = (m_last - m_write_cursor) < (std::ptrdiff_t)n ?
m_last : m_write_cursor + n;
std::size_t copied = end - m_write_cursor;
std::memcpy(m_write_cursor, first, copied);
m_write_cursor += copied;
if (m_write_cursor > m_read_end) m_read_end = m_write_cursor;
first += copied;
n -= copied;
if (n == 0) return;
assert(m_write_cursor == m_last);
m_write_cursor = m_first;
memcpy(m_write_cursor, first, n);
m_write_cursor += n;
}
inline void buffer::erase(std::size_t n)
{
INVARIANT_CHECK;
if (n == 0) return;
assert(!m_empty);
#ifndef NDEBUG
int prev_size = size();
#endif
assert(m_read_cursor <= m_read_end);
m_read_cursor += n;
if (m_read_cursor > m_read_end)
{
m_read_cursor = m_first + (m_read_cursor - m_read_end);
assert(m_read_cursor <= m_write_cursor);
}
m_empty = m_read_cursor == m_write_cursor;
assert(prev_size - n == size());
#ifdef TORRENT_BUFFER_DEBUG
m_debug.erase(m_debug.begin(), m_debug.begin() + n);
#endif
}
inline std::size_t buffer::size() const
{
// ...R***W.
if (m_read_cursor < m_write_cursor)
{
return m_write_cursor - m_read_cursor;
}
// ***W..R*
else
{
if (m_empty) return 0;
return (m_write_cursor - m_first) + (m_read_end - m_read_cursor);
}
}
inline std::size_t buffer::capacity() const
{
return m_last - m_first;
}
inline void buffer::reserve(std::size_t size)
{
std::size_t n = (std::size_t)(capacity() * 1.f);
if (n < size) n = size;
char* buf = (char*)::operator new(n);
char* old = m_first;
if (m_read_cursor < m_write_cursor)
{
// ...R***W.<>.
std::memcpy(
buf + (m_read_cursor - m_first)
, m_read_cursor
, m_write_cursor - m_read_cursor
);
m_write_cursor = buf + (m_write_cursor - m_first);
m_read_cursor = buf + (m_read_cursor - m_first);
m_read_end = m_write_cursor;
m_first = buf;
m_last = buf + n;
}
else
{
// **W..<>.R**
std::size_t skip = n - (m_last - m_first);
std::memcpy(buf, m_first, m_write_cursor - m_first);
std::memcpy(
buf + (m_read_cursor - m_first) + skip
, m_read_cursor
, m_last - m_read_cursor
);
m_write_cursor = buf + (m_write_cursor - m_first);
if (!m_empty)
{
m_read_cursor = buf + (m_read_cursor - m_first) + skip;
m_read_end = buf + (m_read_end - m_first) + skip;
}
else
{
m_read_cursor = m_write_cursor;
m_read_end = m_write_cursor;
}
m_first = buf;
m_last = buf + n;
}
::operator delete (old);
}
#ifndef NDEBUG
inline void buffer::check_invariant() const
{
assert(m_read_end >= m_read_cursor);
assert(m_last >= m_read_cursor);
assert(m_last >= m_write_cursor);
assert(m_last >= m_first);
assert(m_first <= m_read_cursor);
assert(m_first <= m_write_cursor);
#ifdef TORRENT_BUFFER_DEBUG
int a = m_debug.size();
int b = size();
(void)a;
(void)b;
assert(m_debug.size() == size());
#endif
}
#endif
inline buffer::interval_type buffer::data() const
{
INVARIANT_CHECK;
#ifdef TORRENT_BUFFER_DEBUG
if (m_pending_copy)
{
std::copy(m_write_cursor - m_pending_copy, m_write_cursor
, m_debug.end() - m_pending_copy);
m_pending_copy = 0;
}
#endif
// ...R***W.
if (m_read_cursor < m_write_cursor)
{
#ifdef TORRENT_BUFFER_DEBUG
assert(m_debug.size() == size());
assert(std::equal(m_debug.begin(), m_debug.end(), m_read_cursor));
#endif
return interval_type(
const_interval(m_read_cursor, m_write_cursor)
, const_interval(m_last, m_last)
);
}
// **W...R**
else
{
if (m_read_cursor == m_read_end)
{
#ifdef TORRENT_BUFFER_DEBUG
assert(m_debug.size() == size());
assert(std::equal(m_debug.begin(), m_debug.end(), m_first));
#endif
return interval_type(
const_interval(m_first, m_write_cursor)
, const_interval(m_last, m_last));
}
#ifdef TORRENT_BUFFER_DEBUG
assert(m_debug.size() == size());
assert(std::equal(m_debug.begin(), m_debug.begin() + (m_read_end
- m_read_cursor), m_read_cursor));
assert(std::equal(m_debug.begin() + (m_read_end - m_read_cursor), m_debug.end()
, m_first));
#endif
assert(m_read_cursor <= m_read_end || m_empty);
return interval_type(
const_interval(m_read_cursor, m_read_end)
, const_interval(m_first, m_write_cursor)
);
}
}
inline bool buffer::empty() const
{
return m_empty;
}
inline std::size_t buffer::space_left() const
{
if (m_empty) return m_last - m_first;
// ...R***W.
if (m_read_cursor < m_write_cursor)
{
return (m_last - m_write_cursor) + (m_read_cursor - m_first);
}
// ***W..R*
else
{
return m_read_cursor - m_write_cursor;
}
}
} }

View file

@ -510,7 +510,7 @@ namespace libtorrent
int m_packet_size; int m_packet_size;
int m_recv_pos; int m_recv_pos;
std::vector<char> m_recv_buffer; buffer m_recv_buffer;
// this is the buffer where data that is // this is the buffer where data that is
// to be sent is stored until it gets // to be sent is stored until it gets
@ -521,7 +521,7 @@ namespace libtorrent
// waiting for a async_write operation on one // waiting for a async_write operation on one
// buffer, the other is used to write data to // buffer, the other is used to write data to
// be queued up. // be queued up.
std::vector<char> m_send_buffer[2]; buffer m_send_buffer[2];
// the current send buffer is the one to write to. // the current send buffer is the one to write to.
// (m_current_send_buffer + 1) % 2 is the // (m_current_send_buffer + 1) % 2 is the
// buffer we're currently waiting for. // buffer we're currently waiting for.

View file

@ -98,13 +98,18 @@ namespace libtorrent
typedef asio::basic_deadline_timer<libtorrent::ptime> deadline_timer; typedef asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;
inline std::ostream& operator<<(std::ostream& os, tcp::endpoint const& ep) inline std::ostream& print_endpoint(std::ostream& os, tcp::endpoint const& ep)
{ {
address const& a = ep.address(); address const& addr = ep.address();
if (a.is_v6()) asio::error_code ec;
os << "[" << a.to_string() << "]:" << ep.port(); std::string a = addr.to_string(ec);
if (ec) return os;
if (addr.is_v6())
os << "[" << a << "]:";
else else
os << a.to_string() << ":" << ep.port(); os << a << ":";
os << ep.port();
return os; return os;
} }

View file

@ -432,6 +432,7 @@ namespace libtorrent
{ {
m_send_buffer += "ipv6="; m_send_buffer += "ipv6=";
m_send_buffer += req.ipv6; m_send_buffer += req.ipv6;
m_send_buffer += '&';
} }
// extension that tells the tracker that // extension that tells the tracker that

View file

@ -2082,7 +2082,8 @@ namespace libtorrent
p.remote_dl_rate = 0; p.remote_dl_rate = 0;
} }
p.send_buffer_size = send_buffer_size(); p.send_buffer_size = int(m_send_buffer[0].capacity()
+ m_send_buffer[1].capacity());
} }
void peer_connection::cut_receive_buffer(int size, int packet_size) void peer_connection::cut_receive_buffer(int size, int packet_size)
@ -2512,7 +2513,7 @@ namespace libtorrent
void peer_connection::send_buffer(char const* begin, char const* end) void peer_connection::send_buffer(char const* begin, char const* end)
{ {
std::vector<char>& buf = m_send_buffer[m_current_send_buffer]; buffer& buf = m_send_buffer[m_current_send_buffer];
buf.insert(buf.end(), begin, end); buf.insert(buf.end(), begin, end);
setup_send(); setup_send();
} }
@ -2521,7 +2522,7 @@ namespace libtorrent
// return value is destructed // return value is destructed
buffer::interval peer_connection::allocate_send_buffer(int size) buffer::interval peer_connection::allocate_send_buffer(int size)
{ {
std::vector<char>& buf = m_send_buffer[m_current_send_buffer]; buffer& buf = m_send_buffer[m_current_send_buffer];
buf.resize(buf.size() + size); buf.resize(buf.size() + size);
buffer::interval ret(&buf[0] + buf.size() - size, &buf[0] + buf.size()); buffer::interval ret(&buf[0] + buf.size() - size, &buf[0] + buf.size());
return ret; return ret;
@ -2588,7 +2589,7 @@ namespace libtorrent
&& m_recv_pos == 0 && m_recv_pos == 0
&& (m_recv_buffer.capacity() - m_packet_size) > 128) && (m_recv_buffer.capacity() - m_packet_size) > 128)
{ {
std::vector<char>(m_packet_size).swap(m_recv_buffer); buffer(m_packet_size).swap(m_recv_buffer);
} }
int max_receive = m_packet_size - m_recv_pos; int max_receive = m_packet_size - m_recv_pos;
@ -2807,7 +2808,7 @@ namespace libtorrent
if (int(m_send_buffer[i].size()) < 64 if (int(m_send_buffer[i].size()) < 64
&& int(m_send_buffer[i].capacity()) > 128) && int(m_send_buffer[i].capacity()) > 128)
{ {
std::vector<char> tmp(m_send_buffer[i]); buffer tmp(m_send_buffer[i]);
tmp.swap(m_send_buffer[i]); tmp.swap(m_send_buffer[i]);
assert(m_send_buffer[i].capacity() == m_send_buffer[i].size()); assert(m_send_buffer[i].capacity() == m_send_buffer[i].size());
} }

View file

@ -695,14 +695,16 @@ namespace detail
// not even that worked, give up // not even that worked, give up
if (m_alerts.should_post(alert::fatal)) if (m_alerts.should_post(alert::fatal))
{ {
std::string msg = "cannot bind to the given interface '" std::stringstream msg;
+ boost::lexical_cast<std::string>(ep) + "' " + ec.message(); msg << "cannot bind to interface '";
m_alerts.post_alert(listen_failed_alert(ep, msg)); print_endpoint(msg, ep) << "' " << ec.message();
m_alerts.post_alert(listen_failed_alert(ep, msg.str()));
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
std::string msg = "cannot bind to the given interface '" std::stringstream msg;
+ boost::lexical_cast<std::string>(ep) + "' " + ec.message(); msg << "cannot bind to interface '";
(*m_logger) << msg << "\n"; print_endpoint(msg, ep) << "' " << ec.message();
(*m_logger) << msg.str() << "\n";
#endif #endif
return listen_socket_t(); return listen_socket_t();
} }
@ -712,14 +714,16 @@ namespace detail
{ {
if (m_alerts.should_post(alert::fatal)) if (m_alerts.should_post(alert::fatal))
{ {
std::string msg = "cannot listen the given interface '" std::stringstream msg;
+ boost::lexical_cast<std::string>(ep) + "' " + ec.message(); msg << "cannot listen on interface '";
m_alerts.post_alert(listen_failed_alert(ep, msg)); print_endpoint(msg, ep) << "' " << ec.message();
m_alerts.post_alert(listen_failed_alert(ep, msg.str()));
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
std::string msg = "cannot listen the given interface '" std::stringstream msg;
+ boost::lexical_cast<std::string>(ep) + "' " + ec.message(); msg << "cannot listen on interface '";
(*m_logger) << msg << "\n"; print_endpoint(msg, ep) << "' " << ec.message();
(*m_logger) << msg.str() << "\n";
#endif #endif
return listen_socket_t(); return listen_socket_t();
} }
@ -732,7 +736,7 @@ namespace detail
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << "listening on: " << ep.address().to_string() << ":" << ep.port() (*m_logger) << "listening on: " << ep
<< " external port: " << s.external_port << "\n"; << " external port: " << s.external_port << "\n";
#endif #endif
return s; return s;