2
0
mirror of https://github.com/boostorg/asio.git synced 2026-01-28 06:42:08 +00:00
Files
asio/test/ip/multicast.cpp
Christopher Kohlhoff e97ac69ad8 Merge from trunk.
........
  r57393 | hkaiser | 2009-11-05 11:26:15 +1100 (Thu, 05 Nov 2009) | 1 line
  
  Asio: disabled VC workaround for VC2010 beta2 compiler. Fixes #3796.
........
  r58621 | chris_kohlhoff | 2010-01-02 10:04:35 +1100 (Sat, 02 Jan 2010) | 2 lines
  
  Wrap long line.
........
  r58624 | chris_kohlhoff | 2010-01-02 17:09:02 +1100 (Sat, 02 Jan 2010) | 3 lines
  
  Windows needs the OVERLAPPED structure to be valid until both the initiating
  function call has returned and the completion packet has been delivered.
........
  r58625 | chris_kohlhoff | 2010-01-02 18:16:41 +1100 (Sat, 02 Jan 2010) | 2 lines
  
  Use specific type_traits headers.
........
  r58626 | chris_kohlhoff | 2010-01-02 18:18:09 +1100 (Sat, 02 Jan 2010) | 2 lines
  
  Include specific headers in unit tests rather than the convenience header asio.hpp.
........
  r58627 | chris_kohlhoff | 2010-01-02 19:24:12 +1100 (Sat, 02 Jan 2010) | 3 lines
  
  Use boost::addressof to get the address of handler objects, rather than
  applying operator& directly. Fixes #2977.
........
  r58628 | chris_kohlhoff | 2010-01-02 20:48:01 +1100 (Sat, 02 Jan 2010) | 3 lines
  
  Don't block signals while performing system calls, but instead restart the
  calls if they are interrupted.
........
  r58629 | chris_kohlhoff | 2010-01-02 21:20:12 +1100 (Sat, 02 Jan 2010) | 2 lines
  
  Ensure that kqueue support is enabled for BSD platforms. Fixes #3626.
........
  r58630 | chris_kohlhoff | 2010-01-02 21:30:41 +1100 (Sat, 02 Jan 2010) | 2 lines
  
  Add boost_ prefix to extern "C" thread entry point function. Fixes #3809.
........
  r58647 | chris_kohlhoff | 2010-01-03 07:36:59 +1100 (Sun, 03 Jan 2010) | 2 lines
  
  Use a pool of strand implementations to make copying of strands cheaper.
........
  r58650 | chris_kohlhoff | 2010-01-03 08:35:33 +1100 (Sun, 03 Jan 2010) | 4 lines
  
  In getaddrinfo emulation, only check the socket type (SOCK_STREAM or SOCK_DGRAM)
  if a service name has been specified. This should allow the emulation to work
  with raw sockets.
........
  r58651 | chris_kohlhoff | 2010-01-03 08:37:10 +1100 (Sun, 03 Jan 2010) | 3 lines
  
  Add a workaround for some broken Windows firewalls that make a socket
  appear bound to 0.0.0.0 when it is in fact bound to 127.0.0.1.
........
  r58652 | chris_kohlhoff | 2010-01-03 08:38:44 +1100 (Sun, 03 Jan 2010) | 2 lines
  
  Only include implementation headers required for each platform.
........


[SVN r58669]
2010-01-04 11:55:09 +00:00

351 lines
11 KiB
C++

//
// multicast.cpp
// ~~~~~~~~~~~~~
//
// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Disable autolinking for unit tests.
#if !defined(BOOST_ALL_NO_LIB)
#define BOOST_ALL_NO_LIB 1
#endif // !defined(BOOST_ALL_NO_LIB)
// Test that header file is self-contained.
#include <boost/asio/ip/multicast.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/udp.hpp>
#include "../unit_test.hpp"
//------------------------------------------------------------------------------
// ip_multicast_compile test
// ~~~~~~~~~~~~~~~~~~~~~~~~~
// The following test checks that all nested classes, enums and constants in
// ip::multicast compile and link correctly. Runtime failures are ignored.
namespace ip_multicast_compile {
void test()
{
using namespace boost::asio;
namespace ip = boost::asio::ip;
try
{
io_service ios;
ip::udp::socket sock(ios);
const ip::address address;
const ip::address_v4 address_v4;
const ip::address_v6 address_v6;
// join_group class.
ip::multicast::join_group join_group1;
ip::multicast::join_group join_group2(address);
ip::multicast::join_group join_group3(address_v4);
ip::multicast::join_group join_group4(address_v4, address_v4);
ip::multicast::join_group join_group5(address_v6);
ip::multicast::join_group join_group6(address_v6, 1);
sock.set_option(join_group6);
// leave_group class.
ip::multicast::leave_group leave_group1;
ip::multicast::leave_group leave_group2(address);
ip::multicast::leave_group leave_group3(address_v4);
ip::multicast::leave_group leave_group4(address_v4, address_v4);
ip::multicast::leave_group leave_group5(address_v6);
ip::multicast::leave_group leave_group6(address_v6, 1);
sock.set_option(leave_group6);
// outbound_interface class.
ip::multicast::outbound_interface outbound_interface1;
ip::multicast::outbound_interface outbound_interface2(address_v4);
ip::multicast::outbound_interface outbound_interface3(1);
sock.set_option(outbound_interface3);
// hops class.
ip::multicast::hops hops1(1024);
sock.set_option(hops1);
ip::multicast::hops hops2;
sock.get_option(hops2);
hops1 = 1;
static_cast<int>(hops1.value());
// enable_loopback class.
ip::multicast::enable_loopback enable_loopback1(true);
sock.set_option(enable_loopback1);
ip::multicast::enable_loopback enable_loopback2;
sock.get_option(enable_loopback2);
enable_loopback1 = true;
static_cast<bool>(enable_loopback1);
static_cast<bool>(!enable_loopback1);
static_cast<bool>(enable_loopback1.value());
}
catch (std::exception&)
{
}
}
} // namespace ip_multicast_compile
//------------------------------------------------------------------------------
// ip_multicast_runtime test
// ~~~~~~~~~~~~~~~~~~~~~~~~~
// The following test checks the runtime operation of the socket options defined
// in the ip::multicast namespace.
namespace ip_multicast_runtime {
#if defined(__hpux)
// HP-UX doesn't declare this function extern "C", so it is declared again here
// to avoid a linker error about an undefined symbol.
extern "C" unsigned int if_nametoindex(const char*);
#endif // defined(__hpux)
void test()
{
using namespace boost::asio;
namespace ip = boost::asio::ip;
io_service ios;
boost::system::error_code ec;
ip::udp::endpoint ep_v4(ip::address_v4::loopback(), 0);
ip::udp::socket sock_v4(ios);
sock_v4.open(ep_v4.protocol(), ec);
sock_v4.bind(ep_v4, ec);
bool have_v4 = !ec;
ip::udp::endpoint ep_v6(ip::address_v6::loopback(), 0);
ip::udp::socket sock_v6(ios);
sock_v6.open(ep_v6.protocol(), ec);
sock_v6.bind(ep_v6, ec);
bool have_v6 = !ec;
BOOST_CHECK(have_v4 || have_v6);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
// Windows CE seems to have problems with some multicast group addresses.
// The following address works on CE, but as it is not a private multicast
// address it will not be used on other platforms.
const ip::address multicast_address_v4 =
ip::address::from_string("239.0.0.4", ec);
#else // defined(BOOST_WINDOWS) && defined(UNDER_CE)
const ip::address multicast_address_v4 =
ip::address::from_string("239.255.0.1", ec);
#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
BOOST_CHECK(!have_v4 || !ec);
const ip::address multicast_address_v6 =
ip::address::from_string("ff01::1", ec);
BOOST_CHECK(!have_v6 || !ec);
// join_group class.
if (have_v4)
{
ip::multicast::join_group join_group(multicast_address_v4);
sock_v4.set_option(join_group, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
}
if (have_v6)
{
ip::multicast::join_group join_group(multicast_address_v6);
sock_v6.set_option(join_group, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
}
// leave_group class.
if (have_v4)
{
ip::multicast::leave_group leave_group(multicast_address_v4);
sock_v4.set_option(leave_group, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
}
if (have_v6)
{
ip::multicast::leave_group leave_group(multicast_address_v6);
sock_v6.set_option(leave_group, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
}
// outbound_interface class.
if (have_v4)
{
ip::multicast::outbound_interface outbound_interface(
ip::address_v4::loopback());
sock_v4.set_option(outbound_interface, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
}
if (have_v6)
{
#if defined(__hpux)
ip::multicast::outbound_interface outbound_interface(if_nametoindex("lo0"));
#else
ip::multicast::outbound_interface outbound_interface(1);
#endif
sock_v6.set_option(outbound_interface, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
}
// hops class.
if (have_v4)
{
ip::multicast::hops hops1(1);
BOOST_CHECK(hops1.value() == 1);
sock_v4.set_option(hops1, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
ip::multicast::hops hops2;
sock_v4.get_option(hops2, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
BOOST_CHECK(hops2.value() == 1);
ip::multicast::hops hops3(0);
BOOST_CHECK(hops3.value() == 0);
sock_v4.set_option(hops3, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
ip::multicast::hops hops4;
sock_v4.get_option(hops4, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
BOOST_CHECK(hops4.value() == 0);
}
if (have_v6)
{
ip::multicast::hops hops1(1);
BOOST_CHECK(hops1.value() == 1);
sock_v6.set_option(hops1, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
ip::multicast::hops hops2;
sock_v6.get_option(hops2, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
BOOST_CHECK(hops2.value() == 1);
ip::multicast::hops hops3(0);
BOOST_CHECK(hops3.value() == 0);
sock_v6.set_option(hops3, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
ip::multicast::hops hops4;
sock_v6.get_option(hops4, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
BOOST_CHECK(hops4.value() == 0);
}
// enable_loopback class.
if (have_v4)
{
ip::multicast::enable_loopback enable_loopback1(true);
BOOST_CHECK(enable_loopback1.value());
BOOST_CHECK(static_cast<bool>(enable_loopback1));
BOOST_CHECK(!!enable_loopback1);
sock_v4.set_option(enable_loopback1, ec);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
// Option is not supported under Windows CE.
BOOST_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
ec.value() << ", " << ec.message());
#else // defined(BOOST_WINDOWS) && defined(UNDER_CE)
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
ip::multicast::enable_loopback enable_loopback2;
sock_v4.get_option(enable_loopback2, ec);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
// Not supported under Windows CE but can get value.
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
#else // defined(BOOST_WINDOWS) && defined(UNDER_CE)
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
BOOST_CHECK(enable_loopback2.value());
BOOST_CHECK(static_cast<bool>(enable_loopback2));
BOOST_CHECK(!!enable_loopback2);
#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
ip::multicast::enable_loopback enable_loopback3(false);
BOOST_CHECK(!enable_loopback3.value());
BOOST_CHECK(!static_cast<bool>(enable_loopback3));
BOOST_CHECK(!enable_loopback3);
sock_v4.set_option(enable_loopback3, ec);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
// Option is not supported under Windows CE.
BOOST_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
ec.value() << ", " << ec.message());
#else // defined(BOOST_WINDOWS) && defined(UNDER_CE)
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
ip::multicast::enable_loopback enable_loopback4;
sock_v4.get_option(enable_loopback4, ec);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
// Not supported under Windows CE but can get value.
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
#else // defined(BOOST_WINDOWS) && defined(UNDER_CE)
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
BOOST_CHECK(!enable_loopback4.value());
BOOST_CHECK(!static_cast<bool>(enable_loopback4));
BOOST_CHECK(!enable_loopback4);
#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
}
if (have_v6)
{
ip::multicast::enable_loopback enable_loopback1(true);
BOOST_CHECK(enable_loopback1.value());
BOOST_CHECK(static_cast<bool>(enable_loopback1));
BOOST_CHECK(!!enable_loopback1);
sock_v6.set_option(enable_loopback1, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
ip::multicast::enable_loopback enable_loopback2;
sock_v6.get_option(enable_loopback2, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
BOOST_CHECK(enable_loopback2.value());
BOOST_CHECK(static_cast<bool>(enable_loopback2));
BOOST_CHECK(!!enable_loopback2);
ip::multicast::enable_loopback enable_loopback3(false);
BOOST_CHECK(!enable_loopback3.value());
BOOST_CHECK(!static_cast<bool>(enable_loopback3));
BOOST_CHECK(!enable_loopback3);
sock_v6.set_option(enable_loopback3, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
ip::multicast::enable_loopback enable_loopback4;
sock_v6.get_option(enable_loopback4, ec);
BOOST_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
BOOST_CHECK(!enable_loopback4.value());
BOOST_CHECK(!static_cast<bool>(enable_loopback4));
BOOST_CHECK(!enable_loopback4);
}
}
} // namespace ip_multicast_runtime
//------------------------------------------------------------------------------
test_suite* init_unit_test_suite(int, char*[])
{
test_suite* test = BOOST_TEST_SUITE("ip/multicast");
test->add(BOOST_TEST_CASE(&ip_multicast_compile::test));
test->add(BOOST_TEST_CASE(&ip_multicast_runtime::test));
return test;
}