summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Huston <shuston@riverace.com>2012-04-17 22:22:08 +0000
committerSteve Huston <shuston@riverace.com>2012-04-17 22:22:08 +0000
commit647a2e5a4444a8486e3e6214208bf29ecfa81d7c (patch)
treeac7377d3a47b169387e0764b51687c36c2114e4c
parent196f58087a2b4388f44292413ebeac37ac4bc671 (diff)
downloadATCD-647a2e5a4444a8486e3e6214208bf29ecfa81d7c.tar.gz
Merge in multicast changes from trunk ACE 6.1.1 release 3/21/2012 to 4/3/2012
-rw-r--r--ChangeLog59
-rw-r--r--ace/SOCK_Dgram_Mcast.cpp235
-rw-r--r--ace/SOCK_Dgram_Mcast.h169
-rw-r--r--ace/Sock_Connect.cpp13
-rw-r--r--bin/MakeProjectCreator/config/acedefaults.mpb4
-rw-r--r--bin/MakeProjectCreator/config/ipv6.mpb4
-rw-r--r--tests/Multicast_Test.cpp30
7 files changed, 304 insertions, 210 deletions
diff --git a/ChangeLog b/ChangeLog
index 9249e14d710..b33fd579b99 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,62 @@
+Tue Apr 3 22:49:11 UTC 2012 Steve Huston <shuston@riverace.com>
+
+ * ace/SOCK_Dgram_Mcast.cpp (subscribe_ifs): Set the error code when
+ a Windows API call fails. Also, when calling GetAdaptersAddresses()
+ to both check size and get the info, supply GAA_FLAG_SKIP_MULTICAST
+ as the flag value. This avoids obtaining info for joined multicast
+ addresses, not multicastable interfaces. Without the flag, and if
+ some other process does a join between the size-check call and the
+ info-gathering call, the size will be wrong.
+
+Wed Mar 28 21:44:20 UTC 2012 Steve Huston <shuston@riverace.com>
+
+ * tests/Multicast_Test.cpp: Removed the forced set_nic to "lo" for
+ Linux. It's not needed with the changes from:
+ Wed Mar 21 21:57:40 UTC 2012 Steve Huston <shuston@riverace.com>
+
+Sat Mar 24 21:53:13 UTC 2012 Steve Huston <shuston@riverace.com>
+
+ * ace/SOCK_Dgram_Mcast.cpp (subscribe_ifs): For Windows, handle IPv6
+ and IPv4 differently. The make_multicast_ifaddr() call that will end
+ up being made for IPv4 wants the interface's IP address, not name.
+
+ * bin/MakeProjectCreator/config/acedefaults.mpb:
+ * bin/MakeProjectCreator/config/ipv6.mpb: Moved the lit_lib for iphlpapi
+ on Windows from the IPv6 base to acedefaults. SOCK_Dgram_Mcast.cpp
+ uses it for both IPv4 and IPv6 now.
+
+Thu Mar 22 16:23:14 UTC 2012 Steve Huston <shuston@riverace.com>
+
+ * ace/SOCK_Dgram_Mcast.h: Corrected the description of conditions
+ under which using OPT_NULLIFACE_ALL works and neatened things up.
+
+ * tests/Multicast_Test.cpp: Turn on IP_MULTICAST_LOOP all the time.
+ This test requires it and it's not universally the default.
+
+Wed Mar 21 21:57:40 UTC 2012 Steve Huston <shuston@riverace.com>
+
+ * ace/SOCK_Dgram_Mcast.cpp (subscribe_ifs): Expanded the use of
+ code to scan interfaces to be always, not just for IPv6, when
+ subscribing with OPT_NULLIFACE_ALL and no specific interface.
+ Also replaced use of ACE_OS::if_nameindex with getifaddr() when
+ it's available (which was only on Linux anyway) so checks
+ for interface up and multicastable can be made before joining.
+ The code now works for systems with ACE_HAS_GETIFDADDR (incl.
+ Linux, which was my main issue driving this) and Win32. The others
+ end up in the old get_ip_interfaces code which will never work
+ anywhere as far as I can tell because it tries to subscribe to an
+ interface named with the IP address in string form.
+
+ * tests/Multicast_Test.cpp: Removed hack force of interface "lo0"
+ on join(). No need for that with the fix above. For background, this
+ was added at:
+ Thu Jan 21 15:25:30 UTC 2010 Martin Corino <mcorino@remedy.nl>
+
+ * ace/Sock_Connect.cpp (get_ip_interfaces_getifaddr): Will no longer
+ return an interface marked 'down'. Partially fixes Bugzilla #1990
+ but other platform-specific changes are needed to resolve it
+ completely.
+
Wed Mar 07 09:04:40 CET 2012 Johnny Willemsen <jwillemsen@remedy.nl>
* ACE version 6.1.0 released.
diff --git a/ace/SOCK_Dgram_Mcast.cpp b/ace/SOCK_Dgram_Mcast.cpp
index abac401f790..a5d5e5e0c16 100644
--- a/ace/SOCK_Dgram_Mcast.cpp
+++ b/ace/SOCK_Dgram_Mcast.cpp
@@ -12,10 +12,18 @@
#include "ace/OS_NS_sys_socket.h"
#endif
-#if defined (ACE_HAS_IPV6) && defined (ACE_WIN32)
+#if defined (ACE_WIN32)
#include /**/ <iphlpapi.h>
#endif
+#if defined (ACE_HAS_GETIFADDRS)
+# if defined (ACE_VXWORKS)
+# include /**/ <net/ifaddrs.h>
+# else
+# include /**/ <ifaddrs.h>
+# endif /*ACE_VXWORKS */
+#endif /* ACE_HAS_GETIFADDRS */
+
#if !defined (__ACE_INLINE__)
#include "ace/SOCK_Dgram_Mcast.inl"
#endif /* __ACE_INLINE__ */
@@ -253,135 +261,135 @@ ACE_SOCK_Dgram_Mcast::subscribe_ifs (const ACE_INET_Addr &mcast_addr,
if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
&& net_if == 0)
{
-#if defined (ACE_HAS_IPV6)
- if (mcast_addr.get_type () == AF_INET6)
- {
- size_t nr_subscribed = 0;
-# if defined(ACE_LINUX)
- struct if_nameindex *intf = 0;
-
- intf = ACE_OS::if_nameindex ();
-
- if (intf == 0)
- return -1;
-
- int index = 0;
- while (intf[index].if_index != 0 || intf[index].if_name != 0)
- {
- if (this->join (mcast_addr, reuse_addr,
- ACE_TEXT_CHAR_TO_TCHAR(intf[index].if_name)) == 0)
- ++nr_subscribed;
-
- ++index;
- }
+ int family = mcast_addr.get_type ();
+ size_t nr_subscribed = 0;
- ACE_OS::if_freenameindex (intf);
+#if defined (ACE_HAS_GETIFADDRS)
-# elif defined (ACE_WIN32)
+ // Take advantage of the BSD getifaddrs function that simplifies
+ // access to connected interfaces.
+ struct ifaddrs *ifap = 0;
+ struct ifaddrs *p_if = 0;
- IP_ADAPTER_ADDRESSES tmp_addrs;
- // Initial call to determine actual memory size needed
- DWORD dwRetVal;
- ULONG bufLen = 0;
- if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
- 0,
- 0,
- &tmp_addrs,
- &bufLen)) != ERROR_BUFFER_OVERFLOW)
- return -1; // With output bufferlength 0 this can't be right.
+ if (::getifaddrs (&ifap) != 0)
+ return -1;
- // Get required output buffer and retrieve info for real.
- PIP_ADAPTER_ADDRESSES pAddrs;
- char *buf;
- ACE_NEW_RETURN (buf,
- char[bufLen],
- -1);
- pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
- if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
- 0,
- 0,
- pAddrs,
- &bufLen)) != NO_ERROR)
+ // Not every interface is for IP, and not all are up and multicast.
+ for (p_if = ifap;
+ p_if != 0;
+ p_if = p_if->ifa_next)
+ {
+ // Some OSes can return interfaces with no ifa_addr if the
+ // interface has no assigned address.
+ // If there is an address but it's not the family we want, ignore it.
+ if (p_if->ifa_addr == 0 || p_if->ifa_addr->sa_family != family)
+ continue;
+
+ // Check to see if it's up and supports multicast.
+ unsigned int wanted = IFF_UP | IFF_MULTICAST;
+ if ((p_if->ifa_flags & wanted) != wanted)
+ continue;
+
+ // Sometimes the kernel returns 0.0.0.0 as the interface
+ // address, skip those...
+ if (p_if->ifa_addr->sa_family == PF_INET)
{
- delete[] buf; // clean up
- return -1;
- }
+ struct sockaddr_in *addr =
+ reinterpret_cast<sockaddr_in *> (p_if->ifa_addr);
- while (pAddrs)
+ if (addr->sin_addr.s_addr == INADDR_ANY)
+ continue;
+ }
+# if defined (ACE_HAS_IPV6)
+ else if (p_if->ifa_addr->sa_family == AF_INET6)
{
- if (this->join (mcast_addr, reuse_addr,
- ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
- ++nr_subscribed;
+ struct sockaddr_in6 *addr =
+ reinterpret_cast<sockaddr_in6 *> (p_if->ifa_addr);
- pAddrs = pAddrs->Next;
+ // Skip the ANY address
+ if (IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr))
+ continue;
}
+# endif /* ACE_HAS_IPV6 */
- delete[] buf; // clean up
+ // Ok, now join on this interface.
+ if (this->join (mcast_addr,
+ reuse_addr,
+ ACE_TEXT_CHAR_TO_TCHAR(p_if->ifa_name)) == 0)
+ ++nr_subscribed;
+ }
-# endif /* ACE_WIN32 */
+ ::freeifaddrs (ifap);
- if (nr_subscribed == 0)
- {
- errno = ENODEV;
- return -1;
- }
+# elif defined (ACE_WIN32)
- return 1;
- }
- else
+ IP_ADAPTER_ADDRESSES tmp_addrs;
+ // Initial call to determine actual memory size needed
+ DWORD dwRetVal;
+ ULONG bufLen = 0;
+ // Note... GetAdaptersAddresses returns different bufLen values depending
+ // on how many multicast joins there are on the system. To avoid this,
+ // specify that we don't want to know about multicast addresses. This
+ // does not avoid multicastable interfaces and makes the size-check
+ // more reliable across varying conditions.
+ DWORD flags = GAA_FLAG_SKIP_MULTICAST;
+ if ((dwRetVal = ::GetAdaptersAddresses (family,
+ flags,
+ 0,
+ &tmp_addrs,
+ &bufLen)) != ERROR_BUFFER_OVERFLOW)
{
- // Subscribe on all local multicast-capable network interfaces, by
- // doing recursive calls with specific interfaces.
-
- ACE_INET_Addr *if_addrs = 0;
- size_t if_cnt;
+ errno = dwRetVal;
+ return -1; // With output bufferlength 0 this can't be right.
+ }
- if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
- return -1;
+ // Get required output buffer and retrieve info for real.
+ PIP_ADAPTER_ADDRESSES pAddrs;
+ char *buf;
+ ACE_NEW_RETURN (buf,
+ char[bufLen],
+ -1);
+ pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
+ if ((dwRetVal = ::GetAdaptersAddresses (family,
+ flags,
+ 0,
+ pAddrs,
+ &bufLen)) != NO_ERROR)
+ {
+ delete[] buf; // clean up
+ errno = dwRetVal;
+ return -1;
+ }
- size_t nr_subscribed = 0;
+ for (; pAddrs; pAddrs = pAddrs->Next)
+ {
+ if (pAddrs->OperStatus != IfOperStatusUp)
+ continue;
- if (if_cnt < 2)
+ // The ACE_SOCK_Dgram::make_multicast_ifaddr (IPv4), called by join(),
+ // can only deal with a dotted-decimal address, not an interface name.
+ if (family == AF_INET)
{
- if (this->join (mcast_addr,
- reuse_addr,
- ACE_TEXT ("0.0.0.0")) == 0)
+ ACE_INET_Addr intf_addr ((sockaddr_in*)(pAddrs->FirstUnicastAddress->Address.lpSockaddr),
+ pAddrs->FirstUnicastAddress->Address.iSockaddrLength);
+ char intf_addr_str[INET_ADDRSTRLEN];
+ intf_addr.get_host_addr (intf_addr_str, sizeof (intf_addr_str));
+ if (this->join (mcast_addr, reuse_addr,
+ ACE_TEXT_CHAR_TO_TCHAR(intf_addr_str)) == 0)
++nr_subscribed;
}
else
{
- // Iterate through all the interfaces, figure out which ones
- // offer multicast service, and subscribe to them.
- while (if_cnt > 0)
- {
- --if_cnt;
-
- // Convert to 0-based for indexing, next loop check.
- if (if_addrs[if_cnt].get_type () != AF_INET || if_addrs[if_cnt].is_loopback ())
- continue;
- char addr_buf[INET6_ADDRSTRLEN];
- if (this->join (mcast_addr,
- reuse_addr,
- ACE_TEXT_CHAR_TO_TCHAR
- (if_addrs[if_cnt].get_host_addr (addr_buf, INET6_ADDRSTRLEN))) == 0)
- ++nr_subscribed;
- }
+ if (this->join (mcast_addr, reuse_addr,
+ ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
+ ++nr_subscribed;
}
+ }
- delete [] if_addrs;
+ delete[] buf; // clean up
- if (nr_subscribed == 0)
- {
- errno = ENODEV;
- return -1;
- }
+# else
- // 1 indicates a "short-circuit" return. This handles the
- // recursive behavior of checking all the interfaces.
- return 1;
-
- }
-#else
// Subscribe on all local multicast-capable network interfaces, by
// doing recursive calls with specific interfaces.
@@ -391,8 +399,6 @@ ACE_SOCK_Dgram_Mcast::subscribe_ifs (const ACE_INET_Addr &mcast_addr,
if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
return -1;
- size_t nr_subscribed = 0;
-
if (if_cnt < 2)
{
if (this->join (mcast_addr,
@@ -409,7 +415,7 @@ ACE_SOCK_Dgram_Mcast::subscribe_ifs (const ACE_INET_Addr &mcast_addr,
--if_cnt;
// Convert to 0-based for indexing, next loop check.
- if (if_addrs[if_cnt].is_loopback ())
+ if (if_addrs[if_cnt].get_type () != family || if_addrs[if_cnt].is_loopback ())
continue;
char addr_buf[INET6_ADDRSTRLEN];
if (this->join (mcast_addr,
@@ -422,18 +428,19 @@ ACE_SOCK_Dgram_Mcast::subscribe_ifs (const ACE_INET_Addr &mcast_addr,
delete [] if_addrs;
+# endif /* ACE_WIN32 */
+
if (nr_subscribed == 0)
{
errno = ENODEV;
return -1;
}
- // 1 indicates a "short-circuit" return. This handles the
- // recursive behavior of checking all the interfaces.
return 1;
-#endif /* ACE_HAS_IPV6 */
}
+ // Subscribe on a specific interface, or on the default interface.
+
#if defined (ACE_HAS_IPV6)
if (mcast_addr.get_type () == AF_INET6)
{
@@ -441,6 +448,7 @@ ACE_SOCK_Dgram_Mcast::subscribe_ifs (const ACE_INET_Addr &mcast_addr,
return -1;
}
else
+#endif /* ACE_HAS_IPV6 - Fall into IPv4-only case */
{
// Validate passed multicast addr and iface specifications.
if (this->make_multicast_ifaddr (0,
@@ -448,13 +456,6 @@ ACE_SOCK_Dgram_Mcast::subscribe_ifs (const ACE_INET_Addr &mcast_addr,
net_if) == -1)
return -1;
}
-#else
- // Validate passed multicast addr and iface specifications.
- if (this->make_multicast_ifaddr (0,
- mcast_addr,
- net_if) == -1)
- return -1;
-#endif /* ACE_HAS_IPV6 */
return 0;
diff --git a/ace/SOCK_Dgram_Mcast.h b/ace/SOCK_Dgram_Mcast.h
index 6f3c3bc5b62..a2e54969d39 100644
--- a/ace/SOCK_Dgram_Mcast.h
+++ b/ace/SOCK_Dgram_Mcast.h
@@ -46,50 +46,56 @@ ACE_BEGIN_VERSIONED_NAMESPACE_DECL
*
* Supports multiple simultaneous subscriptions, unsubscription from one or
* all subscriptions, and independent send/recv address and interface
- * specifications. Template parameters and/or ctor arguments determine
- * per-instance optional functionality.
+ * specifications. Constructor arguments determine per-instance optional
+ * functionality.
*
- * Note that multicast semantics and implementation details are _very_
+ * Note that multicast semantics and implementation details are @i very
* environment-specific; this class is just a wrapper around the underlying
* implementation and does not try to normalize the concept of multicast
* communications.
*
* Usage Notes:
- * - Send and Recv addresses and network interfaces, but not port#, are
- * independent. While this instance is open, 1 send interface (and a default
- * send address) is in effect and 0, 1, or multiple recv addresses/interfaces
- * are in effect.
+ * - Send and receive addresses and network interfaces, but not port number,
+ * are independent. While this instance is open, one send interface (and a
+ * default send address) is in effect and 0, 1, or multiple receive
+ * addresses/interfaces are in effect.
* - The first open()/subscribe() invocation defines the network interface
* and default address used for all sends by this instance, defines the
- * port# and optionally the multicast address bound to the underlying
- * socket, and defines the (one) port# that is used for all subscribes
- * (subsequent subscribes must pass the same port# or '0').
+ * port number and optionally the multicast address bound to the underlying
+ * socket, and defines the (one) port number that is used for all subscribes
+ * (subsequent subscribes must pass the same port number or 0).
* - The default loopback state is not explicitly set; the environment will
- * determine the default state. Note that some environments (e.g. some Win32)
- * do not allow the default to be changed, and that the semantics of
- * loopback control are environment dependent (e.g. sender vs receiver
- * control).
+ * determine the default state. Note that some environments (e.g. some
+ * Windows versions) do not allow the default to be changed, and that the
+ * semantics of loopback control are environment dependent (e.g. sender vs.
+ * receiver control).
* - In general, due to multicast design and implementation quirks/bugs, it is
* difficult to tell which address a received message was sent to or which
* interface it was received on (even if only one subscription is active).
- * However; there are filtering options that can be applied, to narrow it
+ * However, there are filtering options that can be applied, to narrow it
* down considerably.
*
* Interface specification notes (for subscribe() and unsubscribe()):
- * - If net_if == 0, the null_iface_opt option determines whether only the
- * system "default" interface or all interfaces is affected. Specifying
- * "all" interfaces is supported only for environments for which
- * ACE_Sock_Connect::get_ip_interfaces() is properly implemented.
+ * - If @a net_if == 0, the @c OPT_NULLIFACE_ALL and @c OPT_NULLIFACE_ONE
+ * options determine whether only the system default interface
+ * (if @c OPT_NULLIFACE_ONE is set) or all interfaces (if
+ * @c OPT_NULLIFACE_ALL is set) is affected. Specifying all interfaces
+ * functions correctly only on:
+ * + Windows
+ * + Platforms with the ACE_HAS_GETIFADDRS config setting (includes Linux)
+ * + Platforms which accept the IP address as an interface
+ * name/specification
+ * + Systems with only one non-loopback interface.
+ * Other platforms require additional supporting code.
* - Multiple subscriptions for the same address but different interfaces is
* normally supported, but re-subscription to an address/interface that is
* already subscribed is normally not allowed.
- * - The <net_if> interface specification syntax is environment-specific.
+ * - The @a net_if interface specification syntax is environment-specific.
* UNIX systems will normally use device specifications such as "le0" or
* "elxl1", while other systems will use the IP address of the interface.
* Some platforms, such as pSoS, support only cardinal numbers as network
* interface specifications; for these platforms, just give these numbers in
- * alphanumeric form and <subscribe> will convert them into numbers via
- * ACE_OS::atoi().
+ * string form and join() will convert them into numbers.
*/
class ACE_Export ACE_SOCK_Dgram_Mcast : public ACE_SOCK_Dgram
{
@@ -99,28 +105,30 @@ public:
* @brief Option parameters.
*
* These control per-instance optional functionality. They are set via
- * optional constructor arguments.
+ * an optional constructor argument.
+ *
* @note Certain option values are not valid for all environments (see
* comments in source file for environment-specific restrictions). Default
* values are always valid values for the compilation environment.
*/
enum options
{
- // Define whether a specific (multicast) address (in addition to the port#)
- // is bound to the socket.
- // Notes:
- // - Effect of doing this is stack/environment dependent, but in most
- // environments can be used to filter out unwanted unicast, broadcast, and
- // (other) multicast messages sent to the same port#.
- // - Some IP stacks (e.g. some Win32) do not support binding multicast
- // addresses. Using this option will always cause an <open> error.
- // - It's not strictly possible for user code to do this level of filtering
- // w/out the bind; some environments support ways to determine which address
- // a message was sent _to_, but this class interface does not support access
- // to that info.
- // - The address (and port#) passed to <open> (or the first <subscribe>, if
- // <open> is not explicitly invoked) is the one that is bound.
- //
+ /* Define whether a specific multicast address (in addition to the port
+ * number) is bound to the socket.
+ * @note:
+ * - Effect of doing this is stack/environment dependent, but in most
+ * environments can be used to filter out unwanted unicast, broadcast,
+ * and (other) multicast messages sent to the same port number.
+ * - Some IP stacks (e.g. some Windows) do not support binding multicast
+ * addresses. Using this option will always cause an open() error.
+ * - It's not strictly possible for user code to do this level of filtering
+ * without the bind; some environments support ways to determine which
+ * address a message was sent to, but this class interface does not
+ * support access to that information.
+ * - The address (and port number) passed to open() (or the first
+ * join(), if open() is not explicitly invoked) is the one that is bound.
+ */
+
/// Disable address bind. (Bind only port.)
/// @note This might seem odd, but we need a way to distinguish between
/// default behavior, which might or might not be to bind, and explicitly
@@ -142,20 +150,28 @@ public:
DEFOPT_BINDADDR = OPT_BINDADDR_NO,
#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING = 1) */
- /// Define the interpretation of 'NULL' as a recv interface specification.
- /// If the interface part of a multicast address specification is NULL, it
- /// will be interpreted to mean either "the default interface" or "all
- /// interfaces", depending on the setting of this option.
- /// Notes:
- /// - The 'nulliface_all' option can not be used in environments which do
- /// not fully support the ACE_Sock_Connect::get_ip_interfaces() method
- /// (e.g. non-Windows).
- /// If it is, using NULL for iface will _always_ fail.
- /// - The default behavior in most IP stacks is to use the 'default' interface,
- /// where 'default' has rather ad-hoc semantics.
- /// - This applies only to receives, not sends (which always use only one
- /// interface; NULL means use the "system default" interface).
- /// Supported values:
+ /*
+ * Define the interpretation of NULL as a join interface specification.
+ * If the interface part of a multicast address specification is NULL, it
+ * will be interpreted to mean either "the default interface" or "all
+ * interfaces", depending on the setting of this option.
+ * @note
+ * - The @c OPT_NULLIFACE_ALL option can be used only in the following
+ * environments:
+ * + Windows
+ * + Platforms with the ACE_HAS_GETIFADDRS config setting (includes
+ * Linux)
+ * + Platforms which accept the IP address as an interface
+ * name/specification and for which
+ * ACE_Sock_Connect::get_ip_interfaces() is fully implemented
+ * + Systems with only one non-loopback interface.
+ * Other platforms require additional supporting code.
+ * - The default behavior in most IP stacks is to use the default
+ * interface where "default" has rather ad-hoc semantics.
+ * - This applies only to receives, not sends (which always use only one
+ * interface; NULL means use the "system default" interface).
+ */
+ /// Supported values:
/// If (net_if==NULL), use default interface.
/// @note This might seem odd, but we need a way to distinguish between
/// default behavior, which might or might not be to bind, and explicitly
@@ -179,15 +195,15 @@ public:
// = Initialization routines.
- /// Ctor - Create an unitialized instance and define per-instance optional
+ /// Create an unitialized instance and define per-instance optional
/// functionality.
/**
- * You must invoke open() or subscribe(), to create/bind a socket and define
+ * You must invoke open() or join(), to create/bind a socket and define
* operational parameters, before performing any I/O with this instance.
*/
ACE_SOCK_Dgram_Mcast (options opts = DEFOPTS);
- /// Dtor - Release all resources and implicitly or explicitly unsubscribe
+ /// Release all resources and implicitly or explicitly unsubscribe
/// from all currently subscribed groups.
/**
* The OPT_DTORUNSUB_YES_ option defines whether an explicit unsubscribe() is
@@ -196,31 +212,36 @@ public:
*/
~ACE_SOCK_Dgram_Mcast (void);
- /// Explicitly open/bind the socket and define the network interface
- /// and default multicast address used for sending messages.
/**
+ * Explicitly open/bind the socket and define the network interface
+ * and default multicast address used for sending messages.
+ *
* This method is optional; if not explicitly invoked, it is invoked by
- * the first subscribe(), using the subscribed address/port# and network
+ * the first join(), using the subscribed address/port number and network
* interface parameters.
- * The @a mcast_addr parameter defines the default send address/port# and
- * also the port# and, if the OPT_BINDADDR_YES option is used,
- * the multicast address that is bound to this socket.
- * If the @a net_if parameter != 0, it defines the network interface
- * used for all sends by this instance, otherwise the system "default"
- * interface is used. (The @a net_if parameter is ignored if this
- * feature is not supported by the environment.)
- * The port# in @a mcast_addr may be 0, in which case a system-assigned
- * (ephemeral) port# is used for sending and receiving.
- * If @a reuse_addr != 0, the SO_REUSEADDR option and, if it is supported,
- * the SO_REUSEPORT option are enabled.
*
- * Returns: -1 if the call fails. Failure can occur due to problems with
- * the address, port#, and/or interface parameters or during system open()
+ * @param mcast_addr Defines the default send address/port number and,
+ * if the @c OPT_BINDADDR_YES option is used, the multicast address
+ * that is bound to this socket. The port number in @a mcast_addr
+ * may be 0, in which case a system-assigned (ephemeral) port number
+ * is used for sending and receiving.
+ *
+ * @param net_if If @a net_if is not 0, it defines the network interface
+ * used for all sends by this instance, otherwise the system default
+ * interface is used. (The @a net_if parameter is ignored if this
+ * feature is not supported by the environment.)
+ *
+ * @param reuse_addr If @a reuse_addr is not 0, the @c SO_REUSEADDR option
+ * and, if it is supported, the SO_REUSEPORT option are enabled.
+ *
+ * @retval 0 on success
+ * @retval -1 if the call fails. Failure can occur due to problems with
+ * the address, port, and/or interface parameters or during system open()
* or socket option processing.
*/
- int open (const ACE_INET_Addr &mcast_addr, // Bound & sendto address.
- const ACE_TCHAR *net_if = 0, // Net interface for sends.
- int reuse_addr = 1); // Reuse addr/port sock opt.
+ int open (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if = 0,
+ int reuse_addr = 1);
// = Multicast group subscribe/unsubscribe routines.
diff --git a/ace/Sock_Connect.cpp b/ace/Sock_Connect.cpp
index 332b21bb69e..8973534b202 100644
--- a/ace/Sock_Connect.cpp
+++ b/ace/Sock_Connect.cpp
@@ -777,8 +777,14 @@ get_ip_interfaces_getifaddrs (size_t &count,
p_if != 0;
p_if = p_if->ifa_next)
{
- if (p_if->ifa_addr &&
- p_if->ifa_addr->sa_family == AF_INET)
+ if (p_if->ifa_addr == 0)
+ continue;
+
+ // Check to see if it's up.
+ if ((p_if->ifa_flags & IFF_UP) != IFF_UP)
+ continue;
+
+ if (p_if->ifa_addr->sa_family == AF_INET)
{
struct sockaddr_in *addr =
reinterpret_cast<sockaddr_in *> (p_if->ifa_addr);
@@ -794,8 +800,7 @@ get_ip_interfaces_getifaddrs (size_t &count,
}
}
# if defined (ACE_HAS_IPV6)
- else if (p_if->ifa_addr &&
- p_if->ifa_addr->sa_family == AF_INET6)
+ else if (p_if->ifa_addr->sa_family == AF_INET6)
{
struct sockaddr_in6 *addr =
reinterpret_cast<sockaddr_in6 *> (p_if->ifa_addr);
diff --git a/bin/MakeProjectCreator/config/acedefaults.mpb b/bin/MakeProjectCreator/config/acedefaults.mpb
index 7c7cff5c75c..6798ba1ea52 100644
--- a/bin/MakeProjectCreator/config/acedefaults.mpb
+++ b/bin/MakeProjectCreator/config/acedefaults.mpb
@@ -17,6 +17,10 @@ project: ipv6, vc_warnings, build_files, test_files, svc_conf_files, ace_unicode
macro_for_lib_modifier=1
}
+ specific(prop:windows) {
+ lit_libs += iphlpapi
+ }
+
specific(cdt6) {
win32::platform_libs += ws2_32 mswsock netapi32
release::macros += ACE_NDEBUG ACE_USE_RCSID=0
diff --git a/bin/MakeProjectCreator/config/ipv6.mpb b/bin/MakeProjectCreator/config/ipv6.mpb
index 92473ad7113..b76821b80d1 100644
--- a/bin/MakeProjectCreator/config/ipv6.mpb
+++ b/bin/MakeProjectCreator/config/ipv6.mpb
@@ -2,9 +2,5 @@
// $Id$
feature(ipv6) {
- specific(prop:windows) {
- lit_libs += iphlpapi
- }
-
macros += ACE_HAS_IPV6
}
diff --git a/tests/Multicast_Test.cpp b/tests/Multicast_Test.cpp
index 5d1d8109f12..a053676b1c2 100644
--- a/tests/Multicast_Test.cpp
+++ b/tests/Multicast_Test.cpp
@@ -448,19 +448,11 @@ public:
= ACE_SOCK_Dgram_Mcast::DEFOPTS);
virtual ~MCT_Event_Handler (void);
-#if defined (ACE_LINUX)
- int join (const ACE_INET_Addr &mcast_addr,
- int reuse_addr = 1,
- const ACE_TCHAR *net_if = ACE_TEXT ("lo"));
- int leave (const ACE_INET_Addr &mcast_addr,
- const ACE_TCHAR *net_if = ACE_TEXT ("lo"));
-#else
int join (const ACE_INET_Addr &mcast_addr,
int reuse_addr = 1,
const ACE_TCHAR *net_if = 0);
int leave (const ACE_INET_Addr &mcast_addr,
const ACE_TCHAR *net_if = 0);
-#endif
// = Event Handler hooks.
virtual int handle_input (ACE_HANDLE handle);
@@ -468,6 +460,9 @@ public:
virtual ACE_HANDLE get_handle (void) const;
+ // Turn loopback on/off. Must be called after at least 1 join() is performed.
+ int loopback (bool on_off);
+
protected:
ACE_SOCK_Dgram_Mcast *mcast (void);
int find (const char *buf);
@@ -641,6 +636,14 @@ MCT_Event_Handler::get_handle (void) const
return this->mcast_.get_handle ();
}
+// Turn loopback on/off
+int
+MCT_Event_Handler::loopback (bool on_off)
+{
+ char loopback_on = on_off ? 1 : 0;
+ return this->mcast_.set_option (IP_MULTICAST_LOOP, loopback_on);
+}
+
/******************************************************************************/
/*
@@ -721,6 +724,13 @@ MCT_Task::open (void *)
advance_addr (addr);
+ // This test needs loopback because we're both sending and receiving.
+ // Loopback is usually the default, but be sure.
+ if (-1 == handler->loopback (true))
+ ACE_ERROR ((LM_WARNING,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("MCT_Task::open - enable loopback")));
+
if (this->reactor ()->register_handler (handler, READ_MASK) == -1)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("MCT_Task::open - cannot register ")
@@ -787,9 +797,7 @@ int producer (MCT_Config &config)
ACE_DEBUG ((LM_INFO, ACE_TEXT ("Starting producer...\n")));
ACE_SOCK_Dgram socket (ACE_sap_any_cast (ACE_INET_Addr &), PF_INET);
//FUZZ: enable check_for_lack_ACE_OS
-#if defined (ACE_LINUX)
- socket.set_nic (ACE_TEXT("lo"));
-#endif
+
// Note that is is IPv4 specific and needs to be changed once
//
if (config.ttl () > 1)