some more IPv6 support

This commit is contained in:
Arvid Norberg 2007-09-19 21:54:26 +00:00
parent 338eedf961
commit ba437cf72e
4 changed files with 143 additions and 35 deletions

View File

@ -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<datagram_socket> 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);

View File

@ -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<address> const& interfaces = enum_net_interfaces(get_socket()->io_service(), ec);
for (std::vector<address>::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<std::string> 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)

View File

@ -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;

View File

@ -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<std::string> pla_out(pla);
std::back_insert_iterator<std::string> pld_out(pld);
std::back_insert_iterator<std::string> plf_out(plf);
std::back_insert_iterator<std::string> pla6_out(pla6);
std::back_insert_iterator<std::string> pld6_out(pld6);
std::back_insert_iterator<std::string> plf6_out(plf6);
std::set<tcp::endpoint> dropped;
m_old_peers.swap(dropped);
@ -123,8 +127,6 @@ namespace libtorrent { namespace
bt_peer_connection* p = dynamic_cast<bt_peer_connection*>(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<tcp::endpoint>::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<tcp::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<std::string> pla_out(pla);
std::back_insert_iterator<std::string> plf_out(plf);
std::back_insert_iterator<std::string> pla6_out(pla6);
std::back_insert_iterator<std::string> 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<bt_peer_connection*>(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<char> pex_msg;