Add scope_id support.
This commit is contained in:
parent
5d678037e1
commit
255fd73a86
@ -19,6 +19,7 @@
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/config.hpp>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include <vector>
|
||||
@ -505,8 +506,8 @@ inline int poll_write(socket_type s)
|
||||
#endif // defined(BOOST_WINDOWS)
|
||||
}
|
||||
|
||||
inline const char* inet_ntop(int af, const void* src, char* dest,
|
||||
size_t length)
|
||||
inline const char* inet_ntop(int af, const void* src, char* dest, size_t length,
|
||||
unsigned long scope_id = 0)
|
||||
{
|
||||
set_error(0);
|
||||
#if defined(BOOST_WINDOWS)
|
||||
@ -535,7 +536,7 @@ inline const char* inet_ntop(int af, const void* src, char* dest,
|
||||
ipv6_address->sin6_family = AF_INET6;
|
||||
ipv6_address->sin6_port = 0;
|
||||
ipv6_address->sin6_flowinfo = 0;
|
||||
ipv6_address->sin6_scope_id = 0;
|
||||
ipv6_address->sin6_scope_id = scope_id;
|
||||
memcpy(&ipv6_address->sin6_addr, src, sizeof(in6_addr));
|
||||
}
|
||||
|
||||
@ -553,11 +554,22 @@ inline const char* inet_ntop(int af, const void* src, char* dest,
|
||||
const char* result = error_wrapper(::inet_ntop(af, src, dest, length));
|
||||
if (result == 0 && get_error() == 0)
|
||||
set_error(asio::error::invalid_argument);
|
||||
if (result != 0 && af == AF_INET6 && scope_id != 0)
|
||||
{
|
||||
using namespace std; // For strcat and sprintf.
|
||||
char if_name[IF_NAMESIZE + 1] = "%";
|
||||
const in6_addr* ipv6_address = static_cast<const in6_addr*>(src);
|
||||
bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
|
||||
if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0)
|
||||
sprintf(if_name + 1, "%lu", scope_id);
|
||||
strcat(dest, if_name);
|
||||
}
|
||||
return result;
|
||||
#endif // defined(BOOST_WINDOWS)
|
||||
}
|
||||
|
||||
inline int inet_pton(int af, const char* src, void* dest)
|
||||
inline int inet_pton(int af, const char* src, void* dest,
|
||||
unsigned long* scope_id = 0)
|
||||
{
|
||||
set_error(0);
|
||||
#if defined(BOOST_WINDOWS)
|
||||
@ -594,6 +606,8 @@ inline int inet_pton(int af, const char* src, void* dest)
|
||||
{
|
||||
sockaddr_in6* ipv6_address = reinterpret_cast<sockaddr_in6*>(&address);
|
||||
memcpy(dest, &ipv6_address->sin6_addr, sizeof(in6_addr));
|
||||
if (scope_id)
|
||||
*scope_id = ipv6_address->sin6_scope_id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -606,6 +620,20 @@ inline int inet_pton(int af, const char* src, void* dest)
|
||||
int result = error_wrapper(::inet_pton(af, src, dest));
|
||||
if (result <= 0 && get_error() == 0)
|
||||
set_error(asio::error::invalid_argument);
|
||||
if (result > 0 && af == AF_INET6 && scope_id)
|
||||
{
|
||||
using namespace std; // For strchr and atoi.
|
||||
*scope_id = 0;
|
||||
if (const char* if_name = strchr(src, '%'))
|
||||
{
|
||||
in6_addr* ipv6_address = static_cast<in6_addr*>(dest);
|
||||
bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
|
||||
if (is_link_local)
|
||||
*scope_id = if_nametoindex(if_name + 1);
|
||||
if (*scope_id == 0)
|
||||
*scope_id = atoi(if_name + 1);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
#endif // defined(BOOST_WINDOWS)
|
||||
}
|
||||
|
@ -69,6 +69,7 @@
|
||||
# include <netinet/tcp.h>
|
||||
# include <arpa/inet.h>
|
||||
# include <netdb.h>
|
||||
# include <net/if.h>
|
||||
# if defined(__sun)
|
||||
# include <sys/filio.h>
|
||||
# endif
|
||||
@ -102,7 +103,7 @@ typedef int socket_type;
|
||||
const int invalid_socket = -1;
|
||||
const int socket_error_retval = -1;
|
||||
const int max_addr_v4_str_len = INET_ADDRSTRLEN;
|
||||
const int max_addr_v6_str_len = INET6_ADDRSTRLEN;
|
||||
const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE;
|
||||
typedef sockaddr socket_addr_type;
|
||||
typedef sockaddr_in inet_addr_v4_type;
|
||||
typedef sockaddr_in6 inet_addr_v6_type;
|
||||
|
@ -49,13 +49,15 @@ public:
|
||||
|
||||
/// Default constructor.
|
||||
address()
|
||||
: scope_id_(0)
|
||||
{
|
||||
in6_addr tmp_addr = IN6ADDR_ANY_INIT;
|
||||
addr_ = tmp_addr;
|
||||
}
|
||||
|
||||
/// Construct an address from raw bytes.
|
||||
address(const bytes_type& bytes)
|
||||
/// Construct an address from raw bytes and scope ID.
|
||||
address(const bytes_type& bytes, unsigned long scope_id = 0)
|
||||
: scope_id_(scope_id)
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
memcpy(addr_.s6_addr, bytes.elems, 16);
|
||||
@ -64,7 +66,8 @@ public:
|
||||
/// Construct an address using an IP address string.
|
||||
address(const char* host)
|
||||
{
|
||||
if (asio::detail::socket_ops::inet_pton(AF_INET6, host, &addr_) <= 0)
|
||||
if (asio::detail::socket_ops::inet_pton(
|
||||
AF_INET6, host, &addr_, &scope_id_) <= 0)
|
||||
{
|
||||
asio::error e(asio::detail::socket_ops::get_error());
|
||||
boost::throw_exception(e);
|
||||
@ -75,7 +78,7 @@ public:
|
||||
address(const std::string& host)
|
||||
{
|
||||
if (asio::detail::socket_ops::inet_pton(
|
||||
AF_INET6, host.c_str(), &addr_) <= 0)
|
||||
AF_INET6, host.c_str(), &addr_, &scope_id_) <= 0)
|
||||
{
|
||||
asio::error e(asio::detail::socket_ops::get_error());
|
||||
boost::throw_exception(e);
|
||||
@ -84,7 +87,8 @@ public:
|
||||
|
||||
/// Copy constructor.
|
||||
address(const address& other)
|
||||
: addr_(other.addr_)
|
||||
: addr_(other.addr_),
|
||||
scope_id_(other.scope_id_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -92,6 +96,7 @@ public:
|
||||
address& operator=(const address& other)
|
||||
{
|
||||
addr_ = other.addr_;
|
||||
scope_id_ = other.scope_id_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -111,6 +116,18 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get the scope ID of the address.
|
||||
unsigned long scope_id() const
|
||||
{
|
||||
return scope_id_;
|
||||
}
|
||||
|
||||
/// Set the scope ID of the address.
|
||||
void scope_id(unsigned long id)
|
||||
{
|
||||
scope_id_ = id;
|
||||
}
|
||||
|
||||
/// Get the address in bytes.
|
||||
bytes_type to_bytes() const
|
||||
{
|
||||
@ -126,7 +143,7 @@ public:
|
||||
char addr_str[asio::detail::max_addr_v6_str_len];
|
||||
const char* addr =
|
||||
asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str,
|
||||
asio::detail::max_addr_v6_str_len);
|
||||
asio::detail::max_addr_v6_str_len, scope_id_);
|
||||
if (addr == 0)
|
||||
{
|
||||
asio::error e(asio::detail::socket_ops::get_error());
|
||||
@ -135,6 +152,18 @@ public:
|
||||
return addr;
|
||||
}
|
||||
|
||||
/// Determine whether the address is a loopback address.
|
||||
bool is_loopback() const
|
||||
{
|
||||
return IN6_IS_ADDR_LOOPBACK(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Determine whether the address is unspecified.
|
||||
bool is_unspecified() const
|
||||
{
|
||||
return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Determine whether the address is link local.
|
||||
bool is_link_local() const
|
||||
{
|
||||
@ -165,6 +194,36 @@ public:
|
||||
return IN6_IS_ADDR_MULTICAST(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Determine whether the address is a global multicast address.
|
||||
bool is_multicast_global() const
|
||||
{
|
||||
return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Determine whether the address is a link-local multicast address.
|
||||
bool is_multicast_link_local() const
|
||||
{
|
||||
return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Determine whether the address is a node-local multicast address.
|
||||
bool is_multicast_node_local() const
|
||||
{
|
||||
return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Determine whether the address is a org-local multicast address.
|
||||
bool is_multicast_org_local() const
|
||||
{
|
||||
return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Determine whether the address is a site-local multicast address.
|
||||
bool is_multicast_site_local() const
|
||||
{
|
||||
return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Compare two addresses for equality.
|
||||
friend bool operator==(const address& a1, const address& a2)
|
||||
{
|
||||
@ -204,6 +263,9 @@ public:
|
||||
private:
|
||||
// The underlying IPv6 address.
|
||||
in6_addr addr_;
|
||||
|
||||
// The scope ID associated with the address.
|
||||
unsigned long scope_id_;
|
||||
};
|
||||
|
||||
/// Output an address as a string.
|
||||
@ -216,7 +278,7 @@ private:
|
||||
*
|
||||
* @return The output stream.
|
||||
*
|
||||
* @relates tcp::endpoint
|
||||
* @relates ipv6::address
|
||||
*/
|
||||
template <typename Ostream>
|
||||
Ostream& operator<<(Ostream& os, const address& addr)
|
||||
|
@ -202,7 +202,7 @@ public:
|
||||
addr_.sin6_flowinfo = 0;
|
||||
asio::ipv6::address::bytes_type bytes = addr.to_bytes();
|
||||
memcpy(addr_.sin6_addr.s6_addr, bytes.elems, 16);
|
||||
addr_.sin6_scope_id = 0;
|
||||
addr_.sin6_scope_id = addr.scope_id();
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
@ -274,7 +274,7 @@ public:
|
||||
using namespace std; // For memcpy.
|
||||
asio::ipv6::address::bytes_type bytes;
|
||||
memcpy(bytes.elems, addr_.sin6_addr.s6_addr, 16);
|
||||
return asio::ipv6::address(bytes);
|
||||
return asio::ipv6::address(bytes, addr_.sin6_scope_id);
|
||||
}
|
||||
|
||||
/// Set the IP address associated with the endpoint.
|
||||
@ -283,6 +283,7 @@ public:
|
||||
using namespace std; // For memcpy.
|
||||
asio::ipv6::address::bytes_type bytes = addr.to_bytes();
|
||||
memcpy(addr_.sin6_addr.s6_addr, bytes.elems, 16);
|
||||
addr_.sin6_scope_id = addr.scope_id();
|
||||
}
|
||||
|
||||
/// Compare two endpoints for equality.
|
||||
|
@ -156,7 +156,7 @@ public:
|
||||
addr_.sin6_flowinfo = 0;
|
||||
asio::ipv6::address::bytes_type bytes = addr.to_bytes();
|
||||
memcpy(addr_.sin6_addr.s6_addr, bytes.elems, 16);
|
||||
addr_.sin6_scope_id = 0;
|
||||
addr_.sin6_scope_id = addr.scope_id();
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
@ -228,7 +228,7 @@ public:
|
||||
using namespace std; // For memcpy.
|
||||
asio::ipv6::address::bytes_type bytes;
|
||||
memcpy(bytes.elems, addr_.sin6_addr.s6_addr, 16);
|
||||
return asio::ipv6::address(bytes);
|
||||
return asio::ipv6::address(bytes, addr_.sin6_scope_id);
|
||||
}
|
||||
|
||||
/// Set the IP address associated with the endpoint.
|
||||
@ -237,6 +237,7 @@ public:
|
||||
using namespace std; // For memcpy.
|
||||
asio::ipv6::address::bytes_type bytes = addr.to_bytes();
|
||||
memcpy(addr_.sin6_addr.s6_addr, bytes.elems, 16);
|
||||
addr_.sin6_scope_id = addr.scope_id();
|
||||
}
|
||||
|
||||
/// Compare two endpoints for equality.
|
||||
|
Loading…
Reference in New Issue
Block a user