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_download_rate;
bool broadcast_lsd;
};
``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
`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
===========

View File

@ -72,26 +72,37 @@ namespace libtorrent
void send(char const* buffer, int size, error_code& ec);
void close();
int num_send_sockets() const { return m_unicast_sockets.size(); }
void enable_ip_broadcast(bool e);
private:
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;
char buffer[1024];
udp::endpoint remote;
address_v4 netmask;
void close()
{
if (!socket) return;
error_code 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
, 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
, bool loopback, error_code& ec);
@ -106,6 +117,11 @@ namespace libtorrent
std::list<socket_entry> m_unicast_sockets;
udp::endpoint m_multicast_endpoint;
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 close();
void use_broadcast(bool b);
private:
void resend_announce(error_code const& e, std::string msg);

View File

@ -207,6 +207,7 @@ namespace libtorrent
, strict_end_game_mode(true)
, default_peer_upload_rate(0)
, default_peer_download_rate(0)
, broadcast_lsd(false)
{}
// 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
int default_peer_upload_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

View File

@ -187,6 +187,7 @@ namespace libtorrent
, bool loopback)
: m_multicast_endpoint(multicast_endpoint)
, m_on_receive(handler)
, m_ip_broadcast(false)
{
TORRENT_ASSERT(is_multicast(m_multicast_endpoint.address()));
@ -218,7 +219,22 @@ namespace libtorrent
// , print_address(multicast_endpoint.address()).c_str()
// , ec.message().c_str());
#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));
}
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;
error_code ec;
@ -255,7 +272,7 @@ namespace libtorrent
if (ec) return;
s->bind(udp::endpoint(addr, 0), ec);
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();
s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer))
, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
@ -289,6 +306,9 @@ namespace libtorrent
if (!i->socket) continue;
error_code 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
// extern std::string print_address(address const& addr);
// extern std::string print_endpoint(udp::endpoint const& ep);

View File

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

View File

@ -806,6 +806,12 @@ namespace aux {
}
}
#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();
}
@ -1164,6 +1170,8 @@ namespace aux {
m_auto_manage_time_scaler = 2;
m_settings = s;
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)
update_disk_thread_settings();
@ -3630,6 +3638,8 @@ namespace aux {
m_lsd = new lsd(m_io_service
, m_listen_interface.address()
, 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)