diff --git a/ChangeLog b/ChangeLog index 58cfb1a04..f3aca1c97 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * made the reuse-address flag configurable on the listen socket * moved UDP trackers over to use a single socket * added feature to make asserts log to a file instead of breaking the process (production asserts) @@ -32,6 +33,7 @@ incoming connection * added more detailed instrumentation of the disk I/O thread + * removed the reuse-address flag on the listen socket * fixed bug where local peer discovery and DHT wouldn't be announced to without trackers * fixed bug in bdecoder when decoding invalid messages * added build warning when building with UNICODE but the standard library diff --git a/docs/manual.rst b/docs/manual.rst index be6299711..38511235d 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -207,9 +207,12 @@ The ``session`` class has the following synopsis:: bool is_listening() const; unsigned short listen_port() const; + + enum { listen_reuse_address = 1 }; bool listen_on( std::pair const& port_range - , char const* interface = 0); + , char const* interface = 0 + , int flags = 0); std::auto_ptr pop_alert(); alert const* wait_for_alert(time_duration max_wait); @@ -917,7 +920,8 @@ is_listening() listen_port() listen_on() unsigned short listen_port() const; bool listen_on( std::pair const& port_range - , char const* interface = 0); + , char const* interface = 0 + , int flags = 0); ``is_listening()`` will tell you whether or not the session has successfully opened a listening port. If it hasn't, this function will return false, and @@ -946,6 +950,11 @@ listen on multiple interfaces (typically 0.0.0.0 and ::). This means that if you IPv6 interface doesn't work, you may still see a listen_failed_alert_, even though the IPv4 port succeeded. +The ``flags`` parameter can either be 0 or ``session::listen_reuse_address``, which +will set the reuse address socket option on the listen socket(s). By default, the +listen socket does not use reuse address. If you're running a service that needs +to run on a specific port no matter if it's in use, set this flag. + If you're also starting the DHT, it is a good idea to do that after you've called ``listen_on()``, since the default listen port for the DHT is the same as the tcp listen socket. If you start the DHT first, it will assume the tcp port is free and diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 4f46fcb45..24d8b4778 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -161,7 +161,7 @@ namespace libtorrent #endif void main_thread(); - void open_listen_port(); + void open_listen_port(bool reuse_address); // if we are listening on an IPv6 interface // this will return one of the IPv6 addresses on this @@ -236,7 +236,8 @@ namespace libtorrent bool listen_on( std::pair const& port_range - , const char* net_interface = 0); + , const char* net_interface = 0 + , int flags = 0); bool is_listening() const; torrent_handle add_torrent(add_torrent_params const&, error_code& ec); @@ -580,7 +581,8 @@ namespace libtorrent boost::shared_ptr m_i2p_listen_socket; #endif - listen_socket_t setup_listener(tcp::endpoint ep, int retries, bool v6_only = false); + listen_socket_t setup_listener(tcp::endpoint ep, int retries + , bool v6_only, bool reuse_address); // the settings for the client session_settings m_settings; diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index a5b412f29..37f820fd3 100644 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -322,9 +322,12 @@ 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 }; + bool listen_on( std::pair const& port_range - , const char* net_interface = 0); + , const char* net_interface = 0 + , int flags = 0); // returns the port we ended up listening on unsigned short listen_port() const; diff --git a/src/session.cpp b/src/session.cpp index 9ed8b66a7..10f9fdaae 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -548,10 +548,10 @@ namespace libtorrent bool session::listen_on( std::pair const& port_range - , const char* net_interface) + , const char* net_interface, int flags) { mutex::scoped_lock l(m_impl->m_mutex); - return m_impl->listen_on(port_range, net_interface); + return m_impl->listen_on(port_range, net_interface, flags); } unsigned short session::listen_port() const diff --git a/src/session_impl.cpp b/src/session_impl.cpp index e25a7636d..7ebda0c63 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -744,7 +744,8 @@ namespace aux { boost::bind(&session_impl::on_dht_announce, this, _1)); #endif - open_listen_port(); + // no reuse_address + open_listen_port(false); m_thread.reset(new thread(boost::bind(&session_impl::main_thread, this))); } @@ -1304,13 +1305,14 @@ namespace aux { } session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep - , int retries, bool v6_only) + , int retries, bool v6_only, bool reuse_address) { error_code ec; listen_socket_t s; s.sock.reset(new socket_acceptor(m_io_service)); s.sock->open(ep.protocol(), ec); - s.sock->set_option(socket_acceptor::reuse_address(true), ec); + if (reuse_address) + s.sock->set_option(socket_acceptor::reuse_address(true), ec); #if TORRENT_USE_IPV6 if (ep.protocol() == tcp::v6()) { @@ -1380,7 +1382,7 @@ namespace aux { return s; } - void session_impl::open_listen_port() + void session_impl::open_listen_port(bool reuse_address) { // close the open listen sockets m_listen_sockets.clear(); @@ -1396,7 +1398,7 @@ namespace aux { listen_socket_t s = setup_listener( tcp::endpoint(address_v4::any(), m_listen_interface.port()) - , m_listen_port_retries); + , m_listen_port_retries, false, reuse_address); if (s.sock) { @@ -1420,7 +1422,7 @@ namespace aux { { s = setup_listener( tcp::endpoint(address_v6::any(), m_listen_interface.port()) - , m_listen_port_retries, true); + , m_listen_port_retries, true, reuse_address); if (s.sock) { @@ -1450,7 +1452,7 @@ namespace aux { // binds to the given interface listen_socket_t s = setup_listener( - m_listen_interface, m_listen_port_retries); + m_listen_interface, m_listen_port_retries, false, reuse_address); if (s.sock) { @@ -3193,7 +3195,7 @@ namespace aux { bool session_impl::listen_on( std::pair const& port_range - , const char* net_interface) + , const char* net_interface, int flags) { INVARIANT_CHECK; @@ -3223,7 +3225,7 @@ namespace aux { m_listen_interface = new_interface; - open_listen_port(); + open_listen_port(flags & session::listen_reuse_address); #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING m_logger = create_log("main_session", listen_port(), false); @@ -3430,7 +3432,7 @@ namespace aux { INVARIANT_CHECK; if (m_listen_interface.port() != 0) - open_listen_port(); + open_listen_port(false); if (m_dht) {