Add initial support for IPv6.
This commit is contained in:
parent
068d28d85e
commit
f0e4fcea41
@ -91,6 +91,9 @@ nobase_include_HEADERS = \
|
||||
asio/ipv4/multicast.hpp \
|
||||
asio/ipv4/tcp.hpp \
|
||||
asio/ipv4/udp.hpp \
|
||||
asio/ipv6/address.hpp \
|
||||
asio/ipv6/tcp.hpp \
|
||||
asio/ipv6/udp.hpp \
|
||||
asio/is_read_buffered.hpp \
|
||||
asio/is_write_buffered.hpp \
|
||||
asio/locking_dispatcher.hpp \
|
||||
|
@ -45,6 +45,9 @@
|
||||
#include "asio/ipv4/multicast.hpp"
|
||||
#include "asio/ipv4/tcp.hpp"
|
||||
#include "asio/ipv4/udp.hpp"
|
||||
#include "asio/ipv6/address.hpp"
|
||||
#include "asio/ipv6/tcp.hpp"
|
||||
#include "asio/ipv6/udp.hpp"
|
||||
#include "asio/is_read_buffered.hpp"
|
||||
#include "asio/is_write_buffered.hpp"
|
||||
#include "asio/locking_dispatcher.hpp"
|
||||
|
@ -510,33 +510,45 @@ inline const char* inet_ntop(int af, const void* src, char* dest,
|
||||
{
|
||||
set_error(0);
|
||||
#if defined(BOOST_WINDOWS)
|
||||
using namespace std; // For strncat.
|
||||
using namespace std; // For memcpy.
|
||||
|
||||
if (af != AF_INET)
|
||||
if (af != AF_INET && af != AF_INET6)
|
||||
{
|
||||
set_error(asio::error::address_family_not_supported);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* addr_str = error_wrapper(
|
||||
::inet_ntoa(*static_cast<const in_addr*>(src)));
|
||||
if (addr_str)
|
||||
sockaddr_storage address;
|
||||
DWORD address_length;
|
||||
if (af == AF_INET)
|
||||
{
|
||||
*dest = '\0';
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
strncat_s(dest, length, addr_str, length);
|
||||
#else
|
||||
strncat(dest, addr_str, length);
|
||||
#endif
|
||||
return dest;
|
||||
address_length = sizeof(sockaddr_in);
|
||||
sockaddr_in* ipv4_address = reinterpret_cast<sockaddr_in*>(&address);
|
||||
ipv4_address->sin_family = AF_INET;
|
||||
ipv4_address->sin_port = 0;
|
||||
memcpy(&ipv4_address->sin_addr, src, sizeof(in_addr));
|
||||
}
|
||||
else // AF_INET6
|
||||
{
|
||||
address_length = sizeof(sockaddr_in6);
|
||||
sockaddr_in6* ipv6_address = reinterpret_cast<sockaddr_in6*>(&address);
|
||||
ipv6_address->sin6_family = AF_INET6;
|
||||
ipv6_address->sin6_port = 0;
|
||||
ipv6_address->sin6_flowinfo = 0;
|
||||
ipv6_address->sin6_scope_id = 0;
|
||||
memcpy(&ipv6_address->sin6_addr, src, sizeof(in6_addr));
|
||||
}
|
||||
|
||||
DWORD string_length = length;
|
||||
int result = error_wrapper(::WSAAddressToStringA(
|
||||
reinterpret_cast<sockaddr*>(&address),
|
||||
address_length, 0, dest, &string_length));
|
||||
|
||||
// Windows may not set an error code on failure.
|
||||
if (get_error() == 0)
|
||||
if (result == socket_error_retval && get_error() == 0)
|
||||
set_error(asio::error::invalid_argument);
|
||||
|
||||
return 0;
|
||||
|
||||
return result == socket_error_retval ? 0 : dest;
|
||||
#else // defined(BOOST_WINDOWS)
|
||||
const char* result = error_wrapper(::inet_ntop(af, src, dest, length));
|
||||
if (result == 0 && get_error() == 0)
|
||||
@ -549,26 +561,47 @@ inline int inet_pton(int af, const char* src, void* dest)
|
||||
{
|
||||
set_error(0);
|
||||
#if defined(BOOST_WINDOWS)
|
||||
using namespace std; // For strcmp.
|
||||
using namespace std; // For memcpy and strcmp.
|
||||
|
||||
if (af != AF_INET)
|
||||
if (af != AF_INET && af != AF_INET6)
|
||||
{
|
||||
set_error(asio::error::address_family_not_supported);
|
||||
return -1;
|
||||
}
|
||||
|
||||
u_long_type addr = error_wrapper(::inet_addr(src));
|
||||
if (addr != INADDR_NONE || strcmp(src, "255.255.255.255") == 0)
|
||||
sockaddr_storage address;
|
||||
int address_length = sizeof(sockaddr_storage);
|
||||
int result = error_wrapper(::WSAStringToAddressA(
|
||||
const_cast<char*>(src), af, 0,
|
||||
reinterpret_cast<sockaddr*>(&address),
|
||||
&address_length));
|
||||
|
||||
if (af == AF_INET)
|
||||
{
|
||||
static_cast<in_addr*>(dest)->s_addr = addr;
|
||||
return 1;
|
||||
if (result != socket_error_retval)
|
||||
{
|
||||
sockaddr_in* ipv4_address = reinterpret_cast<sockaddr_in*>(&address);
|
||||
memcpy(dest, &ipv4_address->sin_addr, sizeof(in_addr));
|
||||
}
|
||||
else if (strcmp(src, "255.255.255.255") == 0)
|
||||
{
|
||||
static_cast<in_addr*>(dest)->s_addr = INADDR_NONE;
|
||||
}
|
||||
}
|
||||
else // AF_INET6
|
||||
{
|
||||
if (result != socket_error_retval)
|
||||
{
|
||||
sockaddr_in6* ipv6_address = reinterpret_cast<sockaddr_in6*>(&address);
|
||||
memcpy(dest, &ipv6_address->sin6_addr, sizeof(in6_addr));
|
||||
}
|
||||
}
|
||||
|
||||
// Windows may not set an error code on failure.
|
||||
if (get_error() == 0)
|
||||
if (result == socket_error_retval && get_error() == 0)
|
||||
set_error(asio::error::invalid_argument);
|
||||
|
||||
return 0;
|
||||
return result == socket_error_retval ? -1 : 1;
|
||||
#else // defined(BOOST_WINDOWS)
|
||||
int result = error_wrapper(::inet_pton(af, src, dest));
|
||||
if (result <= 0 && get_error() == 0)
|
||||
|
@ -82,9 +82,11 @@ namespace detail {
|
||||
typedef SOCKET socket_type;
|
||||
const SOCKET invalid_socket = INVALID_SOCKET;
|
||||
const int socket_error_retval = SOCKET_ERROR;
|
||||
const int max_addr_str_len = 256;
|
||||
const int max_addr_v4_str_len = 256;
|
||||
const int max_addr_v6_str_len = 256;
|
||||
typedef sockaddr socket_addr_type;
|
||||
typedef sockaddr_in inet_addr_v4_type;
|
||||
typedef sockaddr_in6 inet_addr_v6_type;
|
||||
typedef int socket_addr_len_type;
|
||||
typedef unsigned long ioctl_arg_type;
|
||||
typedef u_long u_long_type;
|
||||
@ -99,9 +101,11 @@ const int message_do_not_route = MSG_DONTROUTE;
|
||||
typedef int socket_type;
|
||||
const int invalid_socket = -1;
|
||||
const int socket_error_retval = -1;
|
||||
const int max_addr_str_len = INET_ADDRSTRLEN;
|
||||
const int max_addr_v4_str_len = INET_ADDRSTRLEN;
|
||||
const int max_addr_v6_str_len = INET6_ADDRSTRLEN;
|
||||
typedef sockaddr socket_addr_type;
|
||||
typedef sockaddr_in inet_addr_v4_type;
|
||||
typedef sockaddr_in6 inet_addr_v6_type;
|
||||
typedef socklen_t socket_addr_len_type;
|
||||
typedef int ioctl_arg_type;
|
||||
typedef uint32_t u_long_type;
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <string>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
@ -41,12 +42,22 @@ namespace ipv4 {
|
||||
class address
|
||||
{
|
||||
public:
|
||||
/// The type used to represent an address as an array of bytes.
|
||||
typedef boost::array<unsigned char, 4> bytes_type;
|
||||
|
||||
/// Default constructor.
|
||||
address()
|
||||
{
|
||||
addr_.s_addr = 0;
|
||||
}
|
||||
|
||||
/// Construct an address from raw bytes.
|
||||
address(const bytes_type& bytes)
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
memcpy(&addr_.s_addr, bytes.elems, 4);
|
||||
}
|
||||
|
||||
/// Construct an address from a unsigned long in host byte order.
|
||||
address(unsigned long addr)
|
||||
{
|
||||
@ -110,6 +121,15 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get the address in bytes.
|
||||
bytes_type to_bytes() const
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
bytes_type bytes;
|
||||
memcpy(bytes.elems, &addr_.s_addr, 4);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// Get the address as an unsigned long in host byte order
|
||||
unsigned long to_ulong() const
|
||||
{
|
||||
@ -119,10 +139,10 @@ public:
|
||||
/// Get the address as a string in dotted decimal format.
|
||||
std::string to_string() const
|
||||
{
|
||||
char addr_str[asio::detail::max_addr_str_len];
|
||||
char addr_str[asio::detail::max_addr_v4_str_len];
|
||||
const char* addr =
|
||||
asio::detail::socket_ops::inet_ntop(AF_INET, &addr_, addr_str,
|
||||
asio::detail::max_addr_str_len);
|
||||
asio::detail::max_addr_v4_str_len);
|
||||
if (addr == 0)
|
||||
{
|
||||
asio::error e(asio::detail::socket_ops::get_error());
|
||||
|
233
asio/include/asio/ipv6/address.hpp
Normal file
233
asio/include/asio/ipv6/address.hpp
Normal file
@ -0,0 +1,233 @@
|
||||
//
|
||||
// address.hpp
|
||||
// ~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_IPV6_ADDRESS_HPP
|
||||
#define ASIO_IPV6_ADDRESS_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/detail/socket_ops.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace ipv6 {
|
||||
|
||||
/// Implements IP version 6 style addresses.
|
||||
/**
|
||||
* The asio::ipv6::address class provides the ability to use and
|
||||
* manipulate IP version 6 addresses.
|
||||
*
|
||||
* @par Thread Safety:
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*/
|
||||
class address
|
||||
{
|
||||
public:
|
||||
/// The type used to represent an address as an array of bytes.
|
||||
typedef boost::array<unsigned char, 16> bytes_type;
|
||||
|
||||
/// Default constructor.
|
||||
address()
|
||||
{
|
||||
in6_addr tmp_addr = IN6ADDR_ANY_INIT;
|
||||
addr_ = tmp_addr;
|
||||
}
|
||||
|
||||
/// Construct an address from raw bytes.
|
||||
address(const bytes_type& bytes)
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
memcpy(addr_.s6_addr, bytes.elems, 16);
|
||||
}
|
||||
|
||||
/// Construct an address using an IP address string.
|
||||
address(const char* host)
|
||||
{
|
||||
if (asio::detail::socket_ops::inet_pton(AF_INET6, host, &addr_) <= 0)
|
||||
{
|
||||
asio::error e(asio::detail::socket_ops::get_error());
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct an address using an IP address string.
|
||||
address(const std::string& host)
|
||||
{
|
||||
if (asio::detail::socket_ops::inet_pton(
|
||||
AF_INET6, host.c_str(), &addr_) <= 0)
|
||||
{
|
||||
asio::error e(asio::detail::socket_ops::get_error());
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
address(const address& other)
|
||||
: addr_(other.addr_)
|
||||
{
|
||||
}
|
||||
|
||||
/// Assign from another address.
|
||||
address& operator=(const address& other)
|
||||
{
|
||||
addr_ = other.addr_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Assign from an IP address string.
|
||||
address& operator=(const char* addr)
|
||||
{
|
||||
address tmp(addr);
|
||||
addr_ = tmp.addr_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Assign from an IP address string.
|
||||
address& operator=(const std::string& addr)
|
||||
{
|
||||
address tmp(addr);
|
||||
addr_ = tmp.addr_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get the address in bytes.
|
||||
bytes_type to_bytes() const
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
bytes_type bytes;
|
||||
memcpy(bytes.elems, addr_.s6_addr, 16);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// Get the address as a string.
|
||||
std::string to_string() const
|
||||
{
|
||||
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);
|
||||
if (addr == 0)
|
||||
{
|
||||
asio::error e(asio::detail::socket_ops::get_error());
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
/// Determine whether the address is link local.
|
||||
bool is_link_local() const
|
||||
{
|
||||
return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Determine whether the address is site local.
|
||||
bool is_site_local() const
|
||||
{
|
||||
return IN6_IS_ADDR_SITELOCAL(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Determine whether the address is a mapped IPv4 address.
|
||||
bool is_ipv4_mapped() const
|
||||
{
|
||||
return IN6_IS_ADDR_V4MAPPED(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Determine whether the address is an IPv4-compatible address.
|
||||
bool is_ipv4_compatible() const
|
||||
{
|
||||
return IN6_IS_ADDR_V4COMPAT(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Determine whether the address is a multicast address.
|
||||
bool is_multicast() const
|
||||
{
|
||||
return IN6_IS_ADDR_MULTICAST(&addr_) != 0;
|
||||
}
|
||||
|
||||
/// Compare two addresses for equality.
|
||||
friend bool operator==(const address& a1, const address& a2)
|
||||
{
|
||||
using namespace std; // For memcmp.
|
||||
return memcmp(&a1.addr_, &a2.addr_, sizeof(in6_addr)) == 0;
|
||||
}
|
||||
|
||||
/// Compare two addresses for inequality.
|
||||
friend bool operator!=(const address& a1, const address& a2)
|
||||
{
|
||||
using namespace std; // For memcmp.
|
||||
return memcmp(&a1.addr_, &a2.addr_, sizeof(in6_addr)) != 0;
|
||||
}
|
||||
|
||||
/// Compare addresses for ordering.
|
||||
friend bool operator<(const address& a1, const address& a2)
|
||||
{
|
||||
using namespace std; // For memcmp.
|
||||
return memcmp(&a1.addr_, &a2.addr_, sizeof(in6_addr)) < 0;
|
||||
}
|
||||
|
||||
/// Obtain an address object that represents any address.
|
||||
static address any()
|
||||
{
|
||||
return address();
|
||||
}
|
||||
|
||||
/// Obtain an address object that represents the loopback address.
|
||||
static address loopback()
|
||||
{
|
||||
address tmp;
|
||||
in6_addr tmp_addr = IN6ADDR_LOOPBACK_INIT;
|
||||
tmp.addr_ = tmp_addr;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
// The underlying IPv6 address.
|
||||
in6_addr addr_;
|
||||
};
|
||||
|
||||
/// Output an address as a string.
|
||||
/**
|
||||
* Used to output a human-readable string for a specified address.
|
||||
*
|
||||
* @param os The output stream to which the string will be written.
|
||||
*
|
||||
* @param addr The address to be written.
|
||||
*
|
||||
* @return The output stream.
|
||||
*
|
||||
* @relates tcp::endpoint
|
||||
*/
|
||||
template <typename Ostream>
|
||||
Ostream& operator<<(Ostream& os, const address& addr)
|
||||
{
|
||||
os << addr.to_string();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace ipv6
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_IPV6_ADDRESS_HPP
|
347
asio/include/asio/ipv6/tcp.hpp
Normal file
347
asio/include/asio/ipv6/tcp.hpp
Normal file
@ -0,0 +1,347 @@
|
||||
//
|
||||
// tcp.hpp
|
||||
// ~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_IPV6_TCP_HPP
|
||||
#define ASIO_IPV6_TCP_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <cstring>
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
# include <iostream>
|
||||
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
#include <memory>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/basic_socket_acceptor.hpp"
|
||||
#include "asio/basic_stream_socket.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/socket_acceptor_service.hpp"
|
||||
#include "asio/stream_socket_service.hpp"
|
||||
#include "asio/ipv6/address.hpp"
|
||||
#include "asio/detail/socket_ops.hpp"
|
||||
#include "asio/detail/socket_option.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace ipv6 {
|
||||
|
||||
/// Encapsulates the flags needed for TCP.
|
||||
/**
|
||||
* The asio::ipv6::tcp class contains flags necessary for TCP sockets.
|
||||
*
|
||||
* @par Thread Safety:
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Safe.
|
||||
*
|
||||
* @par Concepts:
|
||||
* Protocol.
|
||||
*/
|
||||
class tcp
|
||||
{
|
||||
public:
|
||||
class endpoint;
|
||||
|
||||
/// Obtain an identifier for the type of the protocol.
|
||||
int type() const
|
||||
{
|
||||
return SOCK_STREAM;
|
||||
}
|
||||
|
||||
/// Obtain an identifier for the protocol.
|
||||
int protocol() const
|
||||
{
|
||||
return IPPROTO_TCP;
|
||||
}
|
||||
|
||||
/// Obtain an identifier for the protocol family.
|
||||
int family() const
|
||||
{
|
||||
return PF_INET6;
|
||||
}
|
||||
|
||||
/// Template typedefs for acceptor and socket types.
|
||||
template <typename Allocator>
|
||||
struct types
|
||||
{
|
||||
/// The service type for IPv4 TCP sockets.
|
||||
typedef stream_socket_service<tcp, Allocator> socket_service;
|
||||
|
||||
/// The IPv4 TCP socket type.
|
||||
typedef basic_stream_socket<socket_service> socket;
|
||||
|
||||
/// The service type for IPv4 TCP acceptors.
|
||||
typedef socket_acceptor_service<tcp, Allocator> acceptor_service;
|
||||
|
||||
/// The IPv4 TCP acceptor type.
|
||||
typedef basic_socket_acceptor<acceptor_service> acceptor;
|
||||
};
|
||||
|
||||
/// The IPv4 TCP socket type.
|
||||
typedef types<std::allocator<void> >::socket socket;
|
||||
|
||||
/// The IPv4 TCP acceptor type.
|
||||
typedef types<std::allocator<void> >::acceptor acceptor;
|
||||
|
||||
/// Socket option for disabling the Nagle algorithm.
|
||||
/**
|
||||
* Implements the IPPROTO_TCP/TCP_NODELAY socket option.
|
||||
*
|
||||
* @par Examples:
|
||||
* Setting the option:
|
||||
* @code
|
||||
* asio::stream_socket socket(io_service);
|
||||
* ...
|
||||
* asio::ipv6::tcp::no_delay option(true);
|
||||
* socket.set_option(option);
|
||||
* @endcode
|
||||
*
|
||||
* @par
|
||||
* Getting the current option value:
|
||||
* @code
|
||||
* asio::stream_socket socket(io_service);
|
||||
* ...
|
||||
* asio::ipv6::tcp::no_delay option;
|
||||
* socket.get_option(option);
|
||||
* bool is_set = option.get();
|
||||
* @endcode
|
||||
*
|
||||
* @par Concepts:
|
||||
* Socket_Option, Boolean_Socket_Option.
|
||||
*/
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined no_delay;
|
||||
#else
|
||||
typedef asio::detail::socket_option::boolean<
|
||||
IPPROTO_TCP, TCP_NODELAY> no_delay;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Describes an endpoint for a TCP socket.
|
||||
/**
|
||||
* The asio::ipv6::tcp::endpoint class describes an endpoint that may be
|
||||
* associated with a particular socket.
|
||||
*
|
||||
* @par Thread Safety:
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*
|
||||
* @par Concepts:
|
||||
* Endpoint.
|
||||
*/
|
||||
class tcp::endpoint
|
||||
{
|
||||
public:
|
||||
/// The protocol type associated with the endpoint.
|
||||
typedef tcp protocol_type;
|
||||
|
||||
/// The type of the endpoint structure. This type is dependent on the
|
||||
/// underlying implementation of the socket layer.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined data_type;
|
||||
#else
|
||||
typedef asio::detail::socket_addr_type data_type;
|
||||
#endif
|
||||
|
||||
/// The type for the size of the endpoint structure. This type is dependent on
|
||||
/// the underlying implementation of the socket layer.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined size_type;
|
||||
#else
|
||||
typedef asio::detail::socket_addr_len_type size_type;
|
||||
#endif
|
||||
|
||||
/// Default constructor.
|
||||
endpoint()
|
||||
{
|
||||
addr_.sin6_family = AF_INET6;
|
||||
addr_.sin6_port = 0;
|
||||
addr_.sin6_flowinfo = 0;
|
||||
in6_addr tmp_addr = IN6ADDR_LOOPBACK_INIT;
|
||||
addr_.sin6_addr = tmp_addr;
|
||||
addr_.sin6_scope_id = 0;
|
||||
}
|
||||
|
||||
/// Construct an endpoint using a port number, specified in the host's byte
|
||||
/// order. The IP address will be the any address (i.e. in6addr_any). This
|
||||
/// constructor would typically be used for accepting new connections.
|
||||
endpoint(unsigned short port_num)
|
||||
{
|
||||
addr_.sin6_family = AF_INET6;
|
||||
addr_.sin6_port =
|
||||
asio::detail::socket_ops::host_to_network_short(port_num);
|
||||
addr_.sin6_flowinfo = 0;
|
||||
in6_addr tmp_addr = IN6ADDR_LOOPBACK_INIT;
|
||||
addr_.sin6_addr = tmp_addr;
|
||||
addr_.sin6_scope_id = 0;
|
||||
}
|
||||
|
||||
/// Construct an endpoint using a port number and an IP address. This
|
||||
/// constructor may be used for accepting connections on a specific interface
|
||||
/// or for making a connection to a remote endpoint.
|
||||
endpoint(unsigned short port_num, const asio::ipv6::address& addr)
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
addr_.sin6_family = AF_INET6;
|
||||
addr_.sin6_port =
|
||||
asio::detail::socket_ops::host_to_network_short(port_num);
|
||||
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;
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
endpoint(const endpoint& other)
|
||||
: addr_(other.addr_)
|
||||
{
|
||||
}
|
||||
|
||||
/// Assign from another endpoint.
|
||||
endpoint& operator=(const endpoint& other)
|
||||
{
|
||||
addr_ = other.addr_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// The protocol associated with the endpoint.
|
||||
protocol_type protocol() const
|
||||
{
|
||||
return protocol_type();
|
||||
}
|
||||
|
||||
/// Get the underlying endpoint in the native type.
|
||||
data_type* data()
|
||||
{
|
||||
return reinterpret_cast<data_type*>(&addr_);
|
||||
}
|
||||
|
||||
/// Get the underlying endpoint in the native type.
|
||||
const data_type* data() const
|
||||
{
|
||||
return reinterpret_cast<const data_type*>(&addr_);
|
||||
}
|
||||
|
||||
/// Get the underlying size of the endpoint in the native type.
|
||||
size_type size() const
|
||||
{
|
||||
return sizeof(addr_);
|
||||
}
|
||||
|
||||
/// Set the underlying size of the endpoint in the native type.
|
||||
void size(size_type size)
|
||||
{
|
||||
if (size != sizeof(addr_))
|
||||
{
|
||||
asio::error e(asio::error::invalid_argument);
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the port associated with the endpoint. The port number is always in
|
||||
/// the host's byte order.
|
||||
unsigned short port() const
|
||||
{
|
||||
return asio::detail::socket_ops::network_to_host_short(
|
||||
addr_.sin6_port);
|
||||
}
|
||||
|
||||
/// Set the port associated with the endpoint. The port number is always in
|
||||
/// the host's byte order.
|
||||
void port(unsigned short port_num)
|
||||
{
|
||||
addr_.sin6_port =
|
||||
asio::detail::socket_ops::host_to_network_short(port_num);
|
||||
}
|
||||
|
||||
/// Get the IP address associated with the endpoint.
|
||||
asio::ipv6::address address() const
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/// Set the IP address associated with the endpoint.
|
||||
void address(const asio::ipv6::address& addr)
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
asio::ipv6::address::bytes_type bytes = addr.to_bytes();
|
||||
memcpy(addr_.sin6_addr.s6_addr, bytes.elems, 16);
|
||||
}
|
||||
|
||||
/// Compare two endpoints for equality.
|
||||
friend bool operator==(const endpoint& e1, const endpoint& e2)
|
||||
{
|
||||
return e1.address() == e2.address() && e1.port() == e2.port();
|
||||
}
|
||||
|
||||
/// Compare two endpoints for inequality.
|
||||
friend bool operator!=(const endpoint& e1, const endpoint& e2)
|
||||
{
|
||||
return e1.address() != e2.address() || e1.port() != e2.port();
|
||||
}
|
||||
|
||||
/// Compare endpoints for ordering.
|
||||
friend bool operator<(const endpoint& e1, const endpoint& e2)
|
||||
{
|
||||
if (e1.address() < e2.address())
|
||||
return true;
|
||||
if (e1.address() != e2.address())
|
||||
return false;
|
||||
return e1.port() < e2.port();
|
||||
}
|
||||
|
||||
private:
|
||||
// The underlying IPv4 socket address.
|
||||
asio::detail::inet_addr_v6_type addr_;
|
||||
};
|
||||
|
||||
/// Output an endpoint as a string.
|
||||
/**
|
||||
* Used to output a human-readable string for a specified endpoint.
|
||||
*
|
||||
* @param os The output stream to which the string will be written.
|
||||
*
|
||||
* @param endpoint The endpoint to be written.
|
||||
*
|
||||
* @return The output stream.
|
||||
*
|
||||
* @relates tcp::endpoint
|
||||
*/
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
std::ostream& operator<<(std::ostream& os, const tcp::endpoint& endpoint)
|
||||
{
|
||||
os << '[' << endpoint.address().to_string() << ']' << ':' << endpoint.port();
|
||||
return os;
|
||||
}
|
||||
#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
template <typename Ostream>
|
||||
Ostream& operator<<(Ostream& os, const tcp::endpoint& endpoint)
|
||||
{
|
||||
os << '[' << endpoint.address().to_string() << ']' << ':' << endpoint.port();
|
||||
return os;
|
||||
}
|
||||
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
|
||||
} // namespace ipv6
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_IPV6_TCP_HPP
|
301
asio/include/asio/ipv6/udp.hpp
Normal file
301
asio/include/asio/ipv6/udp.hpp
Normal file
@ -0,0 +1,301 @@
|
||||
//
|
||||
// udp.hpp
|
||||
// ~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_IPV6_UDP_HPP
|
||||
#define ASIO_IPV6_UDP_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
# include <iostream>
|
||||
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
#include <memory>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/basic_datagram_socket.hpp"
|
||||
#include "asio/datagram_socket_service.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/ipv6/address.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace ipv6 {
|
||||
|
||||
/// Encapsulates the flags needed for UDP.
|
||||
/**
|
||||
* The asio::ipv6::udp class contains flags necessary for UDP sockets.
|
||||
*
|
||||
* @par Thread Safety:
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Safe.
|
||||
*
|
||||
* @par Concepts:
|
||||
* Protocol.
|
||||
*/
|
||||
class udp
|
||||
{
|
||||
public:
|
||||
class endpoint;
|
||||
|
||||
/// Obtain an identifier for the type of the protocol.
|
||||
int type() const
|
||||
{
|
||||
return SOCK_DGRAM;
|
||||
}
|
||||
|
||||
/// Obtain an identifier for the protocol.
|
||||
int protocol() const
|
||||
{
|
||||
return IPPROTO_UDP;
|
||||
}
|
||||
|
||||
/// Obtain an identifier for the protocol family.
|
||||
int family() const
|
||||
{
|
||||
return PF_INET6;
|
||||
}
|
||||
|
||||
/// Template typedefs for socket types.
|
||||
template <typename Allocator>
|
||||
struct types
|
||||
{
|
||||
/// The service type for IPv4 UDP sockets.
|
||||
typedef datagram_socket_service<udp, Allocator> socket_service;
|
||||
|
||||
/// The IPv4 UDP socket type.
|
||||
typedef basic_datagram_socket<socket_service> socket;
|
||||
};
|
||||
|
||||
/// The IPv4 UDP socket type.
|
||||
typedef types<std::allocator<void> >::socket socket;
|
||||
};
|
||||
|
||||
/// Describes an endpoint for a UDP socket.
|
||||
/**
|
||||
* The asio::ipv6::udp::endpoint class describes an endpoint that may be
|
||||
* associated with a particular socket.
|
||||
*
|
||||
* @par Thread Safety:
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*
|
||||
* @par Concepts:
|
||||
* Endpoint.
|
||||
*/
|
||||
class udp::endpoint
|
||||
{
|
||||
public:
|
||||
/// The protocol type associated with the endpoint.
|
||||
typedef udp protocol_type;
|
||||
|
||||
/// The type of the endpoint structure. This type is dependent on the
|
||||
/// underlying implementation of the socket layer.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined data_type;
|
||||
#else
|
||||
typedef asio::detail::socket_addr_type data_type;
|
||||
#endif
|
||||
|
||||
/// The type for the size of the endpoint structure. This type is dependent on
|
||||
/// the underlying implementation of the socket layer.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined size_type;
|
||||
#else
|
||||
typedef asio::detail::socket_addr_len_type size_type;
|
||||
#endif
|
||||
|
||||
/// Default constructor.
|
||||
endpoint()
|
||||
{
|
||||
addr_.sin6_family = AF_INET6;
|
||||
addr_.sin6_port = 0;
|
||||
addr_.sin6_flowinfo = 0;
|
||||
in6_addr tmp_addr = IN6ADDR_LOOPBACK_INIT;
|
||||
addr_.sin6_addr = tmp_addr;
|
||||
addr_.sin6_scope_id = 0;
|
||||
}
|
||||
|
||||
/// Construct an endpoint using a port number, specified in the host's byte
|
||||
/// order. The IP address will be the any address (i.e. in6addr_any). This
|
||||
/// constructor would typically be used for accepting new connections.
|
||||
endpoint(unsigned short port_num)
|
||||
{
|
||||
addr_.sin6_family = AF_INET6;
|
||||
addr_.sin6_port =
|
||||
asio::detail::socket_ops::host_to_network_short(port_num);
|
||||
addr_.sin6_flowinfo = 0;
|
||||
in6_addr tmp_addr = IN6ADDR_LOOPBACK_INIT;
|
||||
addr_.sin6_addr = tmp_addr;
|
||||
addr_.sin6_scope_id = 0;
|
||||
}
|
||||
|
||||
/// Construct an endpoint using a port number and an IP address. This
|
||||
/// constructor may be used for accepting connections on a specific interface
|
||||
/// or for making a connection to a remote endpoint.
|
||||
endpoint(unsigned short port_num, const asio::ipv6::address& addr)
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
addr_.sin6_family = AF_INET6;
|
||||
addr_.sin6_port =
|
||||
asio::detail::socket_ops::host_to_network_short(port_num);
|
||||
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;
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
endpoint(const endpoint& other)
|
||||
: addr_(other.addr_)
|
||||
{
|
||||
}
|
||||
|
||||
/// Assign from another endpoint.
|
||||
endpoint& operator=(const endpoint& other)
|
||||
{
|
||||
addr_ = other.addr_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// The protocol associated with the endpoint.
|
||||
protocol_type protocol() const
|
||||
{
|
||||
return protocol_type();
|
||||
}
|
||||
|
||||
/// Get the underlying endpoint in the native type.
|
||||
data_type* data()
|
||||
{
|
||||
return reinterpret_cast<data_type*>(&addr_);
|
||||
}
|
||||
|
||||
/// Get the underlying endpoint in the native type.
|
||||
const data_type* data() const
|
||||
{
|
||||
return reinterpret_cast<const data_type*>(&addr_);
|
||||
}
|
||||
|
||||
/// Get the underlying size of the endpoint in the native type.
|
||||
size_type size() const
|
||||
{
|
||||
return sizeof(addr_);
|
||||
}
|
||||
|
||||
/// Set the underlying size of the endpoint in the native type.
|
||||
void size(size_type size)
|
||||
{
|
||||
if (size != sizeof(addr_))
|
||||
{
|
||||
asio::error e(asio::error::invalid_argument);
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the port associated with the endpoint. The port number is always in
|
||||
/// the host's byte order.
|
||||
unsigned short port() const
|
||||
{
|
||||
return asio::detail::socket_ops::network_to_host_short(
|
||||
addr_.sin6_port);
|
||||
}
|
||||
|
||||
/// Set the port associated with the endpoint. The port number is always in
|
||||
/// the host's byte order.
|
||||
void port(unsigned short port_num)
|
||||
{
|
||||
addr_.sin6_port =
|
||||
asio::detail::socket_ops::host_to_network_short(port_num);
|
||||
}
|
||||
|
||||
/// Get the IP address associated with the endpoint.
|
||||
asio::ipv6::address address() const
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/// Set the IP address associated with the endpoint.
|
||||
void address(const asio::ipv6::address& addr)
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
asio::ipv6::address::bytes_type bytes = addr.to_bytes();
|
||||
memcpy(addr_.sin6_addr.s6_addr, bytes.elems, 16);
|
||||
}
|
||||
|
||||
/// Compare two endpoints for equality.
|
||||
friend bool operator==(const endpoint& e1, const endpoint& e2)
|
||||
{
|
||||
return e1.address() == e2.address() && e1.port() == e2.port();
|
||||
}
|
||||
|
||||
/// Compare two endpoints for inequality.
|
||||
friend bool operator!=(const endpoint& e1, const endpoint& e2)
|
||||
{
|
||||
return e1.address() != e2.address() || e1.port() != e2.port();
|
||||
}
|
||||
|
||||
/// Compare endpoints for ordering.
|
||||
friend bool operator<(const endpoint& e1, const endpoint& e2)
|
||||
{
|
||||
if (e1.address() < e2.address())
|
||||
return true;
|
||||
if (e1.address() != e2.address())
|
||||
return false;
|
||||
return e1.port() < e2.port();
|
||||
}
|
||||
|
||||
private:
|
||||
// The underlying IPv4 socket address.
|
||||
asio::detail::inet_addr_v6_type addr_;
|
||||
};
|
||||
|
||||
/// Output an endpoint as a string.
|
||||
/**
|
||||
* Used to output a human-readable string for a specified endpoint.
|
||||
*
|
||||
* @param os The output stream to which the string will be written.
|
||||
*
|
||||
* @param endpoint The endpoint to be written.
|
||||
*
|
||||
* @return The output stream.
|
||||
*
|
||||
* @relates udp::endpoint
|
||||
*/
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
std::ostream& operator<<(std::ostream& os, const udp::endpoint& endpoint)
|
||||
{
|
||||
os << '[' << endpoint.address().to_string() << ']' << ':' << endpoint.port();
|
||||
return os;
|
||||
}
|
||||
#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
template <typename Ostream>
|
||||
Ostream& operator<<(Ostream& os, const udp::endpoint& endpoint)
|
||||
{
|
||||
os << '[' << endpoint.address().to_string() << ']' << ':' << endpoint.port();
|
||||
return os;
|
||||
}
|
||||
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
|
||||
} // namespace ipv6
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_IPV6_UDP_HPP
|
Loading…
Reference in New Issue
Block a user