3 //=============================================================================
5 * @file SOCK_Dgram_Mcast.h
7 * $Id: SOCK_Dgram_Mcast.h 80826 2008-03-04 14:51:23Z wotte $
9 * @author Irfan Pyrali <irfan@cs.wustl.edu>
10 * @author Tim Harrison <harrison@cs.wustl.edu>
11 * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
12 * @author Bill Fulton <bill_a_fulton@raytheon.com>
13 * @author Don Hinton <dhinton@objectsciences.com>
15 //=============================================================================
17 #ifndef ACE_SOCK_DGRAM_MCAST_H
18 #define ACE_SOCK_DGRAM_MCAST_H
20 #include /**/ "ace/pre.h"
22 #include /**/ "ace/ACE_export.h"
24 #if !defined (ACE_LACKS_PRAGMA_ONCE)
26 #endif /* ACE_LACKS_PRAGMA_ONCE */
28 #include "ace/SOCK_Dgram.h"
29 #include "ace/INET_Addr.h"
31 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
32 # include "ace/Containers_T.h"
33 # include "ace/Synch_Traits.h"
34 # include "ace/Thread_Mutex.h"
35 # if !defined (ACE_SDM_LOCK)
36 # define ACE_SDM_LOCK ACE_SYNCH_MUTEX
37 # endif /* ACE_SDM_LOCK */
38 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
40 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
43 * @class ACE_SOCK_Dgram_Mcast
45 * @brief Defines the ACE socket wrapper for UDP/IP multicast.
47 * Supports multiple simultaneous subscriptions, unsubscription from one or
48 * all subscriptions, and independent send/recv address and interface
49 * specifications. Template parameters and/or ctor arguments determine
50 * per-instance optional functionality.
52 * Note that multicast semantics and implementation details are _very_
53 * environment-specific; this class is just a wrapper around the underlying
54 * implementation and does not try to normalize the concept of multicast
58 * - Send and Recv addresses and network interfaces, but not port#, are
59 * independent. While this instance is open, 1 send interface (and a default
60 * send address) is in effect and 0, 1, or multiple recv addresses/interfaces
62 * - The first <open>/<subscribe> invocation defines the network interface
63 * and default address used for all sends by this instance, defines the
64 * port# and optionally the multicast address bound to the underlying
65 * socket, and defines the (one) port# that is used for all subscribes
66 * (subsequent subscribes must pass the same port# or '0').
67 * - The default loopback state is not explicitly set; the environment will
68 * determine the default state. Note that some environments (e.g. some Win32)
69 * do not allow the default to be changed, and that the semantics of
70 * loopback control are environment dependent (e.g. sender vs receiver
72 * - In general, due to multicast design and implementation quirks/bugs, it is
73 * difficult to tell which address a received message was sent to or which
74 * interface it was received on (even if only one subscription is active).
75 * However; there are filtering options that can be applied, to narrow it
78 * Interface specification notes (for <subscribe> and <unsubscribe>):
79 * - If net_if == 0, the null_iface_opt option determines whether only the
80 * system "default" interface or all interfaces is affected. Specifying
81 * "all" interfaces is supported only for environments for which
82 * <ACE_Sock_Connect::get_ip_interfaces> is properly implemented.
83 * - Multiple subscriptions for the same address but different interfaces is
84 * normally supported, but re-subscription to an address/interface that is
85 * already subscribed is normally not allowed.
86 * - The <net_if> interface specification syntax is environment-specific.
87 * UNIX systems will normally use device specifications such as "le0" or
88 * "elxl1", while other systems will use the IP address of the interface.
89 * Some platforms, such as pSoS, support only cardinal numbers as network
90 * interface specifications; for these platforms, just give these numbers in
91 * alphanumeric form and <subscribe> will convert them into numbers via
94 class ACE_Export ACE_SOCK_Dgram_Mcast
: public ACE_SOCK_Dgram
99 * @brief Option parameters.
101 * These control per-instance optional functionality. They are set via
102 * optional constructor arguments.
103 * @note Certain option values are not valid for all environments (see
104 * comments in source file for environment-specific restrictions). Default
105 * values are always valid values for the compilation environment.
109 // Define whether a specific (multicast) address (in addition to the port#)
110 // is bound to the socket.
112 // - Effect of doing this is stack/environment dependent, but in most
113 // environments can be used to filter out unwanted unicast, broadcast, and
114 // (other) multicast messages sent to the same port#.
115 // - Some IP stacks (e.g. some Win32) do not support binding multicast
116 // addresses. Using this option will always cause an <open> error.
117 // - It's not strictly possible for user code to do this level of filtering
118 // w/out the bind; some environments support ways to determine which address
119 // a message was sent _to_, but this class interface does not support access
121 // - The address (and port#) passed to <open> (or the first <subscribe>, if
122 // <open> is not explicitly invoked) is the one that is bound.
124 /// Disable address bind. (Bind only port.)
125 // Note that this might seem odd, but we need a way to distinquish between
126 // default behavior, which might or might not be to bind, and explicitely
127 // choosing to bind or not to bind--which "is the question." ;-)
129 /// Enable address bind. (Bind port and address.)
130 OPT_BINDADDR_YES
= 1,
131 /// Default value for BINDADDR option. (Environment-dependent.)
132 #if defined (ACE_LACKS_PERFECT_MULTICAST_FILTERING) \
133 && (ACE_LACKS_PERFECT_MULTICAST_FILTERING == 1)
134 // Platforms that don't support perfect filtering. Note that perfect
135 // filtering only really applies to multicast traffic, not unicast
137 DEFOPT_BINDADDR
= OPT_BINDADDR_YES
,
139 // At least some Win32 OS's can not bind mcast addr, so disable it.
140 // General-purpose default behavior is 'disabled', since effect is
141 // environment-specific and side-effects might be surprising.
142 DEFOPT_BINDADDR
= OPT_BINDADDR_NO
,
143 #endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING = 1) */
145 /// Define the interpretation of 'NULL' as a recv interface specification.
146 // If the interface part of a multicast address specification is NULL, it
147 // will be interpreted to mean either "the default interface" or "all
148 // interfaces", depending on the setting of this option.
150 // - The 'nulliface_all' option can not be used in environments which do
151 // not fully support the <ACE_Sock_Connect::get_ip_interfaces> method
152 // (e.g. non-Windows).
153 // If it is, using NULL for iface will _always_ fail.
154 // - The default behavior in most IP stacks is to use the 'default' interface,
155 // where 'default' has rather ad-hoc semantics.
156 // - This applies only to receives, not sends (which always use only one
157 // interface; NULL means use the "system default" interface).
159 /// If (net_if==NULL), use default interface.
160 // Note that this might seem odd, but we need a way to distinquish between
161 // default behavior, which might or might not be to bind, and explicitely
162 // choosing to bind or not to bind--which "is the question." ;-)
163 OPT_NULLIFACE_ONE
= 0,
164 /// If (net_if==NULL), use all mcast interfaces.
165 OPT_NULLIFACE_ALL
= 2,
166 /// Default value for NULLIFACE option. (Environment-dependent.)
168 // This is the (ad-hoc) legacy behavior for Win32/WinSock.
169 // Notice: Older version of WinSock/MSVC may not get all multicast-capable
170 // interfaces (e.g. PPP interfaces).
171 DEFOPT_NULLIFACE
= OPT_NULLIFACE_ALL
,
173 // General-purpose default behavior (as per legacy behavior).
174 DEFOPT_NULLIFACE
= OPT_NULLIFACE_ONE
,
175 #endif /* ACE_WIN32 */
176 /// All default options.
177 DEFOPTS
= DEFOPT_BINDADDR
| DEFOPT_NULLIFACE
180 // = Initialization routines.
182 /// Ctor - Create an unitialized instance and define per-instance optional
185 * You must invoke <open> or <subscribe>, to create/bind a socket and define
186 * operational parameters, before performing any I/O with this instance.
188 ACE_SOCK_Dgram_Mcast (options opts
= DEFOPTS
);
190 /// Dtor - Release all resources and implicitly or explicitly unsubscribe
191 /// from all currently subscribed groups.
193 * The OPT_DTORUNSUB_YES_ option defines whether an explicit <unsusbcribe> is
194 * done by the destructor. If not, most systems will automatically
195 * unsubscribe upon the close of the socket.
197 ~ACE_SOCK_Dgram_Mcast (void);
199 /// Explicitly open/bind the socket and define the network interface
200 /// and default multicast address used for sending messages.
202 * This method is optional; if not explicitly invoked, it is invoked by
203 * the first <subscribe>, using the subscribed address/port# and network
204 * interface paramters.
205 * The <mcast_addr> parameter defines the default send address/port# and
206 * also the port# and, if the OPT_BINDADDR_YES option is used,
207 * the multicast address that is bound to this socket.
208 * If the <send_net_if> parameter != 0, it defines the network interface
209 * used for all sends by this instance, otherwise the system "default"
210 * interface is used. (The <send_net_if> parameter is ignored if this
211 * feature is not supported by the envriornment.)
212 * The port# in <mcast_addr> may be 0, in which case a system-assigned
213 * (ephemeral) port# is used for sending and receiving.
214 * If @a reuse_addr != 0, the SO_REUSEADDR option and, if it is supported,
215 * the SO_REUSEPORT option are enabled.
217 * Returns: -1 if the call fails. Failure can occur due to problems with
218 * the address, port#, and/or interface parameters or during system open()
219 * or socket option processing.
221 int open (const ACE_INET_Addr
&mcast_addr
, // Bound & sendto address.
222 const ACE_TCHAR
*net_if
= 0, // Net interface for sends.
223 int reuse_addr
= 1); // Reuse addr/port sock opt.
225 // = Multicast group subscribe/unsubscribe routines.
227 /// Join a multicast group on a given interface (or all interfaces, if
230 * The given group is joined on the specified interface. If option
231 * OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is joined on
232 * all multicast capable interfaces (IFF supported). Multiple subscriptions
233 * to various address and interface combinations are supported and tracked.
234 * If this is the first invocation of <subscribe>, and <open> was not
235 * previously invoked, <open> will be invoked using <mcast_addr> for binding
236 * the socket and <net_if> as the interface for <send>.
238 * Returns: -1 if the call fails. Failure can occur due to problems with
239 * the address, port#, and/or interface parameters or during the subscription
240 * attempt. Once bind() has been invoked (by the first <open> or
241 * <subscribe>), returns errno of ENXIO if the port# is not 0 and does not
242 * match the bound port#, or if OPT_BINDADDR_YES option is used
243 * and the address does not match the bound address. Returns errno of
244 * ENODEV if the addr/port#/interface parameters appeared valid, but no
245 * subscription(s) succeeded. An error is unconditionally returned if
246 * option OPT_NULLIFACE_ALL is used, <net_if> is NULL, and
247 * <ACE_Sock_Connect::get_ip_interfaces> is not implemented in this
250 * Note that the optional @a reuse_addr parameter does not apply to
251 * subscriptions; it is only used if <open> is implicitly invoked (see above).
253 * Uses the mcast_addr to determine protocol_family, and protocol which
254 * we always pass as 0 anyway.
256 int join (const ACE_INET_Addr
&mcast_addr
,
257 int reuse_addr
= 1, // (see above)
258 const ACE_TCHAR
*net_if
= 0);
261 /// Leave a multicast group on a given interface (or all interfaces, if
264 * The specified group/interface combination is unsubscribed. If option
265 * OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is unsubscribed
266 * from all interfaces (IFF supported).
268 * Returns: -1 if the unsubscribe failed. Most environments will return -1
269 * if there was no active subscription for this address/interface combination.
270 * An error is unconditionally returned if option OPT_NULLIFACE_ALL is used,
271 * <net_if> is = 0, and <ACE_Sock_Connect::get_ip_interfaces> is not
272 * implemented in this environment (_even if_ the <subscribe> specifies a
273 * non- NULL <net_if>).
275 * leave() replaces unsubscribe() and uses mcast_addr to determine
276 * protocol_family, and protocol which we always pass as 0 anyway.
278 int leave (const ACE_INET_Addr
&mcast_addr
,
279 const ACE_TCHAR
*net_if
= 0);
281 // = Data transfer routines.
283 /// Send @a n bytes in @a buf, using the multicast address and network interface
284 /// defined by the first <open> or <subscribe>.
285 ssize_t
send (const void *buf
,
287 int flags
= 0) const;
289 /// Send @a n <iovecs>, using the multicast address and network interface
290 /// defined by the first <open> or <subscribe>.
291 ssize_t
send (const iovec iov
[],
293 int flags
= 0) const;
297 /// Set a socket option.
299 * Set an IP option that takes a char as input, such as IP_MULTICAST_LOOP
300 * or IP_MULTICAST_TTL. This is just a more concise, nice interface to a
301 * subset of possible ACE_SOCK::set_option calls, but only works for
302 * IPPROTO_IP or IPPROTO_IPV6 level options.
304 * Returns 0 on success, -1 on failure.
306 * @deprecated This method has been deprecated since it cannot be used
307 * easily with with IPv6 options. Use ACE_SOCK::set_option instead.
309 int set_option (int option
, char optval
);
311 /// Dump the state of an object.
313 * Logs the setting of all options, the bound address, the send address and
314 * interface, and the list of current subscriptions.
316 void dump (void) const;
318 /// Declare the dynamic allocation hooks.
319 ACE_ALLOC_HOOK_DECLARE
;
323 /// Subscribe to a multicast address on one or more network interface(s).
324 /// (No QoS support.)
325 int subscribe_ifs (const ACE_INET_Addr
&mcast_addr
,
326 const ACE_TCHAR
*net_if
,
329 /// Do subscription processing w/out updating the subscription list.
330 // (Layered method for <subscribe> processing).
331 int subscribe_i (const ACE_INET_Addr
&mcast_addr
,
333 const ACE_TCHAR
*net_if
= 0);
335 /// Unsubscribe from a multicast address on one or more network interface(s).
336 int unsubscribe_ifs (const ACE_INET_Addr
&mcast_addr
,
337 const ACE_TCHAR
*net_if
= 0);
339 /// Do unsubscription processing w/out udpating subscription list.
340 // (Layered method for <unsubscribe> processing).
341 int unsubscribe_i (const ACE_INET_Addr
&mcast_addr
,
342 const ACE_TCHAR
*net_if
= 0);
346 /// Contains common open functionality so that inheriting classes can
348 int open_i (const ACE_INET_Addr
&mcast_addr
, // Bound & sendto address.
349 const ACE_TCHAR
*net_if
= 0, // Net interface for sends.
352 /// Empty the dynamic subscription list.
353 int clear_subs_list (void);
357 /// Per-instance options..
360 /// Multicast address to which local <send> methods send datagrams.
361 ACE_INET_Addr send_addr_
;
362 /// Network interface to which all <send> methods send multicast datagrams.
363 ACE_TCHAR
*send_net_if_
;
365 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
366 typedef ACE_DLList
<ip_mreq
> subscription_list_t
;
367 typedef ACE_DLList_Iterator
<ip_mreq
> subscription_list_iter_t
;
368 /// List of currently subscribed addr/iface pairs (and assc. types).
369 mutable subscription_list_t subscription_list_
;
370 /// Lock used to protect subscription list.
371 mutable ACE_SDM_LOCK subscription_list_lock_
;
372 // (Lock type does not need to support recursive locking.)
373 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
377 ACE_END_VERSIONED_NAMESPACE_DECL
379 #if defined (__ACE_INLINE__)
380 #include "ace/SOCK_Dgram_Mcast.inl"
381 #endif /* __ACE_INLINE__ */
383 #include /**/ "ace/post.h"
384 #endif /* ACE_SOCK_DGRAM_MCAST_H */