attempt to fix #201. Uses separate sockets to send broadcast messages in order to be sure to receive unicast responses

This commit is contained in:
Arvid Norberg 2007-12-22 17:33:04 +00:00
parent 1724ce5974
commit b23e9e3795
2 changed files with 31 additions and 7 deletions

View File

@ -69,12 +69,22 @@ namespace libtorrent
boost::shared_ptr<datagram_socket> socket; boost::shared_ptr<datagram_socket> socket;
char buffer[1024]; char buffer[1024];
udp::endpoint remote; udp::endpoint remote;
void close() { socket->close(); }
}; };
void on_receive(socket_entry* s, asio::error_code const& ec void on_receive(socket_entry* s, asio::error_code const& ec
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
void open_unicast_socket(io_service& ios, address const& addr);
// these sockets are used to
// join the multicast group (on each interface)
// and receive multicast messages
std::list<socket_entry> m_sockets; std::list<socket_entry> m_sockets;
// these sockets are not bound to any
// specific port and are used to
// send messages to the multicast group
// and receive unicast responses
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;

View File

@ -163,12 +163,29 @@ namespace libtorrent
// << " group: " << multicast_endpoint.address() << " ]" << std::endl; // << " group: " << multicast_endpoint.address() << " ]" << std::endl;
#endif #endif
} }
open_unicast_socket(ios, address_v4::any());
open_unicast_socket(ios, address_v6::any());
}
void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr)
{
asio::error_code ec;
boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
s->open(addr.is_v4() ? udp::v4() : udp::v6(), ec);
if (ec) return;
s->bind(udp::endpoint(addr, 0), ec);
if (ec) return;
m_unicast_sockets.push_back(socket_entry(s));
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));
} }
void broadcast_socket::send(char const* buffer, int size, asio::error_code& ec) void broadcast_socket::send(char const* buffer, int size, asio::error_code& ec)
{ {
for (std::list<socket_entry>::iterator i = m_sockets.begin() for (std::list<socket_entry>::iterator i = m_unicast_sockets.begin()
, end(m_sockets.end()); i != end; ++i) , end(m_unicast_sockets.end()); i != end; ++i)
{ {
asio::error_code e; asio::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);
@ -192,11 +209,8 @@ namespace libtorrent
{ {
m_on_receive.clear(); m_on_receive.clear();
for (std::list<socket_entry>::iterator i = m_sockets.begin() std::for_each(m_sockets.begin(), m_sockets.end(), bind(&socket_entry::close, _1));
, end(m_sockets.end()); i != end; ++i) std::for_each(m_unicast_sockets.begin(), m_unicast_sockets.end(), bind(&socket_entry::close, _1));
{
i->socket->close();
}
} }
} }