improved IPv6 support (skips unsupported tests on windows)

This commit is contained in:
Arvid Norberg 2009-04-13 05:11:44 +00:00
parent 9b226daede
commit 189d618261
4 changed files with 44 additions and 19 deletions

View File

@ -48,6 +48,9 @@ namespace libtorrent
TORRENT_EXPORT bool is_any(address const& addr); TORRENT_EXPORT bool is_any(address const& addr);
TORRENT_EXPORT int cidr_distance(address const& a1, address const& a2); TORRENT_EXPORT int cidr_distance(address const& a1, address const& a2);
// determines if the operating system supports IPv6
TORRENT_EXPORT bool supports_ipv6();
int common_bits(unsigned char const* b1 int common_bits(unsigned char const* b1
, unsigned char const* b2, int n); , unsigned char const* b2, int n);

View File

@ -51,7 +51,9 @@ namespace libtorrent
{ {
bool is_local(address const& a) bool is_local(address const& a)
{ {
#if TORRENT_USE_IPV6
if (a.is_v6()) return a.to_v6().is_link_local(); if (a.is_v6()) return a.to_v6().is_link_local();
#endif
address_v4 a4 = a.to_v4(); address_v4 a4 = a.to_v4();
unsigned long ip = a4.to_ulong(); unsigned long ip = a4.to_ulong();
return ((ip & 0xff000000) == 0x0a000000 return ((ip & 0xff000000) == 0x0a000000
@ -61,28 +63,51 @@ namespace libtorrent
bool is_loopback(address const& addr) bool is_loopback(address const& addr)
{ {
#if TORRENT_USE_IPV6
if (addr.is_v4()) if (addr.is_v4())
return addr.to_v4() == address_v4::loopback(); return addr.to_v4() == address_v4::loopback();
else else
return addr.to_v6() == address_v6::loopback(); return addr.to_v6() == address_v6::loopback();
#else
return addr.to_v4() == address_v4::loopback();
#endif
} }
bool is_multicast(address const& addr) bool is_multicast(address const& addr)
{ {
#if TORRENT_USE_IPV6
if (addr.is_v4()) if (addr.is_v4())
return addr.to_v4().is_multicast(); return addr.to_v4().is_multicast();
else else
return addr.to_v6().is_multicast(); return addr.to_v6().is_multicast();
#else
return addr.to_v4().is_multicast();
#endif
} }
bool is_any(address const& addr) bool is_any(address const& addr)
{ {
#if TORRENT_USE_IPV6
if (addr.is_v4()) if (addr.is_v4())
return addr.to_v4() == address_v4::any(); return addr.to_v4() == address_v4::any();
else if (addr.to_v6().is_v4_mapped()) else if (addr.to_v6().is_v4_mapped())
return (addr.to_v6().to_v4() == address_v4::any()); return (addr.to_v6().to_v4() == address_v4::any());
else else
return addr.to_v6() == address_v6::any(); return addr.to_v6() == address_v6::any();
#else
return addr.to_v4() == address_v4::any();
#endif
}
bool supports_ipv6()
{
#if TORRENT_USE_IPV6
error_code ec;
address::from_string("::1", ec);
return !ec;
#else
return false;
#endif
} }
address guess_local_address(io_service& ios) address guess_local_address(io_service& ios)
@ -128,13 +153,16 @@ namespace libtorrent
// between the addresses. // between the addresses.
int cidr_distance(address const& a1, address const& a2) int cidr_distance(address const& a1, address const& a2)
{ {
#if TORRENT_USE_IPV6
if (a1.is_v4() && a2.is_v4()) if (a1.is_v4() && a2.is_v4())
{ {
#endif
// both are v4 // both are v4
address_v4::bytes_type b1 = a1.to_v4().to_bytes(); address_v4::bytes_type b1 = a1.to_v4().to_bytes();
address_v4::bytes_type b2 = a2.to_v4().to_bytes(); address_v4::bytes_type b2 = a2.to_v4().to_bytes();
return address_v4::bytes_type::static_size * 8 return address_v4::bytes_type::static_size * 8
- common_bits(b1.c_array(), b2.c_array(), b1.size()); - common_bits(b1.c_array(), b2.c_array(), b1.size());
#if TORRENT_USE_IPV6
} }
address_v6::bytes_type b1; address_v6::bytes_type b1;
@ -145,6 +173,7 @@ namespace libtorrent
else b2 = a2.to_v6().to_bytes(); else b2 = a2.to_v6().to_bytes();
return address_v6::bytes_type::static_size * 8 return address_v6::bytes_type::static_size * 8
- common_bits(b1.c_array(), b2.c_array(), b1.size()); - common_bits(b1.c_array(), b2.c_array(), b1.size());
#endif
} }
broadcast_socket::broadcast_socket(io_service& ios broadcast_socket::broadcast_socket(io_service& ios

View File

@ -737,27 +737,19 @@ namespace aux {
} }
#if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
#ifdef TORRENT_WINDOWS
// only try to open the IPv6 port if IPv6 is installed // only try to open the IPv6 port if IPv6 is installed
SOCKADDR_STORAGE storage; if (supports_ipv6())
int len = sizeof(storage);
if (WSAStringToAddressA("::1", AF_INET6, 0,
(sockaddr*)&storage, &len) != SOCKET_ERROR)
{ {
#endif s = setup_listener(
tcp::endpoint(address_v6::any(), m_listen_interface.port())
, m_listen_port_retries, true);
s = setup_listener( if (s.sock)
tcp::endpoint(address_v6::any(), m_listen_interface.port()) {
, m_listen_port_retries, true); m_listen_sockets.push_back(s);
async_accept(s.sock);
if (s.sock) }
{
m_listen_sockets.push_back(s);
async_accept(s.sock);
} }
#ifdef TORRENT_WINDOWS
}
#endif
#endif // TORRENT_USE_IPV6 #endif // TORRENT_USE_IPV6
// set our main IPv4 and IPv6 interfaces // set our main IPv4 and IPv6 interfaces

View File

@ -652,7 +652,8 @@ int test_main()
TEST_CHECK(is_local(address::from_string("10.1.1.56", ec))); TEST_CHECK(is_local(address::from_string("10.1.1.56", ec)));
TEST_CHECK(!is_local(address::from_string("14.14.251.63", ec))); TEST_CHECK(!is_local(address::from_string("14.14.251.63", ec)));
TEST_CHECK(is_loopback(address::from_string("127.0.0.1", ec))); TEST_CHECK(is_loopback(address::from_string("127.0.0.1", ec)));
TEST_CHECK(is_loopback(address::from_string("::1", ec))); if (supports_ipv6())
TEST_CHECK(is_loopback(address::from_string("::1", ec)));
TEST_CHECK(is_any(address_v6::any())); TEST_CHECK(is_any(address_v6::any()));
TEST_CHECK(is_any(address_v4::any())); TEST_CHECK(is_any(address_v4::any()));
TEST_CHECK(!is_any(address::from_string("31.53.21.64", ec))); TEST_CHECK(!is_any(address::from_string("31.53.21.64", ec)));