support optional LSD IP broadcast

This commit is contained in:
Arvid Norberg 2010-03-26 17:45:16 +00:00
parent c14042b29e
commit c6f57ce5d7
7 changed files with 71 additions and 5 deletions

View File

@ -3856,6 +3856,7 @@ session_settings
int default_peer_upload_rate; int default_peer_upload_rate;
int default_peer_download_rate; int default_peer_download_rate;
bool broadcast_lsd;
}; };
``user_agent`` this is the client identification to the tracker. ``user_agent`` this is the client identification to the tracker.
@ -4467,6 +4468,11 @@ set on new peer connections (not existing ones). The peer rate limits can
be changed individually later using be changed individually later using
`set_peer_upload_limit() set_peer_download_limit()`_. `set_peer_upload_limit() set_peer_download_limit()`_.
if ``broadcast_lsd`` is set to true, the local peer discovery
(or Local Service Discovery) will not only use IP multicast, but also
broadcast its messages. This can be useful when running on networks
that don't support multicast. It's off by default since it's inefficient.
pe_settings pe_settings
=========== ===========

View File

@ -72,26 +72,37 @@ namespace libtorrent
void send(char const* buffer, int size, error_code& ec); void send(char const* buffer, int size, error_code& ec);
void close(); void close();
int num_send_sockets() const { return m_unicast_sockets.size(); } int num_send_sockets() const { return m_unicast_sockets.size(); }
void enable_ip_broadcast(bool e);
private: private:
struct socket_entry struct socket_entry
{ {
socket_entry(boost::shared_ptr<datagram_socket> const& s): socket(s) {} socket_entry(boost::shared_ptr<datagram_socket> const& s)
: socket(s) {}
socket_entry(boost::shared_ptr<datagram_socket> const& s
, address_v4 const& mask): socket(s), netmask(mask) {}
boost::shared_ptr<datagram_socket> socket; boost::shared_ptr<datagram_socket> socket;
char buffer[1024]; char buffer[1024];
udp::endpoint remote; udp::endpoint remote;
address_v4 netmask;
void close() void close()
{ {
if (!socket) return; if (!socket) return;
error_code ec; error_code ec;
socket->close(ec); socket->close(ec);
} }
address_v4 broadcast_address() const
{
error_code ec;
return address_v4::broadcast(socket->local_endpoint(ec).address().to_v4(), netmask);
}
}; };
void on_receive(socket_entry* s, error_code const& ec void on_receive(socket_entry* s, error_code const& ec
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
void open_unicast_socket(io_service& ios, address const& addr); void open_unicast_socket(io_service& ios, address const& addr
, address_v4 const& mask);
void open_multicast_socket(io_service& ios, address const& addr void open_multicast_socket(io_service& ios, address const& addr
, bool loopback, error_code& ec); , bool loopback, error_code& ec);
@ -106,6 +117,11 @@ namespace libtorrent
std::list<socket_entry> m_unicast_sockets; std::list<socket_entry> m_unicast_sockets;
udp::endpoint m_multicast_endpoint; udp::endpoint m_multicast_endpoint;
receive_handler_t m_on_receive; receive_handler_t m_on_receive;
// if set, use IP broadcast as well as IP multicast
// this is off by default because it's expensive in
// terms of bandwidth usage
bool m_ip_broadcast;
}; };
} }

View File

@ -64,6 +64,8 @@ public:
void announce(sha1_hash const& ih, int listen_port); void announce(sha1_hash const& ih, int listen_port);
void close(); void close();
void use_broadcast(bool b);
private: private:
void resend_announce(error_code const& e, std::string msg); void resend_announce(error_code const& e, std::string msg);

View File

@ -207,6 +207,7 @@ namespace libtorrent
, strict_end_game_mode(true) , strict_end_game_mode(true)
, default_peer_upload_rate(0) , default_peer_upload_rate(0)
, default_peer_download_rate(0) , default_peer_download_rate(0)
, broadcast_lsd(false)
{} {}
// this is the user agent that will be sent to the tracker // this is the user agent that will be sent to the tracker
@ -791,6 +792,12 @@ namespace libtorrent
// each peer will have these limits set on it // each peer will have these limits set on it
int default_peer_upload_rate; int default_peer_upload_rate;
int default_peer_download_rate; int default_peer_download_rate;
// if this is true, the broadcast socket will not only use IP multicast
// but also send the messages on the broadcast address. This is false by
// default in order to avoid flooding networks for no good reason. If
// a network is known not to support multicast, this can be enabled
bool broadcast_lsd;
}; };
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT

