5 // Copyright (c) 2003-2017 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)