00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file SOCK_Dgram_Mcast.h 00006 * 00007 * $Id: SOCK_Dgram_Mcast.h 80826 2008-03-04 14:51:23Z wotte $ 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 @a 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 @a reuse_addr parameter does not apply to 00251 * subscriptions; it is only used if <open> is implicitly invoked (see above). 00252 * 00253 * Uses the mcast_addr to determine protocol_family, and protocol which 00254 * we always pass as 0 anyway. 00255 */ 00256 int join (const ACE_INET_Addr &mcast_addr, 00257 int reuse_addr = 1, // (see above) 00258 const ACE_TCHAR *net_if = 0); 00259 00260 00261 /// Leave a multicast group on a given interface (or all interfaces, if 00262 /// supported). 00263 /** 00264 * The specified group/interface combination is unsubscribed. If option 00265 * OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is unsubscribed 00266 * from all interfaces (IFF supported). 00267 * 00268 * Returns: -1 if the unsubscribe failed. Most environments will return -1 00269 * if there was no active subscription for this address/interface combination. 00270 * An error is unconditionally returned if option OPT_NULLIFACE_ALL is used, 00271 * <net_if> is = 0, and <ACE_Sock_Connect::get_ip_interfaces> is not 00272 * implemented in this environment (_even if_ the <subscribe> specifies a 00273 * non- NULL <net_if>). 00274 * 00275 * leave() replaces unsubscribe() and uses mcast_addr to determine 00276 * protocol_family, and protocol which we always pass as 0 anyway. 00277 */ 00278 int leave (const ACE_INET_Addr &mcast_addr, 00279 const ACE_TCHAR *net_if = 0); 00280 00281 // = Data transfer routines. 00282 00283 /// Send @a n bytes in @a buf, using the multicast address and network interface 00284 /// defined by the first <open> or <subscribe>. 00285 ssize_t send (const void *buf, 00286 size_t n, 00287 int flags = 0) const; 00288 00289 /// Send @a n <iovecs>, using the multicast address and network interface 00290 /// defined by the first <open> or <subscribe>. 00291 ssize_t send (const iovec iov[], 00292 int n, 00293 int flags = 0) const; 00294 00295 // = Options. 00296 00297 /// Set a socket option. 00298 /** 00299 * Set an IP option that takes a char as input, such as IP_MULTICAST_LOOP 00300 * or IP_MULTICAST_TTL. This is just a more concise, nice interface to a 00301 * subset of possible ACE_SOCK::set_option calls, but only works for 00302 * IPPROTO_IP or IPPROTO_IPV6 level options. 00303 * 00304 * Returns 0 on success, -1 on failure. 00305 * 00306 * @deprecated This method has been deprecated since it cannot be used 00307 * easily with with IPv6 options. Use ACE_SOCK::set_option instead. 00308 */ 00309 int set_option (int option, char optval); 00310 00311 /// Dump the state of an object. 00312 /** 00313 * Logs the setting of all options, the bound address, the send address and 00314 * interface, and the list of current subscriptions. 00315 */ 00316 void dump (void) const; 00317 00318 /// Declare the dynamic allocation hooks. 00319 ACE_ALLOC_HOOK_DECLARE; 00320 00321 private: 00322 00323 /// Subscribe to a multicast address on one or more network interface(s). 00324 /// (No QoS support.) 00325 int subscribe_ifs (const ACE_INET_Addr &mcast_addr, 00326 const ACE_TCHAR *net_if, 00327 int reuse_addr); 00328 00329 /// Do subscription processing w/out updating the subscription list. 00330 // (Layered method for <subscribe> processing). 00331 int subscribe_i (const ACE_INET_Addr &mcast_addr, 00332 int reuse_addr = 1, 00333 const ACE_TCHAR *net_if = 0); 00334 00335 /// Unsubscribe from a multicast address on one or more network interface(s). 00336 int unsubscribe_ifs (const ACE_INET_Addr &mcast_addr, 00337 const ACE_TCHAR *net_if = 0); 00338 00339 /// Do unsubscription processing w/out udpating subscription list. 00340 // (Layered method for <unsubscribe> processing). 00341 int unsubscribe_i (const ACE_INET_Addr &mcast_addr, 00342 const ACE_TCHAR *net_if = 0); 00343 00344 protected: 00345 00346 /// Contains common open functionality so that inheriting classes can 00347 /// reuse it. 00348 int open_i (const ACE_INET_Addr &mcast_addr, // Bound & sendto address. 00349 const ACE_TCHAR *net_if = 0, // Net interface for sends. 00350 int reuse_addr = 1); 00351 00352 /// Empty the dynamic subscription list. 00353 int clear_subs_list (void); 00354 00355 private: 00356 00357 /// Per-instance options.. 00358 int opts_; 00359 00360 /// Multicast address to which local <send> methods send datagrams. 00361 ACE_INET_Addr send_addr_; 00362 /// Network interface to which all <send> methods send multicast datagrams. 00363 ACE_TCHAR *send_net_if_; 00364 00365 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE) 00366 typedef ACE_DLList<ip_mreq> subscription_list_t; 00367 typedef ACE_DLList_Iterator<ip_mreq> subscription_list_iter_t; 00368 /// List of currently subscribed addr/iface pairs (and assc. types). 00369 mutable subscription_list_t subscription_list_; 00370 /// Lock used to protect subscription list. 00371 mutable ACE_SDM_LOCK subscription_list_lock_; 00372 // (Lock type does not need to support recursive locking.) 00373 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */ 00374 00375 }; 00376 00377 ACE_END_VERSIONED_NAMESPACE_DECL 00378 00379 #if defined (__ACE_INLINE__) 00380 #include "ace/SOCK_Dgram_Mcast.inl" 00381 #endif /* __ACE_INLINE__ */ 00382 00383 #include /**/ "ace/post.h" 00384 #endif /* ACE_SOCK_DGRAM_MCAST_H */