libtorrent sync 1605
This commit is contained in:
parent
cf116cf3a1
commit
280eed95b6
|
@ -328,14 +328,33 @@ namespace libtorrent
|
||||||
struct TORRENT_EXPORT listen_failed_alert: alert
|
struct TORRENT_EXPORT listen_failed_alert: alert
|
||||||
{
|
{
|
||||||
listen_failed_alert(
|
listen_failed_alert(
|
||||||
const std::string& msg)
|
tcp::endpoint const& ep
|
||||||
|
, std::string const& msg)
|
||||||
: alert(alert::fatal, msg)
|
: alert(alert::fatal, msg)
|
||||||
|
, endpoint(ep)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
tcp::endpoint endpoint;
|
||||||
|
|
||||||
virtual std::auto_ptr<alert> clone() const
|
virtual std::auto_ptr<alert> clone() const
|
||||||
{ return std::auto_ptr<alert>(new listen_failed_alert(*this)); }
|
{ return std::auto_ptr<alert>(new listen_failed_alert(*this)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TORRENT_EXPORT listen_succeeded_alert: alert
|
||||||
|
{
|
||||||
|
listen_succeeded_alert(
|
||||||
|
tcp::endpoint const& ep
|
||||||
|
, std::string const& msg)
|
||||||
|
: alert(alert::fatal, msg)
|
||||||
|
, endpoint(ep)
|
||||||
|
{}
|
||||||
|
|
||||||
|
tcp::endpoint endpoint;
|
||||||
|
|
||||||
|
virtual std::auto_ptr<alert> clone() const
|
||||||
|
{ return std::auto_ptr<alert>(new listen_succeeded_alert(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
struct TORRENT_EXPORT portmap_error_alert: alert
|
struct TORRENT_EXPORT portmap_error_alert: alert
|
||||||
{
|
{
|
||||||
portmap_error_alert(const std::string& msg)
|
portmap_error_alert(const std::string& msg)
|
||||||
|
|
|
@ -189,11 +189,16 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
void operator()();
|
void operator()();
|
||||||
|
|
||||||
void open_listen_port();
|
void open_listen_port() throw();
|
||||||
|
|
||||||
void async_accept();
|
// if we are listening on an IPv6 interface
|
||||||
|
// this will return one of the IPv6 addresses on this
|
||||||
|
// machine, otherwise just an empty endpoint
|
||||||
|
tcp::endpoint get_ipv6_interface() const;
|
||||||
|
|
||||||
|
void async_accept(boost::shared_ptr<socket_acceptor> const& listener);
|
||||||
void on_incoming_connection(boost::shared_ptr<socket_type> const& s
|
void on_incoming_connection(boost::shared_ptr<socket_type> const& s
|
||||||
, boost::weak_ptr<socket_acceptor> const& as, asio::error_code const& e);
|
, boost::weak_ptr<socket_acceptor> listener, asio::error_code const& e);
|
||||||
|
|
||||||
// must be locked to access the data
|
// must be locked to access the data
|
||||||
// in this struct
|
// in this struct
|
||||||
|
@ -393,8 +398,10 @@ namespace libtorrent
|
||||||
// at startup
|
// at startup
|
||||||
int m_key;
|
int m_key;
|
||||||
|
|
||||||
// the range of ports we try to listen on
|
// the number of retries we make when binding the
|
||||||
std::pair<int, int> m_listen_port_range;
|
// listen socket. For each retry the port number
|
||||||
|
// is incremented by one
|
||||||
|
int m_listen_port_retries;
|
||||||
|
|
||||||
// the ip-address of the interface
|
// the ip-address of the interface
|
||||||
// we are supposed to listen on.
|
// we are supposed to listen on.
|
||||||
|
@ -402,17 +409,32 @@ namespace libtorrent
|
||||||
// that we should let the os decide which
|
// that we should let the os decide which
|
||||||
// interface to listen on
|
// interface to listen on
|
||||||
tcp::endpoint m_listen_interface;
|
tcp::endpoint m_listen_interface;
|
||||||
|
|
||||||
// this is typically set to the same as the local
|
|
||||||
// listen port. In case a NAT port forward was
|
|
||||||
// successfully opened, this will be set to the
|
|
||||||
// port that is open on the external (NAT) interface
|
|
||||||
// on the NAT box itself. This is the port that has
|
|
||||||
// to be published to peers, since this is the port
|
|
||||||
// the client is reachable through.
|
|
||||||
int m_external_listen_port;
|
|
||||||
|
|
||||||
boost::shared_ptr<socket_acceptor> m_listen_socket;
|
// if we're listening on an IPv6 interface
|
||||||
|
// this is one of the non local IPv6 interfaces
|
||||||
|
// on this machine
|
||||||
|
tcp::endpoint m_ipv6_interface;
|
||||||
|
|
||||||
|
struct listen_socket_t
|
||||||
|
{
|
||||||
|
listen_socket_t(): external_port(0) {}
|
||||||
|
// this is typically set to the same as the local
|
||||||
|
// listen port. In case a NAT port forward was
|
||||||
|
// successfully opened, this will be set to the
|
||||||
|
// port that is open on the external (NAT) interface
|
||||||
|
// on the NAT box itself. This is the port that has
|
||||||
|
// to be published to peers, since this is the port
|
||||||
|
// the client is reachable through.
|
||||||
|
int external_port;
|
||||||
|
|
||||||
|
// the actual socket
|
||||||
|
boost::shared_ptr<socket_acceptor> sock;
|
||||||
|
};
|
||||||
|
// since we might be listening on multiple interfaces
|
||||||
|
// we might need more than one listen socket
|
||||||
|
std::list<listen_socket_t> m_listen_sockets;
|
||||||
|
|
||||||
|
listen_socket_t setup_listener(tcp::endpoint ep, int retries);
|
||||||
|
|
||||||
// the settings for the client
|
// the settings for the client
|
||||||
session_settings m_settings;
|
session_settings m_settings;
|
||||||
|
|
|
@ -44,6 +44,7 @@ namespace libtorrent
|
||||||
bool is_local(address const& a);
|
bool is_local(address const& a);
|
||||||
bool is_loopback(address const& addr);
|
bool is_loopback(address const& addr);
|
||||||
bool is_multicast(address const& addr);
|
bool is_multicast(address const& addr);
|
||||||
|
bool is_any(address const& addr);
|
||||||
|
|
||||||
address_v4 guess_local_address(asio::io_service&);
|
address_v4 guess_local_address(asio::io_service&);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
std::vector<address> const& enum_net_interfaces(asio::io_service& ios, asio::error_code& ec);
|
std::vector<address> enum_net_interfaces(asio::io_service& ios, asio::error_code& ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -98,6 +98,21 @@ namespace libtorrent
|
||||||
|
|
||||||
typedef asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;
|
typedef asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;
|
||||||
|
|
||||||
|
inline std::ostream& print_endpoint(std::ostream& os, tcp::endpoint const& ep)
|
||||||
|
{
|
||||||
|
address const& addr = ep.address();
|
||||||
|
asio::error_code ec;
|
||||||
|
std::string a = addr.to_string(ec);
|
||||||
|
if (ec) return os;
|
||||||
|
|
||||||
|
if (addr.is_v6())
|
||||||
|
os << "[" << a << "]:";
|
||||||
|
else
|
||||||
|
os << a << ":";
|
||||||
|
os << ep.port();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<class OutIt>
|
template<class OutIt>
|
||||||
|
|
|
@ -113,6 +113,7 @@ namespace libtorrent
|
||||||
std::string url;
|
std::string url;
|
||||||
int key;
|
int key;
|
||||||
int num_want;
|
int num_want;
|
||||||
|
std::string ipv6;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TORRENT_EXPORT request_callback
|
struct TORRENT_EXPORT request_callback
|
||||||
|
|
|
@ -232,18 +232,18 @@ namespace aux
|
||||||
|
|
||||||
// -------------- remote_endpoint -----------
|
// -------------- remote_endpoint -----------
|
||||||
|
|
||||||
template <class EndpointType, class Error_Handler = boost::mpl::void_>
|
template <class EndpointType>
|
||||||
struct remote_endpoint_visitor
|
struct remote_endpoint_visitor_ec
|
||||||
: boost::static_visitor<EndpointType>
|
: boost::static_visitor<EndpointType>
|
||||||
{
|
{
|
||||||
remote_endpoint_visitor(Error_Handler const& error_handler)
|
remote_endpoint_visitor_ec(asio::error_code& ec)
|
||||||
: error_handler(error_handler)
|
: error_code(ec)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
EndpointType operator()(T* p) const
|
EndpointType operator()(T* p) const
|
||||||
{
|
{
|
||||||
return p->remote_endpoint(error_handler);
|
return p->remote_endpoint(error_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndpointType operator()(boost::blank) const
|
EndpointType operator()(boost::blank) const
|
||||||
|
@ -251,11 +251,11 @@ namespace aux
|
||||||
return EndpointType();
|
return EndpointType();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error_Handler const& error_handler;
|
asio::error_code& error_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class EndpointType>
|
template <class EndpointType>
|
||||||
struct remote_endpoint_visitor<EndpointType, boost::mpl::void_>
|
struct remote_endpoint_visitor
|
||||||
: boost::static_visitor<EndpointType>
|
: boost::static_visitor<EndpointType>
|
||||||
{
|
{
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -272,18 +272,18 @@ namespace aux
|
||||||
|
|
||||||
// -------------- local_endpoint -----------
|
// -------------- local_endpoint -----------
|
||||||
|
|
||||||
template <class EndpointType, class Error_Handler = boost::mpl::void_>
|
template <class EndpointType>
|
||||||
struct local_endpoint_visitor
|
struct local_endpoint_visitor_ec
|
||||||
: boost::static_visitor<EndpointType>
|
: boost::static_visitor<EndpointType>
|
||||||
{
|
{
|
||||||
local_endpoint_visitor(Error_Handler const& error_handler)
|
local_endpoint_visitor_ec(asio::error_code& ec)
|
||||||
: error_handler(error_handler)
|
: error_code(ec)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
EndpointType operator()(T* p) const
|
EndpointType operator()(T* p) const
|
||||||
{
|
{
|
||||||
return p->local_endpoint(error_handler);
|
return p->local_endpoint(error_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndpointType operator()(boost::blank) const
|
EndpointType operator()(boost::blank) const
|
||||||
|
@ -291,11 +291,11 @@ namespace aux
|
||||||
return EndpointType();
|
return EndpointType();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error_Handler const& error_handler;
|
asio::error_code& error_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class EndpointType>
|
template <class EndpointType>
|
||||||
struct local_endpoint_visitor<EndpointType, boost::mpl::void_>
|
struct local_endpoint_visitor
|
||||||
: boost::static_visitor<EndpointType>
|
: boost::static_visitor<EndpointType>
|
||||||
{
|
{
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -665,12 +665,11 @@ public:
|
||||||
return boost::apply_visitor(aux::remote_endpoint_visitor<endpoint_type>(), m_variant);
|
return boost::apply_visitor(aux::remote_endpoint_visitor<endpoint_type>(), m_variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Error_Handler>
|
endpoint_type remote_endpoint(asio::error_code& ec)
|
||||||
endpoint_type remote_endpoint(Error_Handler const& error_handler)
|
|
||||||
{
|
{
|
||||||
assert(instantiated());
|
assert(instantiated());
|
||||||
return boost::apply_visitor(
|
return boost::apply_visitor(
|
||||||
aux::remote_endpoint_visitor<endpoint_type, Error_Handler>(error_handler), m_variant
|
aux::remote_endpoint_visitor_ec<endpoint_type>(ec), m_variant
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,12 +679,11 @@ public:
|
||||||
return boost::apply_visitor(aux::local_endpoint_visitor<endpoint_type>(), m_variant);
|
return boost::apply_visitor(aux::local_endpoint_visitor<endpoint_type>(), m_variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Error_Handler>
|
endpoint_type local_endpoint(asio::error_code& ec)
|
||||||
endpoint_type local_endpoint(Error_Handler const& error_handler)
|
|
||||||
{
|
{
|
||||||
assert(instantiated());
|
assert(instantiated());
|
||||||
return boost::apply_visitor(
|
return boost::apply_visitor(
|
||||||
aux::local_endpoint_visitor<endpoint_type, Error_Handler>(error_handler), m_variant
|
aux::local_endpoint_visitor_ec<endpoint_type>(ec), m_variant
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
|
|
||||||
alert_manager::alert_manager()
|
alert_manager::alert_manager()
|
||||||
: m_severity(alert::none)
|
: m_severity(alert::fatal)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
alert_manager::~alert_manager()
|
alert_manager::~alert_manager()
|
||||||
|
|
|
@ -84,6 +84,14 @@ namespace libtorrent
|
||||||
return addr.to_v6().is_multicast();
|
return addr.to_v6().is_multicast();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_any(address const& addr)
|
||||||
|
{
|
||||||
|
if (addr.is_v4())
|
||||||
|
return addr.to_v4() == address_v4::any();
|
||||||
|
else
|
||||||
|
return addr.to_v6() == address_v6::any();
|
||||||
|
}
|
||||||
|
|
||||||
broadcast_socket::broadcast_socket(asio::io_service& ios
|
broadcast_socket::broadcast_socket(asio::io_service& ios
|
||||||
, udp::endpoint const& multicast_endpoint
|
, udp::endpoint const& multicast_endpoint
|
||||||
, receive_handler_t const& handler
|
, receive_handler_t const& handler
|
||||||
|
|
|
@ -50,7 +50,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/version.hpp"
|
#include "libtorrent/version.hpp"
|
||||||
#include "libtorrent/extensions.hpp"
|
#include "libtorrent/extensions.hpp"
|
||||||
#include "libtorrent/aux_/session_impl.hpp"
|
#include "libtorrent/aux_/session_impl.hpp"
|
||||||
#include "libtorrent/enum_net.hpp"
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||||
#include "libtorrent/pe_crypto.hpp"
|
#include "libtorrent/pe_crypto.hpp"
|
||||||
|
@ -1475,18 +1474,14 @@ namespace libtorrent
|
||||||
detail::write_address(remote().address(), out);
|
detail::write_address(remote().address(), out);
|
||||||
handshake["yourip"] = remote_address;
|
handshake["yourip"] = remote_address;
|
||||||
handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue;
|
handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue;
|
||||||
asio::error_code ec;
|
|
||||||
std::vector<address> const& interfaces = enum_net_interfaces(get_socket()->io_service(), ec);
|
tcp::endpoint ep = m_ses.get_ipv6_interface();
|
||||||
for (std::vector<address>::const_iterator i = interfaces.begin()
|
if (ep != tcp::endpoint())
|
||||||
, end(interfaces.end()); i != end; ++i)
|
|
||||||
{
|
{
|
||||||
// TODO: only use global IPv6 addresses
|
|
||||||
if (!i->is_v6() || i->to_v6().is_link_local()) continue;
|
|
||||||
std::string ipv6_address;
|
std::string ipv6_address;
|
||||||
std::back_insert_iterator<std::string> out(ipv6_address);
|
std::back_insert_iterator<std::string> out(ipv6_address);
|
||||||
detail::write_address(*i, out);
|
detail::write_address(ep.address(), out);
|
||||||
handshake["ipv6"] = ipv6_address;
|
handshake["ipv6"] = ipv6_address;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop backwards, to make the first extension be the last
|
// loop backwards, to make the first extension be the last
|
||||||
|
|
|
@ -40,10 +40,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
std::vector<address> const& enum_net_interfaces(asio::io_service& ios, asio::error_code& ec)
|
std::vector<address> enum_net_interfaces(asio::io_service& ios, asio::error_code& ec)
|
||||||
{
|
{
|
||||||
static std::vector<address> ret;
|
std::vector<address> ret;
|
||||||
if (!ret.empty()) return ret;
|
|
||||||
|
|
||||||
#if defined __linux__ || defined __MACH__ || defined(__FreeBSD__)
|
#if defined __linux__ || defined __MACH__ || defined(__FreeBSD__)
|
||||||
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
|
|
@ -428,6 +428,13 @@ namespace libtorrent
|
||||||
m_send_buffer += "supportcrypto=1&";
|
m_send_buffer += "supportcrypto=1&";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!url_has_argument(request, "ipv6") && !req.ipv6.empty())
|
||||||
|
{
|
||||||
|
m_send_buffer += "ipv6=";
|
||||||
|
m_send_buffer += req.ipv6;
|
||||||
|
m_send_buffer += '&';
|
||||||
|
}
|
||||||
|
|
||||||
// extension that tells the tracker that
|
// extension that tells the tracker that
|
||||||
// we don't need any peer_id's in the response
|
// we don't need any peer_id's in the response
|
||||||
if (!url_has_argument(request, "no_peer_id"))
|
if (!url_has_argument(request, "no_peer_id"))
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,6 +162,18 @@ namespace
|
||||||
tcp::endpoint const& m_ep;
|
tcp::endpoint const& m_ep;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct match_peer_id
|
||||||
|
{
|
||||||
|
match_peer_id(peer_id const& id_)
|
||||||
|
: m_id(id_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool operator()(policy::peer const& p) const
|
||||||
|
{ return p.connection && p.connection->pid() == m_id; }
|
||||||
|
|
||||||
|
peer_id const& m_id;
|
||||||
|
};
|
||||||
|
|
||||||
struct match_peer_connection
|
struct match_peer_connection
|
||||||
{
|
{
|
||||||
match_peer_connection(peer_connection const& c)
|
match_peer_connection(peer_connection const& c)
|
||||||
|
@ -1030,6 +1042,12 @@ namespace libtorrent
|
||||||
m_peers.begin()
|
m_peers.begin()
|
||||||
, m_peers.end()
|
, m_peers.end()
|
||||||
, match_peer_endpoint(remote));
|
, match_peer_endpoint(remote));
|
||||||
|
|
||||||
|
if (i == m_peers.end())
|
||||||
|
i = std::find_if(
|
||||||
|
m_peers.begin()
|
||||||
|
, m_peers.end()
|
||||||
|
, match_peer_id(pid));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1156,7 +1174,7 @@ namespace libtorrent
|
||||||
// data from now on
|
// data from now on
|
||||||
void policy::unchoked(peer_connection& c)
|
void policy::unchoked(peer_connection& c)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
if (c.is_interesting())
|
if (c.is_interesting())
|
||||||
{
|
{
|
||||||
request_a_block(*m_torrent, c);
|
request_a_block(*m_torrent, c);
|
||||||
|
@ -1166,7 +1184,7 @@ namespace libtorrent
|
||||||
// called when a peer is interested in us
|
// called when a peer is interested in us
|
||||||
void policy::interested(peer_connection& c)
|
void policy::interested(peer_connection& c)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
assert(std::find_if(m_peers.begin(), m_peers.end()
|
assert(std::find_if(m_peers.begin(), m_peers.end()
|
||||||
, boost::bind<bool>(std::equal_to<peer_connection*>(), bind(&peer::connection, _1)
|
, boost::bind<bool>(std::equal_to<peer_connection*>(), bind(&peer::connection, _1)
|
||||||
|
@ -1278,7 +1296,7 @@ namespace libtorrent
|
||||||
*/
|
*/
|
||||||
bool policy::connect_one_peer()
|
bool policy::connect_one_peer()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
assert(m_torrent->want_more_peers());
|
assert(m_torrent->want_more_peers());
|
||||||
|
|
||||||
|
@ -1291,7 +1309,6 @@ namespace libtorrent
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
|
||||||
p->connected = time_now();
|
p->connected = time_now();
|
||||||
p->connection = m_torrent->connect_to_peer(&*p);
|
p->connection = m_torrent->connect_to_peer(&*p);
|
||||||
assert(p->connection == m_torrent->connection_for(p->ip));
|
assert(p->connection == m_torrent->connection_for(p->ip));
|
||||||
|
@ -1375,7 +1392,7 @@ namespace libtorrent
|
||||||
|
|
||||||
void policy::peer_is_interesting(peer_connection& c)
|
void policy::peer_is_interesting(peer_connection& c)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
c.send_interested();
|
c.send_interested();
|
||||||
if (c.has_peer_choked()
|
if (c.has_peer_choked()
|
||||||
|
|
|
@ -73,6 +73,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
#include "libtorrent/aux_/session_impl.hpp"
|
#include "libtorrent/aux_/session_impl.hpp"
|
||||||
#include "libtorrent/kademlia/dht_tracker.hpp"
|
#include "libtorrent/kademlia/dht_tracker.hpp"
|
||||||
|
#include "libtorrent/enum_net.hpp"
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||||
|
|
||||||
|
@ -512,9 +513,8 @@ namespace detail
|
||||||
, m_download_channel(m_io_service, peer_connection::download_channel)
|
, m_download_channel(m_io_service, peer_connection::download_channel)
|
||||||
, m_upload_channel(m_io_service, peer_connection::upload_channel)
|
, m_upload_channel(m_io_service, peer_connection::upload_channel)
|
||||||
, m_tracker_manager(m_settings, m_tracker_proxy)
|
, m_tracker_manager(m_settings, m_tracker_proxy)
|
||||||
, m_listen_port_range(listen_port_range)
|
, m_listen_port_retries(listen_port_range.second - listen_port_range.first)
|
||||||
, m_listen_interface(address::from_string(listen_interface), listen_port_range.first)
|
, m_listen_interface(address::from_string(listen_interface), listen_port_range.first)
|
||||||
, m_external_listen_port(0)
|
|
||||||
, m_abort(false)
|
, m_abort(false)
|
||||||
, m_max_uploads(8)
|
, m_max_uploads(8)
|
||||||
, m_max_connections(200)
|
, m_max_connections(200)
|
||||||
|
@ -661,129 +661,227 @@ namespace detail
|
||||||
*i = ' ';
|
*i = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::open_listen_port()
|
tcp::endpoint session_impl::get_ipv6_interface() const
|
||||||
{
|
{
|
||||||
try
|
return m_ipv6_interface;
|
||||||
{
|
}
|
||||||
// create listener socket
|
|
||||||
m_listen_socket.reset(new socket_acceptor(m_io_service));
|
|
||||||
|
|
||||||
for(;;)
|
session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep, int retries)
|
||||||
{
|
{
|
||||||
try
|
asio::error_code ec;
|
||||||
{
|
listen_socket_t s;
|
||||||
m_listen_socket->open(m_listen_interface.protocol());
|
s.sock.reset(new socket_acceptor(m_io_service));
|
||||||
m_listen_socket->set_option(socket_acceptor::reuse_address(true));
|
s.sock->open(ep.protocol(), ec);
|
||||||
m_listen_socket->bind(m_listen_interface);
|
s.sock->set_option(socket_acceptor::reuse_address(true), ec);
|
||||||
m_listen_socket->listen();
|
s.sock->bind(ep, ec);
|
||||||
m_listen_interface = m_listen_socket->local_endpoint();
|
while (ec && retries > 0)
|
||||||
m_external_listen_port = m_listen_interface.port();
|
{
|
||||||
break;
|
ec = asio::error_code();
|
||||||
}
|
assert(!ec);
|
||||||
catch (asio::system_error& e)
|
--retries;
|
||||||
{
|
ep.port(ep.port() + 1);
|
||||||
// TODO: make sure this is correct
|
s.sock->bind(ep, ec);
|
||||||
if (e.code() == asio::error::host_not_found
|
|
||||||
|| m_listen_interface.port() == 0)
|
|
||||||
{
|
|
||||||
if (m_alerts.should_post(alert::fatal))
|
|
||||||
{
|
|
||||||
std::string msg = "cannot listen on the given interface '"
|
|
||||||
+ m_listen_interface.address().to_string() + "'";
|
|
||||||
m_alerts.post_alert(listen_failed_alert(msg));
|
|
||||||
}
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
|
||||||
std::string msg = "cannot listen on the given interface '"
|
|
||||||
+ m_listen_interface.address().to_string() + "'";
|
|
||||||
(*m_logger) << msg << "\n";
|
|
||||||
#endif
|
|
||||||
assert(m_listen_socket.unique());
|
|
||||||
m_listen_socket.reset();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
m_listen_socket->close();
|
|
||||||
m_listen_interface.port(m_listen_interface.port() + 1);
|
|
||||||
if (m_listen_interface.port() > m_listen_port_range.second)
|
|
||||||
{
|
|
||||||
std::stringstream msg;
|
|
||||||
msg << "none of the ports in the range ["
|
|
||||||
<< m_listen_port_range.first
|
|
||||||
<< ", " << m_listen_port_range.second
|
|
||||||
<< "] could be opened for listening";
|
|
||||||
m_alerts.post_alert(listen_failed_alert(msg.str()));
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
|
||||||
(*m_logger) << msg.str() << "\n";
|
|
||||||
#endif
|
|
||||||
m_listen_socket.reset();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (asio::system_error& e)
|
if (ec)
|
||||||
|
{
|
||||||
|
// instead of giving up, try
|
||||||
|
// let the OS pick a port
|
||||||
|
ep.port(0);
|
||||||
|
ec = asio::error_code();
|
||||||
|
s.sock->bind(ep, ec);
|
||||||
|
}
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
// not even that worked, give up
|
||||||
|
if (m_alerts.should_post(alert::fatal))
|
||||||
|
{
|
||||||
|
std::stringstream msg;
|
||||||
|
msg << "cannot bind to interface '";
|
||||||
|
print_endpoint(msg, ep) << "' " << ec.message();
|
||||||
|
m_alerts.post_alert(listen_failed_alert(ep, msg.str()));
|
||||||
|
}
|
||||||
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
std::stringstream msg;
|
||||||
|
msg << "cannot bind to interface '";
|
||||||
|
print_endpoint(msg, ep) << "' " << ec.message();
|
||||||
|
(*m_logger) << msg.str() << "\n";
|
||||||
|
#endif
|
||||||
|
return listen_socket_t();
|
||||||
|
}
|
||||||
|
s.external_port = s.sock->local_endpoint(ec).port();
|
||||||
|
s.sock->listen(0, ec);
|
||||||
|
if (ec)
|
||||||
{
|
{
|
||||||
if (m_alerts.should_post(alert::fatal))
|
if (m_alerts.should_post(alert::fatal))
|
||||||
{
|
{
|
||||||
m_alerts.post_alert(listen_failed_alert(
|
std::stringstream msg;
|
||||||
std::string("failed to open listen port: ") + e.what()));
|
msg << "cannot listen on interface '";
|
||||||
|
print_endpoint(msg, ep) << "' " << ec.message();
|
||||||
|
m_alerts.post_alert(listen_failed_alert(ep, msg.str()));
|
||||||
|
}
|
||||||
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
std::stringstream msg;
|
||||||
|
msg << "cannot listen on interface '";
|
||||||
|
print_endpoint(msg, ep) << "' " << ec.message();
|
||||||
|
(*m_logger) << msg.str() << "\n";
|
||||||
|
#endif
|
||||||
|
return listen_socket_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_alerts.should_post(alert::fatal))
|
||||||
|
{
|
||||||
|
std::string msg = "listening on interface "
|
||||||
|
+ boost::lexical_cast<std::string>(ep);
|
||||||
|
m_alerts.post_alert(listen_succeeded_alert(ep, msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
(*m_logger) << "listening on: " << ep
|
||||||
|
<< " external port: " << s.external_port << "\n";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void session_impl::open_listen_port() throw()
|
||||||
|
{
|
||||||
|
// close the open listen sockets
|
||||||
|
m_listen_sockets.clear();
|
||||||
|
m_incoming_connection = false;
|
||||||
|
|
||||||
|
if (is_any(m_listen_interface.address()))
|
||||||
|
{
|
||||||
|
// this means we should open two listen sockets
|
||||||
|
// one for IPv4 and one for IPv6
|
||||||
|
|
||||||
|
listen_socket_t s = setup_listener(
|
||||||
|
tcp::endpoint(address_v4::any(), m_listen_interface.port())
|
||||||
|
, m_listen_port_retries);
|
||||||
|
|
||||||
|
if (s.sock)
|
||||||
|
{
|
||||||
|
m_listen_sockets.push_back(s);
|
||||||
|
async_accept(s.sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
s = setup_listener(
|
||||||
|
tcp::endpoint(address_v6::any(), m_listen_interface.port())
|
||||||
|
, m_listen_port_retries);
|
||||||
|
|
||||||
|
if (s.sock)
|
||||||
|
{
|
||||||
|
m_listen_sockets.push_back(s);
|
||||||
|
async_accept(s.sock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we should only open a single listen socket, that
|
||||||
|
// binds to the given interface
|
||||||
|
|
||||||
|
listen_socket_t s = setup_listener(
|
||||||
|
m_listen_interface, m_listen_port_retries);
|
||||||
|
|
||||||
|
if (s.sock)
|
||||||
|
{
|
||||||
|
m_listen_sockets.push_back(s);
|
||||||
|
async_accept(s.sock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_listen_socket)
|
m_ipv6_interface = tcp::endpoint();
|
||||||
|
|
||||||
|
for (std::list<listen_socket_t>::const_iterator i = m_listen_sockets.begin()
|
||||||
|
, end(m_listen_sockets.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
asio::error_code ec;
|
||||||
(*m_logger) << "listening on port: " << m_listen_interface.port()
|
tcp::endpoint ep = i->sock->local_endpoint(ec);
|
||||||
<< " external port: " << m_external_listen_port << "\n";
|
if (ec || ep.address().is_v4()) continue;
|
||||||
#endif
|
|
||||||
async_accept();
|
if (ep.address().to_v6() != address_v6::any())
|
||||||
if (m_natpmp.get())
|
{
|
||||||
m_natpmp->set_mappings(m_listen_interface.port(), 0);
|
// if we're listening on a specific address
|
||||||
if (m_upnp.get())
|
// pick it
|
||||||
m_upnp->set_mappings(m_listen_interface.port(), 0);
|
m_ipv6_interface = ep;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if we're listening on any IPv6 address, enumerate them and
|
||||||
|
// pick the first non-local address
|
||||||
|
std::vector<address> const& ifs = enum_net_interfaces(m_io_service, ec);
|
||||||
|
for (std::vector<address>::const_iterator i = ifs.begin()
|
||||||
|
, end(ifs.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
if (i->is_v4() || i->to_v6().is_link_local() || i->to_v6().is_loopback()) continue;
|
||||||
|
m_ipv6_interface = tcp::endpoint(*i, ep.port());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_listen_sockets.empty())
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
tcp::endpoint local = m_listen_sockets.front().sock->local_endpoint(ec);
|
||||||
|
if (!ec)
|
||||||
|
{
|
||||||
|
if (m_natpmp.get()) m_natpmp->set_mappings(local.port(), 0);
|
||||||
|
if (m_upnp.get()) m_upnp->set_mappings(local.port(), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::async_accept()
|
void session_impl::async_accept(boost::shared_ptr<socket_acceptor> const& listener)
|
||||||
{
|
{
|
||||||
shared_ptr<socket_type> c(new socket_type(m_io_service));
|
shared_ptr<socket_type> c(new socket_type(m_io_service));
|
||||||
c->instantiate<stream_socket>();
|
c->instantiate<stream_socket>();
|
||||||
m_listen_socket->async_accept(c->get<stream_socket>()
|
listener->async_accept(c->get<stream_socket>()
|
||||||
, bind(&session_impl::on_incoming_connection, this, c
|
, bind(&session_impl::on_incoming_connection, this, c
|
||||||
, weak_ptr<socket_acceptor>(m_listen_socket), _1));
|
, boost::weak_ptr<socket_acceptor>(listener), _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::on_incoming_connection(shared_ptr<socket_type> const& s
|
void session_impl::on_incoming_connection(shared_ptr<socket_type> const& s
|
||||||
, weak_ptr<socket_acceptor> const& listen_socket, asio::error_code const& e) try
|
, weak_ptr<socket_acceptor> listen_socket, asio::error_code const& e) try
|
||||||
{
|
{
|
||||||
if (listen_socket.expired())
|
boost::shared_ptr<socket_acceptor> listener = listen_socket.lock();
|
||||||
return;
|
if (!listener) return;
|
||||||
|
|
||||||
if (e == asio::error::operation_aborted)
|
if (e == asio::error::operation_aborted) return;
|
||||||
return;
|
|
||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
assert(listen_socket.lock() == m_listen_socket);
|
|
||||||
|
|
||||||
if (m_abort) return;
|
if (m_abort) return;
|
||||||
|
|
||||||
|
asio::error_code ec;
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
|
tcp::endpoint ep = listener->local_endpoint(ec);
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
std::string msg = "error accepting connection on '"
|
std::string msg = "error accepting connection on '"
|
||||||
+ m_listen_interface.address().to_string() + "'";
|
+ boost::lexical_cast<std::string>(ep) + "' " + e.message();
|
||||||
(*m_logger) << msg << "\n";
|
(*m_logger) << msg << "\n";
|
||||||
#endif
|
#endif
|
||||||
assert(m_listen_socket.unique());
|
if (m_alerts.should_post(alert::fatal))
|
||||||
// try any random port
|
{
|
||||||
m_listen_interface.port(0);
|
std::string msg = "error accepting connection on '"
|
||||||
open_listen_port();
|
+ boost::lexical_cast<std::string>(ep) + "' " + ec.message();
|
||||||
|
m_alerts.post_alert(listen_failed_alert(ep, msg));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
async_accept();
|
async_accept(listener);
|
||||||
|
|
||||||
// we got a connection request!
|
// we got a connection request!
|
||||||
m_incoming_connection = true;
|
m_incoming_connection = true;
|
||||||
tcp::endpoint endp = s->remote_endpoint();
|
tcp::endpoint endp = s->remote_endpoint(ec);
|
||||||
|
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
(*m_logger) << endp << " <== INCOMING CONNECTION FAILED, could "
|
||||||
|
"not retrieve remote endpoint " << ec.message() << "\n";
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << endp << " <== INCOMING CONNECTION\n";
|
(*m_logger) << endp << " <== INCOMING CONNECTION\n";
|
||||||
|
@ -803,28 +901,22 @@ namespace detail
|
||||||
|
|
||||||
// check if we have any active torrents
|
// check if we have any active torrents
|
||||||
// if we don't reject the connection
|
// if we don't reject the connection
|
||||||
if (m_torrents.empty())
|
if (m_torrents.empty()) return;
|
||||||
|
|
||||||
|
bool has_active_torrent = false;
|
||||||
|
for (torrent_map::iterator i = m_torrents.begin()
|
||||||
|
, end(m_torrents.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
return;
|
if (!i->second->is_paused())
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool has_active_torrent = false;
|
|
||||||
for (torrent_map::iterator i = m_torrents.begin()
|
|
||||||
, end(m_torrents.end()); i != end; ++i)
|
|
||||||
{
|
{
|
||||||
if (!i->second->is_paused())
|
has_active_torrent = true;
|
||||||
{
|
break;
|
||||||
has_active_torrent = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!has_active_torrent)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (!has_active_torrent) return;
|
||||||
|
|
||||||
boost::intrusive_ptr<peer_connection> c(
|
boost::intrusive_ptr<peer_connection> c(
|
||||||
new bt_peer_connection(*this, s, 0));
|
new bt_peer_connection(*this, s, 0));
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
c->m_in_constructor = false;
|
c->m_in_constructor = false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1064,7 +1156,9 @@ namespace detail
|
||||||
if (t.should_request())
|
if (t.should_request())
|
||||||
{
|
{
|
||||||
tracker_request req = t.generate_tracker_request();
|
tracker_request req = t.generate_tracker_request();
|
||||||
req.listen_port = m_external_listen_port;
|
req.listen_port = 0;
|
||||||
|
if (!m_listen_sockets.empty())
|
||||||
|
req.listen_port = m_listen_sockets.front().external_port;
|
||||||
req.key = m_key;
|
req.key = m_key;
|
||||||
m_tracker_manager.queue_request(m_strand, m_half_open, req
|
m_tracker_manager.queue_request(m_strand, m_half_open, req
|
||||||
, t.tracker_login(), m_listen_interface.address(), i->second);
|
, t.tracker_login(), m_listen_interface.address(), i->second);
|
||||||
|
@ -1274,10 +1368,9 @@ namespace detail
|
||||||
{
|
{
|
||||||
eh_initializer();
|
eh_initializer();
|
||||||
|
|
||||||
if (m_listen_port_range.first != 0 && m_listen_port_range.second != 0)
|
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l(m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_mutex);
|
||||||
open_listen_port();
|
if (m_listen_interface.port() != 0) open_listen_port();
|
||||||
}
|
}
|
||||||
|
|
||||||
ptime timer = time_now();
|
ptime timer = time_now();
|
||||||
|
@ -1331,8 +1424,10 @@ namespace detail
|
||||||
&& !i->second->trackers().empty())
|
&& !i->second->trackers().empty())
|
||||||
{
|
{
|
||||||
tracker_request req = i->second->generate_tracker_request();
|
tracker_request req = i->second->generate_tracker_request();
|
||||||
assert(m_external_listen_port > 0);
|
assert(!m_listen_sockets.empty());
|
||||||
req.listen_port = m_external_listen_port;
|
req.listen_port = 0;
|
||||||
|
if (!m_listen_sockets.empty())
|
||||||
|
req.listen_port = m_listen_sockets.front().external_port;
|
||||||
req.key = m_key;
|
req.key = m_key;
|
||||||
std::string login = i->second->tracker_login();
|
std::string login = i->second->tracker_login();
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
@ -1347,8 +1442,8 @@ namespace detail
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// close listen socket
|
// close the listen sockets
|
||||||
m_listen_socket.reset();
|
m_listen_sockets.clear();
|
||||||
|
|
||||||
ptime start(time_now());
|
ptime start(time_now());
|
||||||
l.unlock();
|
l.unlock();
|
||||||
|
@ -1477,10 +1572,12 @@ namespace detail
|
||||||
, bool paused
|
, bool paused
|
||||||
, void* userdata)
|
, void* userdata)
|
||||||
{
|
{
|
||||||
|
assert(!save_path.empty());
|
||||||
|
|
||||||
// if you get this assert, you haven't managed to
|
// if you get this assert, you haven't managed to
|
||||||
// open a listen port. call listen_on() first.
|
// open a listen port. call listen_on() first.
|
||||||
assert(m_external_listen_port > 0);
|
if (m_listen_sockets.empty())
|
||||||
assert(!save_path.empty());
|
throw std::runtime_error("no listen socket opened");
|
||||||
|
|
||||||
if (ti->begin_files() == ti->end_files())
|
if (ti->begin_files() == ti->end_files())
|
||||||
throw std::runtime_error("no files in torrent");
|
throw std::runtime_error("no files in torrent");
|
||||||
|
@ -1489,7 +1586,7 @@ namespace detail
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
mutex::scoped_lock l2(m_checker_impl.m_mutex);
|
mutex::scoped_lock l2(m_checker_impl.m_mutex);
|
||||||
|
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
if (is_aborted())
|
if (is_aborted())
|
||||||
throw std::runtime_error("session is closing");
|
throw std::runtime_error("session is closing");
|
||||||
|
@ -1573,7 +1670,7 @@ namespace detail
|
||||||
// lock the session
|
// lock the session
|
||||||
session_impl::mutex_t::scoped_lock l(m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
// is the torrent already active?
|
// is the torrent already active?
|
||||||
if (!find_torrent(info_hash).expired())
|
if (!find_torrent(info_hash).expired())
|
||||||
|
@ -1628,8 +1725,10 @@ namespace detail
|
||||||
{
|
{
|
||||||
tracker_request req = t.generate_tracker_request();
|
tracker_request req = t.generate_tracker_request();
|
||||||
assert(req.event == tracker_request::stopped);
|
assert(req.event == tracker_request::stopped);
|
||||||
assert(m_external_listen_port > 0);
|
assert(!m_listen_sockets.empty());
|
||||||
req.listen_port = m_external_listen_port;
|
req.listen_port = 0;
|
||||||
|
if (!m_listen_sockets.empty())
|
||||||
|
req.listen_port = m_listen_sockets.front().external_port;
|
||||||
req.key = m_key;
|
req.key = m_key;
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
@ -1684,19 +1783,15 @@ namespace detail
|
||||||
if (net_interface && std::strlen(net_interface) > 0)
|
if (net_interface && std::strlen(net_interface) > 0)
|
||||||
new_interface = tcp::endpoint(address::from_string(net_interface), port_range.first);
|
new_interface = tcp::endpoint(address::from_string(net_interface), port_range.first);
|
||||||
else
|
else
|
||||||
new_interface = tcp::endpoint(address(), port_range.first);
|
new_interface = tcp::endpoint(address_v4::any(), port_range.first);
|
||||||
|
|
||||||
m_listen_port_range = port_range;
|
m_listen_port_retries = port_range.second - port_range.first;
|
||||||
|
|
||||||
// if the interface is the same and the socket is open
|
// if the interface is the same and the socket is open
|
||||||
// don't do anything
|
// don't do anything
|
||||||
if (new_interface == m_listen_interface
|
if (new_interface == m_listen_interface
|
||||||
&& m_listen_socket) return true;
|
&& !m_listen_sockets.empty()) return true;
|
||||||
|
|
||||||
if (m_listen_socket)
|
|
||||||
m_listen_socket.reset();
|
|
||||||
|
|
||||||
m_incoming_connection = false;
|
|
||||||
m_listen_interface = new_interface;
|
m_listen_interface = new_interface;
|
||||||
|
|
||||||
open_listen_port();
|
open_listen_port();
|
||||||
|
@ -1723,13 +1818,14 @@ namespace detail
|
||||||
(*m_logger) << time_now_string() << "\n";
|
(*m_logger) << time_now_string() << "\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return m_listen_socket;
|
return !m_listen_sockets.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short session_impl::listen_port() const
|
unsigned short session_impl::listen_port() const
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
return m_external_listen_port;
|
if (m_listen_sockets.empty()) return 0;
|
||||||
|
return m_listen_sockets.front().external_port;;
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::announce_lsd(sha1_hash const& ih)
|
void session_impl::announce_lsd(sha1_hash const& ih)
|
||||||
|
@ -1777,7 +1873,8 @@ namespace detail
|
||||||
|
|
||||||
if (tcp_port != 0)
|
if (tcp_port != 0)
|
||||||
{
|
{
|
||||||
m_external_listen_port = tcp_port;
|
if (!m_listen_sockets.empty())
|
||||||
|
m_listen_sockets.front().external_port = tcp_port;
|
||||||
if (m_alerts.should_post(alert::info))
|
if (m_alerts.should_post(alert::info))
|
||||||
{
|
{
|
||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
|
@ -1801,7 +1898,7 @@ namespace detail
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
session_status s;
|
session_status s;
|
||||||
s.has_incoming_connections = m_incoming_connection;
|
s.has_incoming_connections = m_incoming_connection;
|
||||||
|
@ -1945,7 +2042,7 @@ namespace detail
|
||||||
bool session_impl::is_listening() const
|
bool session_impl::is_listening() const
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
return m_listen_socket;
|
return !m_listen_sockets.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
session_impl::~session_impl()
|
session_impl::~session_impl()
|
||||||
|
|
|
@ -412,9 +412,9 @@ namespace libtorrent
|
||||||
m_last_dht_announce = now;
|
m_last_dht_announce = now;
|
||||||
// TODO: There should be a way to abort an announce operation on the dht.
|
// TODO: There should be a way to abort an announce operation on the dht.
|
||||||
// when the torrent is destructed
|
// when the torrent is destructed
|
||||||
assert(m_ses.m_external_listen_port > 0);
|
if (m_ses.m_listen_sockets.empty()) return;
|
||||||
m_ses.m_dht->announce(m_torrent_file->info_hash()
|
m_ses.m_dht->announce(m_torrent_file->info_hash()
|
||||||
, m_ses.m_external_listen_port
|
, m_ses.m_listen_sockets.front().external_port
|
||||||
, m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1)));
|
, m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1367,6 +1367,9 @@ namespace libtorrent
|
||||||
req.left = bytes_left();
|
req.left = bytes_left();
|
||||||
if (req.left == -1) req.left = 16*1024;
|
if (req.left == -1) req.left = 16*1024;
|
||||||
req.event = m_event;
|
req.event = m_event;
|
||||||
|
tcp::endpoint ep = m_ses.get_ipv6_interface();
|
||||||
|
if (ep != tcp::endpoint())
|
||||||
|
req.ipv6 = ep.address().to_string();
|
||||||
|
|
||||||
if (m_event != tracker_request::stopped)
|
if (m_event != tracker_request::stopped)
|
||||||
m_event = tracker_request::none;
|
m_event = tracker_request::none;
|
||||||
|
|
|
@ -400,9 +400,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
if (i->first == "pieces"
|
if (i->first == "pieces"
|
||||||
|| i->first == "piece length"
|
|| i->first == "piece length"
|
||||||
|| i->first == "length"
|
|| i->first == "length")
|
||||||
// || i->first == "files"
|
|
||||||
|| i->first == "name")
|
|
||||||
continue;
|
continue;
|
||||||
m_extra_info[i->first] = i->second;
|
m_extra_info[i->first] = i->second;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue