SOCK_Dgram_Mcast.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //=============================================================================
00004 /**
00005  *  @file    SOCK_Dgram_Mcast.h
00006  *
00007  *  SOCK_Dgram_Mcast.h,v 4.59 2006/01/25 19:52:56 jwillemsen Exp
00008  *
00009  *  @author Irfan Pyrali <irfan@cs.wustl.edu>
00010  *  @author Tim Harrison <harrison@cs.wustl.edu>
00011  *  @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
00012  *  @author Bill Fulton <bill_a_fulton@raytheon.com>
00013  *  @author Don Hinton <dhinton@objectsciences.com>
00014  */
00015 //=============================================================================
00016 
00017 #ifndef ACE_SOCK_DGRAM_MCAST_H
00018 #define ACE_SOCK_DGRAM_MCAST_H
00019 
00020 #include /**/ "ace/pre.h"
00021 
00022 #include "ace/ACE_export.h"
00023 
00024 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00025 # pragma once
00026 #endif /* ACE_LACKS_PRAGMA_ONCE */
00027 
00028 #include "ace/SOCK_Dgram.h"
00029 #include "ace/INET_Addr.h"
00030 
00031 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00032 # include "ace/Containers_T.h"
00033 # include "ace/Synch_Traits.h"
00034 # include "ace/Thread_Mutex.h"
00035 # if !defined (ACE_SDM_LOCK)
00036 #  define ACE_SDM_LOCK ACE_SYNCH_MUTEX
00037 # endif /* ACE_SDM_LOCK */
00038 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00039 
00040 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00041 
00042 /**
00043  * @class ACE_SOCK_Dgram_Mcast
00044  *
00045  * @brief Defines the ACE socket wrapper for UDP/IP multicast.
00046  *
00047  * Supports multiple simultaneous subscriptions, unsubscription from one or
00048  * all subscriptions, and independent send/recv address and interface
00049  * specifications.  Template parameters and/or ctor arguments determine
00050  * per-instance optional functionality.
00051  *
00052  * Note that multicast semantics and implementation details are _very_
00053  * environment-specific; this class is just a wrapper around the underlying
00054  * implementation and does not try to normalize the concept of multicast
00055  * communications.
00056  *
00057  * Usage Notes:
00058  * - Send and Recv addresses and network interfaces, but not port#, are
00059  *   independent.  While this instance is open, 1 send interface (and a default
00060  *   send address) is in effect and 0, 1, or multiple recv addresses/interfaces
00061  *   are in effect.
00062  * - The first <open>/<subscribe> invocation defines the network interface
00063  *   and default address used for all sends by this instance, defines the
00064  *   port# and optionally the multicast address bound to the underlying
00065  *   socket, and defines the (one) port# that is used for all subscribes
00066  *   (subsequent subscribes must pass the same port# or '0').
00067  * - The default loopback state is not explicitly set; the environment will
00068  *   determine the default state.  Note that some environments (e.g. some Win32)
00069  *   do not allow the default to be changed, and that the semantics of
00070  *   loopback control are environment dependent (e.g. sender vs receiver
00071  *   control).
00072  * - In general, due to multicast design and implementation quirks/bugs, it is
00073  *   difficult to tell which address a received message was sent to or which
00074  *   interface it was received on (even if only one subscription is active).
00075  *   However; there are filtering options that can be applied, to narrow it
00076  *   down considerably.
00077  *
00078  * Interface specification notes (for <subscribe> and <unsubscribe>):
00079  * - If net_if == 0, the null_iface_opt option determines whether only the
00080  *   system "default" interface or all interfaces is affected.  Specifying
00081  *   "all" interfaces is supported only for environments for which
00082  *   <ACE_Sock_Connect::get_ip_interfaces> is properly implemented.
00083  * - Multiple subscriptions for the same address but different interfaces is
00084  *   normally supported, but re-subscription to an address/interface that is
00085  *   already subscribed is normally not allowed.
00086  * - The <net_if> interface specification syntax is environment-specific.
00087  *   UNIX systems will normally use device specifications such as "le0" or
00088  *   "elxl1", while other systems will use the IP address of the interface.
00089  *   Some platforms, such as pSoS, support only cardinal numbers as network
00090  *   interface specifications; for these platforms, just give these numbers in
00091  *   alphanumeric form and <subscribe> will convert them into numbers via
00092  *   <ACE_OS::atoi>.
00093  */
00094 class ACE_Export ACE_SOCK_Dgram_Mcast : public ACE_SOCK_Dgram
00095 {
00096 public:
00097 
00098   /**
00099    * @brief Option parameters.
00100    *
00101    * These control per-instance optional functionality.  They are set via
00102    * optional constructor arguments.
00103    * @note Certain option values are not valid for all environments (see
00104    * comments in source file for environment-specific restrictions).  Default
00105    * values are always valid values for the compilation environment.
00106    */
00107   enum options
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   };
00179 
00180   // = Initialization routines.
00181 
00182   /// Ctor - Create an unitialized instance and define per-instance optional
00183   /// functionality.
00184   /**
00185    * You must invoke <open> or <subscribe>, to create/bind a socket and define
00186    * operational parameters, before performing any I/O with this instance.
00187    */
00188   ACE_SOCK_Dgram_Mcast (options opts = DEFOPTS);
00189 
00190   /// Dtor - Release all resources and implicitly or explicitly unsubscribe
00191   /// from all currently subscribed groups.
00192   /**
00193    * The OPT_DTORUNSUB_YES_ option defines whether an explicit <unsusbcribe> is
00194    * done by the destructor.  If not, most systems will automatically
00195    * unsubscribe upon the close of the socket.
00196    */
00197   ~ACE_SOCK_Dgram_Mcast (void);
00198 
00199   /// Explicitly open/bind the socket and define the network interface
00200   /// and default multicast address used for sending messages.
00201   /**
00202    * This method is optional; if not explicitly invoked, it is invoked by
00203    * the first <subscribe>, using the subscribed address/port# and network
00204    * interface paramters.
00205    * The <mcast_addr> parameter defines the default send address/port# and
00206    * also the port# and, if the OPT_BINDADDR_YES option is used,
00207    * the multicast address that is bound to this socket.
00208    * If the <send_net_if> parameter != 0, it defines the network interface
00209    * used for all sends by this instance, otherwise the system "default"
00210    * interface is used. (The <send_net_if> parameter is ignored if this
00211    * feature is not supported by the envriornment.)
00212    * The port# in <mcast_addr> may be 0, in which case a system-assigned
00213    * (ephemeral) port# is used for sending and receiving.
00214    * If <reuse_addr> != 0, the SO_REUSEADDR option and, if it is supported,
00215    * the SO_REUSEPORT option are enabled.
00216    *
00217    * Returns: -1 if the call fails.  Failure can occur due to problems with
00218    * the address, port#, and/or interface parameters or during system open()
00219    * or socket option processing.
00220    */
00221   int open (const ACE_INET_Addr &mcast_addr,        // Bound & sendto address.
00222             const ACE_TCHAR *net_if = 0,            // Net interface for sends.
00223             int reuse_addr = 1);                    // Reuse addr/port sock opt.
00224 
00225   // = Multicast group subscribe/unsubscribe routines.
00226 
00227   /// Join a multicast group on a given interface (or all interfaces, if
00228   /// supported).
00229   /**
00230    * The given group is joined on the specified interface.  If option
00231    * OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is joined on
00232    * all multicast capable interfaces (IFF supported).  Multiple subscriptions
00233    * to various address and interface combinations are supported and tracked.
00234    * If this is the first invocation of <subscribe>, and <open> was not
00235    * previously invoked, <open> will be invoked using <mcast_addr> for binding
00236    * the socket and <net_if> as the interface for <send>.
00237    *
00238    * Returns: -1 if the call fails.  Failure can occur due to problems with
00239    * the address, port#, and/or interface parameters or during the subscription
00240    * attempt.  Once bind() has been invoked (by the first <open> or
00241    * <subscribe>), returns errno of ENXIO if the port# is not 0 and does not
00242    * match the bound port#, or if OPT_BINDADDR_YES option is used
00243    * and the address does not match the bound address.  Returns errno of
00244    * ENODEV if the addr/port#/interface parameters appeared valid, but no
00245    * subscription(s) succeeded.  An error is unconditionally returned if
00246    * option OPT_NULLIFACE_ALL is used, <net_if> is NULL, and
00247    * <ACE_Sock_Connect::get_ip_interfaces> is not implemented in this
00248    * environment.
00249    *
00250    * Note that the optional <reuse_addr> parameter does not apply to
00251    * subscriptions; it is only used if <open> is implicitly invoked (see above).
00252    *
00253    * @deprecated This method has been deprecated, please use join() instead.
00254    * In addition, the following parameters have also been deprecated:
00255    * <protocol_family> and <protocol> have no effect.
00256    */
00257   int subscribe (const ACE_INET_Addr &mcast_addr,
00258                  int reuse_addr = 1,               // (see above)
00259                  const ACE_TCHAR *net_if = 0,
00260                  int protocol_family = PF_INET,
00261                  int protocol = 0);
00262 
00263   // join() replaces subscribe() and uses the mcast_addr to determine
00264   // protocol_family, and protocol which we always pass as 0 anyway.
00265   int join (const ACE_INET_Addr &mcast_addr,
00266             int reuse_addr = 1,               // (see above)
00267             const ACE_TCHAR *net_if = 0);
00268 
00269 
00270   /// Leave a multicast group on a given interface (or all interfaces, if
00271   /// supported).
00272   /**
00273    * The specified group/interface combination is unsubscribed.  If option
00274    * OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is unsubscribed
00275    * from all interfaces (IFF supported).
00276    *
00277    * Returns: -1 if the unsubscribe failed. Most environments will return -1
00278    * if there was no active subscription for this address/interface combination.
00279    * An error is unconditionally returned if option OPT_NULLIFACE_ALL is used,
00280    * <net_if> is = 0, and <ACE_Sock_Connect::get_ip_interfaces> is not
00281    * implemented in this environment (_even if_ the <subscribe> specifies a
00282    * non- NULL <net_if>).
00283    *
00284    * @deprecated This method has been deprecated.  Please use leave() instead.
00285    * In addition, <protocol_family> and <protocol> have no effect.
00286    */
00287   int unsubscribe (const ACE_INET_Addr &mcast_addr,
00288                    const ACE_TCHAR *net_if = 0,
00289                    int protocol_family = PF_INET,
00290                    int protocol = 0);
00291 
00292   // leave() replaces unsubscribe() and uses mcast_addr to determine
00293   // protocol_family, and protocol which we always pass as 0 anyway.
00294   int leave (const ACE_INET_Addr &mcast_addr,
00295              const ACE_TCHAR *net_if = 0);
00296 
00297   /// Unsubscribe all current subscriptions.
00298   /**
00299    * Unsubscribe all active group/interface subscriptions (if any).
00300    *
00301    * Returns -1 if any unsubscribe failed, 0 if there are no errors or no
00302    * current subscriptions.
00303    *
00304    * @deprecated This method has been deprecated.  Since a list of groups is
00305    * not maintained (except when ACE_SOCK_DGRAM_MCAST_DUMPABLE is defined),
00306    * it isn't possible to unsubscribe to all the groups without closing
00307    * the socket.  Therefore, if applications wish to unsubscribe to all
00308    * groups without closing the socket, they much keep track of the
00309    * subscriptions and call the above unsubscribe () for each.
00310    */
00311   int unsubscribe (void);
00312 
00313   // = Data transfer routines.
00314 
00315   /// Send <n> bytes in <buf>, using the multicast address and network interface
00316   /// defined by the first <open> or <subscribe>.
00317   ssize_t send (const void *buf,
00318                 size_t n,
00319                 int flags = 0) const;
00320 
00321   /// Send <n> <iovecs>, using the multicast address and network interface
00322   /// defined by the first <open> or <subscribe>.
00323   ssize_t send (const iovec iov[],
00324                 int n,
00325                 int flags = 0) const;
00326 
00327   // = Options.
00328 
00329   /// Set a socket option.
00330   /**
00331    * Set an IP option that takes a char as input, such as IP_MULTICAST_LOOP
00332    * or IP_MULTICAST_TTL.  This is just a more concise, nice interface to a
00333    * subset of possible ACE_SOCK::set_option calls, but only works for
00334    * IPPROTO_IP or IPPROTO_IPV6 level options.
00335    *
00336    * Returns 0 on success, -1 on failure.
00337    *
00338    * @deprecated  This method has been deprecated since it cannot be used
00339    * easily with with IPv6 options. Use ACE_SOCK::set_option instead.
00340    */
00341   int set_option (int option,
00342                   char optval);
00343 
00344   /// Dump the state of an object.
00345   /**
00346    * Logs the setting of all options, the bound address, the send address and
00347    * interface, and the list of current subscriptions.
00348    */
00349   void dump (void) const;
00350 
00351   /// Declare the dynamic allocation hooks.
00352   ACE_ALLOC_HOOK_DECLARE;
00353 
00354 private:
00355 
00356   /// Subscribe to a multicast address on one or more network interface(s).
00357   /// (No QoS support.)
00358   int subscribe_ifs (const ACE_INET_Addr &mcast_addr,
00359                      const ACE_TCHAR *net_if,
00360                      int reuse_addr);
00361 
00362   /// Do subscription processing w/out updating the subscription list.
00363   // (Layered method for <subscribe> processing).
00364   int subscribe_i (const ACE_INET_Addr &mcast_addr,
00365                    int reuse_addr = 1,
00366                    const ACE_TCHAR *net_if = 0);
00367 
00368   /// Unsubscribe from a multicast address on one or more network interface(s).
00369   int unsubscribe_ifs (const ACE_INET_Addr &mcast_addr,
00370                        const ACE_TCHAR *net_if = 0);
00371 
00372   /// Do unsubscription processing w/out udpating subscription list.
00373   //  (Layered method for <unsubscribe> processing).
00374   int unsubscribe_i (const ACE_INET_Addr &mcast_addr,
00375                      const ACE_TCHAR *net_if = 0);
00376 
00377 protected:
00378 
00379   /// Contains common open functionality so that inheriting classes can
00380   /// reuse it.
00381   int open_i (const ACE_INET_Addr &mcast_addr,        // Bound & sendto address.
00382               const ACE_TCHAR *net_if = 0,            // Net interface for sends.
00383               int reuse_addr = 1);
00384 
00385   /// Empty the dynamic subscription list.
00386   int clear_subs_list (void);
00387 
00388 private:
00389 
00390   /// Per-instance options..
00391   int opts_;
00392 
00393   /// Multicast address to which local <send> methods send datagrams.
00394   ACE_INET_Addr  send_addr_;
00395   /// Network interface to which all <send> methods send multicast datagrams.
00396   ACE_TCHAR *send_net_if_;
00397 
00398 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00399  typedef ACE_DLList<ip_mreq>  subscription_list_t;
00400  typedef ACE_DLList_Iterator<ip_mreq>  subscription_list_iter_t;
00401  /// List of currently subscribed addr/iface pairs (and assc. types).
00402  mutable subscription_list_t  subscription_list_;
00403  /// Lock used to protect subscription list.
00404  mutable ACE_SDM_LOCK subscription_list_lock_;
00405      // (Lock type does not need to support recursive locking.)
00406 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00407 
00408 };
00409 
00410 ACE_END_VERSIONED_NAMESPACE_DECL
00411 
00412 #if defined (__ACE_INLINE__)
00413 #include "ace/SOCK_Dgram_Mcast.inl"
00414 #endif /* __ACE_INLINE__ */
00415 
00416 #include /**/ "ace/post.h"
00417 #endif /* ACE_SOCK_DGRAM_MCAST_H */

Generated on Thu Nov 9 09:42:04 2006 for ACE by doxygen 1.3.6