5 // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
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)
16 // Test that header file is self-contained.
17 #include <boost/asio/ip/multicast.hpp>
19 #include <boost/asio/io_service.hpp>
20 #include <boost/asio/ip/udp.hpp>
21 #include "../unit_test.hpp"
23 //------------------------------------------------------------------------------
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.
30 namespace ip_multicast_compile
{
34 using namespace boost::asio
;
35 namespace ip
= boost::asio::ip
;
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
;
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
);
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
);
65 // outbound_interface class.
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
);
74 ip::multicast::hops
hops1(1024);
75 sock
.set_option(hops1
);
76 ip::multicast::hops hops2
;
77 sock
.get_option(hops2
);
79 (void)static_cast<int>(hops1
.value());
81 // enable_loopback class.
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());
92 catch (std::exception
&)
97 } // namespace ip_multicast_compile
99 //------------------------------------------------------------------------------
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.
106 namespace ip_multicast_runtime
{
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)
116 using namespace boost::asio
;
117 namespace ip
= boost::asio::ip
;
120 boost::system::error_code ec
;
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
);
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
);
134 BOOST_ASIO_CHECK(have_v4
|| have_v6
);
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
);
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
);
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());
177 // leave_group class.
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());
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());
194 // leave_group class.
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());
202 // outbound_interface class.
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());
215 ip::multicast::outbound_interface
outbound_interface(if_nametoindex("lo0"));
217 ip::multicast::outbound_interface
outbound_interface(1);
219 sock_v6
.set_option(outbound_interface
, ec
);
220 BOOST_ASIO_CHECK_MESSAGE(!ec
, ec
.value() << ", " << ec
.message());
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());
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);
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());
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);
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());
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);
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());
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);
271 // enable_loopback class.
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)
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)
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)
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)
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());
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
);
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());
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
);
358 } // namespace ip_multicast_runtime
360 //------------------------------------------------------------------------------
362 BOOST_ASIO_TEST_SUITE
365 BOOST_ASIO_TEST_CASE(ip_multicast_compile::test
)
366 BOOST_ASIO_TEST_CASE(ip_multicast_runtime::test
)