Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / SOCK_Dgram_Mcast.h
blob203d5454e8c3a5928db128ae42b3c0fd28542419
1 // -*- C++ -*-
3 //=============================================================================
4 /**
5 * @file SOCK_Dgram_Mcast.h
7 * @author Irfan Pyrali <irfan@cs.wustl.edu>
8 * @author Tim Harrison <harrison@cs.wustl.edu>
9 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
10 * @author Bill Fulton <bill_a_fulton@raytheon.com>
11 * @author Don Hinton <dhinton@objectsciences.com>
13 //=============================================================================
15 #ifndef ACE_SOCK_DGRAM_MCAST_H
16 #define ACE_SOCK_DGRAM_MCAST_H
18 #include /**/ "ace/pre.h"
20 #include /**/ "ace/ACE_export.h"
22 #if !defined (ACE_LACKS_PRAGMA_ONCE)
23 # pragma once
24 #endif /* ACE_LACKS_PRAGMA_ONCE */
26 #include "ace/SOCK_Dgram.h"
27 #include "ace/INET_Addr.h"
29 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
30 # include "ace/Containers_T.h"
31 # include "ace/Synch_Traits.h"
32 # include "ace/Thread_Mutex.h"
33 # if !defined (ACE_SDM_LOCK)
34 # define ACE_SDM_LOCK ACE_SYNCH_MUTEX
35 # endif /* ACE_SDM_LOCK */
36 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
38 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
40 /**
41 * @class ACE_SOCK_Dgram_Mcast
43 * @brief Defines the ACE socket wrapper for UDP/IP multicast.
45 * Supports multiple simultaneous subscriptions, unsubscription from one or
46 * all subscriptions, and independent send/recv address and interface
47 * specifications. Constructor arguments determine per-instance optional
48 * functionality.
50 * Note that multicast semantics and implementation details are @i very
51 * environment-specific; this class is just a wrapper around the underlying
52 * implementation and does not try to normalize the concept of multicast
53 * communications.
55 * Usage Notes:
56 * - Send and receive addresses and network interfaces, but not port number,
57 * are independent. While this instance is open, one send interface (and a
58 * default send address) is in effect and 0, 1, or multiple receive
59 * addresses/interfaces are in effect.
60 * - The first open()/subscribe() invocation defines the network interface
61 * and default address used for all sends by this instance, defines the
62 * port number and optionally the multicast address bound to the underlying
63 * socket, and defines the (one) port number that is used for all subscribes
64 * (subsequent subscribes must pass the same port number or 0).
65 * - The default loopback state is not explicitly set; the environment will
66 * determine the default state. Note that some environments (e.g. some
67 * Windows versions) do not allow the default to be changed, and that the
68 * semantics of loopback control are environment dependent (e.g. sender vs.
69 * receiver control).
70 * - In general, due to multicast design and implementation quirks/bugs, it is
71 * difficult to tell which address a received message was sent to or which
72 * interface it was received on (even if only one subscription is active).
73 * However, there are filtering options that can be applied, to narrow it
74 * down considerably.
76 * Interface specification notes (for subscribe() and unsubscribe()):
77 * - If @a net_if == 0, the @c OPT_NULLIFACE_ALL and @c OPT_NULLIFACE_ONE
78 * options determine whether only the system default interface
79 * (if @c OPT_NULLIFACE_ONE is set) or all interfaces (if
80 * @c OPT_NULLIFACE_ALL is set) is affected. Specifying all interfaces
81 * functions correctly only on:
82 * + Windows
83 * + Platforms with the ACE_HAS_GETIFADDRS config setting (includes Linux)
84 * + Platforms which accept the IP address as an interface
85 * name/specification
86 * + Systems with only one non-loopback interface.
87 * Other platforms require additional supporting code.
88 * - Multiple subscriptions for the same address but different interfaces is
89 * normally supported, but re-subscription to an address/interface that is
90 * already subscribed is normally not allowed.
91 * - The @a net_if interface specification syntax is environment-specific.
92 * UNIX systems will normally use device specifications such as "le0" or
93 * "elxl1", while other systems will use the IP address of the interface.
94 * Some platforms, such as pSoS, support only cardinal numbers as network
95 * interface specifications; for these platforms, just give these numbers in
96 * string form and join() will convert them into numbers.
98 class ACE_Export ACE_SOCK_Dgram_Mcast : public ACE_SOCK_Dgram
100 public:
102 * @brief Option parameters.
104 * These control per-instance optional functionality. They are set via
105 * an optional constructor argument.
107 * @note Certain option values are not valid for all environments (see
108 * comments in source file for environment-specific restrictions). Default
109 * values are always valid values for the compilation environment.
111 enum options
113 /* Define whether a specific multicast address (in addition to the port
114 * number) is bound to the socket.
115 * @note:
116 * - Effect of doing this is stack/environment dependent, but in most
117 * environments can be used to filter out unwanted unicast, broadcast,
118 * and (other) multicast messages sent to the same port number.
119 * - Some IP stacks (e.g. some Windows) do not support binding multicast
120 * addresses. Using this option will always cause an open() error.
121 * - It's not strictly possible for user code to do this level of filtering
122 * without the bind; some environments support ways to determine which
123 * address a message was sent to, but this class interface does not
124 * support access to that information.
125 * - The address (and port number) passed to open() (or the first
126 * join(), if open() is not explicitly invoked) is the one that is bound.
129 /// Disable address bind. (Bind only port.)
130 /// @note This might seem odd, but we need a way to distinguish between
131 /// default behavior, which might or might not be to bind, and explicitly
132 /// choosing to bind or not to bind--which "is the question." ;-)
133 OPT_BINDADDR_NO = 0,
134 /// Enable address bind. (Bind port and address.)
135 OPT_BINDADDR_YES = 1,
136 /// Default value for BINDADDR option. (Environment-dependent.)
137 #if defined (ACE_LACKS_PERFECT_MULTICAST_FILTERING) \
138 && (ACE_LACKS_PERFECT_MULTICAST_FILTERING == 1)
139 /// Platforms that don't support perfect filtering. Note that perfect
140 /// filtering only really applies to multicast traffic, not unicast
141 /// or broadcast.
142 DEFOPT_BINDADDR = OPT_BINDADDR_YES,
143 # else
144 /// At least some Win32 OS's can not bind mcast addr, so disable it.
145 /// General-purpose default behavior is 'disabled', since effect is
146 /// environment-specific and side-effects might be surprising.
147 DEFOPT_BINDADDR = OPT_BINDADDR_NO,
148 #endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING = 1) */
151 * Define the interpretation of NULL as a join interface specification.
152 * If the interface part of a multicast address specification is NULL, it
153 * will be interpreted to mean either "the default interface" or "all
154 * interfaces", depending on the setting of this option.
155 * @note
156 * - The @c OPT_NULLIFACE_ALL option can be used only in the following
157 * environments:
158 * + Windows
159 * + Platforms with the ACE_HAS_GETIFADDRS config setting (includes
160 * Linux)
161 * + Platforms which accept the IP address as an interface
162 * name/specification and for which
163 * ACE_Sock_Connect::get_ip_interfaces() is fully implemented
164 * + Systems with only one non-loopback interface.
165 * Other platforms require additional supporting code.
166 * - The default behavior in most IP stacks is to use the default
167 * interface where "default" has rather ad-hoc semantics.
168 * - This applies only to receives, not sends (which always use only one
169 * interface; NULL means use the "system default" interface).
171 /// Supported values:
172 /// If (net_if==NULL), use default interface.
173 /// @note This might seem odd, but we need a way to distinguish between
174 /// default behavior, which might or might not be to bind, and explicitly
175 /// choosing to bind or not to bind--which "is the question." ;-)
176 OPT_NULLIFACE_ONE = 0,
177 /// If (net_if==NULL), use all mcast interfaces.
178 OPT_NULLIFACE_ALL = 2,
179 /// Default value for NULLIFACE option. (Environment-dependent.)
180 #ifdef ACE_WIN32
181 /// This is the (ad-hoc) legacy behavior for Win32/WinSock.
182 /// @note Older version of WinSock/MSVC may not get all multicast-capable
183 /// interfaces (e.g. PPP interfaces).
184 DEFOPT_NULLIFACE = OPT_NULLIFACE_ALL,
185 #else
186 /// General-purpose default behavior (as per legacy behavior).
187 DEFOPT_NULLIFACE = OPT_NULLIFACE_ONE,
188 #endif /* ACE_WIN32 */
189 /// All default options.
190 DEFOPTS = DEFOPT_BINDADDR | DEFOPT_NULLIFACE
193 /// Create an unitialized instance and define per-instance optional
194 /// functionality.
196 * You must invoke open() or join(), to create/bind a socket and define
197 * operational parameters, before performing any I/O with this instance.
199 ACE_SOCK_Dgram_Mcast (options opts = DEFOPTS);
201 /// Release all resources and implicitly or explicitly unsubscribe
202 /// from all currently subscribed groups.
204 * The OPT_DTORUNSUB_YES_ option defines whether an explicit unsubscribe() is
205 * done by the destructor. If not, most systems will automatically
206 * unsubscribe upon the close of the socket.
208 ~ACE_SOCK_Dgram_Mcast ();
211 * Explicitly open/bind the socket and define the network interface
212 * and default multicast address used for sending messages.
214 * This method is optional; if not explicitly invoked, it is invoked by
215 * the first join(), using the subscribed address/port number and network
216 * interface parameters.
218 * @param mcast_addr Defines the default send address/port number and,
219 * if the @c OPT_BINDADDR_YES option is used, the multicast address
220 * that is bound to this socket. The port number in @a mcast_addr
221 * may be 0, in which case a system-assigned (ephemeral) port number
222 * is used for sending and receiving.
224 * @param net_if If @a net_if is not 0, it defines the network interface
225 * used for all sends by this instance, otherwise the system default
226 * interface is used. (The @a net_if parameter is ignored if this
227 * feature is not supported by the environment.)
229 * @param reuse_addr If @a reuse_addr is not 0, the @c SO_REUSEADDR option
230 * and, if it is supported, the SO_REUSEPORT option are enabled.
232 * @retval 0 on success
233 * @retval -1 if the call fails. Failure can occur due to problems with
234 * the address, port, and/or interface parameters or during system open()
235 * or socket option processing.
237 int open (const ACE_INET_Addr &mcast_addr,
238 const ACE_TCHAR *net_if = 0,
239 int reuse_addr = 1);
241 // = Multicast group subscribe/unsubscribe routines.
243 /// Join a multicast group on a given interface (or all interfaces, if
244 /// supported).
246 * The given group is joined on the specified interface. If option
247 * OPT_NULLIFACE_ALL is used and @a net_if is = 0, the group is joined on
248 * all multicast capable interfaces (IFF supported). Multiple subscriptions
249 * to various address and interface combinations are supported and tracked.
250 * If this is the first invocation of subscribe(), and open() was not
251 * previously invoked, open() will be invoked using @a mcast_addr for binding
252 * the socket and @a net_if as the interface for send().
254 * Returns: -1 if the call fails. Failure can occur due to problems with
255 * the address, port#, and/or interface parameters or during the subscription
256 * attempt. Once bind() has been invoked (by the first open() or
257 * subscribe()), returns errno of ENXIO if the port# is not 0 and does not
258 * match the bound port#, or if OPT_BINDADDR_YES option is used
259 * and the address does not match the bound address. Returns errno of
260 * ENODEV if the addr/port#/interface parameters appeared valid, but no
261 * subscription(s) succeeded. An error is unconditionally returned if
262 * option OPT_NULLIFACE_ALL is used, @a net_if is NULL, and
263 * ACE_Sock_Connect::get_ip_interfaces() is not implemented in this
264 * environment.
266 * Note that the optional @a reuse_addr parameter does not apply to
267 * subscriptions; it is only used if open() is implicitly invoked (see above).
269 * Uses the mcast_addr to determine protocol_family, and protocol which
270 * we always pass as 0 anyway.
272 int join (const ACE_INET_Addr &mcast_addr,
273 int reuse_addr = 1, // (see above)
274 const ACE_TCHAR *net_if = 0);
277 /// Leave a multicast group on a given interface (or all interfaces, if
278 /// supported).
280 * The specified group/interface combination is unsubscribed. If option
281 * OPT_NULLIFACE_ALL is used and @a net_if is = 0, the group is unsubscribed
282 * from all interfaces (IFF supported).
284 * Returns: -1 if the unsubscribe failed. Most environments will return -1
285 * if there was no active subscription for this address/interface combination.
286 * An error is unconditionally returned if option OPT_NULLIFACE_ALL is used,
287 * @a net_if is = 0, and ACE_Sock_Connect::get_ip_interfaces() is not
288 * implemented in this environment (_even if_ the subscribe() specifies a
289 * non- NULL @a net_if).
291 * leave() replaces unsubscribe() and uses mcast_addr to determine
292 * protocol_family, and protocol which we always pass as 0 anyway.
294 int leave (const ACE_INET_Addr &mcast_addr,
295 const ACE_TCHAR *net_if = 0);
297 // = Data transfer routines.
299 /// Send @a n bytes in @a buf, using the multicast address and network interface
300 /// defined by the first open() or subscribe().
301 ssize_t send (const void *buf,
302 size_t n,
303 int flags = 0) const;
305 /// Send @a n iovecs, using the multicast address and network interface
306 /// defined by the first open() or subscribe().
307 ssize_t send (const iovec iov[],
308 int n,
309 int flags = 0) const;
311 // = Options.
313 /// Set a socket option.
315 * Set an IP option that takes a char as input, such as IP_MULTICAST_LOOP
316 * or IP_MULTICAST_TTL. This is just a more concise, nice interface to a
317 * subset of possible ACE_SOCK::set_option calls, but only works for
318 * IPPROTO_IP or IPPROTO_IPV6 level options.
320 * Returns 0 on success, -1 on failure.
322 * @deprecated This method has been deprecated since it cannot be used
323 * easily with with IPv6 options. Use ACE_SOCK::set_option instead.
325 int set_option (int option, char optval);
327 /// Dump the state of an object.
329 * Logs the setting of all options, the bound address, the send address and
330 * interface, and the list of current subscriptions.
332 void dump () const;
334 /// Declare the dynamic allocation hooks.
335 ACE_ALLOC_HOOK_DECLARE;
337 /// Override write accessor for the constructor options (@see enum options above)
338 /// This class is typically default instantiated in a connection handler templated
339 /// framework so these cannot be specified on construction.
340 void opts (int opts);
342 /// Read accessor for the constructor options (@see enum options above)
343 int opts () const;
345 private:
346 /// Subscribe to a multicast address on one or more network interface(s).
347 /// (No QoS support.)
348 int subscribe_ifs (const ACE_INET_Addr &mcast_addr,
349 const ACE_TCHAR *net_if,
350 int reuse_addr);
352 /// Do subscription processing w/out updating the subscription list.
353 /// (Layered method for subscribe() processing).
354 int subscribe_i (const ACE_INET_Addr &mcast_addr,
355 int reuse_addr = 1,
356 const ACE_TCHAR *net_if = 0);
358 /// Unsubscribe from a multicast address on one or more network interface(s).
359 int unsubscribe_ifs (const ACE_INET_Addr &mcast_addr,
360 const ACE_TCHAR *net_if = 0);
362 /// Do unsubscription processing w/out udpating subscription list.
363 /// (Layered method for <unsubscribe> processing).
364 int unsubscribe_i (const ACE_INET_Addr &mcast_addr,
365 const ACE_TCHAR *net_if = 0);
367 protected:
368 /// Contains common open functionality so that inheriting classes can
369 /// reuse it.
370 int open_i (const ACE_INET_Addr &mcast_addr, // Bound & sendto address.
371 const ACE_TCHAR *net_if = 0, // Net interface for sends.
372 int reuse_addr = 1);
374 /// Empty the dynamic subscription list.
375 int clear_subs_list ();
377 /// Multicast address to which local send() methods send datagrams.
378 ACE_INET_Addr send_addr_;
379 /// Network interface to which all send() methods send multicast datagrams.
380 ACE_TCHAR* send_net_if_ {};
382 private:
383 /// Per-instance options..
384 int opts_;
386 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
387 typedef ACE_DLList<ip_mreq> subscription_list_t;
388 typedef ACE_DLList_Iterator<ip_mreq> subscription_list_iter_t;
389 /// List of currently subscribed addr/iface pairs (and assc. types).
390 mutable subscription_list_t subscription_list_;
391 /// Lock used to protect subscription list.
392 mutable ACE_SDM_LOCK subscription_list_lock_;
393 // (Lock type does not need to support recursive locking.)
394 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
397 ACE_END_VERSIONED_NAMESPACE_DECL
399 #if defined (__ACE_INLINE__)
400 #include "ace/SOCK_Dgram_Mcast.inl"
401 #endif /* __ACE_INLINE__ */
403 #include /**/ "ace/post.h"
404 #endif /* ACE_SOCK_DGRAM_MCAST_H */