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
30namespace boost {
31namespace asio {
32namespace ip {
33namespace detail {
34
35endpoint::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
43endpoint::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(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(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
72endpoint::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(port_num);
82 data_.v4.sin_addr.s_addr =
83 boost::asio::detail::socket_ops::host_to_network_long(
84 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(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(data_.v6.sin6_addr.s6_addr, bytes.data(), 16);
96 data_.v6.sin6_scope_id =
97 static_cast<boost::asio::detail::u_long_type>(
98 v6_addr.scope_id());
99 }
100}
101
102void 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(ec);
108 }
109}
110
111unsigned short endpoint::port() const
112{
113 if (is_v4())
114 {
115 return boost::asio::detail::socket_ops::network_to_host_short(
116 data_.v4.sin_port);
117 }
118 else
119 {
120 return boost::asio::detail::socket_ops::network_to_host_short(
121 data_.v6.sin6_port);
122 }
123}
124
125void 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(port_num);
131 }
132 else
133 {
134 data_.v6.sin6_port
135 = boost::asio::detail::socket_ops::host_to_network_short(port_num);
136 }
137}
138
139boost::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 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(bytes.data(), data_.v6.sin6_addr.s6_addr, 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
160void endpoint::address(const boost::asio::ip::address& addr)
161{
162 endpoint tmp_endpoint(addr, port());
163 data_ = tmp_endpoint.data_;
164}
165
166bool operator==(const endpoint& e1, const endpoint& e2)
167{
168 return e1.address() == e2.address() && e1.port() == e2.port();
169}
170
171bool 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)
181std::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(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