From ba437cf72ee5bc36ac31719402fe7e7f9e33cb84 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 19 Sep 2007 21:54:26 +0000 Subject: [PATCH] some more IPv6 support --- src/broadcast_socket.cpp | 72 ++++++++++++++++++++++++--------- src/bt_peer_connection.cpp | 14 +++++++ src/http_tracker_connection.cpp | 23 ++++++++--- src/ut_pex.cpp | 69 ++++++++++++++++++++++++++----- 4 files changed, 143 insertions(+), 35 deletions(-) diff --git a/src/broadcast_socket.cpp b/src/broadcast_socket.cpp index 9355ffc95..3aaadcc81 100644 --- a/src/broadcast_socket.cpp +++ b/src/broadcast_socket.cpp @@ -43,7 +43,7 @@ namespace libtorrent { bool is_local(address const& a) { - if (a.is_v6()) return false; + if (a.is_v6()) return a.to_v6().is_link_local(); address_v4 a4 = a.to_v4(); unsigned long ip = a4.to_ulong(); return ((ip & 0xff000000) == 0x0a000000 @@ -58,15 +58,32 @@ namespace libtorrent udp::resolver::iterator i = r.resolve(udp::resolver::query(asio::ip::host_name(), "0")); for (;i != udp::resolver_iterator(); ++i) { - // ignore the loopback - if (i->endpoint().address() == address_v4((127 << 24) + 1)) continue; + address const& a = i->endpoint().address(); // ignore non-IPv4 addresses - if (i->endpoint().address().is_v4()) break; + if (!a.is_v4()) break; + // ignore the loopback + if (a.to_v4() == address_v4::loopback()) continue; } if (i == udp::resolver_iterator()) return address_v4::any(); return i->endpoint().address().to_v4(); } + bool is_loopback(address const& addr) + { + if (addr.is_v4()) + return addr.to_v4() == address_v4::loopback(); + else + return addr.to_v6() == address_v6::loopback(); + } + + bool is_multicast(address const& addr) + { + if (addr.is_v4()) + return addr.to_v4().is_multicast(); + else + return addr.to_v6().is_multicast(); + } + broadcast_socket::broadcast_socket(asio::io_service& ios , udp::endpoint const& multicast_endpoint , receive_handler_t const& handler @@ -74,8 +91,7 @@ namespace libtorrent : m_multicast_endpoint(multicast_endpoint) , m_on_receive(handler) { - assert(m_multicast_endpoint.address().is_v4()); - assert(m_multicast_endpoint.address().to_v4().is_multicast()); + assert(is_multicast(m_multicast_endpoint.address())); using namespace asio::ip::multicast; @@ -86,21 +102,39 @@ namespace libtorrent , end(interfaces.end()); i != end; ++i) { // only broadcast to IPv4 addresses that are not local - if (!i->is_v4() || !is_local(*i)) continue; - // ignore the loopback interface - if (i->to_v4() == address_v4((127 << 24) + 1)) continue; + if (!is_local(*i)) continue; + // only multicast on compatible networks + if (i->is_v4() != multicast_endpoint.address().is_v4()) continue; + // ignore any loopback interface + if (is_loopback(*i)) continue; boost::shared_ptr s(new datagram_socket(ios)); - s->open(udp::v4(), ec); - if (ec) continue; - s->set_option(datagram_socket::reuse_address(true), ec); - if (ec) continue; - s->bind(udp::endpoint(address_v4::any(), multicast_endpoint.port()), ec); - if (ec) continue; - s->set_option(join_group(multicast_endpoint.address()), ec); - if (ec) continue; - s->set_option(outbound_interface(i->to_v4()), ec); - if (ec) continue; + if (i->is_v4()) + { + s->open(udp::v4(), ec); + if (ec) continue; + s->set_option(datagram_socket::reuse_address(true), ec); + if (ec) continue; + s->bind(udp::endpoint(address_v4::any(), multicast_endpoint.port()), ec); + if (ec) continue; + s->set_option(join_group(multicast_endpoint.address()), ec); + if (ec) continue; + s->set_option(outbound_interface(i->to_v4()), ec); + if (ec) continue; + } + else + { + s->open(udp::v6(), ec); + if (ec) continue; + s->set_option(datagram_socket::reuse_address(true), ec); + if (ec) continue; + s->bind(udp::endpoint(address_v6::any(), multicast_endpoint.port()), ec); + if (ec) continue; + s->set_option(join_group(multicast_endpoint.address()), ec); + if (ec) continue; +// s->set_option(outbound_interface(i->to_v6()), ec); +// if (ec) continue; + } s->set_option(hops(255), ec); if (ec) continue; s->set_option(enable_loopback(loopback), ec); diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index f7f137437..ab61d98f9 100755 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -50,6 +50,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/version.hpp" #include "libtorrent/extensions.hpp" #include "libtorrent/aux_/session_impl.hpp" +#include "libtorrent/enum_net.hpp" #ifndef TORRENT_DISABLE_ENCRYPTION #include "libtorrent/pe_crypto.hpp" @@ -1474,6 +1475,19 @@ namespace libtorrent detail::write_address(remote().address(), out); handshake["yourip"] = remote_address; handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue; + asio::error_code ec; + std::vector
const& interfaces = enum_net_interfaces(get_socket()->io_service(), ec); + for (std::vector
::const_iterator i = interfaces.begin() + , end(interfaces.end()); i != end; ++i) + { + // TODO: only use global IPv6 addresses + if (!i->is_v6() || i->to_v6().is_link_local()) continue; + std::string ipv6_address; + std::back_insert_iterator out(ipv6_address); + detail::write_address(*i, out); + handshake["ipv6"] = ipv6_address; + break; + } // loop backwards, to make the first extension be the last // to fill in the handshake (i.e. give the first extensions priority) diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index c316b5b4e..3fcd97dbc 100755 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -890,12 +890,7 @@ namespace libtorrent peer_entry p; p.pid.clear(); - std::stringstream ip_str; - ip_str << (int)detail::read_uint8(i) << "."; - ip_str << (int)detail::read_uint8(i) << "."; - ip_str << (int)detail::read_uint8(i) << "."; - ip_str << (int)detail::read_uint8(i); - p.ip = ip_str.str(); + p.ip = detail::read_v4_address(i).to_string(); p.port = detail::read_uint16(i); peer_list.push_back(p); } @@ -910,6 +905,22 @@ namespace libtorrent } } + if (entry const* ipv6_peers = e.find_key("peers6")) + { + std::string const& peers = ipv6_peers->string(); + for (std::string::const_iterator i = peers.begin(); + i != peers.end();) + { + if (std::distance(i, peers.end()) < 18) break; + + peer_entry p; + p.pid.clear(); + p.ip = detail::read_v6_address(i).to_string(); + p.port = detail::read_uint16(i); + peer_list.push_back(p); + } + } + // look for optional scrape info int complete = -1; int incomplete = -1; diff --git a/src/ut_pex.cpp b/src/ut_pex.cpp index 15913573e..18fe715ee 100644 --- a/src/ut_pex.cpp +++ b/src/ut_pex.cpp @@ -67,8 +67,6 @@ namespace libtorrent { namespace if (!p.is_local()) return false; // don't send out peers that we haven't successfully connected to if (p.is_connecting()) return false; - // ut pex does not support IPv6 - if (!p.remote().address().is_v4()) return false; return true; } @@ -98,9 +96,15 @@ namespace libtorrent { namespace std::string& pla = pex["added"].string(); std::string& pld = pex["dropped"].string(); std::string& plf = pex["added.f"].string(); + std::string& pla6 = pex["added6"].string(); + std::string& pld6 = pex["dropped6"].string(); + std::string& plf6 = pex["added6.f"].string(); std::back_insert_iterator pla_out(pla); std::back_insert_iterator pld_out(pld); std::back_insert_iterator plf_out(plf); + std::back_insert_iterator pla6_out(pla6); + std::back_insert_iterator pld6_out(pld6); + std::back_insert_iterator plf6_out(plf6); std::set dropped; m_old_peers.swap(dropped); @@ -123,8 +127,6 @@ namespace libtorrent { namespace bt_peer_connection* p = dynamic_cast(i->second); if (!p) continue; - // i->first was added since the last time - detail::write_endpoint(i->first, pla_out); // no supported flags to set yet // 0x01 - peer supports encryption // 0x02 - peer is a seed @@ -132,7 +134,17 @@ namespace libtorrent { namespace #ifndef TORRENT_DISABLE_ENCRYPTION flags |= p->supports_encryption() ? 1 : 0; #endif - detail::write_uint8(flags, plf_out); + // i->first was added since the last time + if (i->first.address().is_v4()) + { + detail::write_endpoint(i->first, pla_out); + detail::write_uint8(flags, plf_out); + } + else + { + detail::write_endpoint(i->first, pla6_out); + detail::write_uint8(flags, plf6_out); + } ++num_added; } else @@ -146,8 +158,10 @@ namespace libtorrent { namespace for (std::set::const_iterator i = dropped.begin() , end(dropped.end());i != end; ++i) { - if (!i->address().is_v4()) continue; - detail::write_endpoint(*i, pld_out); + if (i->address().is_v4()) + detail::write_endpoint(*i, pld_out); + else + detail::write_endpoint(*i, pld6_out); } m_ut_pex_msg.clear(); @@ -227,6 +241,28 @@ namespace libtorrent { namespace char flags = detail::read_uint8(fin); p.peer_from_tracker(adr, pid, peer_info::pex, flags); } + + if (entry const* p6 = pex_msg.find_key("added6")) + { + std::string const& peers6 = p6->string(); + std::string const& peer6_flags = pex_msg["added6.f"].string(); + + int num_peers = peers6.length() / 18; + char const* in = peers6.c_str(); + char const* fin = peer6_flags.c_str(); + + if (int(peer6_flags.size()) != num_peers) + return true; + + peer_id pid(0); + policy& p = m_torrent.get_policy(); + for (int i = 0; i < num_peers; ++i) + { + tcp::endpoint adr = detail::read_v6_endpoint(in); + char flags = detail::read_uint8(fin); + p.peer_from_tracker(adr, pid, peer_info::pex, flags); + } + } } catch (std::exception&) { @@ -279,8 +315,13 @@ namespace libtorrent { namespace pex["dropped"].string(); std::string& pla = pex["added"].string(); std::string& plf = pex["added.f"].string(); + pex["dropped6"].string(); + std::string& pla6 = pex["added6"].string(); + std::string& plf6 = pex["added6.f"].string(); std::back_insert_iterator pla_out(pla); std::back_insert_iterator plf_out(plf); + std::back_insert_iterator pla6_out(pla6); + std::back_insert_iterator plf6_out(plf6); int num_added = 0; for (torrent::peer_iterator i = m_torrent.begin() @@ -295,8 +336,6 @@ namespace libtorrent { namespace bt_peer_connection* p = dynamic_cast(i->second); if (!p) continue; - // i->first was added since the last time - detail::write_endpoint(i->first, pla_out); // no supported flags to set yet // 0x01 - peer supports encryption // 0x02 - peer is a seed @@ -304,7 +343,17 @@ namespace libtorrent { namespace #ifndef TORRENT_DISABLE_ENCRYPTION flags |= p->supports_encryption() ? 1 : 0; #endif - detail::write_uint8(flags, plf_out); + // i->first was added since the last time + if (i->first.address().is_v4()) + { + detail::write_endpoint(i->first, pla_out); + detail::write_uint8(flags, plf_out); + } + else + { + detail::write_endpoint(i->first, pla6_out); + detail::write_uint8(flags, plf6_out); + } ++num_added; } std::vector pex_msg;