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