summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2002-11-15 21:44:15 +0000
committerdhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2002-11-15 21:44:15 +0000
commit333c899079a4ed90e9e45922af3dc68a59f3d05b (patch)
tree054fe0633bccb35488d43d1f4532d6c968977d60
parentce1a4fc109ee0b044b6c8b9c8a13985e5c00ac52 (diff)
downloadATCD-333c899079a4ed90e9e45922af3dc68a59f3d05b.tar.gz
ChangeLogTag:Fri Nov 15 20:33:02 UTC 2002 Don Hinton <dhinton@ieee.org>
-rw-r--r--ChangeLog25
-rw-r--r--ChangeLogs/ChangeLog-03a25
-rw-r--r--ace/SOCK_Dgram_Mcast.cpp12
-rw-r--r--ace/SOCK_Dgram_Mcast.h32
-rw-r--r--ace/config-aix-4.x.h6
-rw-r--r--ace/config-all.h11
-rw-r--r--ace/config-freebsd.h5
-rw-r--r--ace/config-linux-common.h5
-rw-r--r--ace/config-netbsd.h5
-rw-r--r--ace/config-openbsd.h5
-rw-r--r--tests/Multicast_Test.cpp208
11 files changed, 252 insertions, 87 deletions
diff --git a/ChangeLog b/ChangeLog
index 96f4420a0d1..cf7e64e8e47 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+Fri Nov 15 20:33:02 UTC 2002 Don Hinton <dhinton@ieee.org>
+
+ * ace/SOCK_Dgram_Mcast.h:
+ * ace/config-all.h: Added new macro for platforms that don't yet
+ implement the new IGMPv3, perfect multicast filtering, and
+ replaced the #ifdef linux in the ACE_SOCK_Dgram_Mcast::ctor
+ with the new macro, since this isn't just a linux thing.
+
+ * ace/config-aix-4.x.h:
+ * ace/config-freebsd.h:
+ * ace/config-linux-common.h:
+ * ace/config-netbsd.h:
+ * ace/config-openbsd.h:
+ Defined ACE_LACKS_PERFECT_MULTICAST_FILTERING for these platforms.
+
+ * ace/SOCK_Dgram_Mcast.cpp (open_i): Removed redundant call to
+ ACE_SOCK::set_option() to set SO_REUSEADDR, since it's set in
+ the call to ACE_SOCK::open(). This fixes [bug 1111].
+
+ * tests/Multicast_Test.cpp: Enhanced test by adding new options
+ control the wait time when running test as a CONSUMER only,
+ and contol the TTL so the test could be used over routers.
+ Also cleaned up the code a bit to make it more readable. Thanks
+ to Bill Fulton for motivating these enhancements.
+
Fri Nov 15 14:16:10 2002 Nanbor Wang <nanbor@cs.wustl.edu>
* ace/Thread_Exit.h:
diff --git a/ChangeLogs/ChangeLog-03a b/ChangeLogs/ChangeLog-03a
index 96f4420a0d1..cf7e64e8e47 100644
--- a/ChangeLogs/ChangeLog-03a
+++ b/ChangeLogs/ChangeLog-03a
@@ -1,3 +1,28 @@
+Fri Nov 15 20:33:02 UTC 2002 Don Hinton <dhinton@ieee.org>
+
+ * ace/SOCK_Dgram_Mcast.h:
+ * ace/config-all.h: Added new macro for platforms that don't yet
+ implement the new IGMPv3, perfect multicast filtering, and
+ replaced the #ifdef linux in the ACE_SOCK_Dgram_Mcast::ctor
+ with the new macro, since this isn't just a linux thing.
+
+ * ace/config-aix-4.x.h:
+ * ace/config-freebsd.h:
+ * ace/config-linux-common.h:
+ * ace/config-netbsd.h:
+ * ace/config-openbsd.h:
+ Defined ACE_LACKS_PERFECT_MULTICAST_FILTERING for these platforms.
+
+ * ace/SOCK_Dgram_Mcast.cpp (open_i): Removed redundant call to
+ ACE_SOCK::set_option() to set SO_REUSEADDR, since it's set in
+ the call to ACE_SOCK::open(). This fixes [bug 1111].
+
+ * tests/Multicast_Test.cpp: Enhanced test by adding new options
+ control the wait time when running test as a CONSUMER only,
+ and contol the TTL so the test could be used over routers.
+ Also cleaned up the code a bit to make it more readable. Thanks
+ to Bill Fulton for motivating these enhancements.
+
Fri Nov 15 14:16:10 2002 Nanbor Wang <nanbor@cs.wustl.edu>
* ace/Thread_Exit.h:
diff --git a/ace/SOCK_Dgram_Mcast.cpp b/ace/SOCK_Dgram_Mcast.cpp
index dd8e83e5323..528e0aa1e09 100644
--- a/ace/SOCK_Dgram_Mcast.cpp
+++ b/ace/SOCK_Dgram_Mcast.cpp
@@ -162,18 +162,12 @@ ACE_SOCK_Dgram_Mcast::open_i (const ACE_INET_Addr &mcast_addr,
int reuse_addr)
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open_i");
- // ACE_SOCK::open calls this if reuse_addr is set, so we only need to
- // add the port
- // Process addr/port reuse option.
+ // ACE_SOCK::open calls this if reuse_addr is set, so we only need to
+ // process port reuse option.
if (reuse_addr)
{
- int one = 1;
- if (this->ACE_SOCK::set_option (SOL_SOCKET,
- SO_REUSEADDR,
- &one,
- sizeof one) == -1)
- return -1;
#if defined (SO_REUSEPORT)
+ int one = 1;
if (this->ACE_SOCK::set_option (SOL_SOCKET,
SO_REUSEPORT,
&one,
diff --git a/ace/SOCK_Dgram_Mcast.h b/ace/SOCK_Dgram_Mcast.h
index 5057ac1beb9..e9e3970a800 100644
--- a/ace/SOCK_Dgram_Mcast.h
+++ b/ace/SOCK_Dgram_Mcast.h
@@ -117,20 +117,26 @@ public:
// - The address (and port#) passed to <open> (or the first <subscribe>, if
// <open> is not explicitly invoked) is the one that is bound.
//
+ /// Disable address bind. (Bind only port.)
+ // Note that this might seem odd, but we need a way to distinquish between
+ // default behavior, which might or might not be to bind, and explicitely
+ // choosing to bind or not to bind--which "is the question." ;-)
+ OPT_BINDADDR_NO = 0,
/// Enable address bind. (Bind port and address.)
OPT_BINDADDR_YES = 1,
/// Default value for BINDADDR option. (Environment-dependent.)
-#ifdef linux
- // (Bring forward ad-hoc legacy hack: enable if 'linux' macro is defined)
+#if defined (ACE_LACKS_PERFECT_MULTICAST_FILTERING) \
+ && (ACE_LACKS_PERFECT_MULTICAST_FILTERING == 1)
+ // Platforms that don't support perfect filtering. Note that perfect
+ // filtering only really applies to multicast traffic, not unicast
+ // or broadcast.
DEFOPT_BINDADDR = OPT_BINDADDR_YES,
-#elif defined (ACE_WIN32)
+# else
// At least some Win32 OS's can not bind mcast addr, so disable it.
- DEFOPT_BINDADDR = 0,
-#else // !linux && !WIN32
// General-purpose default behavior is 'disabled', since effect is
// environment-specific and side-effects might be surprising.
- DEFOPT_BINDADDR = 0,
-#endif
+ 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
@@ -146,6 +152,11 @@ public:
// - 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 that this might seem odd, but we need a way to distinquish between
+ // default behavior, which might or might not be to bind, and explicitely
+ // choosing to bind or not to bind--which "is the question." ;-)
+ OPT_NULLIFACE_ONE = 0,
/// If (net_if==NULL), use all mcast interfaces.
OPT_NULLIFACE_ALL = 2,
/// Default value for NULLIFACE option. (Environment-dependent.)
@@ -156,11 +167,10 @@ public:
DEFOPT_NULLIFACE = OPT_NULLIFACE_ALL,
#else
// General-purpose default behavior (as per legacy behavior).
- DEFOPT_NULLIFACE = 0,
+ DEFOPT_NULLIFACE = OPT_NULLIFACE_ONE,
#endif /* ACE_WIN32 */
/// All default options.
DEFOPTS = DEFOPT_BINDADDR | DEFOPT_NULLIFACE
-
};
// = Initialization routines.
@@ -318,7 +328,9 @@ public:
* or <IP_MULTICAST_TTL>. This is just a more concise, nice interface to a
* subset of possible <ACE_SOCK::set_option> calls, but only works for
* IPPROTO_IP or IPPROTO_IPV6 level options. Use <ACE_SOCK::set_option>
- * directly to set anything else.
+ * directly to set anything else.
+ * \deprecated { This method has been deprecated since it cannot be used
+ * easily with with IPv6 options.}
* Returns 0 on success, -1 on failure.
*/
int set_option (int option,
diff --git a/ace/config-aix-4.x.h b/ace/config-aix-4.x.h
index 045c2211a3a..1fd1a72fd5b 100644
--- a/ace/config-aix-4.x.h
+++ b/ace/config-aix-4.x.h
@@ -151,6 +151,12 @@
#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
#define ACE_HAS_NONCONST_SELECT_TIMEVAL
#define ACE_HAS_IP_MULTICAST
+
+// Lacks perfect filtering, must bind group address.
+#if !defined ACE_LACKS_PERFECT_MULTICAST_FILTERING
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING */
+
#define ACE_HAS_MSG
#if (ACE_AIX_VERS < 402)
# define ACE_LACKS_MSG_ACCRIGHTS
diff --git a/ace/config-all.h b/ace/config-all.h
index 7c5670da39a..16734aa9798 100644
--- a/ace/config-all.h
+++ b/ace/config-all.h
@@ -23,6 +23,17 @@
#endif /* ACE_LACKS_PRAGMA_ONCE */
// =========================================================================
+// Perfect Multicast filting refers to RFC 3376, where a socket is only
+// delivered dgrams for groups joined even if it didn't bind the group
+// address. We turn this option off by default, although most OS's
+// except for Windows and Solaris probably lack perfect filtering.
+// =========================================================================
+
+# if !defined (ACE_LACKS_PERFECT_MULTICAST_FILTERING)
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 0
+# endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING */
+
+// =========================================================================
// Enable/Disable Features By Default
// =========================================================================
diff --git a/ace/config-freebsd.h b/ace/config-freebsd.h
index dc75e4104ff..f68947ba310 100644
--- a/ace/config-freebsd.h
+++ b/ace/config-freebsd.h
@@ -139,6 +139,11 @@ extern "C" { char * cuserid (char *s); }
// platform supports IP multicast
#define ACE_HAS_IP_MULTICAST
+// Lacks perfect filtering, must bind group address.
+#if !defined ACE_LACKS_PERFECT_MULTICAST_FILTERING
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING */
+
// Compiler/platform has <alloca.h>
//#define ACE_HAS_ALLOCA_H
diff --git a/ace/config-linux-common.h b/ace/config-linux-common.h
index 473ce1e6345..466b0a476f9 100644
--- a/ace/config-linux-common.h
+++ b/ace/config-linux-common.h
@@ -221,6 +221,11 @@
# define ACE_HAS_IP_MULTICAST
#endif /* ! ACE_HAS_IP_MULTICAST */
+// At least for IPv4, Linux lacks perfect filtering.
+#if !defined ACE_LACKS_PERFECT_MULTICAST_FILTERING
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING */
+
#define ACE_HAS_BIG_FD_SET
// Linux defines struct msghdr in /usr/include/socket.h
diff --git a/ace/config-netbsd.h b/ace/config-netbsd.h
index 386ef450277..ab5eadae6e7 100644
--- a/ace/config-netbsd.h
+++ b/ace/config-netbsd.h
@@ -127,6 +127,11 @@ ange */
// platform supports IP multicast
#define ACE_HAS_IP_MULTICAST
+// Lacks perfect filtering, must bind group address.
+#if !defined ACE_LACKS_PERFECT_MULTICAST_FILTERING
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING */
+
// Compiler/platform has <alloca.h>
//#define ACE_HAS_ALLOCA_H
diff --git a/ace/config-openbsd.h b/ace/config-openbsd.h
index 80bba4e6729..d2913998331 100644
--- a/ace/config-openbsd.h
+++ b/ace/config-openbsd.h
@@ -94,6 +94,11 @@
// platform supports IP multicast
#define ACE_HAS_IP_MULTICAST
+// Lacks perfect filtering, must bind group address.
+#if !defined ACE_LACKS_PERFECT_MULTICAST_FILTERING
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING */
+
// Compiler/platform has <alloca.h>
//#define ACE_HAS_ALLOCA_H
diff --git a/tests/Multicast_Test.cpp b/tests/Multicast_Test.cpp
index a69bd5e1098..27039cbabb8 100644
--- a/tests/Multicast_Test.cpp
+++ b/tests/Multicast_Test.cpp
@@ -24,8 +24,9 @@
// particular platform.
//
// The list of destination groups start at 239.255.0.1 (default) and
-// increment by 1 up to 5 (default) groups. Both of these values can be
-// overridden via command-line options.
+// increment by 1 up to 5 (default) groups. Both of these values, as well
+// as others, can be overridden via command-line options. Use the -?
+// option to display the usage message...
//
// = AUTHOR
// Don Hinton <dhinton@ieee.org>
@@ -89,9 +90,11 @@ public:
: group_start_ (MCT_START_PORT, MCT_START_GROUP),
groups_ (0),
debug_ (0),
- type_ (BOTH),
+ role_ (BOTH),
sdm_opts_ (ACE_SOCK_Dgram_Mcast::DEFOPTS),
- iterations_ (MCT_ITERATIONS)
+ iterations_ (MCT_ITERATIONS),
+ ttl_ (1),
+ wait_ (2)
{
if (IP_MAX_MEMBERSHIPS == 0)
this->groups_ = MCT_GROUPS;
@@ -106,8 +109,10 @@ public:
void dump (void) const;
int groups (void) const { return this->groups_;}
const ACE_INET_Addr group_start (void) const { return this->group_start_;}
- u_long type (void) const { return this->type_;}
+ u_long role (void) const { return this->role_;}
int iterations (void) const { return this->iterations_;}
+ int ttl (void) const { return this->ttl_;}
+ int wait (void) const { return this->wait_;}
ACE_SOCK_Dgram_Mcast::options options (void) const
{
return ACE_static_cast (ACE_SOCK_Dgram_Mcast::options, this->sdm_opts_);
@@ -123,14 +128,20 @@ private:
// Debug flag.
int debug_;
- // Type, i.e., PRODUCER, CONSUMER, BOTH: defaults to BOTH
- u_long type_;
+ // Role, i.e., PRODUCER, CONSUMER, BOTH: defaults to BOTH
+ u_long role_;
// ACE_SOCK_Dgram_Mcast ctor options
u_long sdm_opts_;
// Producer iterations
int iterations_;
+
+ // TTL, time to live, for use over routers.
+ int ttl_;
+
+ // Time to wait on CONSUMER threads to end before killing test.
+ int wait_;
};
int
@@ -145,7 +156,7 @@ MCT_Config::open (int argc, ACE_TCHAR *argv[])
'g',
ACE_Get_Opt::ARG_REQUIRED) != 0)
ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT (" Unable to add MCastGroupStart option.\n")),
+ ACE_TEXT (" Unable to add GroupStart option.\n")),
1);
if (getopt.long_option (ACE_TEXT ("Groups"),
@@ -160,11 +171,11 @@ MCT_Config::open (int argc, ACE_TCHAR *argv[])
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT (" Unable to add Debug option.\n")), 1);
- if (getopt.long_option (ACE_TEXT ("Type"),
- 't',
+ if (getopt.long_option (ACE_TEXT ("Role"),
+ 'r',
ACE_Get_Opt::ARG_REQUIRED) != 0)
ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT (" Unable to add Type option.\n")), 1);
+ ACE_TEXT (" Unable to add Role option.\n")), 1);
if (getopt.long_option (ACE_TEXT ("SDM_options"),
'm',
@@ -180,9 +191,23 @@ MCT_Config::open (int argc, ACE_TCHAR *argv[])
ACE_TEXT (" Unable to add iterations option.\n")),
1);
+ if (getopt.long_option (ACE_TEXT ("TTL"),
+ 't',
+ ACE_Get_Opt::ARG_REQUIRED) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT (" Unable to add TTL option.\n")),
+ 1);
+
+ if (getopt.long_option (ACE_TEXT ("Wait"),
+ 'w',
+ ACE_Get_Opt::ARG_REQUIRED) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT (" Unable to add wait option.\n")),
+ 1);
+
if (getopt.long_option (ACE_TEXT ("help"),
'h',
- ACE_Get_Opt::ARG_REQUIRED) != 0)
+ ACE_Get_Opt::NO_ARG) != 0)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT (" Unable to add help option.\n")),
1);
@@ -212,10 +237,8 @@ MCT_Config::open (int argc, ACE_TCHAR *argv[])
}
break;
case 'i':
- {
- this->iterations_ = ACE_OS::atoi (getopt.opt_arg ());
- break;
- }
+ this->iterations_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
case 'n':
{
int n = ACE_OS::atoi (getopt.opt_arg ());
@@ -231,13 +254,13 @@ MCT_Config::open (int argc, ACE_TCHAR *argv[])
case 'd':
this->debug_ = 1;
break;
- case 't':
+ case 'r':
{
ACE_TCHAR *c = getopt.opt_arg ();
if (ACE_OS::strcasecmp (c, ACE_TEXT ("CONSUMER")) == 0)
- this->type_ = CONSUMER;
+ this->role_ = CONSUMER;
else if (ACE_OS::strcasecmp (c, ACE_TEXT ("PRODUCER")) == 0)
- this->type_ = PRODUCER;
+ this->role_ = PRODUCER;
else
{
help = 1;
@@ -247,11 +270,12 @@ MCT_Config::open (int argc, ACE_TCHAR *argv[])
break;
case 'm':
{
+ //@todo add back OPT_BINDADDR_NO...
ACE_TCHAR *c = getopt.opt_arg ();
if (ACE_OS::strcasecmp (c, ACE_TEXT ("OPT_BINDADDR_YES")) == 0)
ACE_SET_BITS (this->sdm_opts_,
ACE_SOCK_Dgram_Mcast::OPT_BINDADDR_YES);
- else if (ACE_OS::strcasecmp (c, ACE_TEXT ("~OPT_BINDADDR_YES")) == 0)
+ else if (ACE_OS::strcasecmp (c, ACE_TEXT ("OPT_BINDADDR_NO")) == 0)
ACE_CLR_BITS (this->sdm_opts_,
ACE_SOCK_Dgram_Mcast::OPT_BINDADDR_YES);
else if (ACE_OS::strcasecmp (c, ACE_TEXT ("DEFOPT_BINDADDR")) == 0)
@@ -264,7 +288,7 @@ MCT_Config::open (int argc, ACE_TCHAR *argv[])
else if (ACE_OS::strcasecmp (c, ACE_TEXT ("OPT_NULLIFACE_ALL")) == 0)
ACE_SET_BITS (this->sdm_opts_,
ACE_SOCK_Dgram_Mcast::OPT_NULLIFACE_ALL);
- else if (ACE_OS::strcasecmp (c, ACE_TEXT ("~OPT_NULLIFACE_ALL")) == 0)
+ else if (ACE_OS::strcasecmp (c, ACE_TEXT ("OPT_NULLIFACE_ONE")) == 0)
ACE_CLR_BITS (this->sdm_opts_,
ACE_SOCK_Dgram_Mcast::OPT_NULLIFACE_ALL);
else if (ACE_OS::strcasecmp (c, ACE_TEXT ("DEFOPT_NULLIFACE")) == 0)
@@ -283,6 +307,12 @@ MCT_Config::open (int argc, ACE_TCHAR *argv[])
}
}
break;
+ case 't':
+ this->ttl_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'w':
+ this->wait_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
case ':':
// This means an option requiring an argument didn't have one.
ACE_ERROR ((LM_ERROR,
@@ -296,8 +326,7 @@ MCT_Config::open (int argc, ACE_TCHAR *argv[])
case 'h':
default:
if (ACE_OS::strcmp (argv[getopt.opt_ind () - 1], ACE_TEXT ("-?")) != 0
- && ACE_OS::strcmp (argv[getopt.opt_ind () - 1],
- ACE_TEXT ("-h")) != 0)
+ && getopt.opt_opt () != 'h')
// Don't allow unknown options.
ACE_ERROR ((LM_ERROR,
ACE_TEXT (" Found an unknown option (%c) ")
@@ -319,19 +348,29 @@ MCT_Config::open (int argc, ACE_TCHAR *argv[])
ACE_TEXT ("usage: %s [options]\n")
ACE_TEXT ("Options:\n")
ACE_TEXT (" -g {STRING} --GroupStart={STRING} ")
- ACE_TEXT ("starting multicast group address ")
- ACE_TEXT ("(default=239.255.0.1)\n")
+ ACE_TEXT ("starting multicast group address\n")
+ ACE_TEXT (" ")
+ ACE_TEXT ("(default=239.255.0.1:16000)\n")
ACE_TEXT (" -n {#} --Groups={#} ")
ACE_TEXT ("number of groups (default=5)\n")
- ACE_TEXT (" -d --debug ")
+ ACE_TEXT (" -d --Debug ")
ACE_TEXT ("debug flag (default=off)\n")
- ACE_TEXT (" -t {STRING} --Type={STRING} ")
- ACE_TEXT ("type {PRODUCER|CONSUMER|BOTH} (default=BOTH)\n")
+ ACE_TEXT (" -r {STRING} --Role={STRING} ")
+ ACE_TEXT ("role {PRODUCER|CONSUMER|BOTH}\n")
+ ACE_TEXT (" ")
+ ACE_TEXT ("(default=BOTH)\n")
ACE_TEXT (" -m {STRING} --SDM_options={STRING} ")
- ACE_TEXT ("ACE_SOCK_Dgram_Mcast ctor options ")
+ ACE_TEXT ("ACE_SOCK_Dgram_Mcast ctor options\n")
+ ACE_TEXT (" ")
ACE_TEXT ("(default=DEFOPTS)\n")
ACE_TEXT (" -i {#} --Iterations={#} ")
ACE_TEXT ("number of iterations (default=100)\n")
+ ACE_TEXT (" -t {#} --TTL={#} ")
+ ACE_TEXT ("time to live (default=1)\n")
+ ACE_TEXT (" -w {#} --Wait={#} ")
+ ACE_TEXT ("number of seconds to wait on CONSUMER\n")
+ ACE_TEXT (" ")
+ ACE_TEXT ("(default=2)\n")
ACE_TEXT (" -h/? --help ")
ACE_TEXT ("show this message\n"),
argv[0]));
@@ -346,7 +385,7 @@ void
MCT_Config::dump (void) const
{
ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
- ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" Dumping MCast_Config\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" Dumping MCT_Config\n")));
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("\tIP_MAX_MEMBERSHIPS = %d\n"),
IP_MAX_MEMBERSHIPS));
@@ -354,11 +393,11 @@ MCT_Config::dump (void) const
ACE_TEXT ("\tgroups_ = %d\n"),
this->groups_));
ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT ("\ttype_ = %s\n"),
- (ACE_BIT_ENABLED (this->type_, PRODUCER)
- && ACE_BIT_ENABLED (this->type_, CONSUMER))
+ ACE_TEXT ("\trole_ = %s\n"),
+ (ACE_BIT_ENABLED (this->role_, PRODUCER)
+ && ACE_BIT_ENABLED (this->role_, CONSUMER))
? ACE_TEXT ("PRODUCER/CONSUMER")
- : ACE_BIT_ENABLED (this->type_, PRODUCER)
+ : ACE_BIT_ENABLED (this->role_, PRODUCER)
? ACE_TEXT ("PRODUCER")
: ACE_TEXT ("CONSUMER")));
ACE_DEBUG ((LM_DEBUG,
@@ -367,11 +406,18 @@ MCT_Config::dump (void) const
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("\titerations_ = %d\n"),
this->iterations_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\tttl_ = %d\n"),
+ this->ttl_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\twait_ = %d\n"),
+ this->wait_));
// Note that this call to get_host_addr is the non-reentrant
// version, but it's okay for us.
ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT ("\tgroups_start_ = %s\n"),
- this->group_start_.get_host_addr ()));
+ ACE_TEXT ("\tgroups_start_ = %s:%d\n"),
+ this->group_start_.get_host_addr (),
+ this->group_start_.get_port_number ()));
ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
}
@@ -700,6 +746,51 @@ int send_dgram (ACE_SOCK_Dgram &socket, ACE_INET_Addr addr, int done = 0)
return 0;
}
+int producer (MCT_Config &config)
+{
+ int retval = 0;
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("Starting producer...\n")));
+ ACE_SOCK_Dgram socket (ACE_sap_any_cast (ACE_INET_Addr &));
+
+ // Note that is is IPv4 specific and needs to be changed once
+ //
+ if (config.ttl () > 1)
+ {
+ int ttl = config.ttl ();
+ if (socket.set_option (IPPROTO_IP,
+ IP_MULTICAST_TTL,
+ (void*) &ttl,
+ sizeof ttl) != 0)
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("could net set socket option IP_MULTICAST_TTL ")
+ ACE_TEXT ("= %d\n"),
+ ttl));
+ else
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("set IP_MULTICAST_TTL = %d\n"), ttl));
+ }
+
+ int iterations = config.iterations ();
+ // we add an extra 5 groups for noise.
+ int groups = config.groups () + 5;
+ for (int i = 0; (i < iterations || iterations == 0) && !finished; ++i)
+ {
+ ACE_INET_Addr addr = config.group_start ();
+ for (int j = 0; j < groups && !finished; ++j)
+ {
+ if ((retval += send_dgram (socket, addr,
+ ((i + 1) == iterations))) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("Calling send_dgram.\n")));
+ if ((retval += advance_addr (addr)) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Calling advance_addr.\n")));
+ }
+ // Give the task thread a chance to run.
+ ACE_Thread::yield ();
+ }
+ return retval;
+}
+
/*
* Advance the address by 1, e.g., 239.255.0.1 => 239.255.0.2
* Note that the algorithm is somewhat simplistic, but sufficient for our
@@ -755,10 +846,11 @@ ACE_TMAIN (int argc, ACE_TCHAR *argv[])
const ACE_TCHAR *temp = ACE_TEXT ("Multicast_Test");
ACE_TString test = temp;
- if (ACE_BIT_DISABLED (config.type (), MCT_Config::PRODUCER)
- || ACE_BIT_DISABLED (config.type (), MCT_Config::CONSUMER))
+ u_long role = config.role ();
+ if (ACE_BIT_DISABLED (role, MCT_Config::PRODUCER)
+ || ACE_BIT_DISABLED (role, MCT_Config::CONSUMER))
{
- if (ACE_BIT_ENABLED (config.type (), MCT_Config::PRODUCER))
+ if (ACE_BIT_ENABLED (role, MCT_Config::PRODUCER))
test += ACE_TEXT ("-PRODUCER");
else
test += ACE_TEXT ("-CONSUMER");
@@ -774,12 +866,11 @@ ACE_TMAIN (int argc, ACE_TCHAR *argv[])
if (config.debug ())
config.dump ();
- // not sure if this should be here are
ACE_Reactor *reactor = ACE_Reactor::instance ();
MCT_Task *task = new MCT_Task (config, reactor);
- if (ACE_BIT_ENABLED (config.type (), MCT_Config::CONSUMER))
+ if (ACE_BIT_ENABLED (role, MCT_Config::CONSUMER))
{
ACE_DEBUG ((LM_INFO, ACE_TEXT ("Starting consumer...\n")));
// Open makes it an active object.
@@ -787,31 +878,10 @@ ACE_TMAIN (int argc, ACE_TCHAR *argv[])
}
// now produce the datagrams...
- if (ACE_BIT_ENABLED (config.type (), MCT_Config::PRODUCER))
- {
- ACE_DEBUG ((LM_INFO, ACE_TEXT ("Starting producer...\n")));
- ACE_SOCK_Dgram socket (ACE_sap_any_cast (ACE_INET_Addr &));
- int iterations = config.iterations ();
- // we add an extra 5 groups for noise.
- int groups = config.groups () + 5;
- for (int i = 0; i < iterations && !finished; ++i)
- {
- ACE_INET_Addr addr = config.group_start ();
- for (int j = 0; j < groups && !finished; ++j)
- {
- if ((retval += send_dgram (socket, addr,
- ((i + 1) == iterations))) == -1)
- ACE_ERROR ((LM_ERROR, ACE_TEXT ("Calling send_dgram.\n")));
- if ((retval += advance_addr (addr)) == -1)
- ACE_ERROR ((LM_ERROR,
- ACE_TEXT ("Calling advance_addr.\n")));
- }
- // Give the task thread a chance to run.
- ACE_Thread::yield ();
- }
- }
+ if (ACE_BIT_ENABLED (role, MCT_Config::PRODUCER))
+ retval += producer (config);
- if (ACE_BIT_ENABLED (config.type (), MCT_Config::CONSUMER))
+ if (ACE_BIT_ENABLED (role, MCT_Config::CONSUMER))
{
// and wait for everything to finish
ACE_DEBUG ((LM_INFO,
@@ -819,9 +889,11 @@ ACE_TMAIN (int argc, ACE_TCHAR *argv[])
// Wait for the threads to exit.
// But, wait for a limited time since we could hang if the last udp
// message isn't received.
- const ACE_Time_Value max_wait ( 2/* seconds */);
- const ACE_Time_Value wait_time (ACE_OS::gettimeofday () + max_wait);
- if (ACE_Thread_Manager::instance ()->wait (&wait_time) == -1)
+ ACE_Time_Value max_wait ( config.wait ()/* seconds */);
+ ACE_Time_Value wait_time (ACE_OS::gettimeofday () + max_wait);
+ ACE_Time_Value *ptime = ACE_BIT_ENABLED (role, MCT_Config::PRODUCER)
+ ? &wait_time : 0;
+ if (ACE_Thread_Manager::instance ()->wait (ptime) == -1)
{
if (errno == ETIME)
ACE_ERROR ((LM_ERROR,