View File

@ -187,6 +187,7 @@ namespace libtorrent
, bool loopback) , bool loopback)
: m_multicast_endpoint(multicast_endpoint) : m_multicast_endpoint(multicast_endpoint)
, m_on_receive(handler) , m_on_receive(handler)
, m_ip_broadcast(false)
{ {
TORRENT_ASSERT(is_multicast(m_multicast_endpoint.address())); TORRENT_ASSERT(is_multicast(m_multicast_endpoint.address()));
@ -218,7 +219,22 @@ namespace libtorrent
// , print_address(multicast_endpoint.address()).c_str() // , print_address(multicast_endpoint.address()).c_str()
// , ec.message().c_str()); // , ec.message().c_str());
#endif #endif
open_unicast_socket(ios, i->interface_address); open_unicast_socket(ios, i->interface_address
, i->netmask.is_v4() ? i->netmask.to_v4() : address_v4());
}
}
void broadcast_socket::enable_ip_broadcast(bool e)
{
if (e == m_ip_broadcast) return;
m_ip_broadcast = e;
asio::socket_base::broadcast option(m_ip_broadcast);
for (std::list<socket_entry>::iterator i = m_unicast_sockets.begin()
, end(m_unicast_sockets.end()); i != end; ++i)
{
if (i->socket) continue;
i->socket->set_option(option);
} }
} }
@ -246,7 +262,8 @@ namespace libtorrent
, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2)); , se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
} }
void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr) void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr
, address_v4 const& mask)
{ {
using namespace asio::ip::multicast; using namespace asio::ip::multicast;
error_code ec; error_code ec;
@ -255,7 +272,7 @@ namespace libtorrent
if (ec) return; if (ec) return;
s->bind(udp::endpoint(addr, 0), ec); s->bind(udp::endpoint(addr, 0), ec);
if (ec) return; if (ec) return;
m_unicast_sockets.push_back(socket_entry(s)); m_unicast_sockets.push_back(socket_entry(s, mask));
socket_entry& se = m_unicast_sockets.back(); socket_entry& se = m_unicast_sockets.back();
s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer)) s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer))
, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2)); , se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
@ -289,6 +306,9 @@ namespace libtorrent
if (!i->socket) continue; if (!i->socket) continue;
error_code e; error_code e;
i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e); i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e);
if (m_ip_broadcast && i->socket->local_endpoint(e).address().is_v4())
i->socket->send_to(asio::buffer(buffer, size)
, udp::endpoint(i->broadcast_address(), m_multicast_endpoint.port()), 0, e);
#ifndef NDEBUG #ifndef NDEBUG
// extern std::string print_address(address const& addr); // extern std::string print_address(address const& addr);
// extern std::string print_endpoint(udp::endpoint const& ep); // extern std::string print_endpoint(udp::endpoint const& ep);

View File

@ -213,3 +213,8 @@ void lsd::close()
m_callback.clear(); m_callback.clear();
} }
void lsd::use_broadcast(bool b)
{
m_socket.enable_ip_broadcast(b);
}

View File

@ -806,6 +806,12 @@ namespace aux {
} }
} }
#endif #endif
if (m_settings.connection_speed < 0) m_settings.connection_speed = 200;
if (m_settings.broadcast_lsd && m_lsd)
m_lsd->use_broadcast(true);
update_disk_thread_settings(); update_disk_thread_settings();
} }
@ -1164,6 +1170,8 @@ namespace aux {
m_auto_manage_time_scaler = 2; m_auto_manage_time_scaler = 2;
m_settings = s; m_settings = s;
if (m_settings.connection_speed < 0) m_settings.connection_speed = 200; if (m_settings.connection_speed < 0) m_settings.connection_speed = 200;
if (m_settings.broadcast_lsd && m_lsd)
m_lsd->use_broadcast(true);
if (update_disk_io_thread) if (update_disk_io_thread)
update_disk_thread_settings(); update_disk_thread_settings();
@ -3630,6 +3638,8 @@ namespace aux {
m_lsd = new lsd(m_io_service m_lsd = new lsd(m_io_service
, m_listen_interface.address() , m_listen_interface.address()
, bind(&session_impl::on_lsd_peer, this, _1, _2)); , bind(&session_impl::on_lsd_peer, this, _1, _2));
if (m_settings.broadcast_lsd)
m_lsd->use_broadcast(true);
} }
void session_impl::start_natpmp(natpmp* n) void session_impl::start_natpmp(natpmp* n)