ACE_SOCK_Dgram_Mcast Class Reference

Defines the ACE socket wrapper for UDP/IP multicast. More...

#include <SOCK_Dgram_Mcast.h>

Inheritance diagram for ACE_SOCK_Dgram_Mcast:

Inheritance graph
[legend]
Collaboration diagram for ACE_SOCK_Dgram_Mcast:

Collaboration graph
[legend]
List of all members.

Public Types

 OPT_BINDADDR_NO = 0
 Disable address bind. (Bind only port.).
 OPT_BINDADDR_YES = 1
 Enable address bind. (Bind port and address.).
 DEFOPT_BINDADDR = OPT_BINDADDR_NO
 Default value for BINDADDR option. (Environment-dependent.).
 OPT_NULLIFACE_ONE = 0
 If (net_if==NULL), use default interface.
 OPT_NULLIFACE_ALL = 2
 If (net_if==NULL), use all mcast interfaces.
 DEFOPT_NULLIFACE = OPT_NULLIFACE_ONE
 Default value for NULLIFACE option. (Environment-dependent.).
 DEFOPTS = DEFOPT_BINDADDR | DEFOPT_NULLIFACE
 All default options.
enum  options {
  OPT_BINDADDR_NO = 0, OPT_BINDADDR_YES = 1, DEFOPT_BINDADDR = OPT_BINDADDR_NO, OPT_NULLIFACE_ONE = 0,
  OPT_NULLIFACE_ALL = 2, DEFOPT_NULLIFACE = OPT_NULLIFACE_ONE, DEFOPTS = DEFOPT_BINDADDR | DEFOPT_NULLIFACE
}
 Option parameters. More...

Public Member Functions

 ACE_SOCK_Dgram_Mcast (options opts=DEFOPTS)
 ~ACE_SOCK_Dgram_Mcast (void)
int open (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if=0, int reuse_addr=1)
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)
ssize_t send (const void *buf, size_t n, int flags=0) const
ssize_t send (const iovec iov[], int n, int flags=0) const
int set_option (int option, char optval)
 Set a socket option.
void dump (void) const
 Dump the state of an object.

Public Attributes

 ACE_ALLOC_HOOK_DECLARE
 Declare the dynamic allocation hooks.

Protected Member Functions

int open_i (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if=0, int reuse_addr=1)
int clear_subs_list (void)
 Empty the dynamic subscription list.

Private Member Functions

int subscribe_ifs (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if, int reuse_addr)
int subscribe_i (const ACE_INET_Addr &mcast_addr, int reuse_addr=1, const ACE_TCHAR *net_if=0)
 Do subscription processing w/out updating the subscription list.
int unsubscribe_ifs (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if=0)
 Unsubscribe from a multicast address on one or more network interface(s).
int unsubscribe_i (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if=0)
 Do unsubscription processing w/out udpating subscription list.

Private Attributes

int opts_
 Per-instance options..
ACE_INET_Addr send_addr_
 Multicast address to which local <send> methods send datagrams.
ACE_TCHARsend_net_if_
 Network interface to which all <send> methods send multicast datagrams.

Detailed Description

Defines the ACE socket wrapper for UDP/IP multicast.

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.

Note that multicast semantics and implementation details are _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:

Interface specification notes (for <subscribe> and <unsubscribe>):

Definition at line 94 of file SOCK_Dgram_Mcast.h.


Member Enumeration Documentation

enum ACE_SOCK_Dgram_Mcast::options

Option parameters.

These control per-instance optional functionality. They are set via optional constructor arguments.

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.
Enumerator:
OPT_BINDADDR_NO  Disable address bind. (Bind only port.).
OPT_BINDADDR_YES  Enable address bind. (Bind port and address.).
DEFOPT_BINDADDR  Default value for BINDADDR option. (Environment-dependent.).
OPT_NULLIFACE_ONE  If (net_if==NULL), use default interface.
OPT_NULLIFACE_ALL  If (net_if==NULL), use all mcast interfaces.
DEFOPT_NULLIFACE  Default value for NULLIFACE option. (Environment-dependent.).
DEFOPTS  All default options.

Definition at line 107 of file SOCK_Dgram_Mcast.h.

