Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

SOCK_Dgram_Mcast.h

Go to the documentation of this file.
00001 /* -*- C++ -*- */
00002 
00003 //=============================================================================
00004 /**
00005  *  @file    SOCK_Dgram_Mcast.h
00006  *
00007  *  $Id: SOCK_Dgram_Mcast.h,v 1.1.1.4 2003/02/21 18:36:32 chad 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 and Don Hinton <dhinton@objectsciences.com>
00014  */
00015 //=============================================================================
00016 
00017 
00018 #ifndef ACE_SOCK_DGRAM_MCAST_H
00019 #define ACE_SOCK_DGRAM_MCAST_H
00020 #include "ace/pre.h"
00021 
00022 #include "ace/SOCK_Dgram.h"
00023 
00024 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00025 # pragma once
00026 #endif /* ACE_LACKS_PRAGMA_ONCE */
00027 
00028 #include "ace/INET_Addr.h"
00029 
00030 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00031 # include "ace/Containers_T.h"
00032 # include "ace/Synch_T.h"
00033 # if !defined (ACE_SDM_LOCK)
00034 #  define ACE_SDM_LOCK ACE_SYNCH_MUTEX
00035 # endif /* ACE_SDM_LOCK */
00036 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00037 
00038 /**
00039  * @class ACE_SOCK_Dgram_Mcast
00040  *
00041  * @brief Defines the ACE socket wrapper for UDP/IP multicast.
00042  *
00043  * Supports multiple simultaneous subscriptions, unsubscription from one or
00044  * all subscriptions, and independent send/recv address and interface
00045  * specifications.  Template parameters and/or ctor arguments determine
00046  * per-instance optional functionality.
00047  *
00048  * Note that multicast semantics and implementation details are _very_
00049  * environment-specific; this class is just a wrapper around the underlying
00050  * implementation and does not try to normalize the concept of multicast
00051  * communications.
00052  *
00053  * Usage Notes:
00054  * - Send and Recv addresses and network interfaces, but not port#, are
00055  *   independent.  While this instance is open, 1 send interface (and a default
00056  *   send address) is in effect and 0, 1, or multiple recv addresses/interfaces
00057  *   are in effect.
00058  * - The first <open>/<subscribe> invocation defines the network interface
00059  *   and default address used for all sends by this instance, defines the
00060  *   port# and optionally the multicast address bound to the underlying
00061  *   socket, and defines the (one) port# that is used for all subscribes
00062  *   (subsequent subscribes must pass the same port# or '0').
00063  * - The default loopback state is not explicitly set; the environment will
00064  *   determine the default state.  Note that some environments (e.g. some Win32)
00065  *   do not allow the default to be changed, and that the semantics of
00066  *   loopback control are environment dependent (e.g. sender vs receiver
00067  *   control).
00068  * - In general, due to multicast design and implementation quirks/bugs, it is
00069  *   difficult to tell which address a received message was sent to or which
00070  *   interface it was received on (even if only one subscription is active).
00071  *   However; there are filtering options that can be applied, to narrow it
00072  *   down considerably.
00073  *
00074  * Interface specification notes (for <subscribe> and <unsubscribe>):
00075  * - If net_if == 0, the null_iface_opt option determines whether only the
00076  *   system "default" interface or all interfaces is affected.  Specifying
00077  *   "all" interfaces is supported only for environments for which
00078  *   <ACE_Sock_Connect::get_ip_interfaces> is properly implemented.
00079  * - Multiple subscriptions for the same address but different interfaces is
00080  *   normally supported, but re-subscription to an address/interface that is
00081  *   already subscribed is normally not allowed.
00082  * - The <net_if> interface specification syntax is environment-specific.
00083  *   UNIX systems will normally use device specifications such as "le0" or
00084  *   "elxl1", while other systems will use the IP address of the interface.
00085  *   Some platforms, such as pSoS, support only cardinal numbers as network
00086  *   interface specifications; for these platforms, just give these numbers in
00087  *   alphanumeric form and <subscribe> will convert them into numbers via
00088  *   <ACE_OS::atoi>.
00089  */
00090 class ACE_Export ACE_SOCK_Dgram_Mcast : public ACE_SOCK_Dgram
00091 {
00092 public:
00093 
00094   /**
00095    * @brief Option parameters.
00096    *
00097    * These control per-instance optional functionality.  They are set via
00098    * optional constructor arguments.
00099    * Note: Certain option values are not valid for all environments (see
00100    * comments in source file for environment-specific restrictions).  Default
00101    * values are always valid values for the compilation environment.
00102    */
00103   enum  options
00104   {
00105   // Define whether a specific (multicast) address (in addition to the port#)
00106   // is bound to the socket.
00107   // Notes:
00108   // - Effect of doing this is stack/environment dependent, but in most
00109   //   environments can be used to filter out unwanted unicast, broadcast, and
00110   //   (other) multicast messages sent to the same port#.
00111   // - Some IP stacks (e.g. some Win32) do not support binding multicast
00112   //   addresses.  Using this option will always cause an <open> error.
00113   // - It's not strictly possible for user code to do this level of filtering
00114   //   w/out the bind; some environments support ways to determine which address
00115   //   a message was sent _to_, but this class interface does not support access
00116   //   to that info.
00117   // - The address (and port#) passed to <open> (or the first <subscribe>, if
00118   //   <open> is not explicitly invoked) is the one that is bound.
00119   //
00120     /// Disable address bind. (Bind only port.)
00121     // Note that this might seem odd, but we need a way to distinquish between
00122     // default behavior, which might or might not be to bind, and explicitely
00123     // choosing to bind or not to bind--which "is the question." ;-)
00124     OPT_BINDADDR_NO   = 0,
00125     /// Enable address bind. (Bind port and address.)
00126     OPT_BINDADDR_YES   = 1,
00127     /// Default value for BINDADDR option. (Environment-dependent.)
00128 #if defined (ACE_LACKS_PERFECT_MULTICAST_FILTERING) \
00129     && (ACE_LACKS_PERFECT_MULTICAST_FILTERING == 1)
00130       // Platforms that don't support perfect filtering. Note that perfect
00131       // filtering only really applies to multicast traffic, not unicast 
00132       // or broadcast.
00133       DEFOPT_BINDADDR  = OPT_BINDADDR_YES,
00134 # else
00135       // At least some Win32 OS's can not bind mcast addr, so disable it.
00136       // General-purpose default behavior is 'disabled', since effect is
00137       // environment-specific and side-effects might be surprising.
00138       DEFOPT_BINDADDR  = OPT_BINDADDR_NO,
00139 #endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING = 1) */
00140   //
00141   /// Define the interpretation of 'NULL' as a recv interface specification.
00142   // If the interface part of a multicast address specification is NULL, it
00143   // will be interpreted to mean either "the default interface" or "all
00144   // interfaces", depending on the setting of this option.
00145   // Notes:
00146   // - The 'nulliface_all' option can not be used in environments which do
00147   //   not fully support the <ACE_Sock_Connect::get_ip_interfaces> method
00148   //   (e.g. non-Windows).
00149   //   If it is, using NULL for iface will _always_ fail.
00150   // - The default behavior in most IP stacks is to use the 'default' interface,
00151   //   where 'default' has rather ad-hoc semantics.
00152   // - This applies only to receives, not sends (which always use only one
00153   //   interface; NULL means use the "system default" interface).
00154   // Supported values:
00155     /// If (net_if==NULL), use default interface.
00156     // Note that this might seem odd, but we need a way to distinquish between
00157     // default behavior, which might or might not be to bind, and explicitely
00158     // choosing to bind or not to bind--which "is the question." ;-)
00159     OPT_NULLIFACE_ONE  = 0,
00160     /// If (net_if==NULL), use all mcast interfaces.
00161     OPT_NULLIFACE_ALL  = 2,
00162     /// Default value for NULLIFACE option. (Environment-dependent.)
00163 #ifdef ACE_WIN32
00164       // This is the (ad-hoc) legacy behavior for Win32/WinSock.
00165       // Notice: Older version of WinSock/MSVC may not get all multicast-capable
00166       // interfaces (e.g. PPP interfaces).
00167       DEFOPT_NULLIFACE = OPT_NULLIFACE_ALL,
00168 #else
00169       // General-purpose default behavior (as per legacy behavior).
00170       DEFOPT_NULLIFACE = OPT_NULLIFACE_ONE,
00171 #endif /* ACE_WIN32 */
00172     /// All default options.
00173     DEFOPTS = DEFOPT_BINDADDR | DEFOPT_NULLIFACE
00174   };
00175 
00176   // = Initialization routines.
00177 
00178   /// Ctor - Create an unitialized instance and define per-instance optional
00179   /// functionality.
00180   /**
00181    * You must invoke <open> or <subscribe>, to create/bind a socket and define
00182    * operational parameters, before performing any I/O with this instance.
00183    */
00184   ACE_SOCK_Dgram_Mcast (options opts = DEFOPTS);
00185 
00186   /// Dtor - Release all resources and implicitly or explicitly unsubscribe
00187   /// from all currently subscribed groups.
00188   /**
00189    * The OPT_DTORUNSUB_YES_ option defines whether an explicit <unsusbcribe> is
00190    * done by the destructor.  If not, most systems will automatically
00191    * unsubscribe upon the close of the socket.
00192    */
00193   ~ACE_SOCK_Dgram_Mcast (void);
00194 
00195   /// Explicitly open/bind the socket and define the network interface
00196   /// and default multicast address used for sending messages.
00197   /**
00198    * This method is optional; if not explicitly invoked, it is invoked by
00199    * the first <subscribe>, using the subscribed address/port# and network
00200    * interface paramters.
00201    * The <mcast_addr> parameter defines the default send address/port# and
00202    * also the port# and, if the OPT_BINDADDR_YES option is used,
00203    * the multicast address that is bound to this socket.
00204    * If the <send_net_if> parameter != 0, it defines the network interface
00205    * used for all sends by this instance, otherwise the system "default"
00206    * interface is used. (The <send_net_if> parameter is ignored if this
00207    * feature is not supported by the envriornment.)
00208    * The port# in <mcast_addr> may be 0, in which case a system-assigned
00209    * (ephemeral) port# is used for sending and receiving.
00210    * If <reuse_addr> != 0, the SO_REUSEADDR option and, if it is supported,
00211    * the SO_REUSEPORT option are enabled.
00212    *
00213    * Returns: -1 if the call fails.  Failure can occur due to problems with
00214    * the address, port#, and/or interface parameters or during system open()
00215    * or socket option processing.
00216    */
00217   int open (const ACE_INET_Addr &mcast_addr,        // Bound & sendto address.
00218             const ACE_TCHAR *net_if = 0,            // Net interface for sends.
00219             int reuse_addr = 1);                    // Reuse addr/port sock opt.
00220 
00221   // = Multicast group subscribe/unsubscribe routines.
00222 
00223   /// Join a multicast group on a given interface (or all interfaces, if
00224   /// supported).
00225   /**
00226    * The given group is joined on the specified interface.  If option
00227    * OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is joined on
00228    * all multicast capable interfaces (IFF supported).  Multiple subscriptions
00229    * to various address and interface combinations are supported and tracked.
00230    * If this is the first invocation of <subscribe>, and <open> was not
00231    * previously invoked, <open> will be invoked using <mcast_addr> for binding
00232    * the socket and <net_if> as the interface for <send>.
00233    *
00234    * Returns: -1 if the call fails.  Failure can occur due to problems with
00235    * the address, port#, and/or interface parameters or during the subscription
00236    * attempt.  Once bind() has been invoked (by the first <open> or
00237    * <subscribe>), returns errno of ENXIO if the port# is not 0 and does not
00238    * match the bound port#, or if OPT_BINDADDR_YES option is used
00239    * and the address does not match the bound address.  Returns errno of
00240    * ENODEV if the addr/port#/interface parameters appeared valid, but no
00241    * subscription(s) succeeded.  An error is unconditionally returned if
00242    * option OPT_NULLIFACE_ALL is used, <net_if> is NULL, and 
00243    * <ACE_Sock_Connect::get_ip_interfaces> is not implemented in this
00244    * environment.
00245    *
00246    * Note that the optional <reuse_addr> parameter does not apply to 
00247    * subscriptions; it is only used if <open> is implicitly invoked (see above).
00248    *
00249    * NOTICE - This method has been deprecated, please use join() instead.  In
00250    * addition, the following paramters have also been deprecated: 
00251    * <protocol_family> and <protocol> have no effect. 
00252    */
00253   int subscribe (const ACE_INET_Addr &mcast_addr,
00254                  int reuse_addr = 1,               // (see above)
00255                  const ACE_TCHAR *net_if = 0,
00256                  int protocol_family = PF_INET,    
00257                  int protocol = 0);                
00258 
00259   // join() replaces subscribe() and uses the mcast_addr to determine 
00260   // protocol_family, and protocol which we always pass as 0 anyway.
00261   int join (const ACE_INET_Addr &mcast_addr,
00262             int reuse_addr = 1,               // (see above)
00263             const ACE_TCHAR *net_if = 0);
00264 
00265 
00266   /// Leave a multicast group on a given interface (or all interfaces, if
00267   /// supported).
00268   /**
00269    * The specified group/interface combination is unsubscribed.  If option
00270    * OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is unsubscribed
00271    * from all interfaces (IFF supported).
00272    *
00273    * Returns: -1 if the unsubscribe failed. Most environments will return -1
00274    * if there was no active subscription for this address/interface combination.
00275    * An error is unconditionally returned if option OPT_NULLIFACE_ALL is used,
00276    * <net_if> is = 0, and <ACE_Sock_Connect::get_ip_interfaces> is not
00277    * implemented in this environment (_even if_ the <subscribe> specifies a
00278    * non- NULL <net_if>).
00279    *
00280    * NOTICE - This method has been deprecated.  Please use leave() instead.
00281    * In addition, <protocol_family> and <protocol> have no effect.
00282    */
00283   int unsubscribe (const ACE_INET_Addr &mcast_addr,
00284                    const ACE_TCHAR *net_if = 0,
00285                    int protocol_family = PF_INET,
00286                    int protocol = 0);
00287 
00288   // leave() replaces unsubscribe() and uses mcast_addr to determine 
00289   // protocol_family, and protocol which we always pass as 0 anyway.
00290   int leave (const ACE_INET_Addr &mcast_addr,
00291              const ACE_TCHAR *net_if = 0);
00292 
00293   /// Unsubscribe all current subscriptions.
00294   /**
00295    * Unsubscribe all active group/interface subscriptions (if any).
00296    *
00297    * Returns -1 if any unsubscribe failed, 0 if there are no errors or no
00298    * current subscriptions.
00299    *
00300    * This method has been deprecated.  Since a list of groups is not 
00301    * maintained (except when ACE_SOCK_DGRAM_MCAST_DUMPABLE is defined), 
00302    * it isn't possible to unsubscribe to all the groups without closing 
00303    * the socket.  Therefore, if applications wish to unsubscribe to all
00304    * groups without closing the socket, they much keep track of the 
00305    * subscriptions and call the above unsubscribe () for each.
00306    */
00307   int unsubscribe (void);
00308 
00309   // = Data transfer routines.
00310 
00311   /// Send <n> bytes in <buf>, using the multicast address and network interface
00312   /// defined by the first <open> or <subscribe>.
00313   ssize_t send (const void *buf,
00314                 size_t n,
00315                 int flags = 0) const;
00316 
00317   /// Send <n> <iovecs>, using the multicast address and network interface
00318   /// defined by the first <open> or <subscribe>.
00319   ssize_t send (const iovec iov[],
00320                 int n,
00321                 int flags = 0) const;
00322 
00323   // = Options.
00324 
00325   /// Set a socket option.
00326   /**
00327    * Set an ip option that takes a char as input, such as <IP_MULTICAST_LOOP>
00328    * or <IP_MULTICAST_TTL>.  This is just a more concise, nice interface to a
00329    * subset of possible <ACE_SOCK::set_option> calls, but only works for 
00330    * IPPROTO_IP or IPPROTO_IPV6 level options.  Use <ACE_SOCK::set_option> 
00331    * directly to set anything else. 
00332    * \deprecated { This method has been deprecated since it cannot be used
00333    * easily with with IPv6 options.}
00334    * Returns 0 on success, -1 on failure.
00335    */
00336   int set_option (int option,
00337                   char optval);
00338 
00339   /// Dump the state of an object.
00340   /**
00341    * Logs the setting of all options, the bound address, the send address and
00342    * interface, and the list of current subscriptions.
00343    */
00344   void dump (void) const;
00345 
00346   /// Declare the dynamic allocation hooks.
00347   ACE_ALLOC_HOOK_DECLARE;
00348 
00349 private:
00350 
00351   /// Subscribe to a multicast address on one or more network interface(s).
00352   /// (No QoS support.)
00353   int subscribe_ifs (const ACE_INET_Addr &mcast_addr,
00354                      const ACE_TCHAR *net_if,
00355                      int reuse_addr);
00356 
00357   /// Do subscription processing w/out updating the subscription list.
00358   //  (Layered method for <subscribe> processing).
00359   int subscribe_i (const ACE_INET_Addr &mcast_addr,
00360                    int reuse_addr = 1,
00361                    const ACE_TCHAR *net_if = 0);
00362 
00363   /// Unsubscribe from a multicast address on one or more network interface(s).
00364   int unsubscribe_ifs (const ACE_INET_Addr &mcast_addr,
00365                        const ACE_TCHAR *net_if = 0);
00366 
00367   /// Do unsubscription processing w/out udpating subscription list.
00368   //  (Layered method for <unsubscribe> processing).
00369   int unsubscribe_i (const ACE_INET_Addr &mcast_addr,
00370                      const ACE_TCHAR *net_if = 0);
00371 
00372 protected:
00373 
00374   /// Contains common open functionality so that inheriting classes can
00375   /// reuse it.
00376   int open_i (const ACE_INET_Addr &mcast_addr,        // Bound & sendto address.
00377               const ACE_TCHAR *net_if = 0,            // Net interface for sends.
00378               int reuse_addr = 1); 
00379 
00380   /// Create a multicast addr/if pair, in format useful for system calls.
00381   /// If mreq param is NULL, just verify the passed addr/interface specs.
00382   int make_multicast_ifaddr (ip_mreq *mreq,     // Put result here, if != NULL.
00383                              const ACE_INET_Addr &mcast_addr,
00384                              const ACE_TCHAR *net_if);
00385 
00386   /// Create a multicast addr/if pair.  This method factors out common
00387   /// code called by <make_multicast_address> and <subscribe>.
00388   int make_multicast_ifaddr_i (ip_mreq* mreq,   // Put result here, if != NULL.
00389                                const ACE_INET_Addr &mcast_addr,
00390                                const ACE_TCHAR *net_if = ACE_LIB_TEXT ("le0"));
00391 
00392   /// Empty the dynamic subscription list.  
00393   int clear_subs_list (void);
00394 
00395 private:
00396 
00397   /// Per-instance options..
00398   int opts_;
00399 
00400   /// Multicast address to which local <send> methods send datagrams.
00401   ACE_INET_Addr  send_addr_;
00402   /// Network interface to which all <send> methods send multicast datagrams.
00403   ACE_TCHAR *send_net_if_;
00404 
00405 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00406  typedef ACE_DLList<ip_mreq>  subscription_list_t;
00407  typedef ACE_DLList_Iterator<ip_mreq>  subscription_list_iter_t;
00408  /// List of currently subscribed addr/iface pairs (and assc. types).
00409  ACE_MUTABLE subscription_list_t  subscription_list_;
00410  /// Lock used to protect subscription list.
00411  ACE_MUTABLE ACE_SDM_LOCK subscription_list_lock_;
00412      // (Lock type does not need to support recursive locking.)
00413 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00414 
00415 };
00416 
00417 #if !defined (ACE_LACKS_INLINE_FUNCTIONS)
00418 #include "ace/SOCK_Dgram_Mcast.i"
00419 #endif /* ACE_LACKS_INLINE_FUNCTIONS */
00420 
00421 #include "ace/post.h"
00422 #endif /* ACE_SOCK_DGRAM_MCAST_H */

Generated on Mon Jun 16 11:21:20 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002