1//
2// ip/impl/address_v4.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_IMPL_ADDRESS_V4_IPP
12#define ASIO_IP_IMPL_ADDRESS_V4_IPP
13
14
15#include "asio/detail/config.hpp"
16#include <climits>
17#include <stdexcept>
18#include "asio/error.hpp"
19#include "asio/detail/socket_ops.hpp"
20#include "asio/detail/throw_error.hpp"
21#include "asio/detail/throw_exception.hpp"
22#include "asio/ip/address_v4.hpp"
23
24#include "asio/detail/push_options.hpp"
25
26namespace asio {
27namespace ip {
28
29address_v4::address_v4(const address_v4::bytes_type& bytes)
30{
31#if UCHAR_MAX > 0xFF
32  if (bytes[0] > 0xFF || bytes[1] > 0xFF
33      || bytes[2] > 0xFF || bytes[3] > 0xFF)
34  {
35    std::out_of_range ex("address_v4 from bytes_type");
36    asio::detail::throw_exception(ex);
37  }
38#endif // UCHAR_MAX > 0xFF
39
40  using namespace std; // For memcpy.
41  memcpy(&addr_.s_addr, bytes.data(), 4);
42}
43
44address_v4::address_v4(unsigned long addr)
45{
46#if ULONG_MAX > 0xFFFFFFFF
47  if (addr > 0xFFFFFFFF)
48  {
49    std::out_of_range ex("address_v4 from unsigned long");
50    asio::detail::throw_exception(ex);
51  }
52#endif // ULONG_MAX > 0xFFFFFFFF
53
54  addr_.s_addr = asio::detail::socket_ops::host_to_network_long(
55      static_cast<asio::detail::u_long_type>(addr));
56}
57
58address_v4::bytes_type address_v4::to_bytes() const
59{
60  using namespace std; // For memcpy.
61  bytes_type bytes;
62  memcpy(bytes.data(), &addr_.s_addr, 4);
63  return bytes;
64}
65
66unsigned long address_v4::to_ulong() const
67{
68  return asio::detail::socket_ops::network_to_host_long(addr_.s_addr);
69}
70
71std::string address_v4::to_string() const
72{
73  asio::error_code ec;
74  std::string addr = to_string(ec);
75  asio::detail::throw_error(ec);
76  return addr;
77}
78
79std::string address_v4::to_string(asio::error_code& ec) const
80{
81  char addr_str[asio::detail::max_addr_v4_str_len];
82  const char* addr =
83    asio::detail::socket_ops::inet_ntop(
84        ASIO_OS_DEF(AF_INET), &addr_, addr_str,
85        asio::detail::max_addr_v4_str_len, 0, ec);
86  if (addr == 0)
87    return std::string();
88  return addr;
89}
90
91address_v4 address_v4::from_string(const char* str)
92{
93  asio::error_code ec;
94  address_v4 addr = from_string(str, ec);
95  asio::detail::throw_error(ec);
96  return addr;
97}
98
99address_v4 address_v4::from_string(
100    const char* str, asio::error_code& ec)
101{
102  address_v4 tmp;
103  if (asio::detail::socket_ops::inet_pton(
104        ASIO_OS_DEF(AF_INET), str, &tmp.addr_, 0, ec) <= 0)
105    return address_v4();
106  return tmp;
107}
108
109address_v4 address_v4::from_string(const std::string& str)
110{
111  return from_string(str.c_str());
112}
113
114address_v4 address_v4::from_string(
115    const std::string& str, asio::error_code& ec)
116{
117  return from_string(str.c_str(), ec);
118}
119
120bool address_v4::is_loopback() const
121{
122  return (to_ulong() & 0xFF000000) == 0x7F000000;
123}
124
125bool address_v4::is_unspecified() const
126{
127  return to_ulong() == 0;
128}
129
130bool address_v4::is_class_a() const
131{
132  return (to_ulong() & 0x80000000) == 0;
133}
134
135bool address_v4::is_class_b() const
136{
137  return (to_ulong() & 0xC0000000) == 0x80000000;
138}
139
140bool address_v4::is_class_c() const
141{
142  return (to_ulong() & 0xE0000000) == 0xC0000000;
143}
144
145bool address_v4::is_multicast() const
146{
147  return (to_ulong() & 0xF0000000) == 0xE0000000;
148}
149
150address_v4 address_v4::broadcast(const address_v4& addr, const address_v4& mask)
151{
152  return address_v4(addr.to_ulong() | (mask.to_ulong() ^ 0xFFFFFFFF));
153}
154
155address_v4 address_v4::netmask(const address_v4& addr)
156{
157  if (addr.is_class_a())
158    return address_v4(0xFF000000);
159  if (addr.is_class_b())
160    return address_v4(0xFFFF0000);
161  if (addr.is_class_c())
162    return address_v4(0xFFFFFF00);
163  return address_v4(0xFFFFFFFF);
164}
165
166} // namespace ip
167} // namespace asio
168
169#include "asio/detail/pop_options.hpp"
170
171#endif // ASIO_IP_IMPL_ADDRESS_V4_IPP
172