00108   {
00109   // Define whether a specific (multicast) address (in addition to the port#)
00110   // is bound to the socket.
00111   // Notes:
00112   // - Effect of doing this is stack/environment dependent, but in most
00113   //   environments can be used to filter out unwanted unicast, broadcast, and
00114   //   (other) multicast messages sent to the same port#.
00115   // - Some IP stacks (e.g. some Win32) do not support binding multicast
00116   //   addresses.  Using this option will always cause an <open> error.
00117   // - It's not strictly possible for user code to do this level of filtering
00118   //   w/out the bind; some environments support ways to determine which address
00119   //   a message was sent _to_, but this class interface does not support access
00120   //   to that info.
00121   // - The address (and port#) passed to <open> (or the first <subscribe>, if
00122   //   <open> is not explicitly invoked) is the one that is bound.
00123   //
00124     /// Disable address bind. (Bind only port.)
00125     // Note that this might seem odd, but we need a way to distinquish between
00126     // default behavior, which might or might not be to bind, and explicitely
00127     // choosing to bind or not to bind--which "is the question." ;-)
00128     OPT_BINDADDR_NO   = 0,
00129     /// Enable address bind. (Bind port and address.)
00130     OPT_BINDADDR_YES   = 1,
00131     /// Default value for BINDADDR option. (Environment-dependent.)
00132 #if defined (ACE_LACKS_PERFECT_MULTICAST_FILTERING) \
00133     && (ACE_LACKS_PERFECT_MULTICAST_FILTERING == 1)
00134       // Platforms that don't support perfect filtering. Note that perfect
00135       // filtering only really applies to multicast traffic, not unicast
00136       // or broadcast.
00137       DEFOPT_BINDADDR  = OPT_BINDADDR_YES,
00138 # else
00139       // At least some Win32 OS's can not bind mcast addr, so disable it.
00140       // General-purpose default behavior is 'disabled', since effect is
00141       // environment-specific and side-effects might be surprising.
00142       DEFOPT_BINDADDR  = OPT_BINDADDR_NO,
00143 #endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING = 1) */
00144   //
00145   /// Define the interpretation of 'NULL' as a recv interface specification.
00146   // If the interface part of a multicast address specification is NULL, it
00147   // will be interpreted to mean either "the default interface" or "all
00148   // interfaces", depending on the setting of this option.
00149   // Notes:
00150   // - The 'nulliface_all' option can not be used in environments which do
00151   //   not fully support the <ACE_Sock_Connect::get_ip_interfaces> method
00152   //   (e.g. non-Windows).
00153   //   If it is, using NULL for iface will _always_ fail.
00154   // - The default behavior in most IP stacks is to use the 'default' interface,
00155   //   where 'default' has rather ad-hoc semantics.
00156   // - This applies only to receives, not sends (which always use only one
00157   //   interface; NULL means use the "system default" interface).
00158   // Supported values:
00159     /// If (net_if==NULL), use default interface.
00160     // Note that this might seem odd, but we need a way to distinquish between
00161     // default behavior, which might or might not be to bind, and explicitely
00162     // choosing to bind or not to bind--which "is the question." ;-)
00163     OPT_NULLIFACE_ONE  = 0,
00164     /// If (net_if==NULL), use all mcast interfaces.
00165     OPT_NULLIFACE_ALL  = 2,
00166     /// Default value for NULLIFACE option. (Environment-dependent.)
00167 #ifdef ACE_WIN32
00168       // This is the (ad-hoc) legacy behavior for Win32/WinSock.
00169       // Notice: Older version of WinSock/MSVC may not get all multicast-capable
00170       // interfaces (e.g. PPP interfaces).
00171       DEFOPT_NULLIFACE = OPT_NULLIFACE_ALL,
00172 #else
00173       // General-purpose default behavior (as per legacy behavior).
00174       DEFOPT_NULLIFACE = OPT_NULLIFACE_ONE,
00175 #endif /* ACE_WIN32 */
00176     /// All default options.
00177     DEFOPTS = DEFOPT_BINDADDR | DEFOPT_NULLIFACE
00178   };


Constructor & Destructor Documentation

ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast ( options  opts = DEFOPTS  ) 

You must invoke <open> or <subscribe>, to create/bind a socket and define operational parameters, before performing any I/O with this instance.

Definition at line 133 of file SOCK_Dgram_Mcast.cpp.

References ACE_TRACE.

00134   :  opts_ (opts),
00135      send_net_if_ (0)
00136 {
00137   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast");
00138 }

ACE_SOCK_Dgram_Mcast::~ACE_SOCK_Dgram_Mcast ( void   ) 

The OPT_DTORUNSUB_YES_ option defines whether an explicit <unsusbcribe> is done by the destructor. If not, most systems will automatically unsubscribe upon the close of the socket.

Definition at line 141 of file SOCK_Dgram_Mcast.cpp.

References ACE_TRACE, clear_subs_list(), and send_net_if_.

00142 {
00143   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::~ACE_SOCK_Dgram_Mcast");
00144 
00145   // Free memory and optionally unsubscribe from currently subscribed group(s).
00146   delete [] this->send_net_if_;
00147   this->clear_subs_list ();
00148 }


Member Function Documentation

int ACE_SOCK_Dgram_Mcast::clear_subs_list ( void   )  [protected]

Empty the dynamic subscription list.

Definition at line 909 of file SOCK_Dgram_Mcast.cpp.

References ACE_GUARD_RETURN, and ACE_TRACE.

Referenced by ~ACE_SOCK_Dgram_Mcast().

00910 {
00911   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::clear_subs_list");
00912   int result = 0;
00913 
00914 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00915   ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00916                             this->subscription_list_lock_, -1));
00917   subscription_list_iter_t iter (this->subscription_list_);
00918   for (; !iter.done (); /*Hack: Do _not_ ::advance after remove*/)
00919     {
00920       ip_mreq  *pm = iter.next ();
00921       iter.remove ();
00922       delete pm;
00923     }
00924 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00925   return result;
00926 }

void ACE_SOCK_Dgram_Mcast::dump ( void   )  const

Dump the state of an object.

Logs the setting of all options, the bound address, the send address and interface, and the list of current subscriptions.

Reimplemented from ACE_SOCK_Dgram.

Definition at line 68 of file SOCK_Dgram_Mcast.cpp.

References ACE_BEGIN_DUMP, ACE_BIT_ENABLED, ACE_DEBUG, ACE_END_DUMP, ACE_GUARD, ACE_NTOHL, ACE_TEXT, ACE_TRACE, ACE_SDM_helpers::addr_to_string(), LM_DEBUG, MAXNAMELEN, ACE_OS::strcmp(), and ACE_OS::strcpy().

00069 {
00070 #if defined (ACE_HAS_DUMP)
00071   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::dump");
00072 
00073   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00074 
00075 # if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00076   ACE_TCHAR addr_string[MAXNAMELEN + 1];
00077 
00078   ACE_DEBUG ((LM_DEBUG,
00079               ACE_TEXT ("\nOptions: bindaddr=%s, nulliface=%s\n"),
00080               ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES) ?
00081                 ACE_TEXT ("<Bound>") : ACE_TEXT ("<Not Bound>"),
00082               ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL) ?
00083                 ACE_TEXT ("<All Ifaces>") : ACE_TEXT ("<Default Iface>")));
00084 
00085   // Show default send addr, port#, and interface.
00086   ACE_SDM_helpers::addr_to_string (this->send_addr_, addr_string,
00087                                    sizeof addr_string, 0);
00088   ACE_DEBUG ((LM_DEBUG,
00089               ACE_TEXT ("Send addr=%s iface=%s\n"),
00090               addr_string,
00091               this->send_net_if_ ? this->send_net_if_
00092                                  : ACE_TEXT ("<default>")));
00093 
00094   // Show list of subscribed addresses.
00095   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Subscription list:\n")));
00096 
00097   ACE_MT (ACE_GUARD (ACE_SDM_LOCK, guard, this->subscription_list_lock_));
00098   subscription_list_iter_t  iter (this->subscription_list_);
00099   for ( ; !iter.done (); iter.advance ())
00100     {
00101       ACE_TCHAR iface_string[MAXNAMELEN + 1];
00102       ip_mreq *pm = iter.next ();
00103 
00104       // Get subscribed address (w/out port# info - not relevant).
00105       ACE_INET_Addr ip_addr (static_cast<u_short> (0),
00106                              ACE_NTOHL (pm->IMR_MULTIADDR.s_addr));
00107       ACE_SDM_helpers::addr_to_string (ip_addr, addr_string,
00108                                        sizeof addr_string, 1);
00109 
00110       // Get interface address/specification.
00111       ACE_INET_Addr if_addr (static_cast<u_short> (0),
00112                              ACE_NTOHL (pm->imr_interface.s_addr));
00113       ACE_SDM_helpers::addr_to_string (if_addr, iface_string,
00114                                        sizeof iface_string, 1);
00115       if (ACE_OS::strcmp (iface_string, ACE_TEXT ("0.0.0.0")) == 0)
00116         // Receives on system default iface. (Note that null_iface_opt_
00117         // option processing has already occurred.)
00118         ACE_OS::strcpy (iface_string, ACE_TEXT ("<default>"));
00119 
00120       // Dump info.
00121       ACE_DEBUG ((LM_DEBUG,
00122                   ACE_TEXT ("\taddr=%s iface=%s\n"),
00123                   addr_string,
00124                   iface_string));
00125     }
00126 # endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00127   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00128 #endif /* ACE_HAS_DUMP */
00129 }

int ACE_SOCK_Dgram_Mcast::join ( const ACE_INET_Addr mcast_addr,
int  reuse_addr = 1,
const ACE_TCHAR net_if = 0 
)

The given group is joined on the specified interface. If option OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is joined on all multicast capable interfaces (IFF supported). Multiple subscriptions to various address and interface combinations are supported and tracked. If this is the first invocation of <subscribe>, and <open> was not previously invoked, <open> will be invoked using <mcast_addr> for binding the socket and <net_if> as the interface for <send>.

Returns: -1 if the call fails. Failure can occur due to problems with the address, port#, and/or interface parameters or during the subscription attempt. Once bind() has been invoked (by the first <open> or <subscribe>), returns errno of ENXIO if the port# is not 0 and does not match the bound port#, or if OPT_BINDADDR_YES option is used and the address does not match the bound address. Returns errno of ENODEV if the addr/port#/interface parameters appeared valid, but no subscription(s) succeeded. An error is unconditionally returned if option OPT_NULLIFACE_ALL is used, <net_if> is NULL, and <ACE_Sock_Connect::get_ip_interfaces> is not implemented in this environment.

Note that the optional reuse_addr parameter does not apply to subscriptions; it is only used if <open> is implicitly invoked (see above).

Uses the mcast_addr to determine protocol_family, and protocol which we always pass as 0 anyway.

Definition at line 466 of file SOCK_Dgram_Mcast.cpp.

References ACE_BIT_ENABLED, ACE_ERROR, ACE_GUARD_RETURN, ACE_TEXT, ACE_TRACE, ACE_SDM_helpers::addr_to_string(), ENXIO, ACE_INET_Addr::get_port_number(), LM_ERROR, MAXNAMELEN, OPT_BINDADDR_YES, send_addr_, ACE_INET_Addr::set_port_number(), and subscribe_i().

00469 {
00470   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::join");
00471   ACE_INET_Addr subscribe_addr = mcast_addr;
00472 
00473   // If port# is 0, insert bound port# if it is set. (To satisfy lower-level
00474   // port# validation.)
00475   u_short def_port_number = this->send_addr_.get_port_number ();
00476   if (subscribe_addr.get_port_number () == 0
00477       && def_port_number != 0)
00478     {
00479       subscribe_addr.set_port_number (def_port_number);
00480     }
00481 
00482   // Check for port# different than bound port#.
00483   u_short sub_port_number = mcast_addr.get_port_number ();
00484   if (sub_port_number != 0
00485       && def_port_number != 0
00486       && sub_port_number != def_port_number)
00487     {
00488       ACE_ERROR ((LM_ERROR,
00489                   ACE_TEXT ("Subscribed port# (%u) different than bound ")
00490                   ACE_TEXT ("port# (%u).\n"),
00491                   (u_int) sub_port_number,
00492                   (u_int) def_port_number));
00493       errno = ENXIO;
00494       return -1;
00495     }
00496 
00497   // If bind_addr_opt_ is enabled, check for address different than
00498   // bound address.
00499   ACE_INET_Addr tmp_addr (this->send_addr_);
00500   tmp_addr.set_port_number (mcast_addr.get_port_number ()); // force equal port numbers
00501   if (ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES)
00502       && !this->send_addr_.is_any ()
00503       && this->send_addr_ != mcast_addr)
00504     {
00505       ACE_TCHAR sub_addr_string[MAXNAMELEN + 1];
00506       ACE_TCHAR bound_addr_string[MAXNAMELEN + 1];
00507       ACE_SDM_helpers::addr_to_string (mcast_addr, sub_addr_string,
00508                                        sizeof sub_addr_string, 1);
00509       ACE_SDM_helpers::addr_to_string (this->send_addr_, bound_addr_string,
00510                                        sizeof bound_addr_string, 1);
00511       ACE_ERROR ((LM_ERROR,
00512                   ACE_TEXT ("Subscribed address (%s) different than ")
00513                   ACE_TEXT ("bound address (%s).\n"),
00514                   sub_addr_string,
00515                   bound_addr_string));
00516       errno = ENXIO;
00517       return -1;
00518     }
00519 
00520   // Attempt subscription.
00521   int result = this->subscribe_i (subscribe_addr, reuse_addr, net_if);
00522 
00523 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00524   if (result == 0)
00525     {
00526       // Add this addr/iface info to the list of subscriptions.
00527       // (Assumes this is unique addr/iface combo - most systems don't allow
00528       // re-sub to same addr/iface.)
00529       ip_mreq  *pmreq = new ip_mreq;
00530       // (should not fail)
00531       if (this->make_multicast_ifaddr (pmreq, subscribe_addr, net_if) != -1)
00532         {
00533           ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00534                                     this->subscription_list_lock_, -1));
00535           this->subscription_list_.insert_tail (pmreq);
00536           return 0;
00537         }
00538       // this still isn't really right. If ACE_GUARD_RETURN fails, we leak.
00539       // Need to add one of Chris' fancy ace auto pointers (bound?).
00540       delete pmreq;
00541     }
00542 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00543 
00544   return result >= 0 ? 0 : result;
00545 }

int ACE_SOCK_Dgram_Mcast::leave ( const ACE_INET_Addr mcast_addr,
const ACE_TCHAR net_if = 0 
)

The specified group/interface combination is unsubscribed. If option OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is unsubscribed from all interfaces (IFF supported).

Returns: -1 if the unsubscribe failed. Most environments will return -1 if there was no active subscription for this address/interface combination. An error is unconditionally returned if option OPT_NULLIFACE_ALL is used, <net_if> is = 0, and <ACE_Sock_Connect::get_ip_interfaces> is not implemented in this environment (_even if_ the <subscribe> specifies a non- NULL <net_if>).

leave() replaces unsubscribe() and uses mcast_addr to determine protocol_family, and protocol which we always pass as 0 anyway.

Definition at line 798 of file SOCK_Dgram_Mcast.cpp.

References ACE_GUARD_RETURN, ACE_TRACE, ACE_SDM_helpers::is_equal(), and unsubscribe_i().

00800 {
00801   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::leave");
00802   // Unsubscribe.
00803   int result = this->unsubscribe_i (mcast_addr,
00804                                     net_if);
00805 
00806 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00807   // (Unconditionally) Remove this addr/if from subscription list.
00808   // (Addr/if is removed even if unsubscribe failed)
00809   ip_mreq  tgt_mreq;
00810   if (this->make_multicast_ifaddr (&tgt_mreq,
00811                                    mcast_addr,
00812                                    net_if) != -1)
00813     {
00814       ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00815                                 this->subscription_list_lock_, -1));
00816       subscription_list_iter_t iter (this->subscription_list_);
00817       for (; !iter.done (); iter.advance ())
00818         {
00819           ip_mreq  *pm = iter.next ();
00820           if (ACE_SDM_helpers::is_equal (*pm, tgt_mreq))
00821             {
00822               iter.remove ();
00823               delete pm;
00824               break;
00825             }
00826         }
00827     }
00828 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00829 
00830   return result >= 0 ? 0 : result;
00831 }

int ACE_SOCK_Dgram_Mcast::open ( const ACE_INET_Addr mcast_addr,
const ACE_TCHAR net_if = 0,
int  reuse_addr = 1 
)

This method is optional; if not explicitly invoked, it is invoked by the first <subscribe>, using the subscribed address/port# and network interface paramters. The <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 <send_net_if> parameter != 0, it defines the network interface used for all sends by this instance, otherwise the system "default" interface is used. (The <send_net_if> parameter is ignored if this feature is not supported by the envriornment.) The port# in <mcast_addr> may be 0, in which case a system-assigned (ephemeral) port# is used for sending and receiving. If 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() or socket option processing.

Definition at line 151 of file SOCK_Dgram_Mcast.cpp.

References ACE_TRACE, ACE_Addr::get_type(), ACE_SOCK::open(), open_i(), and SOCK_DGRAM.

00154 {
00155   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open");
00156 
00157   // Only perform the <open> initialization if we haven't been opened
00158   // earlier.
00159   // No sanity check?  We should probably flag an error if the user
00160   // makes multiple calls to open().
00161   if (this->get_handle () != ACE_INVALID_HANDLE)
00162     return 0;
00163 
00164   // Invoke lower-layer ::open.
00165   if (ACE_SOCK::open (SOCK_DGRAM,
00166                       mcast_addr.get_type (),
00167                       0, // always use 0
00168                       reuse_addr) == -1)
00169     return -1;
00170 
00171   return this->open_i (mcast_addr, net_if, reuse_addr);
00172 }

int ACE_SOCK_Dgram_Mcast::open_i ( const ACE_INET_Addr mcast_addr,
const ACE_TCHAR net_if = 0,
int  reuse_addr = 1 
) [protected]

Contains common open functionality so that inheriting classes can reuse it.

Definition at line 175 of file SOCK_Dgram_Mcast.cpp.

References ACE_BIT_DISABLED, ACE_TRACE, ACE_INET_Addr::get_port_number(), ACE_Addr::get_type(), OPT_BINDADDR_YES, send_addr_, send_net_if_, ACE_INET_Addr::set(), ACE_INET_Addr::set_port_number(), ACE_SOCK_Dgram::shared_open(), SOL_SOCKET, ACE_OS::strcpy(), and ACE_OS::strlen().

Referenced by open().

00178 {
00179   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open_i");
00180   // ACE_SOCK::open calls this if reuse_addr is set, so we only need to
00181   // process port reuse option.
00182   if (reuse_addr)
00183     {
00184 #if defined (SO_REUSEPORT)
00185       int one = 1;
00186       if (this->ACE_SOCK::set_option (SOL_SOCKET,
00187                                       SO_REUSEPORT,
00188                                       &one,
00189                                       sizeof one) == -1)
00190         return -1;
00191 #endif /* SO_REUSEPORT */
00192     }
00193 
00194   // Create an address/port# to bind the socket to. Use mcast_addr to
00195   // initialize bind_addy to pick up the correct protocol family. If
00196   // OPT_BINDADDR_YES is set, then we're done. Else use mcast_addr's
00197   // port number and use the "any" address.
00198   ACE_INET_Addr bind_addy (mcast_addr);
00199   if (ACE_BIT_DISABLED (this->opts_, OPT_BINDADDR_YES))
00200     {
00201 #if defined (ACE_HAS_IPV6)
00202       if (mcast_addr.get_type () == PF_INET6)
00203         {
00204           if (bind_addy.set (mcast_addr.get_port_number (), "::",
00205                              1, AF_INET6) == -1)
00206             return -1;
00207         }
00208       else
00209         // Bind to "any" address and explicit port#.
00210         if (bind_addy.set (mcast_addr.get_port_number ()) == -1)
00211           return -1;
00212 #else
00213       // Bind to "any" address and explicit port#.
00214       if (bind_addy.set (mcast_addr.get_port_number ()) == -1)
00215         return -1;
00216 #endif /* ACE_HAS_IPV6 */
00217     }
00218 
00219   // Bind to the address (which may be INADDR_ANY) and port# (which may be 0)
00220   if (ACE_SOCK_Dgram::shared_open (bind_addy, bind_addy.get_type ()) == -1)
00221     return -1;
00222 
00223   // Cache the actual bound address (which may be INADDR_ANY)
00224   // and the actual bound port# (which will be a valid, non-zero port#).
00225   ACE_INET_Addr bound_addy;
00226   if (this->get_local_addr (bound_addy) == -1)
00227     {
00228       // (Unexpected failure - should be bound to something)
00229       if (bound_addy.set (bind_addy) == -1)
00230         {
00231           // (Shouldn't happen - bind_addy is a valid addy; punt.)
00232           return -1;
00233         }
00234     }
00235 
00236   this->send_addr_ = mcast_addr;
00237   this->send_addr_.set_port_number (bound_addy.get_port_number ());
00238   if (net_if)
00239     {
00240       if (this->set_nic (net_if, mcast_addr.get_type ()))
00241         return -1;
00242 
00243       this->send_net_if_ = new ACE_TCHAR[ACE_OS::strlen (net_if) + 1];
00244       ACE_OS::strcpy (this->send_net_if_, net_if);
00245     }
00246 
00247   return 0;
00248 }

ACE_INLINE ssize_t ACE_SOCK_Dgram_Mcast::send ( const iovec  iov[],
int  n,
int  flags = 0 
) const

Send n <iovecs>, using the multicast address and network interface defined by the first <open> or <subscribe>.

Definition at line 41 of file SOCK_Dgram_Mcast.inl.

References ACE_TRACE, and ACE_SOCK_Dgram::send().

00044 {
00045   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::send");
00046   return this->ACE_SOCK_Dgram::send (iov,
00047                                      n,
00048                                      this->send_addr_,
00049                                      flags);
00050 }

ACE_INLINE ssize_t ACE_SOCK_Dgram_Mcast::send ( const void *  buf,
size_t  n,
int  flags = 0 
) const

Send n bytes in buf, using the multicast address and network interface defined by the first <open> or <subscribe>.

Definition at line 29 of file SOCK_Dgram_Mcast.inl.

References ACE_TRACE, and ACE_SOCK_Dgram::send().

00032 {
00033   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::send");
00034   return this->ACE_SOCK_Dgram::send (buf,
00035                                      n,
00036                                      this->send_addr_,
00037                                      flags);
00038 }

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE int ACE_SOCK_Dgram_Mcast::set_option ( int  option,
char  optval 
)

Set a socket option.

Set an IP option that takes a char as input, such as IP_MULTICAST_LOOP 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.

Returns 0 on success, -1 on failure.

Deprecated:
This method has been deprecated since it cannot be used easily with with IPv6 options. Use ACE_SOCK::set_option instead.

Definition at line 8 of file SOCK_Dgram_Mcast.inl.

References ACE_TRACE, IPPROTO_IP, and ACE_SOCK::set_option().

00010 {
00011   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::set_option");
00012 
00013   if (this->get_handle () == ACE_INVALID_HANDLE)
00014     return -1;
00015 
00016   int level = IPPROTO_IP;
00017 #if defined (IPPROTO_IPV6) && ! defined (INTEGRITY)
00018   if (this->send_addr_.get_type () == PF_INET6)
00019     level = IPPROTO_IPV6;
00020 #endif /* IPPROTO_IPV6 */
00021 
00022   return this->ACE_SOCK::set_option (level,
00023                                      option,
00024                                      &optval,
00025                                      sizeof (optval));
00026 }

int ACE_SOCK_Dgram_Mcast::subscribe_i ( const ACE_INET_Addr mcast_addr,
int  reuse_addr = 1,
const ACE_TCHAR net_if = 0 
) [private]

Do subscription processing w/out updating the subscription list.

Definition at line 549 of file SOCK_Dgram_Mcast.cpp.

References ACE_TRACE, ACE_Addr::get_type(), IP_ADD_MEMBERSHIP, IPPROTO_IP, and subscribe_ifs().

Referenced by join().

00552 {
00553   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_i");
00554   ip_mreq  mreq;
00555 #if defined (ACE_HAS_IPV6)
00556   ipv6_mreq mreq6;
00557 #endif /* __linux__ && ACE_HAS_IPV6 */
00558 
00559   // Open the socket IFF this is the first ::subscribe and ::open
00560   // was not explicitly invoked.
00561   if (this->open (mcast_addr,
00562                   net_if,
00563                   reuse_addr) == -1)
00564     return -1;
00565 
00566   // Only do this if net_if == 0, i.e., INADDR_ANY
00567   if (net_if == 0)
00568     {
00569       int result = this->subscribe_ifs (mcast_addr,
00570                                         net_if,
00571                                         reuse_addr);
00572       // Check for error or "short-circuit" return.
00573       if (result != 0)
00574         return result;
00575     }
00576 
00577 #if defined (ACE_HAS_IPV6)
00578   if (mcast_addr.get_type () == AF_INET6)
00579     {
00580       if (this->make_multicast_ifaddr6 (&mreq6, mcast_addr, net_if) == -1)
00581         return -1;
00582       // Tell IP stack to pass messages sent to this group.
00583       else if (this->ACE_SOCK::set_option (IPPROTO_IPV6,
00584                                            IPV6_JOIN_GROUP,
00585                                            &mreq6,
00586                                            sizeof mreq6) == -1)
00587         return -1;
00588 
00589       return 0;
00590     }
00591   // Fall through for IPv4 case
00592 #endif /* ACE_HAS_IPV6 */
00593 
00594   // Create multicast addr/if struct.
00595   if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00596     return -1;
00597   // Tell IP stack to pass messages sent to this group.
00598   else if (this->ACE_SOCK::set_option (IPPROTO_IP,
00599                                        IP_ADD_MEMBERSHIP,
00600                                        &mreq,
00601                                        sizeof mreq) == -1)
00602     return -1;
00603 
00604   return 0;
00605 }

int ACE_SOCK_Dgram_Mcast::subscribe_ifs ( const ACE_INET_Addr mcast_addr,
const ACE_TCHAR net_if,
int  reuse_addr 
) [private]

Subscribe to a multicast address on one or more network interface(s). (No QoS support.)

Definition at line 251 of file SOCK_Dgram_Mcast.cpp.

References ACE_BIT_ENABLED, ACE_NEW_RETURN, ACE_TEXT, ACE_TEXT_CHAR_TO_TCHAR, ACE_TRACE, AF_INET, ACE::get_ip_interfaces(), ACE_Addr::get_type(), and OPT_NULLIFACE_ALL.

Referenced by subscribe_i().

00254 {
00255   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_ifs");
00256 
00257   if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
00258       && net_if == 0)
00259     {
00260 #if defined (ACE_HAS_IPV6)
00261       if (mcast_addr.get_type () == AF_INET6)
00262         {
00263           size_t nr_subscribed = 0;
00264 # if defined(__linux__)
00265           struct if_nameindex *intf;
00266 
00267           intf = ACE_OS::if_nameindex ();
00268 
00269           if (intf == 0)
00270             return -1;
00271 
00272           int index = 0;
00273           while (intf[index].if_index != 0 || intf[index].if_name != 0)
00274             {
00275               if (this->join (mcast_addr, reuse_addr,
00276                               ACE_TEXT_CHAR_TO_TCHAR(intf[index].if_name)) == 0)
00277                 ++nr_subscribed;
00278 
00279               ++index;
00280             }
00281 
00282           ACE_OS::if_freenameindex (intf);
00283 
00284 # elif defined (ACE_WIN32)
00285 
00286           IP_ADAPTER_ADDRESSES tmp_addrs;
00287           // Initial call to determine actual memory size needed
00288           DWORD dwRetVal;
00289           ULONG bufLen = 0;
00290           if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00291                                                   0,
00292                                                   0,
00293                                                   &tmp_addrs,
00294                                                   &bufLen)) != ERROR_BUFFER_OVERFLOW)
00295             return -1; // With output bufferlength 0 this can't be right.
00296 
00297           // Get required output buffer and retrieve info for real.
00298           PIP_ADAPTER_ADDRESSES pAddrs;
00299           char *buf;
00300           ACE_NEW_RETURN (buf,
00301                           char[bufLen],
00302                           -1);
00303           pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
00304           if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00305                                                   0,
00306                                                   0,
00307                                                   pAddrs,
00308                                                   &bufLen)) != NO_ERROR)
00309             {
00310               delete[] buf; // clean up
00311               return -1;
00312             }
00313 
00314           while (pAddrs)
00315             {
00316               if (this->join (mcast_addr, reuse_addr,
00317                               ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
00318                 ++nr_subscribed;
00319 
00320               pAddrs = pAddrs->Next;
00321             }
00322 
00323           delete[] buf; // clean up
00324 
00325 # endif /* ACE_WIN32 */
00326 
00327           if (nr_subscribed == 0)
00328             {
00329               errno = ENODEV;
00330               return -1;
00331             }
00332 
00333           return 1;
00334         }
00335       else
00336         {
00337           // Subscribe on all local multicast-capable network interfaces, by
00338           // doing recursive calls with specific interfaces.
00339 
00340           ACE_INET_Addr *if_addrs = 0;
00341           size_t if_cnt;
00342 
00343           if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00344             return -1;
00345 
00346           size_t nr_subscribed = 0;
00347 
00348           if (if_cnt < 2)
00349             {
00350               if (this->join (mcast_addr,
00351                               reuse_addr,
00352                               ACE_TEXT ("0.0.0.0")) == 0)
00353                 ++nr_subscribed;
00354             }
00355           else
00356             {
00357               // Iterate through all the interfaces, figure out which ones
00358               // offer multicast service, and subscribe to them.
00359               while (if_cnt > 0)
00360                 {
00361                   --if_cnt;
00362 
00363                   // Convert to 0-based for indexing, next loop check.
00364                   if (if_addrs[if_cnt].get_type () != AF_INET || if_addrs[if_cnt].is_loopback ())
00365                     continue;
00366                   if (this->join (mcast_addr,
00367                                   reuse_addr,
00368                                   ACE_TEXT_CHAR_TO_TCHAR
00369                                    (if_addrs[if_cnt].get_host_addr ())) == 0)
00370                     ++nr_subscribed;
00371                 }
00372             }
00373 
00374           delete [] if_addrs;
00375 
00376           if (nr_subscribed == 0)
00377             {
00378               errno = ENODEV;
00379               return -1;
00380             }
00381 
00382           // 1 indicates a "short-circuit" return.  This handles the
00383           // recursive behavior of checking all the interfaces.
00384           return 1;
00385 
00386         }
00387 #else
00388       // Subscribe on all local multicast-capable network interfaces, by
00389       // doing recursive calls with specific interfaces.
00390 
00391       ACE_INET_Addr *if_addrs = 0;
00392       size_t if_cnt;
00393 
00394       if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00395         return -1;
00396 
00397       size_t nr_subscribed = 0;
00398 
00399       if (if_cnt < 2)
00400         {
00401           if (this->join (mcast_addr,
00402                           reuse_addr,
00403                           ACE_TEXT ("0.0.0.0")) == 0)
00404             ++nr_subscribed;
00405         }
00406       else
00407         {
00408           // Iterate through all the interfaces, figure out which ones
00409           // offer multicast service, and subscribe to them.
00410           while (if_cnt > 0)
00411             {
00412               --if_cnt;
00413 
00414               // Convert to 0-based for indexing, next loop check.
00415               if (if_addrs[if_cnt].is_loopback ())
00416                 continue;
00417               if (this->join (mcast_addr,
00418                               reuse_addr,
00419                               ACE_TEXT_CHAR_TO_TCHAR
00420                                      (if_addrs[if_cnt].get_host_addr ())) == 0)
00421                 ++nr_subscribed;
00422             }
00423         }
00424 
00425       delete [] if_addrs;
00426 
00427       if (nr_subscribed == 0)
00428         {
00429           errno = ENODEV;
00430           return -1;
00431         }
00432 
00433       // 1 indicates a "short-circuit" return.  This handles the
00434       // recursive behavior of checking all the interfaces.
00435       return 1;
00436 #endif /* ACE_HAS_IPV6 */
00437     }
00438 
00439 #if defined (ACE_HAS_IPV6)
00440   if (mcast_addr.get_type () == AF_INET6)
00441     {
00442       if (this->make_multicast_ifaddr6 (0, mcast_addr, net_if) == -1)
00443         return -1;
00444     }
00445   else
00446     {
00447       // Validate passed multicast addr and iface specifications.
00448       if (this->make_multicast_ifaddr (0,
00449                                        mcast_addr,
00450                                        net_if) == -1)
00451         return -1;
00452     }
00453 #else
00454     // Validate passed multicast addr and iface specifications.
00455     if (this->make_multicast_ifaddr (0,
00456                                      mcast_addr,
00457                                      net_if) == -1)
00458       return -1;
00459 #endif /* ACE_HAS_IPV6 */
00460 
00461   return 0;
00462 
00463 }

int ACE_SOCK_Dgram_Mcast::unsubscribe_i ( const ACE_INET_Addr mcast_addr,
const ACE_TCHAR net_if = 0 
) [private]

Do unsubscription processing w/out udpating subscription list.

Definition at line 835 of file SOCK_Dgram_Mcast.cpp.

References ACE_TRACE, ACE_Addr::get_type(), IP_DROP_MEMBERSHIP, IPPROTO_IP, ACE_SOCK::set_option(), and unsubscribe_ifs().

Referenced by leave().

00837 {
00838   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_i");
00839 
00840   int result = this->unsubscribe_ifs (mcast_addr,
00841                                       net_if);
00842 
00843   // Check for error or "short-circuit" return.
00844   if (result != 0)
00845     return result;
00846 
00847 #if defined (ACE_HAS_IPV6)
00848   if (mcast_addr.get_type () == AF_INET6)
00849     {
00850       // Validate addr/if specifications and create addr/if struct.
00851       ipv6_mreq  mreq;
00852       if (this->make_multicast_ifaddr6 (&mreq, mcast_addr, net_if) == -1)
00853         {
00854           return -1;
00855         }
00856       // Tell network device driver to stop reading datagrams with the
00857       // <mcast_addr>.
00858       else if (ACE_SOCK::set_option (IPPROTO_IPV6,
00859                                      IPV6_LEAVE_GROUP,
00860                                      &mreq,
00861                                      sizeof mreq) == -1)
00862         {
00863           return -1;
00864         }
00865 
00866     }
00867   else  // IPv4
00868     {
00869       // Validate addr/if specifications and create addr/if struct.
00870       ip_mreq  mreq;
00871       if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00872         {
00873           return -1;
00874         }
00875       // Tell network device driver to stop reading datagrams with the
00876       // <mcast_addr>.
00877       else if (ACE_SOCK::set_option (IPPROTO_IP,
00878                                      IP_DROP_MEMBERSHIP,
00879                                      &mreq,
00880                                  sizeof mreq) == -1)
00881         {
00882           return -1;
00883         }
00884 
00885     }
00886 #else
00887   // Validate addr/if specifications and create addr/if struct.
00888   ip_mreq  mreq;
00889   if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00890     {
00891       return -1;
00892     }
00893   // Tell network device driver to stop reading datagrams with the
00894   // <mcast_addr>.
00895   // Note, this is not IPv6 friendly...
00896   else if (ACE_SOCK::set_option (IPPROTO_IP,
00897                                  IP_DROP_MEMBERSHIP,
00898                                  &mreq,
00899                                  sizeof mreq) == -1)
00900     {
00901       return -1;
00902     }
00903 #endif /* ACE_HAS_IPV6 */
00904 
00905   return 0;
00906 }

int ACE_SOCK_Dgram_Mcast::unsubscribe_ifs ( const ACE_INET_Addr mcast_addr,
const ACE_TCHAR net_if = 0 
) [private]

Unsubscribe from a multicast address on one or more network interface(s).

Definition at line 608 of file SOCK_Dgram_Mcast.cpp.

References ACE_BIT_ENABLED, ACE_NEW_RETURN, ACE_TEXT, ACE_TEXT_CHAR_TO_TCHAR, ACE_TRACE, AF_INET, ACE::get_ip_interfaces(), ACE_Addr::get_type(), and OPT_NULLIFACE_ALL.

Referenced by unsubscribe_i().

00610 {
00611   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_ifs");
00612 
00613 
00614   if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
00615       && net_if == 0)
00616     {
00617 #if defined (ACE_HAS_IPV6)
00618       if (mcast_addr.get_type () == AF_INET6)
00619         {
00620           size_t nr_unsubscribed = 0;
00621 # if defined(__linux__)
00622 
00623           struct if_nameindex *intf;
00624 
00625           intf = ACE_OS::if_nameindex ();
00626 
00627           if (intf == 0)
00628             return -1;
00629 
00630           int index = 0;
00631           while (intf[index].if_index != 0 || intf[index].if_name != 0)
00632             {
00633               if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(intf[index].if_name)) == 0)
00634                 ++nr_unsubscribed;
00635 
00636               ++index;
00637             }
00638 
00639           ACE_OS::if_freenameindex (intf);
00640 
00641 # elif defined (ACE_WIN32)
00642 
00643           IP_ADAPTER_ADDRESSES tmp_addrs;
00644           // Initial call to determine actual memory size needed
00645           DWORD dwRetVal;
00646           ULONG bufLen = 0;
00647           if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00648                                                   0,
00649                                                   0,
00650                                                   &tmp_addrs,
00651                                                   &bufLen)) != ERROR_BUFFER_OVERFLOW)
00652             return -1; // With output bufferlength 0 this can't be right.
00653 
00654           // Get required output buffer and retrieve info for real.
00655           PIP_ADAPTER_ADDRESSES pAddrs;
00656           char *buf;
00657           ACE_NEW_RETURN (buf,
00658                           char[bufLen],
00659                           -1);
00660           pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
00661           if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00662                                                   0,
00663                                                   0,
00664                                                   pAddrs,
00665                                                   &bufLen)) != NO_ERROR)
00666             {
00667               delete[] buf; // clean up
00668               return -1;
00669             }
00670 
00671           while (pAddrs)
00672             {
00673               if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
00674                 ++nr_unsubscribed;
00675 
00676               pAddrs = pAddrs->Next;
00677             }
00678 
00679           delete[] buf; // clean up
00680 
00681 # endif /* ACE_WIN32 */
00682 
00683           if (nr_unsubscribed == 0)
00684             {
00685               errno = ENODEV;
00686               return -1;
00687             }
00688 
00689           return 1;
00690 
00691 
00692         }
00693       else
00694         {
00695           // Unsubscribe on all local multicast-capable network interfaces, by
00696           // doing recursive calls with specific interfaces.
00697 
00698           ACE_INET_Addr *if_addrs = 0;
00699           size_t if_cnt;
00700 
00701           // NOTE - <get_ip_interfaces> doesn't always get all of the
00702           // interfaces.  In particular, it may not get a PPP interface.  This
00703           // is a limitation of the way <get_ip_interfaces> works with
00704           // old versions of MSVC.  The reliable way of getting the interface
00705           // list is available only with MSVC 5 and newer.
00706           if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00707             return -1;
00708 
00709           size_t nr_unsubscribed = 0;
00710 
00711           if (if_cnt < 2)
00712             {
00713               if (this->leave (mcast_addr,
00714                                ACE_TEXT ("0.0.0.0")) == 0)
00715                 ++nr_unsubscribed;
00716             }
00717           else
00718             {
00719               while (if_cnt > 0)
00720                 {
00721                   --if_cnt;
00722                   // Convert to 0-based for indexing, next loop check
00723                   if (if_addrs[if_cnt].get_type () != AF_INET || if_addrs[if_cnt].is_loopback ())
00724                     continue;
00725                   if (this->leave (mcast_addr,
00726                                    ACE_TEXT_CHAR_TO_TCHAR
00727                                    (if_addrs[if_cnt].get_host_addr ())) == 0)
00728                     ++nr_unsubscribed;
00729                 }
00730             }
00731 
00732           delete [] if_addrs;
00733 
00734           if (nr_unsubscribed == 0)
00735             {
00736               errno = ENODEV;
00737               return -1;
00738             }
00739 
00740           return 1;
00741 
00742         }
00743 #else /* ACE_HAS_IPV6 */
00744       // Unsubscribe on all local multicast-capable network interfaces, by
00745       // doing recursive calls with specific interfaces.
00746 
00747       ACE_INET_Addr *if_addrs = 0;
00748       size_t if_cnt;
00749 
00750       // NOTE - <get_ip_interfaces> doesn't always get all of the
00751       // interfaces.  In particular, it may not get a PPP interface.  This
00752       // is a limitation of the way <get_ip_interfaces> works with
00753       // old versions of MSVC.  The reliable way of getting the interface list
00754       // is available only with MSVC 5 and newer.
00755       if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00756         return -1;
00757 
00758       size_t nr_unsubscribed = 0;
00759 
00760       if (if_cnt < 2)
00761         {
00762           if (this->leave (mcast_addr,
00763                            ACE_TEXT ("0.0.0.0")) == 0)
00764             ++nr_unsubscribed;
00765         }
00766       else
00767         {
00768           while (if_cnt > 0)
00769             {
00770               --if_cnt;
00771               // Convert to 0-based for indexing, next loop check
00772               if (if_addrs[if_cnt].is_loopback ())
00773                 continue;
00774               if (this->leave (mcast_addr,
00775                                ACE_TEXT_CHAR_TO_TCHAR
00776                                (if_addrs[if_cnt].get_host_addr ())) == 0)
00777                 ++nr_unsubscribed;
00778             }
00779         }
00780 
00781       delete [] if_addrs;
00782 
00783       if (nr_unsubscribed == 0)
00784         {
00785           errno = ENODEV;
00786           return -1;
00787         }
00788 
00789       return 1;
00790 #endif /* !ACE_HAS_IPV6 */
00791     }
00792 
00793   return 0;
00794 }


Member Data Documentation

ACE_SOCK_Dgram_Mcast::ACE_ALLOC_HOOK_DECLARE

Declare the dynamic allocation hooks.

Reimplemented from ACE_SOCK_Dgram.

Definition at line 319 of file SOCK_Dgram_Mcast.h.

int ACE_SOCK_Dgram_Mcast::opts_ [private]

Per-instance options..

Definition at line 358 of file SOCK_Dgram_Mcast.h.

ACE_INET_Addr ACE_SOCK_Dgram_Mcast::send_addr_ [private]

Multicast address to which local <send> methods send datagrams.

Definition at line 361 of file SOCK_Dgram_Mcast.h.

Referenced by join(), and open_i().

ACE_TCHAR* ACE_SOCK_Dgram_Mcast::send_net_if_ [private]

Network interface to which all <send> methods send multicast datagrams.

Definition at line 363 of file SOCK_Dgram_Mcast.h.

Referenced by open_i(), and ~ACE_SOCK_Dgram_Mcast().


The documentation for this class was generated from the following files:
Generated on Tue Feb 2 17:35:38 2010 for ACE by  doxygen 1.4.7