1// 2// ip/detail/impl/endpoint.ipp 3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4// 5// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6// 7// Distributed under the Boost Software License, Version 1.0. (See accompanying 8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9// 10 11#ifndef ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP 12#define ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP 13 14#if defined(_MSC_VER) && (_MSC_VER >= 1200) 15# pragma once 16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18#include "asio/detail/config.hpp" 19#include <cstring> 20#if !defined(ASIO_NO_IOSTREAM) 21# include <sstream> 22#endif // !defined(ASIO_NO_IOSTREAM) 23#include "asio/detail/socket_ops.hpp" 24#include "asio/detail/throw_error.hpp" 25#include "asio/error.hpp" 26#include "asio/ip/detail/endpoint.hpp" 27 28#include "asio/detail/push_options.hpp" 29 30namespace asio { 31namespace ip { 32namespace detail { 33 34endpoint::endpoint() 35 : data_() 36{ 37 data_.v4.sin_family = ASIO_OS_DEF(AF_INET); 38 data_.v4.sin_port = 0; 39 data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); 40} 41 42endpoint::endpoint(int family, unsigned short port_num) 43 : data_() 44{ 45 using namespace std; // For memcpy. 46 if (family == ASIO_OS_DEF(AF_INET)) 47 { 48 data_.v4.sin_family = ASIO_OS_DEF(AF_INET); 49 data_.v4.sin_port = 50 asio::detail::socket_ops::host_to_network_short(port_num); 51 data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); 52 } 53 else 54 { 55 data_.v6.sin6_family = ASIO_OS_DEF(AF_INET6); 56 data_.v6.sin6_port = 57 asio::detail::socket_ops::host_to_network_short(port_num); 58 data_.v6.sin6_flowinfo = 0; 59 data_.v6.sin6_addr.s6_addr[0] = 0; data_.v6.sin6_addr.s6_addr[1] = 0; 60 data_.v6.sin6_addr.s6_addr[2] = 0, data_.v6.sin6_addr.s6_addr[3] = 0; 61 data_.v6.sin6_addr.s6_addr[4] = 0, data_.v6.sin6_addr.s6_addr[5] = 0; 62 data_.v6.sin6_addr.s6_addr[6] = 0, data_.v6.sin6_addr.s6_addr[7] = 0; 63 data_.v6.sin6_addr.s6_addr[8] = 0, data_.v6.sin6_addr.s6_addr[9] = 0; 64 data_.v6.sin6_addr.s6_addr[10] = 0, data_.v6.sin6_addr.s6_addr[11] = 0; 65 data_.v6.sin6_addr.s6_addr[12] = 0, data_.v6.sin6_addr.s6_addr[13] = 0; 66 data_.v6.sin6_addr.s6_addr[14] = 0, data_.v6.sin6_addr.s6_addr[15] = 0; 67 data_.v6.sin6_scope_id = 0; 68 } 69} 70 71endpoint::endpoint(const asio::ip::address& addr, 72 unsigned short port_num) 73 : data_() 74{ 75 using namespace std; // For memcpy. 76 if (addr.is_v4()) 77 { 78 data_.v4.sin_family = ASIO_OS_DEF(AF_INET); 79 data_.v4.sin_port = 80 asio::detail::socket_ops::host_to_network_short(port_num); 81 data_.v4.sin_addr.s_addr = 82 asio::detail::socket_ops::host_to_network_long( 83 addr.to_v4().to_uint()); 84 } 85 else 86 { 87 data_.v6.sin6_family = ASIO_OS_DEF(AF_INET6); 88 data_.v6.sin6_port = 89 asio::detail::socket_ops::host_to_network_short(port_num); 90 data_.v6.sin6_flowinfo = 0; 91 asio::ip::address_v6 v6_addr = addr.to_v6(); 92 asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes(); 93 memcpy(data_.v6.sin6_addr.s6_addr, bytes.data(), 16); 94 data_.v6.sin6_scope_id = 95 static_cast<asio::detail::u_long_type>( 96 v6_addr.scope_id()); 97 } 98} 99 100void endpoint::resize(std::size_t new_size) 101{ 102 if (new_size > sizeof(asio::detail::sockaddr_storage_type)) 103 { 104 asio::error_code ec(asio::error::invalid_argument); 105 asio::detail::throw_error(ec); 106 } 107} 108 109unsigned short endpoint::port() const 110{ 111 if (is_v4()) 112 { 113 return asio::detail::socket_ops::network_to_host_short( 114 data_.v4.sin_port); 115 } 116 else 117 { 118 return asio::detail::socket_ops::network_to_host_short( 119 data_.v6.sin6_port); 120 } 121} 122 123void endpoint::port(unsigned short port_num) 124{ 125 if (is_v4()) 126 { 127 data_.v4.sin_port 128 = asio::detail::socket_ops::host_to_network_short(port_num); 129 } 130 else 131 { 132 data_.v6.sin6_port 133 = asio::detail::socket_ops::host_to_network_short(port_num); 134 } 135} 136 137asio::ip::address endpoint::address() const 138{ 139 using namespace std; // For memcpy. 140 if (is_v4()) 141 { 142 return asio::ip::address_v4( 143 asio::detail::socket_ops::network_to_host_long( 144 data_.v4.sin_addr.s_addr)); 145 } 146 else 147 { 148 asio::ip::address_v6::bytes_type bytes; 149#if defined(ASIO_HAS_STD_ARRAY) 150 memcpy(bytes.data(), data_.v6.sin6_addr.s6_addr, 16); 151#else // defined(ASIO_HAS_STD_ARRAY) 152 memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16); 153#endif // defined(ASIO_HAS_STD_ARRAY) 154 return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id); 155 } 156} 157 158void endpoint::address(const asio::ip::address& addr) 159{ 160 endpoint tmp_endpoint(addr, port()); 161 data_ = tmp_endpoint.data_; 162} 163 164bool operator==(const endpoint& e1, const endpoint& e2) 165{ 166 return e1.address() == e2.address() && e1.port() == e2.port(); 167} 168 169bool operator<(const endpoint& e1, const endpoint& e2) 170{ 171 if (e1.address() < e2.address()) 172 return true; 173 if (e1.address() != e2.address()) 174 return false; 175 return e1.port() < e2.port(); 176} 177 178#if !defined(ASIO_NO_IOSTREAM) 179std::string endpoint::to_string() const 180{ 181 std::ostringstream tmp_os; 182 tmp_os.imbue(std::locale::classic()); 183 if (is_v4()) 184 tmp_os << address(); 185 else 186 tmp_os << '[' << address() << ']'; 187 tmp_os << ':' << port(); 188 189 return tmp_os.str(); 190} 191#endif // !defined(ASIO_NO_IOSTREAM) 192 193} // namespace detail 194} // namespace ip 195} // namespace asio 196 197#include "asio/detail/pop_options.hpp" 198 199#endif // ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP 200