Imported Upstream version 1.64.0
[platform/upstream/boost.git] / libs / asio / test / ip / multicast.cpp
1 //
2 // multicast.cpp
3 // ~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2017 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 // Disable autolinking for unit tests.
12 #if !defined(BOOST_ALL_NO_LIB)
13 #define BOOST_ALL_NO_LIB 1
14 #endif // !defined(BOOST_ALL_NO_LIB)
15
16 // Test that header file is self-contained.
17 #include <boost/asio/ip/multicast.hpp>
18
19 #include <boost/asio/io_service.hpp>
20 #include <boost/asio/ip/udp.hpp>
21 #include "../unit_test.hpp"
22
23 //------------------------------------------------------------------------------
24
25 // ip_multicast_compile test
26 // ~~~~~~~~~~~~~~~~~~~~~~~~~
27 // The following test checks that all nested classes, enums and constants in
28 // ip::multicast compile and link correctly. Runtime failures are ignored.
29
30 namespace ip_multicast_compile {
31
32 void test()
33 {
34   using namespace boost::asio;
35   namespace ip = boost::asio::ip;
36
37   try
38   {
39     io_service ios;
40     ip::udp::socket sock(ios);
41     const ip::address address;
42     const ip::address_v4 address_v4;
43     const ip::address_v6 address_v6;
44
45     // join_group class.
46
47     ip::multicast::join_group join_group1;
48     ip::multicast::join_group join_group2(address);
49     ip::multicast::join_group join_group3(address_v4);
50     ip::multicast::join_group join_group4(address_v4, address_v4);
51     ip::multicast::join_group join_group5(address_v6);
52     ip::multicast::join_group join_group6(address_v6, 1);
53     sock.set_option(join_group6);
54
55     // leave_group class.
56
57     ip::multicast::leave_group leave_group1;
58     ip::multicast::leave_group leave_group2(address);
59     ip::multicast::leave_group leave_group3(address_v4);
60     ip::multicast::leave_group leave_group4(address_v4, address_v4);
61     ip::multicast::leave_group leave_group5(address_v6);
62     ip::multicast::leave_group leave_group6(address_v6, 1);
63     sock.set_option(leave_group6);
64
65     // outbound_interface class.
66
67     ip::multicast::outbound_interface outbound_interface1;
68     ip::multicast::outbound_interface outbound_interface2(address_v4);
69     ip::multicast::outbound_interface outbound_interface3(1);
70     sock.set_option(outbound_interface3);
71
72     // hops class.
73
74     ip::multicast::hops hops1(1024);
75     sock.set_option(hops1);
76     ip::multicast::hops hops2;
77     sock.get_option(hops2);
78     hops1 = 1;
79     (void)static_cast<int>(hops1.value());
80
81     // enable_loopback class.
82
83     ip::multicast::enable_loopback enable_loopback1(true);
84     sock.set_option(enable_loopback1);
85     ip::multicast::enable_loopback enable_loopback2;
86     sock.get_option(enable_loopback2);
87     enable_loopback1 = true;
88     (void)static_cast<bool>(enable_loopback1);
89     (void)static_cast<bool>(!enable_loopback1);
90     (void)static_cast<bool>(enable_loopback1.value());
91   }
92   catch (std::exception&)
93   {
94   }
95 }
96
97 } // namespace ip_multicast_compile
98
99 //------------------------------------------------------------------------------
100
101 // ip_multicast_runtime test
102 // ~~~~~~~~~~~~~~~~~~~~~~~~~
103 // The following test checks the runtime operation of the socket options defined
104 // in the ip::multicast namespace.
105
106 namespace ip_multicast_runtime {
107
108 #if defined(__hpux)
109 // HP-UX doesn't declare this function extern "C", so it is declared again here
110 // to avoid a linker error about an undefined symbol.
111 extern "C" unsigned int if_nametoindex(const char*);
112 #endif // defined(__hpux)
113
114 void test()
115 {
116   using namespace boost::asio;
117   namespace ip = boost::asio::ip;
118
119   io_service ios;
120   boost::system::error_code ec;
121
122   ip::udp::endpoint ep_v4(ip::address_v4::loopback(), 0);
123   ip::udp::socket sock_v4(ios);
124   sock_v4.open(ep_v4.protocol(), ec);
125   sock_v4.bind(ep_v4, ec);
126   bool have_v4 = !ec;
127
128   ip::udp::endpoint ep_v6(ip::address_v6::loopback(), 0);
129   ip::udp::socket sock_v6(ios);
130   sock_v6.open(ep_v6.protocol(), ec);
131   sock_v6.bind(ep_v6, ec);
132   bool have_v6 = !ec;
133
134   BOOST_ASIO_CHECK(have_v4 || have_v6);
135
136 #if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
137   // Windows CE seems to have problems with some multicast group addresses.
138   // The following address works on CE, but as it is not a private multicast
139   // address it will not be used on other platforms.
140   const ip::address multicast_address_v4 =
141     ip::address::from_string("239.0.0.4", ec);
142 #else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
143   const ip::address multicast_address_v4 =
144     ip::address::from_string("239.255.0.1", ec);
145 #endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
146   BOOST_ASIO_CHECK(!have_v4 || !ec);
147
148 #if (defined(__MACH__) && defined(__APPLE__)) \
149   || defined(__FreeBSD__) \
150   || defined(__NetBSD__) \
151   || defined(__OpenBSD__)
152   const ip::address multicast_address_v6 =
153     ip::address::from_string("ff02::1%lo0", ec);
154 #else // (defined(__MACH__) && defined(__APPLE__))
155       //   || defined(__FreeBSD__)
156       //   || defined(__NetBSD__)
157       //   || defined(__OpenBSD__)
158   const ip::address multicast_address_v6 =
159     ip::address::from_string("ff01::1", ec);
160 #endif // (defined(__MACH__) && defined(__APPLE__))
161        //   || defined(__FreeBSD__)
162        //   || defined(__NetBSD__)
163        //   || defined(__OpenBSD__)
164   BOOST_ASIO_CHECK(!have_v6 || !ec);
165
166   // join_group class.
167
168   if (have_v4)
169   {
170     ip::multicast::join_group join_group(multicast_address_v4);
171     sock_v4.set_option(join_group, ec);
172     BOOST_ASIO_CHECK_MESSAGE(!ec || ec == error::no_such_device,
173                        ec.value() << ", " << ec.message());
174
175     if (!ec)
176     {
177       // leave_group class.
178
179       ip::multicast::leave_group leave_group(multicast_address_v4);
180       sock_v4.set_option(leave_group, ec);
181       BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
182     }
183   }
184
185   if (have_v6)
186   {
187     ip::multicast::join_group join_group(multicast_address_v6);
188     sock_v6.set_option(join_group, ec);
189     BOOST_ASIO_CHECK_MESSAGE(!ec || ec == error::no_such_device,
190                        ec.value() << ", " << ec.message());
191
192     if (!ec)
193     {
194       // leave_group class.
195
196       ip::multicast::leave_group leave_group(multicast_address_v6);
197       sock_v6.set_option(leave_group, ec);
198       BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
199     }
200   }
201
202   // outbound_interface class.
203
204   if (have_v4)
205   {
206     ip::multicast::outbound_interface outbound_interface(
207         ip::address_v4::loopback());
208     sock_v4.set_option(outbound_interface, ec);
209     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
210   }
211
212   if (have_v6)
213   {
214 #if defined(__hpux)
215     ip::multicast::outbound_interface outbound_interface(if_nametoindex("lo0"));
216 #else
217     ip::multicast::outbound_interface outbound_interface(1);
218 #endif
219     sock_v6.set_option(outbound_interface, ec);
220     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
221   }
222
223   // hops class.
224
225   if (have_v4)
226   {
227     ip::multicast::hops hops1(1);
228     BOOST_ASIO_CHECK(hops1.value() == 1);
229     sock_v4.set_option(hops1, ec);
230     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
231
232     ip::multicast::hops hops2;
233     sock_v4.get_option(hops2, ec);
234     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
235     BOOST_ASIO_CHECK(hops2.value() == 1);
236
237     ip::multicast::hops hops3(0);
238     BOOST_ASIO_CHECK(hops3.value() == 0);
239     sock_v4.set_option(hops3, ec);
240     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
241
242     ip::multicast::hops hops4;
243     sock_v4.get_option(hops4, ec);
244     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
245     BOOST_ASIO_CHECK(hops4.value() == 0);
246   }
247
248   if (have_v6)
249   {
250     ip::multicast::hops hops1(1);
251     BOOST_ASIO_CHECK(hops1.value() == 1);
252     sock_v6.set_option(hops1, ec);
253     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
254
255     ip::multicast::hops hops2;
256     sock_v6.get_option(hops2, ec);
257     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
258     BOOST_ASIO_CHECK(hops2.value() == 1);
259
260     ip::multicast::hops hops3(0);
261     BOOST_ASIO_CHECK(hops3.value() == 0);
262     sock_v6.set_option(hops3, ec);
263     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
264
265     ip::multicast::hops hops4;
266     sock_v6.get_option(hops4, ec);
267     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
268     BOOST_ASIO_CHECK(hops4.value() == 0);
269   }
270
271   // enable_loopback class.
272
273   if (have_v4)
274   {
275     ip::multicast::enable_loopback enable_loopback1(true);
276     BOOST_ASIO_CHECK(enable_loopback1.value());
277     BOOST_ASIO_CHECK(static_cast<bool>(enable_loopback1));
278     BOOST_ASIO_CHECK(!!enable_loopback1);
279     sock_v4.set_option(enable_loopback1, ec);
280 #if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
281     // Option is not supported under Windows CE.
282     BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
283         ec.value() << ", " << ec.message());
284 #else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
285     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
286 #endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
287
288     ip::multicast::enable_loopback enable_loopback2;
289     sock_v4.get_option(enable_loopback2, ec);
290 #if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
291     // Not supported under Windows CE but can get value.
292     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
293 #else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
294     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
295     BOOST_ASIO_CHECK(enable_loopback2.value());
296     BOOST_ASIO_CHECK(static_cast<bool>(enable_loopback2));
297     BOOST_ASIO_CHECK(!!enable_loopback2);
298 #endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
299
300     ip::multicast::enable_loopback enable_loopback3(false);
301     BOOST_ASIO_CHECK(!enable_loopback3.value());
302     BOOST_ASIO_CHECK(!static_cast<bool>(enable_loopback3));
303     BOOST_ASIO_CHECK(!enable_loopback3);
304     sock_v4.set_option(enable_loopback3, ec);
305 #if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
306     // Option is not supported under Windows CE.
307     BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
308         ec.value() << ", " << ec.message());
309 #else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
310     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
311 #endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
312
313     ip::multicast::enable_loopback enable_loopback4;
314     sock_v4.get_option(enable_loopback4, ec);
315 #if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
316     // Not supported under Windows CE but can get value.
317     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
318 #else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
319     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
320     BOOST_ASIO_CHECK(!enable_loopback4.value());
321     BOOST_ASIO_CHECK(!static_cast<bool>(enable_loopback4));
322     BOOST_ASIO_CHECK(!enable_loopback4);
323 #endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
324   }
325
326   if (have_v6)
327   {
328     ip::multicast::enable_loopback enable_loopback1(true);
329     BOOST_ASIO_CHECK(enable_loopback1.value());
330     BOOST_ASIO_CHECK(static_cast<bool>(enable_loopback1));
331     BOOST_ASIO_CHECK(!!enable_loopback1);
332     sock_v6.set_option(enable_loopback1, ec);
333     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
334
335     ip::multicast::enable_loopback enable_loopback2;
336     sock_v6.get_option(enable_loopback2, ec);
337     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
338     BOOST_ASIO_CHECK(enable_loopback2.value());
339     BOOST_ASIO_CHECK(static_cast<bool>(enable_loopback2));
340     BOOST_ASIO_CHECK(!!enable_loopback2);
341
342     ip::multicast::enable_loopback enable_loopback3(false);
343     BOOST_ASIO_CHECK(!enable_loopback3.value());
344     BOOST_ASIO_CHECK(!static_cast<bool>(enable_loopback3));
345     BOOST_ASIO_CHECK(!enable_loopback3);
346     sock_v6.set_option(enable_loopback3, ec);
347     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
348
349     ip::multicast::enable_loopback enable_loopback4;
350     sock_v6.get_option(enable_loopback4, ec);
351     BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
352     BOOST_ASIO_CHECK(!enable_loopback4.value());
353     BOOST_ASIO_CHECK(!static_cast<bool>(enable_loopback4));
354     BOOST_ASIO_CHECK(!enable_loopback4);
355   }
356 }
357
358 } // namespace ip_multicast_runtime
359
360 //------------------------------------------------------------------------------
361
362 BOOST_ASIO_TEST_SUITE
363 (
364   "ip/multicast",
365   BOOST_ASIO_TEST_CASE(ip_multicast_compile::test)
366   BOOST_ASIO_TEST_CASE(ip_multicast_runtime::test)
367 )