forked from premiere/premiere-libtorrent
added session::listen_no_system_port flag to prevent libtorrent from ever binding the listen socket to port 0
This commit is contained in:
parent
a86ad2f7b9
commit
cb6f38f056
|
@ -1,3 +1,4 @@
|
||||||
|
* added session::listen_no_system_port flag to prevent libtorrent from ever binding the listen socket to port 0
|
||||||
* added option to not recheck on missing or incomplete resume data
|
* added option to not recheck on missing or incomplete resume data
|
||||||
* extended stats logging with statistics=on builds
|
* extended stats logging with statistics=on builds
|
||||||
* added new session functions to more efficiently query torrent status
|
* added new session functions to more efficiently query torrent status
|
||||||
|
|
|
@ -207,9 +207,14 @@ The ``session`` class has the following synopsis::
|
||||||
bool is_listening() const;
|
bool is_listening() const;
|
||||||
unsigned short listen_port() const;
|
unsigned short listen_port() const;
|
||||||
|
|
||||||
enum { listen_reuse_address = 1 };
|
enum {
|
||||||
bool listen_on(
|
listen_reuse_address = 1,
|
||||||
|
listen_no_system_port = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
void listen_on(
|
||||||
std::pair<int, int> const& port_range
|
std::pair<int, int> const& port_range
|
||||||
|
, error_code& ec
|
||||||
, char const* interface = 0
|
, char const* interface = 0
|
||||||
, int flags = 0);
|
, int flags = 0);
|
||||||
|
|
||||||
|
@ -927,8 +932,15 @@ is_listening() listen_port() listen_on()
|
||||||
|
|
||||||
bool is_listening() const;
|
bool is_listening() const;
|
||||||
unsigned short listen_port() const;
|
unsigned short listen_port() const;
|
||||||
bool listen_on(
|
|
||||||
|
enum {
|
||||||
|
listen_reuse_address = 1,
|
||||||
|
listen_no_system_port = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
void listen_on(
|
||||||
std::pair<int, int> const& port_range
|
std::pair<int, int> const& port_range
|
||||||
|
, error_code& ec
|
||||||
, char const* interface = 0
|
, char const* interface = 0
|
||||||
, int flags = 0);
|
, int flags = 0);
|
||||||
|
|
||||||
|
@ -946,12 +958,18 @@ will be opened with these new settings. The port range is the ports it will try
|
||||||
to listen on, if the first port fails, it will continue trying the next port within
|
to listen on, if the first port fails, it will continue trying the next port within
|
||||||
the range and so on. The interface parameter can be left as 0, in that case the
|
the range and so on. The interface parameter can be left as 0, in that case the
|
||||||
os will decide which interface to listen on, otherwise it should be the ip-address
|
os will decide which interface to listen on, otherwise it should be the ip-address
|
||||||
of the interface you want the listener socket bound to. ``listen_on()`` returns true
|
of the interface you want the listener socket bound to. ``listen_on()`` returns the
|
||||||
if it managed to open the socket, and false if it failed. If it fails, it will also
|
error code of the operation in ``ec``. If this indicates success, the session is
|
||||||
generate an appropriate alert (listen_failed_alert_). If all ports in the specified
|
listening on a port within the specified range. If it fails, it will also
|
||||||
range fails to be opened for listening, libtorrent will try to use port 0 (which
|
generate an appropriate alert (listen_failed_alert_).
|
||||||
tells the operating system to pick a port that's free). If that still fails you
|
|
||||||
may see a listen_failed_alert_ with port 0 even if you didn't ask to listen on it.
|
If all ports in the specified range fails to be opened for listening, libtorrent will
|
||||||
|
try to use port 0 (which tells the operating system to pick a port that's free). If
|
||||||
|
that still fails you may see a listen_failed_alert_ with port 0 even if you didn't
|
||||||
|
ask to listen on it.
|
||||||
|
|
||||||
|
It is possible to prevent libtorrent from binding to port 0 by passing in the flag
|
||||||
|
``session::no_system_port`` in the ``flags`` argument.
|
||||||
|
|
||||||
The interface parameter can also be a hostname that will resolve to the device you
|
The interface parameter can also be a hostname that will resolve to the device you
|
||||||
want to listen on. If you don't specify an interface, libtorrent may attempt to
|
want to listen on. If you don't specify an interface, libtorrent may attempt to
|
||||||
|
|
|
@ -174,7 +174,7 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
void main_thread();
|
void main_thread();
|
||||||
|
|
||||||
void open_listen_port(bool reuse_address);
|
void open_listen_port(int flags, error_code& ec);
|
||||||
|
|
||||||
// if we are listening on an IPv6 interface
|
// if we are listening on an IPv6 interface
|
||||||
// this will return one of the IPv6 addresses on this
|
// this will return one of the IPv6 addresses on this
|
||||||
|
@ -260,8 +260,9 @@ namespace libtorrent
|
||||||
|
|
||||||
void set_port_filter(port_filter const& f);
|
void set_port_filter(port_filter const& f);
|
||||||
|
|
||||||
bool listen_on(
|
void listen_on(
|
||||||
std::pair<int, int> const& port_range
|
std::pair<int, int> const& port_range
|
||||||
|
, error_code& ec
|
||||||
, const char* net_interface = 0
|
, const char* net_interface = 0
|
||||||
, int flags = 0);
|
, int flags = 0);
|
||||||
bool is_listening() const;
|
bool is_listening() const;
|
||||||
|
@ -667,7 +668,7 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
listen_socket_t setup_listener(tcp::endpoint ep, int retries
|
listen_socket_t setup_listener(tcp::endpoint ep, int retries
|
||||||
, bool v6_only, bool reuse_address);
|
, bool v6_only, int flags, error_code& ec);
|
||||||
|
|
||||||
// the settings for the client
|
// the settings for the client
|
||||||
session_settings m_settings;
|
session_settings m_settings;
|
||||||
|
|
|
@ -317,11 +317,25 @@ namespace libtorrent
|
||||||
// this function will return false on failure.
|
// this function will return false on failure.
|
||||||
// If it fails, it will also generate alerts describing
|
// If it fails, it will also generate alerts describing
|
||||||
// the error. It will return true on success.
|
// the error. It will return true on success.
|
||||||
enum { listen_reuse_address = 1 };
|
enum
|
||||||
|
{
|
||||||
|
listen_reuse_address = 0x01,
|
||||||
|
listen_no_system_port = 0x02
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
|
// deprecated in 0.16
|
||||||
|
TORRENT_DEPRECATED_PREFIX
|
||||||
bool listen_on(
|
bool listen_on(
|
||||||
std::pair<int, int> const& port_range
|
std::pair<int, int> const& port_range
|
||||||
, const char* net_interface = 0
|
, const char* net_interface = 0
|
||||||
|
, int flags = 0) TORRENT_DEPRECATED;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void listen_on(
|
||||||
|
std::pair<int, int> const& port_range
|
||||||
|
, error_code& ec
|
||||||
|
, const char* net_interface = 0
|
||||||
, int flags = 0);
|
, int flags = 0);
|
||||||
|
|
||||||
// returns the port we ended up listening on
|
// returns the port we ended up listening on
|
||||||
|
|
|
@ -306,6 +306,12 @@ namespace libtorrent
|
||||||
m_impl->m_io_service.post(boost::bind(&fun_wrap, &done, &m_impl->cond, &m_impl->mut, boost::function<void(void)>(boost::bind(&session_impl:: x, m_impl.get(), a1, a2, a3)))); \
|
m_impl->m_io_service.post(boost::bind(&fun_wrap, &done, &m_impl->cond, &m_impl->mut, boost::function<void(void)>(boost::bind(&session_impl:: x, m_impl.get(), a1, a2, a3)))); \
|
||||||
do { m_impl->cond.wait(l); } while(!done)
|
do { m_impl->cond.wait(l); } while(!done)
|
||||||
|
|
||||||
|
#define TORRENT_SYNC_CALL4(x, a1, a2, a3, a4) \
|
||||||
|
bool done = false; \
|
||||||
|
mutex::scoped_lock l(m_impl->mut); \
|
||||||
|
m_impl->m_io_service.post(boost::bind(&fun_wrap, &done, &m_impl->cond, &m_impl->mut, boost::function<void(void)>(boost::bind(&session_impl:: x, m_impl.get(), a1, a2, a3, a4)))); \
|
||||||
|
do { m_impl->cond.wait(l); } while(!done)
|
||||||
|
|
||||||
#define TORRENT_SYNC_CALL_RET(type, x) \
|
#define TORRENT_SYNC_CALL_RET(type, x) \
|
||||||
bool done = false; \
|
bool done = false; \
|
||||||
type r; \
|
type r; \
|
||||||
|
@ -648,12 +654,23 @@ namespace libtorrent
|
||||||
TORRENT_ASYNC_CALL2(remove_torrent, h, options);
|
TORRENT_ASYNC_CALL2(remove_torrent, h, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
bool session::listen_on(
|
bool session::listen_on(
|
||||||
std::pair<int, int> const& port_range
|
std::pair<int, int> const& port_range
|
||||||
, const char* net_interface, int flags)
|
, const char* net_interface, int flags)
|
||||||
{
|
{
|
||||||
TORRENT_SYNC_CALL_RET3(bool, listen_on, port_range, net_interface, flags);
|
error_code ec;
|
||||||
return r;
|
TORRENT_SYNC_CALL4(listen_on, port_range, boost::ref(ec), net_interface, flags);
|
||||||
|
return bool(ec);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void session::listen_on(
|
||||||
|
std::pair<int, int> const& port_range
|
||||||
|
, error_code& ec
|
||||||
|
, const char* net_interface, int flags)
|
||||||
|
{
|
||||||
|
TORRENT_SYNC_CALL4(listen_on, port_range, boost::ref(ec), net_interface, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short session::listen_port() const
|
unsigned short session::listen_port() const
|
||||||
|
|
|
@ -974,8 +974,8 @@ namespace aux {
|
||||||
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING
|
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string() << " open listen port\n";
|
(*m_logger) << time_now_string() << " open listen port\n";
|
||||||
#endif
|
#endif
|
||||||
// no reuse_address
|
// no reuse_address and allow system defined port
|
||||||
open_listen_port(false);
|
open_listen_port(0, ec);
|
||||||
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING
|
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string() << " done starting session\n";
|
(*m_logger) << time_now_string() << " done starting session\n";
|
||||||
#endif
|
#endif
|
||||||
|
@ -1706,32 +1706,36 @@ namespace aux {
|
||||||
}
|
}
|
||||||
|
|
||||||
session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep
|
session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep
|
||||||
, int retries, bool v6_only, bool reuse_address)
|
, int retries, bool v6_only, int flags, error_code& ec)
|
||||||
{
|
{
|
||||||
error_code ec;
|
|
||||||
listen_socket_t s;
|
listen_socket_t s;
|
||||||
s.sock.reset(new socket_acceptor(m_io_service));
|
s.sock.reset(new socket_acceptor(m_io_service));
|
||||||
s.sock->open(ep.protocol(), ec);
|
s.sock->open(ep.protocol(), ec);
|
||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
(*m_logger) << "failed to open socket: " << print_endpoint(ep)
|
(*m_logger) << "failed to open socket: " << print_endpoint(ep)
|
||||||
<< ": " << ec.message() << "\n" << "\n";
|
<< ": " << ec.message() << "\n" << "\n";
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if (reuse_address)
|
return listen_socket_t();
|
||||||
s.sock->set_option(socket_acceptor::reuse_address(true), ec);
|
}
|
||||||
|
if (flags & session::listen_reuse_address)
|
||||||
|
{
|
||||||
|
error_code err; // ignore errors here
|
||||||
|
s.sock->set_option(socket_acceptor::reuse_address(true), err);
|
||||||
|
}
|
||||||
#if TORRENT_USE_IPV6
|
#if TORRENT_USE_IPV6
|
||||||
if (ep.protocol() == tcp::v6())
|
if (ep.protocol() == tcp::v6())
|
||||||
{
|
{
|
||||||
s.sock->set_option(v6only(v6_only), ec);
|
error_code err; // ignore errors here
|
||||||
|
s.sock->set_option(v6only(v6_only), err);
|
||||||
#ifdef TORRENT_WINDOWS
|
#ifdef TORRENT_WINDOWS
|
||||||
|
|
||||||
#ifndef PROTECTION_LEVEL_UNRESTRICTED
|
#ifndef PROTECTION_LEVEL_UNRESTRICTED
|
||||||
#define PROTECTION_LEVEL_UNRESTRICTED 10
|
#define PROTECTION_LEVEL_UNRESTRICTED 10
|
||||||
#endif
|
#endif
|
||||||
// enable Teredo on windows
|
// enable Teredo on windows
|
||||||
s.sock->set_option(v6_protection_level(PROTECTION_LEVEL_UNRESTRICTED), ec);
|
s.sock->set_option(v6_protection_level(PROTECTION_LEVEL_UNRESTRICTED), err);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1744,15 +1748,15 @@ namespace aux {
|
||||||
, print_endpoint(ep).c_str(), ec.message().c_str());
|
, print_endpoint(ep).c_str(), ec.message().c_str());
|
||||||
(*m_logger) << time_now_string() << " " << msg << "\n";
|
(*m_logger) << time_now_string() << " " << msg << "\n";
|
||||||
#endif
|
#endif
|
||||||
ec = error_code();
|
ec.clear();
|
||||||
TORRENT_ASSERT_VAL(!ec, ec);
|
TORRENT_ASSERT_VAL(!ec, ec);
|
||||||
--retries;
|
--retries;
|
||||||
ep.port(ep.port() + 1);
|
ep.port(ep.port() + 1);
|
||||||
s.sock->bind(ep, ec);
|
s.sock->bind(ep, ec);
|
||||||
}
|
}
|
||||||
if (ec)
|
if (ec && !(flags & session::listen_no_system_port))
|
||||||
{
|
{
|
||||||
// instead of giving up, try
|
// instead of giving up, trying
|
||||||
// let the OS pick a port
|
// let the OS pick a port
|
||||||
ep.port(0);
|
ep.port(0);
|
||||||
ec = error_code();
|
ec = error_code();
|
||||||
|
@ -1772,7 +1776,7 @@ namespace aux {
|
||||||
return listen_socket_t();
|
return listen_socket_t();
|
||||||
}
|
}
|
||||||
s.external_port = s.sock->local_endpoint(ec).port();
|
s.external_port = s.sock->local_endpoint(ec).port();
|
||||||
s.sock->listen(m_settings.listen_queue_size, ec);
|
if (!ec) s.sock->listen(m_settings.listen_queue_size, ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
if (m_alerts.should_post<listen_failed_alert>())
|
if (m_alerts.should_post<listen_failed_alert>())
|
||||||
|
@ -1796,7 +1800,7 @@ namespace aux {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::open_listen_port(bool reuse_address)
|
void session_impl::open_listen_port(int flags, error_code& ec)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_network_thread());
|
TORRENT_ASSERT(is_network_thread());
|
||||||
|
|
||||||
|
@ -1814,14 +1818,13 @@ namespace aux {
|
||||||
|
|
||||||
listen_socket_t s = setup_listener(
|
listen_socket_t s = setup_listener(
|
||||||
tcp::endpoint(address_v4::any(), m_listen_interface.port())
|
tcp::endpoint(address_v4::any(), m_listen_interface.port())
|
||||||
, m_listen_port_retries, false, reuse_address);
|
, m_listen_port_retries, false, flags, ec);
|
||||||
|
|
||||||
if (s.sock)
|
if (s.sock)
|
||||||
{
|
{
|
||||||
// update the listen_interface member with the
|
// update the listen_interface member with the
|
||||||
// actual port we ended up listening on, so that the other
|
// actual port we ended up listening on, so that the other
|
||||||
// sockets can be bound to the same one
|
// sockets can be bound to the same one
|
||||||
error_code ec;
|
|
||||||
m_listen_interface.port(s.sock->local_endpoint(ec).port());
|
m_listen_interface.port(s.sock->local_endpoint(ec).port());
|
||||||
|
|
||||||
m_listen_sockets.push_back(s);
|
m_listen_sockets.push_back(s);
|
||||||
|
@ -1834,7 +1837,7 @@ namespace aux {
|
||||||
{
|
{
|
||||||
s = setup_listener(
|
s = setup_listener(
|
||||||
tcp::endpoint(address_v6::any(), m_listen_interface.port())
|
tcp::endpoint(address_v6::any(), m_listen_interface.port())
|
||||||
, m_listen_port_retries, true, reuse_address);
|
, m_listen_port_retries, true, flags, ec);
|
||||||
|
|
||||||
if (s.sock)
|
if (s.sock)
|
||||||
{
|
{
|
||||||
|
@ -1864,7 +1867,7 @@ namespace aux {
|
||||||
// binds to the given interface
|
// binds to the given interface
|
||||||
|
|
||||||
listen_socket_t s = setup_listener(
|
listen_socket_t s = setup_listener(
|
||||||
m_listen_interface, m_listen_port_retries, false, reuse_address);
|
m_listen_interface, m_listen_port_retries, false, flags, ec);
|
||||||
|
|
||||||
if (s.sock)
|
if (s.sock)
|
||||||
{
|
{
|
||||||
|
@ -1876,10 +1879,8 @@ namespace aux {
|
||||||
else
|
else
|
||||||
m_ipv4_interface = m_listen_interface;
|
m_ipv4_interface = m_listen_interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code ec;
|
|
||||||
m_udp_socket.bind(udp::endpoint(m_listen_interface.address(), m_listen_interface.port()), ec);
|
m_udp_socket.bind(udp::endpoint(m_listen_interface.address(), m_listen_interface.port()), ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
|
@ -4097,8 +4098,9 @@ namespace aux {
|
||||||
TORRENT_ASSERT(m_torrents.find(i_hash) == m_torrents.end());
|
TORRENT_ASSERT(m_torrents.find(i_hash) == m_torrents.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool session_impl::listen_on(
|
void session_impl::listen_on(
|
||||||
std::pair<int, int> const& port_range
|
std::pair<int, int> const& port_range
|
||||||
|
, error_code& ec
|
||||||
, const char* net_interface, int flags)
|
, const char* net_interface, int flags)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
@ -4106,7 +4108,6 @@ namespace aux {
|
||||||
tcp::endpoint new_interface;
|
tcp::endpoint new_interface;
|
||||||
if (net_interface && std::strlen(net_interface) > 0)
|
if (net_interface && std::strlen(net_interface) > 0)
|
||||||
{
|
{
|
||||||
error_code ec;
|
|
||||||
new_interface = tcp::endpoint(address::from_string(net_interface, ec), port_range.first);
|
new_interface = tcp::endpoint(address::from_string(net_interface, ec), port_range.first);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
|
@ -4114,29 +4115,33 @@ namespace aux {
|
||||||
(*m_logger) << time_now_string() << "listen_on: " << net_interface
|
(*m_logger) << time_now_string() << "listen_on: " << net_interface
|
||||||
<< " failed: " << ec.message() << "\n";
|
<< " failed: " << ec.message() << "\n";
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
new_interface = tcp::endpoint(address_v4::any(), port_range.first);
|
new_interface = tcp::endpoint(address_v4::any(), port_range.first);
|
||||||
|
}
|
||||||
|
|
||||||
m_listen_port_retries = port_range.second - port_range.first;
|
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_sockets.empty()) return true;
|
&& !m_listen_sockets.empty())
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(ec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_listen_interface = new_interface;
|
m_listen_interface = new_interface;
|
||||||
|
|
||||||
open_listen_port(flags & session::listen_reuse_address);
|
open_listen_port(flags, ec);
|
||||||
|
|
||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
m_logger = create_log("main_session", listen_port(), false);
|
m_logger = create_log("main_session", listen_port(), false);
|
||||||
(*m_logger) << time_now_string() << "\n";
|
(*m_logger) << time_now_string() << "\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return !m_listen_sockets.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
address session_impl::listen_address() const
|
address session_impl::listen_address() const
|
||||||
|
@ -4373,7 +4378,10 @@ namespace aux {
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
if (m_listen_interface.port() != 0)
|
if (m_listen_interface.port() != 0)
|
||||||
open_listen_port(false);
|
{
|
||||||
|
error_code ec;
|
||||||
|
open_listen_port(0, ec);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_dht)
|
if (m_dht)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue