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