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

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_ALL, 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 subscribe (const ACE_INET_Addr &mcast_addr, int reuse_addr=1, const ACE_TCHAR *net_if=0, int protocol_family=PF_INET, int protocol=0)
int join (const ACE_INET_Addr &mcast_addr, int reuse_addr=1, const ACE_TCHAR *net_if=0)
int unsubscribe (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if=0, int protocol_family=PF_INET, int protocol=0)
int leave (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if=0)
int unsubscribe (void)
 Unsubscribe all current subscriptions.

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 methods send datagrams.

ACE_TCHARsend_net_if_
 Network interface to which all 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 and ):

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.
Enumeration values:
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.

Referenced by ACE_SOCK_Dgram_Mcast().

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 or , 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, and options.

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 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 974 of file SOCK_Dgram_Mcast.cpp.

References ACE_GUARD_RETURN, and ACE_TRACE.

Referenced by ~ACE_SOCK_Dgram_Mcast().

00975 {
00976   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::clear_subs_list");
00977   int  result = 0;
00978 
00979 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00980   ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00981                             this->subscription_list_lock_, -1));
00982   subscription_list_iter_t iter (this->subscription_list_);
00983   for (; !iter.done (); /*Hack: Do _not_ ::advance after remove*/)
00984     {
00985       ip_mreq  *pm = iter.next ();
00986       iter.remove ();
00987       delete pm;
00988     }
00989 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00990   return result;
00991 }

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_LIB_TEXT, ACE_NTOHL, ACE_TCHAR, ACE_TRACE, ACE_SDM_helpers::addr_to_string(), LM_DEBUG, MAXNAMELEN, OPT_BINDADDR_YES, OPT_NULLIFACE_ALL, 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_LIB_TEXT ("\nOptions: bindaddr=%s, nulliface=%s\n"),
00080               ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES) ?
00081                 ACE_LIB_TEXT ("<Bound>") : ACE_LIB_TEXT ("<Not Bound>"),
00082               ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL) ?
00083                 ACE_LIB_TEXT ("<All Ifaces>") : ACE_LIB_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_LIB_TEXT ("Send addr=%s iface=%s\n"),
00090               addr_string,
00091               this->send_net_if_ ? this->send_net_if_
00092                                  : ACE_LIB_TEXT ("<default>")));
00093 
00094   // Show list of subscribed addresses.
00095   ACE_DEBUG ((LM_DEBUG, ACE_LIB_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_LIB_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_LIB_TEXT ("<default>"));
00119 
00120       // Dump info.
00121       ACE_DEBUG ((LM_DEBUG,
00122                   ACE_LIB_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
 

Definition at line 482 of file SOCK_Dgram_Mcast.cpp.

References ACE_BIT_ENABLED, ACE_ERROR, ACE_GUARD_RETURN, ACE_LIB_TEXT, ACE_TCHAR, ACE_TRACE, ACE_SDM_helpers::addr_to_string(), ENXIO, ACE_INET_Addr::get_port_number(), ACE_INET_Addr::is_any(), LM_ERROR, ACE_SOCK_Dgram::make_multicast_ifaddr(), MAXNAMELEN, OPT_BINDADDR_YES, send_addr_, ACE_INET_Addr::set_port_number(), and subscribe_i().

Referenced by subscribe(), and subscribe_ifs().

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

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

Definition at line 843 of file SOCK_Dgram_Mcast.cpp.

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

Referenced by unsubscribe(), and unsubscribe_ifs().

00845 {
00846   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::leave");
00847   // Unsubscribe.
00848   int result = this->unsubscribe_i (mcast_addr,
00849                                     net_if);
00850 
00851 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00852   // (Unconditionally) Remove this addr/if from subscription list.
00853   // (Addr/if is removed even if unsubscribe failed)
00854   ip_mreq  tgt_mreq;
00855   if (this->make_multicast_ifaddr (&tgt_mreq,
00856                                    mcast_addr,
00857                                    net_if) != -1)
00858     {
00859       ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00860                                 this->subscription_list_lock_, -1));
00861       subscription_list_iter_t iter (this->subscription_list_);
00862       for (; !iter.done (); iter.advance ())
00863         {
00864           ip_mreq  *pm = iter.next ();
00865           if (ACE_SDM_helpers::is_equal (*pm, tgt_mreq))
00866             {
00867               iter.remove ();
00868               delete pm;
00869               break;
00870             }
00871         }
00872     }
00873 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00874 
00875   return result >= 0 ? 0 : result;
00876 }

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 , using the subscribed address/port# and network interface paramters. The 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 parameter != 0, it defines the network interface used for all sends by this instance, otherwise the system "default" interface is used. (The parameter is ignored if this feature is not supported by the envriornment.) The port# in may be 0, in which case a system-assigned (ephemeral) port# is used for sending and receiving. If != 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_TCHAR, ACE_TRACE, ACE_IPC_SAP::get_handle(), ACE_Addr::get_type(), ACE_SOCK::open(), and open_i().

Referenced by subscribe_i().

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_TCHAR, ACE_TRACE, ACE_SOCK::get_local_addr(), ACE_INET_Addr::get_port_number(), ACE_Addr::get_type(), OPT_BINDADDR_YES, send_addr_, send_net_if_, ACE_INET_Addr::set(), ACE_SOCK_Dgram::set_nic(), ACE_SOCK::set_option(), ACE_INET_Addr::set_port_number(), ACE_SOCK_Dgram::shared_open(), 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 , using the multicast address and network interface defined by the first or .

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 bytes in , using the multicast address and network interface defined by the first or .

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, ACE_IPC_SAP::get_handle(), ACE_Addr::get_type(), send_addr_, 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 const ACE_INET_Addr mcast_addr,
int  reuse_addr = 1,
const ACE_TCHAR net_if = 0,
int  protocol_family = PF_INET,
int  protocol = 0
 

The given group is joined on the specified interface. If option OPT_NULLIFACE_ALL is used and 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 , and was not previously invoked, will be invoked using for binding the socket and as the interface for .

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 or ), 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, is NULL, and <ACE_Sock_Connect::get_ip_interfaces> is not implemented in this environment.

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

Deprecated:
This method has been deprecated, please use join() instead. In addition, the following parameters have also been deprecated: and have no effect.

Definition at line 467 of file SOCK_Dgram_Mcast.cpp.

References ACE_TCHAR, ACE_TRACE, and join().

Referenced by subscribe_ifs().

00472 {
00473   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe");
00474 
00475   ACE_UNUSED_ARG (protocol_family);
00476   ACE_UNUSED_ARG (protocol);
00477 
00478   return this->join (mcast_addr,reuse_addr, net_if);
00479 }

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 565 of file SOCK_Dgram_Mcast.cpp.

References ACE_TCHAR, ACE_TRACE, ACE_Addr::get_type(), IP_ADD_MEMBERSHIP, ACE_SOCK_Dgram::make_multicast_ifaddr(), ACE_SOCK_Dgram::make_multicast_ifaddr6(), open(), ACE_SOCK::set_option(), and subscribe_ifs().

Referenced by join().

00568 {
00569   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_i");
00570   ip_mreq  mreq;
00571 #if defined (ACE_HAS_IPV6)
00572   ipv6_mreq mreq6;
00573 #endif /* __linux__ && ACE_HAS_IPV6 */
00574 
00575   // Open the socket IFF this is the first ::subscribe and ::open
00576   // was not explicitly invoked.
00577   if (this->open (mcast_addr,
00578                   net_if,
00579                   reuse_addr) == -1)
00580     return -1;
00581 
00582   // Only do this if net_if == 0, i.e., INADDR_ANY
00583   if (net_if == 0)
00584     {
00585       int result = this->subscribe_ifs (mcast_addr,
00586                                         net_if,
00587                                         reuse_addr);
00588       // Check for error or "short-circuit" return.
00589       if (result != 0)
00590         return result;
00591     }
00592 
00593 #if defined (ACE_HAS_IPV6)
00594   if (mcast_addr.get_type () == AF_INET6)
00595     {
00596       if (this->make_multicast_ifaddr6 (&mreq6, mcast_addr, net_if) == -1)
00597         return -1;
00598       // Tell IP stack to pass messages sent to this group.
00599       else if (this->ACE_SOCK::set_option (IPPROTO_IPV6,
00600                                            IPV6_JOIN_GROUP,
00601                                            &mreq6,
00602                                            sizeof mreq6) == -1)
00603         return -1;
00604     }
00605   else
00606     {
00607       // Create multicast addr/if struct.
00608       if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00609         return -1;
00610       // Tell IP stack to pass messages sent to this group.
00611       else if (this->ACE_SOCK::set_option (IPPROTO_IP,
00612                                            IP_ADD_MEMBERSHIP,
00613                                            &mreq,
00614                                            sizeof mreq) == -1)
00615         return -1;
00616 
00617     }
00618 #else
00619   if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00620     return -1;
00621   // Tell IP stack to pass messages sent to this group.
00622   // Note, this is not IPv6 compliant.
00623   else if (this->ACE_SOCK::set_option (IPPROTO_IP,
00624                                        IP_ADD_MEMBERSHIP,
00625                                        &mreq,
00626                                        sizeof mreq) == -1)
00627     return -1;
00628 
00629 #endif /* ACE_HAS_IPV6 */
00630 
00631   return 0;
00632 }

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_LIB_TEXT, ACE_NEW_RETURN, ACE_TCHAR, ACE_TEXT_CHAR_TO_TCHAR, ACE_TRACE, ACE::get_ip_interfaces(), ACE_Addr::get_type(), ACE_INET_Addr::is_loopback(), join(), ACE_SOCK_Dgram::make_multicast_ifaddr(), ACE_SOCK_Dgram::make_multicast_ifaddr6(), OPT_NULLIFACE_ALL, and subscribe().

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                                                   NULL,
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                                                   NULL,
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->subscribe (mcast_addr,
00351                                    reuse_addr,
00352                                    ACE_LIB_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->subscribe (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->subscribe (mcast_addr,
00402                                reuse_addr,
00403                                ACE_LIB_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->subscribe (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 void   ) 
 

Unsubscribe all current subscriptions.

Unsubscribe all active group/interface subscriptions (if any).

Returns -1 if any unsubscribe failed, 0 if there are no errors or no current subscriptions.

Deprecated:
This method has been deprecated. Since a list of groups is not maintained (except when ACE_SOCK_DGRAM_MCAST_DUMPABLE is defined), it isn't possible to unsubscribe to all the groups without closing the socket. Therefore, if applications wish to unsubscribe to all groups without closing the socket, they much keep track of the subscriptions and call the above unsubscribe () for each.

Definition at line 954 of file SOCK_Dgram_Mcast.cpp.

References ACE_ERROR_RETURN, ACE_LIB_TEXT, ACE_TRACE, and LM_INFO.

00955 {
00956   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe");
00957 
00958   // Can't implement this reliably without keeping an expensive list,
00959   // and can't close the socket since the caller may want to continue
00960   // using the socket to send() or join() new groups.  Even if we
00961   // wanted to be clever and reopen the socket, we'd need to know what
00962   // options had been set, and reset them--and we have no way of doing
00963   // that either. :-(
00964   // Should this return -1?
00965   ACE_ERROR_RETURN ((LM_INFO,
00966                      ACE_LIB_TEXT ("ACE_SOCK_Dgram_Mcast::unsubscribe (void) ")
00967                      ACE_LIB_TEXT ("has been deprecated. You must either ")
00968                      ACE_LIB_TEXT ("close to socket to unsubscribe to all ")
00969                      ACE_LIB_TEXT ("or unsubscribe to each individually.\n")),
00970                      0);
00971 }

int ACE_SOCK_Dgram_Mcast::unsubscribe const ACE_INET_Addr mcast_addr,
const ACE_TCHAR net_if = 0,
int  protocol_family = PF_INET,
int  protocol = 0
 

The specified group/interface combination is unsubscribed. If option OPT_NULLIFACE_ALL is used and 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, is = 0, and <ACE_Sock_Connect::get_ip_interfaces> is not implemented in this environment (_even if_ the specifies a non- NULL ).

Deprecated:
This method has been deprecated. Please use leave() instead. In addition, and have no effect.

Definition at line 829 of file SOCK_Dgram_Mcast.cpp.

References ACE_TCHAR, ACE_TRACE, and leave().

00833 {
00834   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe");
00835 
00836   ACE_UNUSED_ARG (protocol_family);
00837   ACE_UNUSED_ARG (protocol);
00838 
00839   return this->leave (mcast_addr, net_if);
00840 }

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 880 of file SOCK_Dgram_Mcast.cpp.

References ACE_TCHAR, ACE_TRACE, ACE_Addr::get_type(), IP_DROP_MEMBERSHIP, ACE_SOCK_Dgram::make_multicast_ifaddr(), ACE_SOCK_Dgram::make_multicast_ifaddr6(), ACE_SOCK::set_option(), and unsubscribe_ifs().

Referenced by leave().

00882 {
00883   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_i");
00884 
00885   int result = this->unsubscribe_ifs (mcast_addr,
00886                                       net_if);
00887 
00888   // Check for error or "short-circuit" return.
00889   if (result != 0)
00890     return result;
00891 
00892 #if defined (ACE_HAS_IPV6)
00893   if (mcast_addr.get_type () == AF_INET6)
00894     {
00895       // Validate addr/if specifications and create addr/if struct.
00896       ipv6_mreq  mreq;
00897       if (this->make_multicast_ifaddr6 (&mreq, mcast_addr, net_if) == -1)
00898         {
00899           return -1;
00900         }
00901       // Tell network device driver to stop reading datagrams with the
00902       // <mcast_addr>.
00903       else if (ACE_SOCK::set_option (IPPROTO_IPV6,
00904                                      IPV6_LEAVE_GROUP,
00905                                      &mreq,
00906                                      sizeof mreq) == -1)
00907         {
00908           return -1;
00909         }
00910 
00911     }
00912   else  // IPv4
00913     {
00914       // Validate addr/if specifications and create addr/if struct.
00915       ip_mreq  mreq;
00916       if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00917         {
00918           return -1;
00919         }
00920       // Tell network device driver to stop reading datagrams with the
00921       // <mcast_addr>.
00922       else if (ACE_SOCK::set_option (IPPROTO_IP,
00923                                      IP_DROP_MEMBERSHIP,
00924                                      &mreq,
00925                                  sizeof mreq) == -1)
00926         {
00927           return -1;
00928         }
00929 
00930     }
00931 #else
00932   // Validate addr/if specifications and create addr/if struct.
00933   ip_mreq  mreq;
00934   if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00935     {
00936       return -1;
00937     }
00938   // Tell network device driver to stop reading datagrams with the
00939   // <mcast_addr>.
00940   // Note, this is not IPv6 friendly...
00941   else if (ACE_SOCK::set_option (IPPROTO_IP,
00942                                  IP_DROP_MEMBERSHIP,
00943                                  &mreq,
00944                                  sizeof mreq) == -1)
00945     {
00946       return -1;
00947     }
00948 #endif /* ACE_HAS_IPV6 */
00949 
00950   return 0;
00951 }

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 635 of file SOCK_Dgram_Mcast.cpp.

References ACE_BIT_ENABLED, ACE_LIB_TEXT, ACE_NEW_RETURN, ACE_TCHAR, ACE_TEXT_CHAR_TO_TCHAR, ACE_TRACE, ACE::get_ip_interfaces(), ACE_Addr::get_type(), ACE_INET_Addr::is_loopback(), leave(), and OPT_NULLIFACE_ALL.

Referenced by unsubscribe_i().

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


Member Data Documentation

ACE_SOCK_Dgram_Mcast::ACE_ALLOC_HOOK_DECLARE
 

Declare the dynamic allocation hooks.

Reimplemented from ACE_SOCK_Dgram.

Definition at line 352 of file SOCK_Dgram_Mcast.h.

int ACE_SOCK_Dgram_Mcast::opts_ [private]
 

Per-instance options..

Definition at line 391 of file SOCK_Dgram_Mcast.h.

ACE_INET_Addr ACE_SOCK_Dgram_Mcast::send_addr_ [private]
 

Multicast address to which local methods send datagrams.

Definition at line 394 of file SOCK_Dgram_Mcast.h.

Referenced by join(), open_i(), and set_option().

ACE_TCHAR* ACE_SOCK_Dgram_Mcast::send_net_if_ [private]
 

Network interface to which all methods send multicast datagrams.

Definition at line 396 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 Thu Nov 9 11:29:52 2006 for ACE by doxygen 1.3.6