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
|
||||
* extended stats logging with statistics=on builds
|
||||
* 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;
|
||||
unsigned short listen_port() const;
|
||||
|
||||
enum { listen_reuse_address = 1 };
|
||||
bool listen_on(
|
||||
enum {
|
||||
listen_reuse_address = 1,
|
||||
listen_no_system_port = 2
|
||||
};
|
||||
|
||||
void listen_on(
|
||||
std::pair<int, int> const& port_range
|
||||
, error_code& ec
|
||||
, char const* interface = 0
|
||||
, int flags = 0);
|
||||
|
||||
|
@ -927,8 +932,15 @@ is_listening() listen_port() listen_on()
|
|||
|
||||
bool is_listening() 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
|
||||
, error_code& ec
|
||||
, char const* interface = 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
|
||||
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
|
||||
of the interface you want the listener socket bound to. ``listen_on()`` returns true
|
||||
if it managed to open the socket, and false if it failed. If it fails, it will also
|
||||
generate an appropriate alert (listen_failed_alert_). 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.
|
||||
of the interface you want the listener socket bound to. ``listen_on()`` returns the
|
||||
error code of the operation in ``ec``. If this indicates success, the session is
|
||||
listening on a port within the specified range. If it fails, it will also
|
||||
generate an appropriate alert (listen_failed_alert_).
|
||||
|
||||
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
|
||||
want to listen on. If you don't specify an interface, libtorrent may attempt to
|
||||
|
|
|
@ -174,7 +174,7 @@ namespace libtorrent
|
|||
#endif
|
||||
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
|
||||
// this will return one of the IPv6 addresses on this
|
||||
|
@ -260,8 +260,9 @@ namespace libtorrent
|
|||
|
||||
void set_port_filter(port_filter const& f);
|
||||
|
||||
bool listen_on(
|
||||
void listen_on(
|
||||
std::pair<int, int> const& port_range
|
||||
, error_code& ec
|
||||
, const char* net_interface = 0
|
||||
, int flags = 0);
|
||||
bool is_listening() const;
|
||||
|
@ -667,7 +668,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
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
|
||||
session_settings m_settings;
|
||||
|
|
|
@ -317,11 +317,25 @@ namespace libtorrent
|
|||
// this function will return false on failure.
|
||||
// If it fails, it will also generate alerts describing
|
||||
// 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(
|
||||
std::pair<int, int> const& port_range
|
||||
, 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);
|
||||
|
||||
// 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)))); \
|
||||
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) \
|
||||
bool done = false; \
|
||||
type r; \
|
||||
|
@ -648,12 +654,23 @@ namespace libtorrent
|
|||
TORRENT_ASYNC_CALL2(remove_torrent, h, options);
|
||||
}
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
bool session::listen_on(
|
||||
std::pair<int, int> const& port_range
|
||||
, const char* net_interface, int flags)
|
||||
{
|
||||
TORRENT_SYNC_CALL_RET3(bool, listen_on, port_range, net_interface, flags);
|
||||
return r;
|
||||
error_code ec;
|
||||
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
|
||||
|
|
|
@ -974,8 +974,8 @@ namespace aux {
|
|||
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " open listen port\n";
|
||||
#endif
|
||||
// no reuse_address
|
||||
open_listen_port(false);
|
||||
// no reuse_address and allow system defined port
|
||||
open_listen_port(0, ec);
|
||||
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " done starting session\n";
|
||||
#endif
|
||||
|
@ -1706,32 +1706,36 @@ namespace aux {
|
|||
}
|
||||
|
||||
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;
|
||||
s.sock.reset(new socket_acceptor(m_io_service));
|
||||
s.sock->open(ep.protocol(), ec);
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
if (ec)
|
||||
{
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
(*m_logger) << "failed to open socket: " << print_endpoint(ep)
|
||||
<< ": " << ec.message() << "\n" << "\n";
|
||||
}
|
||||
#endif
|
||||
if (reuse_address)
|
||||
s.sock->set_option(socket_acceptor::reuse_address(true), ec);
|
||||
return listen_socket_t();
|
||||
}
|
||||
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 (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
|
||||
|
||||
#ifndef PROTECTION_LEVEL_UNRESTRICTED
|
||||
#define PROTECTION_LEVEL_UNRESTRICTED 10
|
||||
#endif
|
||||
// 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
|
||||
|
@ -1744,15 +1748,15 @@ namespace aux {
|
|||
, print_endpoint(ep).c_str(), ec.message().c_str());
|
||||
(*m_logger) << time_now_string() << " " << msg << "\n";
|
||||
#endif
|
||||
ec = error_code();
|
||||
ec.clear();
|
||||
TORRENT_ASSERT_VAL(!ec, ec);
|
||||
--retries;
|
||||
ep.port(ep.port() + 1);
|
||||
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
|
||||
ep.port(0);
|
||||
ec = error_code();
|
||||
|
@ -1772,7 +1776,7 @@ namespace aux {
|
|||
return listen_socket_t();
|
||||
}
|
||||
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 (m_alerts.should_post<listen_failed_alert>())
|
||||
|
@ -1796,7 +1800,7 @@ namespace aux {
|
|||
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());
|
||||
|
||||
|
@ -1814,14 +1818,13 @@ namespace aux {
|
|||
|
||||
listen_socket_t s = setup_listener(
|
||||
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)
|
||||
{
|
||||
// update the listen_interface member with the
|
||||
// actual port we ended up listening on, so that the other
|
||||
// sockets can be bound to the same one
|
||||
error_code ec;
|
||||
m_listen_interface.port(s.sock->local_endpoint(ec).port());
|
||||
|
||||
m_listen_sockets.push_back(s);
|
||||
|
@ -1834,7 +1837,7 @@ namespace aux {
|
|||
{
|
||||
s = setup_listener(
|
||||
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)
|
||||
{
|
||||
|
@ -1864,7 +1867,7 @@ namespace aux {
|
|||
// binds to the given interface
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -1876,10 +1879,8 @@ namespace aux {
|
|||
else
|
||||
m_ipv4_interface = m_listen_interface;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
error_code ec;
|
||||
m_udp_socket.bind(udp::endpoint(m_listen_interface.address(), m_listen_interface.port()), ec);
|
||||
if (ec)
|
||||
{
|
||||
|
@ -4097,8 +4098,9 @@ namespace aux {
|
|||
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
|
||||
, error_code& ec
|
||||
, const char* net_interface, int flags)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -4106,7 +4108,6 @@ namespace aux {
|
|||
tcp::endpoint new_interface;
|
||||
if (net_interface && std::strlen(net_interface) > 0)
|
||||
{
|
||||
error_code ec;
|
||||
new_interface = tcp::endpoint(address::from_string(net_interface, ec), port_range.first);
|
||||
if (ec)
|
||||
{
|
||||
|
@ -4114,29 +4115,33 @@ namespace aux {
|
|||
(*m_logger) << time_now_string() << "listen_on: " << net_interface
|
||||
<< " failed: " << ec.message() << "\n";
|
||||
#endif
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_interface = tcp::endpoint(address_v4::any(), port_range.first);
|
||||
}
|
||||
|
||||
m_listen_port_retries = port_range.second - port_range.first;
|
||||
|
||||
// if the interface is the same and the socket is open
|
||||
// don't do anything
|
||||
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;
|
||||
|
||||
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
|
||||
m_logger = create_log("main_session", listen_port(), false);
|
||||
(*m_logger) << time_now_string() << "\n";
|
||||
#endif
|
||||
|
||||
return !m_listen_sockets.empty();
|
||||
}
|
||||
|
||||
address session_impl::listen_address() const
|
||||
|
@ -4373,7 +4378,10 @@ namespace aux {
|
|||
INVARIANT_CHECK;
|
||||
|
||||
if (m_listen_interface.port() != 0)
|
||||
open_listen_port(false);
|
||||
{
|
||||
error_code ec;
|
||||
open_listen_port(0, ec);
|
||||
}
|
||||
|
||||
if (m_dht)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue