Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / ACE / tests / Multicast_Interfaces_Test.cpp
blob5455277bc86d8670a7b115b24be0ad804e3319a6
1 /* -*- C++ -*- */
3 //=============================================================================
4 /**
5 * @file Multicast_Interfaces_Test.cpp
7 * This is a sanity-check test of ACE_SOCK_Dgram_Mcast::join by
8 * interface name on platforms that support it.
9 * It retrieves the valid local interface names and attempts to
10 * perform a multicast join on all interfaces and then on each
11 * individual interface separately. If IPv6 is enabled, it will
12 * attempt to join on an IPv6 multicast address as well.
14 * @author Timothy Simpson <simpsont@objectcomputing.com>
16 //=============================================================================
18 #include "test_config.h"
20 #include "ace/OS_Memory.h"
21 #include "ace/OS_NS_sys_utsname.h"
22 #include "ace/SOCK_Dgram_Mcast.h"
23 #include "ace/SString.h"
25 #if defined (ACE_HAS_GETIFADDRS)
26 # include "ace/os_include/os_ifaddrs.h"
27 #endif /* ACE_HAS_GETIFADDRS */
29 #include <set>
31 using nameset = std::set<ACE_TString>;
33 #if defined (ACE_WIN32)
34 void
35 get_valid_ipv4_interface_names_win32 (nameset &names)
37 names.clear ();
39 // Initial call to determine actual memory size needed
40 IP_ADAPTER_ADDRESSES tmp_addrs;
41 ULONG bufLen = 0;
42 if (GetAdaptersAddresses (AF_INET, 0, 0, &tmp_addrs, &bufLen) != ERROR_BUFFER_OVERFLOW)
44 return;
47 // Get required output buffer and retrieve info for real.
48 char *buf = 0;
49 ACE_NEW (buf, char[bufLen]);
50 PIP_ADAPTER_ADDRESSES pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
51 if (::GetAdaptersAddresses (AF_INET, 0, 0, pAddrs, &bufLen) != NO_ERROR)
53 delete[] buf;
54 return;
57 while (pAddrs)
59 if (pAddrs->OperStatus == IfOperStatusUp && !(pAddrs->Flags & IP_ADAPTER_NO_MULTICAST))
61 PIP_ADAPTER_UNICAST_ADDRESS pUnicast = pAddrs->FirstUnicastAddress;
62 LPSOCKADDR sa = pUnicast->Address.lpSockaddr;
63 if (sa->sa_family == AF_INET)
65 names.insert (ACE_TEXT_WCHAR_TO_TCHAR (pAddrs->FriendlyName));
68 pAddrs = pAddrs->Next;
71 delete[] buf;
73 #elif defined (ACE_HAS_GETIFADDRS)
74 void
75 get_valid_ipv4_interface_names_getifaddrs (nameset &names)
77 ifaddrs *ifap = 0;
78 ifaddrs *p_if = 0;
80 if (::getifaddrs (&ifap) != 0)
81 return;
83 for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
85 if (p_if->ifa_flags & IFF_MULTICAST &&
86 p_if->ifa_addr->sa_family == AF_INET)
88 sockaddr_in *addr = reinterpret_cast<sockaddr_in *> (p_if->ifa_addr);
90 if (addr->sin_addr.s_addr != INADDR_ANY)
92 names.insert (ACE_TEXT_CHAR_TO_TCHAR (p_if->ifa_name));
97 ::freeifaddrs (ifap);
99 #endif /* ACE_WIN32 */
101 void
102 get_valid_ipv4_interface_names (nameset &names)
104 #if defined (ACE_WIN32)
105 get_valid_ipv4_interface_names_win32 (names);
106 #elif defined (ACE_HAS_GETIFADDRS)
107 get_valid_ipv4_interface_names_getifaddrs (names);
108 #endif /* ACE_WIN32 */
111 #if defined (ACE_HAS_IPV6)
112 #if defined (ACE_WIN32)
113 void
114 get_valid_ipv6_interface_names_win32 (nameset &names)
116 names.clear ();
118 // Initial call to determine actual memory size needed
119 IP_ADAPTER_ADDRESSES tmp_addrs;
120 ULONG bufLen = 0;
121 if (GetAdaptersAddresses (AF_INET, 0, 0, &tmp_addrs, &bufLen) != ERROR_BUFFER_OVERFLOW)
123 return;
126 // Get required output buffer and retrieve info for real.
127 char *buf = 0;
128 ACE_NEW (buf, char[bufLen]);
129 PIP_ADAPTER_ADDRESSES pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
130 if (::GetAdaptersAddresses (AF_INET6, 0, 0, pAddrs, &bufLen) != NO_ERROR)
132 delete[] buf;
133 return;
136 while (pAddrs)
138 if (pAddrs->OperStatus == IfOperStatusUp && !(pAddrs->Flags & IP_ADAPTER_NO_MULTICAST))
140 PIP_ADAPTER_UNICAST_ADDRESS pUnicast = pAddrs->FirstUnicastAddress;
141 LPSOCKADDR sa = pUnicast->Address.lpSockaddr;
142 if (sa->sa_family == AF_INET6)
144 names.insert (ACE_TEXT_WCHAR_TO_TCHAR (pAddrs->FriendlyName));
147 pAddrs = pAddrs->Next;
150 delete[] buf;
152 #elif defined (ACE_HAS_GETIFADDRS)
153 void
154 get_valid_ipv6_interface_names_getifaddrs (nameset &names)
156 ifaddrs *ifap = 0;
157 ifaddrs *p_if = 0;
159 if (::getifaddrs (&ifap) != 0)
160 return;
162 for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
164 if (p_if->ifa_flags & IFF_MULTICAST &&
165 p_if->ifa_addr->sa_family == AF_INET6)
167 sockaddr_in6 *addr = reinterpret_cast<sockaddr_in6 *> (p_if->ifa_addr);
169 if (!IN6_IS_ADDR_UNSPECIFIED (&addr->sin6_addr))
171 names.insert (ACE_TEXT_CHAR_TO_TCHAR (p_if->ifa_name));
176 ::freeifaddrs (ifap);
178 #endif /*ACE_WIN32 */
180 void
181 get_valid_ipv6_interface_names (nameset &names)
183 #if defined (ACE_WIN32)
184 get_valid_ipv6_interface_names_win32 (names);
185 #elif defined (ACE_HAS_GETIFADDRS)
186 get_valid_ipv6_interface_names_getifaddrs (names);
187 #endif /* ACE_WIN32 */
189 #endif /* ACE_HAS_IPV6 */
192 create_socket_and_join_multicast (const ACE_INET_Addr &mc_addr, const ACE_TString &if_name)
194 int result = 0;
195 ACE_SOCK_Dgram_Mcast sock;
196 sock.opts (ACE_SOCK_Dgram_Mcast::OPT_BINDADDR_NO | ACE_SOCK_Dgram_Mcast::DEFOPT_NULLIFACE);
197 result = sock.join (mc_addr, 1, if_name.empty () ? 0 : if_name.c_str ());
198 result |= sock.close ();
199 return result;
203 run_main (int, ACE_TCHAR *[])
205 ACE_START_TEST (ACE_TEXT ("Multicast_Interfaces_Test"));
207 int result = 0;
209 ACE_utsname uname;
210 ACE_OS::uname (&uname);
211 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Machine: %C running on %C\n"),
212 uname.nodename, uname.machine ));
213 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Platform: %C, %C, %C\n"),
214 uname.sysname, uname.release, uname.version ));
216 nameset names;
218 get_valid_ipv4_interface_names (names);
219 ACE_INET_Addr ipv4_mc_addr ("239.255.0.7:1234", AF_INET);
220 result |= create_socket_and_join_multicast (ipv4_mc_addr, ACE_TString ());
221 for (nameset::const_iterator it = names.begin (); result == 0 && it != names.end (); ++it)
223 result |= create_socket_and_join_multicast (ipv4_mc_addr, *it);
226 #if defined (ACE_HAS_IPV6)
227 names.clear ();
228 get_valid_ipv6_interface_names (names);
229 ACE_INET_Addr ipv6_mc_addr ("ff03::7:4321", AF_INET6);
230 result |= create_socket_and_join_multicast (ipv6_mc_addr, ACE_TString ());
231 for (nameset::const_iterator it = names.begin (); result == 0 && it != names.end (); ++it)
233 result |= create_socket_and_join_multicast (ipv6_mc_addr, *it);
235 #endif /* ACE_HAS_IPV6 */
237 ACE_END_TEST;
238 return result;