diff options
author | dhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2002-11-15 21:44:15 +0000 |
---|---|---|
committer | dhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2002-11-15 21:44:15 +0000 |
commit | 333c899079a4ed90e9e45922af3dc68a59f3d05b (patch) | |
tree | 054fe0633bccb35488d43d1f4532d6c968977d60 | |
parent | ce1a4fc109ee0b044b6c8b9c8a13985e5c00ac52 (diff) | |
download | ATCD-333c899079a4ed90e9e45922af3dc68a59f3d05b.tar.gz |
ChangeLogTag:Fri Nov 15 20:33:02 UTC 2002 Don Hinton <dhinton@ieee.org>
-rw-r--r-- | ChangeLog | 25 | ||||
-rw-r--r-- | ChangeLogs/ChangeLog-03a | 25 | ||||
-rw-r--r-- | ace/SOCK_Dgram_Mcast.cpp | 12 | ||||
-rw-r--r-- | ace/SOCK_Dgram_Mcast.h | 32 | ||||
-rw-r--r-- | ace/config-aix-4.x.h | 6 | ||||
-rw-r--r-- | ace/config-all.h | 11 | ||||
-rw-r--r-- | ace/config-freebsd.h | 5 | ||||
-rw-r--r-- | ace/config-linux-common.h | 5 | ||||
-rw-r--r-- | ace/config-netbsd.h | 5 | ||||
-rw-r--r-- | ace/config-openbsd.h | 5 | ||||
-rw-r--r-- | tests/Multicast_Test.cpp | 208 |
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, |