From ddc1ee62953acde0e87ba1d7d25bbaf773ad94d5 Mon Sep 17 00:00:00 2001 From: Marcos Pinto Date: Thu, 20 Sep 2007 16:28:41 +0000 Subject: [PATCH] enum fixes and ipv6 update --- .../include/libtorrent/bandwidth_manager.hpp | 1 - .../include/libtorrent/broadcast_socket.hpp | 4 +- libtorrent/include/libtorrent/storage.hpp | 1 - .../include/libtorrent/torrent_handle.hpp | 1 - libtorrent/src/broadcast_socket.cpp | 73 ++++++++++++++----- libtorrent/src/bt_peer_connection.cpp | 14 ++++ libtorrent/src/enum_net.cpp | 13 +++- libtorrent/src/http_tracker_connection.cpp | 23 ++++-- libtorrent/src/peer_connection.cpp | 1 - libtorrent/src/policy.cpp | 1 - libtorrent/src/storage.cpp | 19 ++--- libtorrent/src/torrent.cpp | 1 - libtorrent/src/torrent_handle.cpp | 1 - libtorrent/src/upnp.cpp | 1 - libtorrent/src/ut_pex.cpp | 69 +++++++++++++++--- 15 files changed, 167 insertions(+), 56 deletions(-) diff --git a/libtorrent/include/libtorrent/bandwidth_manager.hpp b/libtorrent/include/libtorrent/bandwidth_manager.hpp index d84f68bfe..38aa67f43 100644 --- a/libtorrent/include/libtorrent/bandwidth_manager.hpp +++ b/libtorrent/include/libtorrent/bandwidth_manager.hpp @@ -493,4 +493,3 @@ private: #endif - diff --git a/libtorrent/include/libtorrent/broadcast_socket.hpp b/libtorrent/include/libtorrent/broadcast_socket.hpp index 6e44de0ad..23be67b0d 100644 --- a/libtorrent/include/libtorrent/broadcast_socket.hpp +++ b/libtorrent/include/libtorrent/broadcast_socket.hpp @@ -42,6 +42,9 @@ namespace libtorrent { bool is_local(address const& a); + bool is_loopback(address const& addr); + bool is_multicast(address const& addr); + address_v4 guess_local_address(asio::io_service&); typedef boost::functionendpoint().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); @@ -150,4 +184,3 @@ namespace libtorrent } - diff --git a/libtorrent/src/bt_peer_connection.cpp b/libtorrent/src/bt_peer_connection.cpp index f7f137437..ab61d98f9 100755 --- a/libtorrent/src/bt_peer_connection.cpp +++ b/libtorrent/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/libtorrent/src/enum_net.cpp b/libtorrent/src/enum_net.cpp index 54af814d6..172719793 100644 --- a/libtorrent/src/enum_net.cpp +++ b/libtorrent/src/enum_net.cpp @@ -72,8 +72,17 @@ namespace libtorrent ifreq const& item = *reinterpret_cast(ifr); if (item.ifr_addr.sa_family == AF_INET) { - ret.push_back(address::from_string( - inet_ntoa(((sockaddr_in const*)&item.ifr_addr)->sin_addr))); + typedef asio::ip::address_v4::bytes_type bytes_t; + bytes_t b; + memcpy(&b[0], &((sockaddr_in const*)&item.ifr_addr)->sin_addr, b.size()); + ret.push_back(address_v4(b)); + } + else if (item.ifr_addr.sa_family == AF_INET6) + { + typedef asio::ip::address_v6::bytes_type bytes_t; + bytes_t b; + memcpy(&b[0], &((sockaddr_in6 const*)&item.ifr_addr)->sin6_addr, b.size()); + ret.push_back(address_v6(b)); } #if defined __MACH__ || defined(__FreeBSD__) diff --git a/libtorrent/src/http_tracker_connection.cpp b/libtorrent/src/http_tracker_connection.cpp index c316b5b4e..3fcd97dbc 100755 --- a/libtorrent/src/http_tracker_connection.cpp +++ b/libtorrent/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/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index ab5476e85..25bc0ba63 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -3022,4 +3022,3 @@ namespace libtorrent } } - diff --git a/libtorrent/src/policy.cpp b/libtorrent/src/policy.cpp index ca82a3868..4faed837e 100755 --- a/libtorrent/src/policy.cpp +++ b/libtorrent/src/policy.cpp @@ -1551,4 +1551,3 @@ namespace libtorrent } } - diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index 96159391c..dbf6a9382 100755 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -400,20 +400,22 @@ namespace libtorrent partial.update(&m_scratch_buffer[0], ph.offset); whole.update(&m_scratch_buffer[0], slot_size1); hasher partial_copy = ph.h; - std::cerr << partial_copy.final() << " " << partial.final() << std::endl; assert(ph.offset == 0 || partial_copy.final() == partial.final()); #endif int slot_size = piece_size - ph.offset; - if (slot_size == 0) + if (slot_size > 0) { - assert(ph.h.final() == whole.final()); - return ph.h.final(); + m_scratch_buffer.resize(slot_size); + read_impl(&m_scratch_buffer[0], slot, ph.offset, slot_size, true); + ph.h.update(&m_scratch_buffer[0], slot_size); } - m_scratch_buffer.resize(slot_size); - read_impl(&m_scratch_buffer[0], slot, ph.offset, slot_size, true); - ph.h.update(&m_scratch_buffer[0], slot_size); - assert(whole.final() == ph.h.final()); +#ifndef NDEBUG + sha1_hash ret = ph.h.final(); + assert(ret == whole.final()); + return ret; +#else return ph.h.final(); +#endif } void storage::initialize(bool allocate_files) @@ -2213,4 +2215,3 @@ namespace libtorrent #endif } // namespace libtorrent - diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 221697284..252461bc6 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -2937,4 +2937,3 @@ namespace libtorrent } - diff --git a/libtorrent/src/torrent_handle.cpp b/libtorrent/src/torrent_handle.cpp index 1ca3a27ef..ebef802a8 100755 --- a/libtorrent/src/torrent_handle.cpp +++ b/libtorrent/src/torrent_handle.cpp @@ -1001,4 +1001,3 @@ namespace libtorrent } - diff --git a/libtorrent/src/upnp.cpp b/libtorrent/src/upnp.cpp index 567cc6347..ad50595a2 100644 --- a/libtorrent/src/upnp.cpp +++ b/libtorrent/src/upnp.cpp @@ -980,4 +980,3 @@ void upnp::close() } } - diff --git a/libtorrent/src/ut_pex.cpp b/libtorrent/src/ut_pex.cpp index 15913573e..18fe715ee 100644 --- a/libtorrent/src/ut_pex.cpp +++ b/libtorrent/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;