Defines the ACE socket wrapper for UDP/IP multicast. More...
#include <SOCK_Dgram_Mcast.h>


Public Types | |
| enum | options { OPT_BINDADDR_NO = 0, OPT_BINDADDR_YES = 1, DEFOPT_BINDADDR = OPT_BINDADDR_NO, OPT_NULLIFACE_ONE = 0, OPT_NULLIFACE_ALL = 2, DEFOPT_NULLIFACE = OPT_NULLIFACE_ONE, DEFOPTS = DEFOPT_BINDADDR | DEFOPT_NULLIFACE } |
Option parameters. More... | |
Public Member Functions | |
| ACE_SOCK_Dgram_Mcast (options opts=DEFOPTS) | |
| ~ACE_SOCK_Dgram_Mcast (void) | |
| int | open (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if=0, int reuse_addr=1) |
| int | join (const ACE_INET_Addr &mcast_addr, int reuse_addr=1, const ACE_TCHAR *net_if=0) |
| int | leave (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if=0) |
| ssize_t | send (const void *buf, size_t n, int flags=0) const |
| ssize_t | send (const iovec iov[], int n, int flags=0) const |
| int | set_option (int option, char optval) |
| Set a socket option. | |
| void | dump (void) const |
| Dump the state of an object. | |
Public Attributes | |
| ACE_ALLOC_HOOK_DECLARE | |
| Declare the dynamic allocation hooks. | |
Protected Member Functions | |
| int | open_i (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if=0, int reuse_addr=1) |
| int | clear_subs_list (void) |
| Empty the dynamic subscription list. | |
Private Member Functions | |
| int | subscribe_ifs (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if, int reuse_addr) |
| int | subscribe_i (const ACE_INET_Addr &mcast_addr, int reuse_addr=1, const ACE_TCHAR *net_if=0) |
| Do subscription processing w/out updating the subscription list. | |
| int | unsubscribe_ifs (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if=0) |
| Unsubscribe from a multicast address on one or more network interface(s). | |
| int | unsubscribe_i (const ACE_INET_Addr &mcast_addr, const ACE_TCHAR *net_if=0) |
| Do unsubscription processing w/out udpating subscription list. | |
Private Attributes | |
| int | opts_ |
| Per-instance options.. | |
| ACE_INET_Addr | send_addr_ |
| Multicast address to which local <send> methods send datagrams. | |
| ACE_TCHAR * | send_net_if_ |
| Network interface to which all <send> methods send multicast datagrams. | |
Defines the ACE socket wrapper for UDP/IP multicast.
Supports multiple simultaneous subscriptions, unsubscription from one or all subscriptions, and independent send/recv address and interface specifications. Template parameters and/or ctor arguments determine per-instance optional functionality.
Note that multicast semantics and implementation details are _very_ environment-specific; this class is just a wrapper around the underlying implementation and does not try to normalize the concept of multicast communications.
Usage Notes:
Interface specification notes (for <subscribe> and <unsubscribe>):
Definition at line 94 of file SOCK_Dgram_Mcast.h.
Option parameters.
These control per-instance optional functionality. They are set via optional constructor arguments.
Definition at line 107 of file SOCK_Dgram_Mcast.h.
{
// Define whether a specific (multicast) address (in addition to the port#)
// is bound to the socket.
// Notes:
// - Effect of doing this is stack/environment dependent, but in most
// environments can be used to filter out unwanted unicast, broadcast, and
// (other) multicast messages sent to the same port#.
// - Some IP stacks (e.g. some Win32) do not support binding multicast
// addresses. Using this option will always cause an <open> error.
// - It's not strictly possible for user code to do this level of filtering
// w/out the bind; some environments support ways to determine which address
// a message was sent _to_, but this class interface does not support access
// to that info.
// - The address (and port#) passed to <open> (or the first <subscribe>, if
// <open> is not explicitly invoked) is the one that is bound.
//
/// Disable address bind. (Bind only port.)
// Note that this might seem odd, but we need a way to distinquish between
// default behavior, which might or might not be to bind, and explicitely
// choosing to bind or not to bind--which "is the question." ;-)
OPT_BINDADDR_NO = 0,
/// Enable address bind. (Bind port and address.)
OPT_BINDADDR_YES = 1,
/// Default value for BINDADDR option. (Environment-dependent.)
#if defined (ACE_LACKS_PERFECT_MULTICAST_FILTERING) \
&& (ACE_LACKS_PERFECT_MULTICAST_FILTERING == 1)
// Platforms that don't support perfect filtering. Note that perfect
// filtering only really applies to multicast traffic, not unicast
// or broadcast.
DEFOPT_BINDADDR = OPT_BINDADDR_YES,
# else
// At least some Win32 OS's can not bind mcast addr, so disable it.
// General-purpose default behavior is 'disabled', since effect is
// environment-specific and side-effects might be surprising.
DEFOPT_BINDADDR = OPT_BINDADDR_NO,
#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING = 1) */
//
/// Define the interpretation of 'NULL' as a recv interface specification.
// If the interface part of a multicast address specification is NULL, it
// will be interpreted to mean either "the default interface" or "all
// interfaces", depending on the setting of this option.
// Notes:
// - The 'nulliface_all' option can not be used in environments which do
// not fully support the <ACE_Sock_Connect::get_ip_interfaces> method
// (e.g. non-Windows).
// If it is, using NULL for iface will _always_ fail.
// - The default behavior in most IP stacks is to use the 'default' interface,
// where 'default' has rather ad-hoc semantics.
// - This applies only to receives, not sends (which always use only one
// interface; NULL means use the "system default" interface).
// Supported values:
/// If (net_if==NULL), use default interface.
// Note that this might seem odd, but we need a way to distinquish between
// default behavior, which might or might not be to bind, and explicitely
// choosing to bind or not to bind--which "is the question." ;-)
OPT_NULLIFACE_ONE = 0,
/// If (net_if==NULL), use all mcast interfaces.
OPT_NULLIFACE_ALL = 2,
/// Default value for NULLIFACE option. (Environment-dependent.)
#ifdef ACE_WIN32
// This is the (ad-hoc) legacy behavior for Win32/WinSock.
// Notice: Older version of WinSock/MSVC may not get all multicast-capable
// interfaces (e.g. PPP interfaces).
DEFOPT_NULLIFACE = OPT_NULLIFACE_ALL,
#else
// General-purpose default behavior (as per legacy behavior).
DEFOPT_NULLIFACE = OPT_NULLIFACE_ONE,
#endif /* ACE_WIN32 */
/// All default options.
DEFOPTS = DEFOPT_BINDADDR | DEFOPT_NULLIFACE
};
| ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast | ( | ACE_SOCK_Dgram_Mcast::options | opts = DEFOPTS |
) |
Ctor - Create an unitialized instance and define per-instance optional functionality. You must invoke <open> or <subscribe>, to create/bind a socket and define operational parameters, before performing any I/O with this instance.
Definition at line 133 of file SOCK_Dgram_Mcast.cpp.
: opts_ (opts), send_net_if_ (0) { ACE_TRACE ("ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast"); }
| ACE_SOCK_Dgram_Mcast::~ACE_SOCK_Dgram_Mcast | ( | void | ) |
Dtor - Release all resources and implicitly or explicitly unsubscribe from all currently subscribed groups. The OPT_DTORUNSUB_YES_ option defines whether an explicit <unsusbcribe> is done by the destructor. If not, most systems will automatically unsubscribe upon the close of the socket.
Definition at line 141 of file SOCK_Dgram_Mcast.cpp.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::~ACE_SOCK_Dgram_Mcast");
// Free memory and optionally unsubscribe from currently subscribed group(s).
delete [] this->send_net_if_;
this->clear_subs_list ();
}
| int ACE_SOCK_Dgram_Mcast::clear_subs_list | ( | void | ) | [protected] |
Empty the dynamic subscription list.
Definition at line 913 of file SOCK_Dgram_Mcast.cpp.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::clear_subs_list");
int result = 0;
#if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
this->subscription_list_lock_, -1));
subscription_list_iter_t iter (this->subscription_list_);
for (; !iter.done (); /*Hack: Do _not_ ::advance after remove*/)
{
ip_mreq *pm = iter.next ();
iter.remove ();
delete pm;
}
#endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
return result;
}
| void ACE_SOCK_Dgram_Mcast::dump | ( | void | ) | const |
Dump the state of an object.
Logs the setting of all options, the bound address, the send address and interface, and the list of current subscriptions.
Reimplemented from ACE_SOCK_Dgram.
Definition at line 68 of file SOCK_Dgram_Mcast.cpp.
{
#if defined (ACE_HAS_DUMP)
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::dump");
ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
# if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
ACE_TCHAR addr_string[MAXNAMELEN + 1];
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("\nOptions: bindaddr=%s, nulliface=%s\n"),
ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES) ?
ACE_TEXT ("<Bound>") : ACE_TEXT ("<Not Bound>"),
ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL) ?
ACE_TEXT ("<All Ifaces>") : ACE_TEXT ("<Default Iface>")));
// Show default send addr, port#, and interface.
ACE_SDM_helpers::addr_to_string (this->send_addr_, addr_string,
sizeof addr_string, 0);
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("Send addr=%s iface=%s\n"),
addr_string,
this->send_net_if_ ? this->send_net_if_
: ACE_TEXT ("<default>")));
// Show list of subscribed addresses.
ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Subscription list:\n")));
ACE_MT (ACE_GUARD (ACE_SDM_LOCK, guard, this->subscription_list_lock_));
subscription_list_iter_t iter (this->subscription_list_);
for ( ; !iter.done (); iter.advance ())
{
ACE_TCHAR iface_string[MAXNAMELEN + 1];
ip_mreq *pm = iter.next ();
// Get subscribed address (w/out port# info - not relevant).
ACE_INET_Addr ip_addr (static_cast<u_short> (0),
ACE_NTOHL (pm->IMR_MULTIADDR.s_addr));
ACE_SDM_helpers::addr_to_string (ip_addr, addr_string,
sizeof addr_string, 1);
// Get interface address/specification.
ACE_INET_Addr if_addr (static_cast<u_short> (0),
ACE_NTOHL (pm->imr_interface.s_addr));
ACE_SDM_helpers::addr_to_string (if_addr, iface_string,
sizeof iface_string, 1);
if (ACE_OS::strcmp (iface_string, ACE_TEXT ("0.0.0.0")) == 0)
// Receives on system default iface. (Note that null_iface_opt_
// option processing has already occurred.)
ACE_OS::strcpy (iface_string, ACE_TEXT ("<default>"));
// Dump info.
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("\taddr=%s iface=%s\n"),
addr_string,
iface_string));
}
# endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
#endif /* ACE_HAS_DUMP */
}
| int ACE_SOCK_Dgram_Mcast::join | ( | const ACE_INET_Addr & | mcast_addr, | |
| int | reuse_addr = 1, |
|||
| const ACE_TCHAR * | net_if = 0 | |||
| ) |
Join a multicast group on a given interface (or all interfaces, if supported). The given group is joined on the specified interface. If option OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is joined on all multicast capable interfaces (IFF supported). Multiple subscriptions to various address and interface combinations are supported and tracked. If this is the first invocation of <subscribe>, and <open> was not previously invoked, <open> will be invoked using <mcast_addr> for binding the socket and <net_if> as the interface for <send>.
Returns: -1 if the call fails. Failure can occur due to problems with the address, port#, and/or interface parameters or during the subscription attempt. Once bind() has been invoked (by the first <open> or <subscribe>), returns errno of ENXIO if the port# is not 0 and does not match the bound port#, or if OPT_BINDADDR_YES option is used and the address does not match the bound address. Returns errno of ENODEV if the addr/port#/interface parameters appeared valid, but no subscription(s) succeeded. An error is unconditionally returned if option OPT_NULLIFACE_ALL is used, <net_if> is NULL, and <ACE_Sock_Connect::get_ip_interfaces> is not implemented in this environment.
Note that the optional reuse_addr parameter does not apply to subscriptions; it is only used if <open> is implicitly invoked (see above).
Uses the mcast_addr to determine protocol_family, and protocol which we always pass as 0 anyway.
Definition at line 468 of file SOCK_Dgram_Mcast.cpp.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::join");
ACE_INET_Addr subscribe_addr = mcast_addr;
// If port# is 0, insert bound port# if it is set. (To satisfy lower-level
// port# validation.)
u_short def_port_number = this->send_addr_.get_port_number ();
if (subscribe_addr.get_port_number () == 0
&& def_port_number != 0)
{
subscribe_addr.set_port_number (def_port_number);
}
// Check for port# different than bound port#.
u_short sub_port_number = mcast_addr.get_port_number ();
if (sub_port_number != 0
&& def_port_number != 0
&& sub_port_number != def_port_number)
{
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("Subscribed port# (%u) different than bound ")
ACE_TEXT ("port# (%u).\n"),
(u_int) sub_port_number,
(u_int) def_port_number));
errno = ENXIO;
return -1;
}
// If bind_addr_opt_ is enabled, check for address different than
// bound address.
ACE_INET_Addr tmp_addr (this->send_addr_);
tmp_addr.set_port_number (mcast_addr.get_port_number ()); // force equal port numbers
if (ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES)
&& !this->send_addr_.is_any ()
&& this->send_addr_ != mcast_addr)
{
ACE_TCHAR sub_addr_string[MAXNAMELEN + 1];
ACE_TCHAR bound_addr_string[MAXNAMELEN + 1];
ACE_SDM_helpers::addr_to_string (mcast_addr, sub_addr_string,
sizeof sub_addr_string, 1);
ACE_SDM_helpers::addr_to_string (this->send_addr_, bound_addr_string,
sizeof bound_addr_string, 1);
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("Subscribed address (%s) different than ")
ACE_TEXT ("bound address (%s).\n"),
sub_addr_string,
bound_addr_string));
errno = ENXIO;
return -1;
}
// Attempt subscription.
int result = this->subscribe_i (subscribe_addr, reuse_addr, net_if);
#if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
if (result == 0)
{
// Add this addr/iface info to the list of subscriptions.
// (Assumes this is unique addr/iface combo - most systems don't allow
// re-sub to same addr/iface.)
ip_mreq *pmreq = new ip_mreq;
// (should not fail)
if (this->make_multicast_ifaddr (pmreq, subscribe_addr, net_if) != -1)
{
ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
this->subscription_list_lock_, -1));
this->subscription_list_.insert_tail (pmreq);
return 0;
}
// this still isn't really right. If ACE_GUARD_RETURN fails, we leak.
// Need to add one of Chris' fancy ace auto pointers (bound?).
delete pmreq;
}
#endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
return result >= 0 ? 0 : result;
}
| int ACE_SOCK_Dgram_Mcast::leave | ( | const ACE_INET_Addr & | mcast_addr, | |
| const ACE_TCHAR * | net_if = 0 | |||
| ) |
Leave a multicast group on a given interface (or all interfaces, if supported). The specified group/interface combination is unsubscribed. If option OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is unsubscribed from all interfaces (IFF supported).
Returns: -1 if the unsubscribe failed. Most environments will return -1 if there was no active subscription for this address/interface combination. An error is unconditionally returned if option OPT_NULLIFACE_ALL is used, <net_if> is = 0, and <ACE_Sock_Connect::get_ip_interfaces> is not implemented in this environment (_even if_ the <subscribe> specifies a non- NULL <net_if>).
leave() replaces unsubscribe() and uses mcast_addr to determine protocol_family, and protocol which we always pass as 0 anyway.
Definition at line 802 of file SOCK_Dgram_Mcast.cpp.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::leave");
// Unsubscribe.
int result = this->unsubscribe_i (mcast_addr,
net_if);
#if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
// (Unconditionally) Remove this addr/if from subscription list.
// (Addr/if is removed even if unsubscribe failed)
ip_mreq tgt_mreq;
if (this->make_multicast_ifaddr (&tgt_mreq,
mcast_addr,
net_if) != -1)
{
ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
this->subscription_list_lock_, -1));
subscription_list_iter_t iter (this->subscription_list_);
for (; !iter.done (); iter.advance ())
{
ip_mreq *pm = iter.next ();
if (ACE_SDM_helpers::is_equal (*pm, tgt_mreq))
{
iter.remove ();
delete pm;
break;
}
}
}
#endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
return result >= 0 ? 0 : result;
}
| int ACE_SOCK_Dgram_Mcast::open | ( | const ACE_INET_Addr & | mcast_addr, | |
| const ACE_TCHAR * | net_if = 0, |
|||
| int | reuse_addr = 1 | |||
| ) |
Explicitly open/bind the socket and define the network interface and default multicast address used for sending messages. This method is optional; if not explicitly invoked, it is invoked by the first <subscribe>, using the subscribed address/port# and network interface parameters. The <mcast_addr> parameter defines the default send address/port# and also the port# and, if the OPT_BINDADDR_YES option is used, the multicast address that is bound to this socket. If the <send_net_if> parameter != 0, it defines the network interface used for all sends by this instance, otherwise the system "default" interface is used. (The <send_net_if> parameter is ignored if this feature is not supported by the envriornment.) The port# in <mcast_addr> may be 0, in which case a system-assigned (ephemeral) port# is used for sending and receiving. If reuse_addr != 0, the SO_REUSEADDR option and, if it is supported, the SO_REUSEPORT option are enabled.
Returns: -1 if the call fails. Failure can occur due to problems with the address, port#, and/or interface parameters or during system open() or socket option processing.
Definition at line 151 of file SOCK_Dgram_Mcast.cpp.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open");
// Only perform the <open> initialization if we haven't been opened
// earlier.
// No sanity check? We should probably flag an error if the user
// makes multiple calls to open().
if (this->get_handle () != ACE_INVALID_HANDLE)
return 0;
// Invoke lower-layer ::open.
if (ACE_SOCK::open (SOCK_DGRAM,
mcast_addr.get_type (),
0, // always use 0
reuse_addr) == -1)
return -1;
return this->open_i (mcast_addr, net_if, reuse_addr);
}
| int ACE_SOCK_Dgram_Mcast::open_i | ( | const ACE_INET_Addr & | mcast_addr, | |
| const ACE_TCHAR * | net_if = 0, |
|||
| int | reuse_addr = 1 | |||
| ) | [protected] |
Contains common open functionality so that inheriting classes can reuse it.
Definition at line 175 of file SOCK_Dgram_Mcast.cpp.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open_i");
// ACE_SOCK::open calls this if reuse_addr is set, so we only need to
// process port reuse option.
if (reuse_addr)
{
#if defined (SO_REUSEPORT)
int one = 1;
if (this->ACE_SOCK::set_option (SOL_SOCKET,
SO_REUSEPORT,
&one,
sizeof one) == -1)
return -1;
#endif /* SO_REUSEPORT */
}
// Create an address/port# to bind the socket to. Use mcast_addr to
// initialize bind_addy to pick up the correct protocol family. If
// OPT_BINDADDR_YES is set, then we're done. Else use mcast_addr's
// port number and use the "any" address.
ACE_INET_Addr bind_addy (mcast_addr);
if (ACE_BIT_DISABLED (this->opts_, OPT_BINDADDR_YES))
{
#if defined (ACE_HAS_IPV6)
if (mcast_addr.get_type () == PF_INET6)
{
if (bind_addy.set (mcast_addr.get_port_number (), "::",
1, AF_INET6) == -1)
return -1;
}
else
// Bind to "any" address and explicit port#.
if (bind_addy.set (mcast_addr.get_port_number ()) == -1)
return -1;
#else
// Bind to "any" address and explicit port#.
if (bind_addy.set (mcast_addr.get_port_number ()) == -1)
return -1;
#endif /* ACE_HAS_IPV6 */
}
// Bind to the address (which may be INADDR_ANY) and port# (which may be 0)
if (ACE_SOCK_Dgram::shared_open (bind_addy, bind_addy.get_type ()) == -1)
return -1;
// Cache the actual bound address (which may be INADDR_ANY)
// and the actual bound port# (which will be a valid, non-zero port#).
ACE_INET_Addr bound_addy;
if (this->get_local_addr (bound_addy) == -1)
{
// (Unexpected failure - should be bound to something)
if (bound_addy.set (bind_addy) == -1)
{
// (Shouldn't happen - bind_addy is a valid addy; punt.)
return -1;
}
}
this->send_addr_ = mcast_addr;
this->send_addr_.set_port_number (bound_addy.get_port_number ());
if (net_if)
{
if (this->set_nic (net_if, mcast_addr.get_type ()))
return -1;
this->send_net_if_ = new ACE_TCHAR[ACE_OS::strlen (net_if) + 1];
ACE_OS::strcpy (this->send_net_if_, net_if);
}
return 0;
}
| ssize_t ACE_SOCK_Dgram_Mcast::send | ( | const void * | buf, | |
| size_t | n, | |||
| int | flags = 0 | |||
| ) | const |
Send n bytes in buf, using the multicast address and network interface defined by the first <open> or <subscribe>.
Definition at line 29 of file SOCK_Dgram_Mcast.inl.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::send");
return this->ACE_SOCK_Dgram::send (buf,
n,
this->send_addr_,
flags);
}
| ssize_t ACE_SOCK_Dgram_Mcast::send | ( | const iovec | iov[], | |
| int | n, | |||
| int | flags = 0 | |||
| ) | const |
Send n <iovecs>, using the multicast address and network interface defined by the first <open> or <subscribe>.
Definition at line 41 of file SOCK_Dgram_Mcast.inl.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::send");
return this->ACE_SOCK_Dgram::send (iov,
n,
this->send_addr_,
flags);
}
| int ACE_SOCK_Dgram_Mcast::set_option | ( | int | option, | |
| char | optval | |||
| ) |
Set a socket option.
Set an IP option that takes a char as input, such as IP_MULTICAST_LOOP or IP_MULTICAST_TTL. This is just a more concise, nice interface to a subset of possible ACE_SOCK::set_option calls, but only works for IPPROTO_IP or IPPROTO_IPV6 level options.
Returns 0 on success, -1 on failure.
Definition at line 8 of file SOCK_Dgram_Mcast.inl.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::set_option");
if (this->get_handle () == ACE_INVALID_HANDLE)
return -1;
int level = IPPROTO_IP;
#if defined (IPPROTO_IPV6) && ! defined (INTEGRITY)
if (this->send_addr_.get_type () == PF_INET6)
level = IPPROTO_IPV6;
#endif /* IPPROTO_IPV6 */
return this->ACE_SOCK::set_option (level,
option,
&optval,
sizeof (optval));
}
| int ACE_SOCK_Dgram_Mcast::subscribe_i | ( | const ACE_INET_Addr & | mcast_addr, | |
| int | reuse_addr = 1, |
|||
| const ACE_TCHAR * | net_if = 0 | |||
| ) | [private] |
Do subscription processing w/out updating the subscription list.
Definition at line 551 of file SOCK_Dgram_Mcast.cpp.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_i");
ip_mreq mreq;
#if defined (ACE_HAS_IPV6)
ipv6_mreq mreq6;
#endif /* __linux__ && ACE_HAS_IPV6 */
// Open the socket IFF this is the first ::subscribe and ::open
// was not explicitly invoked.
if (this->open (mcast_addr,
net_if,
reuse_addr) == -1)
return -1;
// Only do this if net_if == 0, i.e., INADDR_ANY
if (net_if == 0)
{
int result = this->subscribe_ifs (mcast_addr,
net_if,
reuse_addr);
// Check for error or "short-circuit" return.
if (result != 0)
return result;
}
#if defined (ACE_HAS_IPV6)
if (mcast_addr.get_type () == AF_INET6)
{
if (this->make_multicast_ifaddr6 (&mreq6, mcast_addr, net_if) == -1)
return -1;
// Tell IP stack to pass messages sent to this group.
else if (this->ACE_SOCK::set_option (IPPROTO_IPV6,
IPV6_JOIN_GROUP,
&mreq6,
sizeof mreq6) == -1)
return -1;
return 0;
}
// Fall through for IPv4 case
#endif /* ACE_HAS_IPV6 */
// Create multicast addr/if struct.
if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
return -1;
// Tell IP stack to pass messages sent to this group.
else if (this->ACE_SOCK::set_option (IPPROTO_IP,
IP_ADD_MEMBERSHIP,
&mreq,
sizeof mreq) == -1)
return -1;
return 0;
}
| int ACE_SOCK_Dgram_Mcast::subscribe_ifs | ( | const ACE_INET_Addr & | mcast_addr, | |
| const ACE_TCHAR * | net_if, | |||
| int | reuse_addr | |||
| ) | [private] |
Subscribe to a multicast address on one or more network interface(s). (No QoS support.)
Definition at line 251 of file SOCK_Dgram_Mcast.cpp.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_ifs");
if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
&& net_if == 0)
{
#if defined (ACE_HAS_IPV6)
if (mcast_addr.get_type () == AF_INET6)
{
size_t nr_subscribed = 0;
# if defined(__linux__)
struct if_nameindex *intf;
intf = ACE_OS::if_nameindex ();
if (intf == 0)
return -1;
int index = 0;
while (intf[index].if_index != 0 || intf[index].if_name != 0)
{
if (this->join (mcast_addr, reuse_addr,
ACE_TEXT_CHAR_TO_TCHAR(intf[index].if_name)) == 0)
++nr_subscribed;
++index;
}
ACE_OS::if_freenameindex (intf);
# elif defined (ACE_WIN32)
IP_ADAPTER_ADDRESSES tmp_addrs;
// Initial call to determine actual memory size needed
DWORD dwRetVal;
ULONG bufLen = 0;
if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
0,
0,
&tmp_addrs,
&bufLen)) != ERROR_BUFFER_OVERFLOW)
return -1; // With output bufferlength 0 this can't be right.
// Get required output buffer and retrieve info for real.
PIP_ADAPTER_ADDRESSES pAddrs;
char *buf;
ACE_NEW_RETURN (buf,
char[bufLen],
-1);
pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
0,
0,
pAddrs,
&bufLen)) != NO_ERROR)
{
delete[] buf; // clean up
return -1;
}
while (pAddrs)
{
if (this->join (mcast_addr, reuse_addr,
ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
++nr_subscribed;
pAddrs = pAddrs->Next;
}
delete[] buf; // clean up
# endif /* ACE_WIN32 */
if (nr_subscribed == 0)
{
errno = ENODEV;
return -1;
}
return 1;
}
else
{
// Subscribe on all local multicast-capable network interfaces, by
// doing recursive calls with specific interfaces.
ACE_INET_Addr *if_addrs = 0;
size_t if_cnt;
if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
return -1;
size_t nr_subscribed = 0;
if (if_cnt < 2)
{
if (this->join (mcast_addr,
reuse_addr,
ACE_TEXT ("0.0.0.0")) == 0)
++nr_subscribed;
}
else
{
// Iterate through all the interfaces, figure out which ones
// offer multicast service, and subscribe to them.
while (if_cnt > 0)
{
--if_cnt;
// Convert to 0-based for indexing, next loop check.
if (if_addrs[if_cnt].get_type () != AF_INET || if_addrs[if_cnt].is_loopback ())
continue;
char addr_buf[INET6_ADDRSTRLEN];
if (this->join (mcast_addr,
reuse_addr,
ACE_TEXT_CHAR_TO_TCHAR
(if_addrs[if_cnt].get_host_addr (addr_buf, INET6_ADDRSTRLEN))) == 0)
++nr_subscribed;
}
}
delete [] if_addrs;
if (nr_subscribed == 0)
{
errno = ENODEV;
return -1;
}
// 1 indicates a "short-circuit" return. This handles the
// recursive behavior of checking all the interfaces.
return 1;
}
#else
// Subscribe on all local multicast-capable network interfaces, by
// doing recursive calls with specific interfaces.
ACE_INET_Addr *if_addrs = 0;
size_t if_cnt;
if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
return -1;
size_t nr_subscribed = 0;
if (if_cnt < 2)
{
if (this->join (mcast_addr,
reuse_addr,
ACE_TEXT ("0.0.0.0")) == 0)
++nr_subscribed;
}
else
{
// Iterate through all the interfaces, figure out which ones
// offer multicast service, and subscribe to them.
while (if_cnt > 0)
{
--if_cnt;
// Convert to 0-based for indexing, next loop check.
if (if_addrs[if_cnt].is_loopback ())
continue;
char addr_buf[INET6_ADDRSTRLEN];
if (this->join (mcast_addr,
reuse_addr,
ACE_TEXT_CHAR_TO_TCHAR
(if_addrs[if_cnt].get_host_addr (addr_buf, INET6_ADDRSTRLEN))) == 0)
++nr_subscribed;
}
}
delete [] if_addrs;
if (nr_subscribed == 0)
{
errno = ENODEV;
return -1;
}
// 1 indicates a "short-circuit" return. This handles the
// recursive behavior of checking all the interfaces.
return 1;
#endif /* ACE_HAS_IPV6 */
}
#if defined (ACE_HAS_IPV6)
if (mcast_addr.get_type () == AF_INET6)
{
if (this->make_multicast_ifaddr6 (0, mcast_addr, net_if) == -1)
return -1;
}
else
{
// Validate passed multicast addr and iface specifications.
if (this->make_multicast_ifaddr (0,
mcast_addr,
net_if) == -1)
return -1;
}
#else
// Validate passed multicast addr and iface specifications.
if (this->make_multicast_ifaddr (0,
mcast_addr,
net_if) == -1)
return -1;
#endif /* ACE_HAS_IPV6 */
return 0;
}
| int ACE_SOCK_Dgram_Mcast::unsubscribe_i | ( | const ACE_INET_Addr & | mcast_addr, | |
| const ACE_TCHAR * | net_if = 0 | |||
| ) | [private] |
Do unsubscription processing w/out udpating subscription list.
Definition at line 839 of file SOCK_Dgram_Mcast.cpp.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_i");
int result = this->unsubscribe_ifs (mcast_addr,
net_if);
// Check for error or "short-circuit" return.
if (result != 0)
return result;
#if defined (ACE_HAS_IPV6)
if (mcast_addr.get_type () == AF_INET6)
{
// Validate addr/if specifications and create addr/if struct.
ipv6_mreq mreq;
if (this->make_multicast_ifaddr6 (&mreq, mcast_addr, net_if) == -1)
{
return -1;
}
// Tell network device driver to stop reading datagrams with the
// <mcast_addr>.
else if (ACE_SOCK::set_option (IPPROTO_IPV6,
IPV6_LEAVE_GROUP,
&mreq,
sizeof mreq) == -1)
{
return -1;
}
}
else // IPv4
{
// Validate addr/if specifications and create addr/if struct.
ip_mreq mreq;
if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
{
return -1;
}
// Tell network device driver to stop reading datagrams with the
// <mcast_addr>.
else if (ACE_SOCK::set_option (IPPROTO_IP,
IP_DROP_MEMBERSHIP,
&mreq,
sizeof mreq) == -1)
{
return -1;
}
}
#else
// Validate addr/if specifications and create addr/if struct.
ip_mreq mreq;
if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
{
return -1;
}
// Tell network device driver to stop reading datagrams with the
// <mcast_addr>.
// Note, this is not IPv6 friendly...
else if (ACE_SOCK::set_option (IPPROTO_IP,
IP_DROP_MEMBERSHIP,
&mreq,
sizeof mreq) == -1)
{
return -1;
}
#endif /* ACE_HAS_IPV6 */
return 0;
}
| int ACE_SOCK_Dgram_Mcast::unsubscribe_ifs | ( | const ACE_INET_Addr & | mcast_addr, | |
| const ACE_TCHAR * | net_if = 0 | |||
| ) | [private] |
Unsubscribe from a multicast address on one or more network interface(s).
Definition at line 610 of file SOCK_Dgram_Mcast.cpp.
{
ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_ifs");
if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
&& net_if == 0)
{
#if defined (ACE_HAS_IPV6)
if (mcast_addr.get_type () == AF_INET6)
{
size_t nr_unsubscribed = 0;
# if defined(__linux__)
struct if_nameindex *intf;
intf = ACE_OS::if_nameindex ();
if (intf == 0)
return -1;
int index = 0;
while (intf[index].if_index != 0 || intf[index].if_name != 0)
{
if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(intf[index].if_name)) == 0)
++nr_unsubscribed;
++index;
}
ACE_OS::if_freenameindex (intf);
# elif defined (ACE_WIN32)
IP_ADAPTER_ADDRESSES tmp_addrs;
// Initial call to determine actual memory size needed
DWORD dwRetVal;
ULONG bufLen = 0;
if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
0,
0,
&tmp_addrs,
&bufLen)) != ERROR_BUFFER_OVERFLOW)
return -1; // With output bufferlength 0 this can't be right.
// Get required output buffer and retrieve info for real.
PIP_ADAPTER_ADDRESSES pAddrs;
char *buf;
ACE_NEW_RETURN (buf,
char[bufLen],
-1);
pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
0,
0,
pAddrs,
&bufLen)) != NO_ERROR)
{
delete[] buf; // clean up
return -1;
}
while (pAddrs)
{
if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
++nr_unsubscribed;
pAddrs = pAddrs->Next;
}
delete[] buf; // clean up
# endif /* ACE_WIN32 */
if (nr_unsubscribed == 0)
{
errno = ENODEV;
return -1;
}
return 1;
}
else
{
// Unsubscribe on all local multicast-capable network interfaces, by
// doing recursive calls with specific interfaces.
ACE_INET_Addr *if_addrs = 0;
size_t if_cnt;
// NOTE - <get_ip_interfaces> doesn't always get all of the
// interfaces. In particular, it may not get a PPP interface. This
// is a limitation of the way <get_ip_interfaces> works with
// old versions of MSVC. The reliable way of getting the interface
// list is available only with MSVC 5 and newer.
if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
return -1;
size_t nr_unsubscribed = 0;
if (if_cnt < 2)
{
if (this->leave (mcast_addr,
ACE_TEXT ("0.0.0.0")) == 0)
++nr_unsubscribed;
}
else
{
while (if_cnt > 0)
{
--if_cnt;
// Convert to 0-based for indexing, next loop check
if (if_addrs[if_cnt].get_type () != AF_INET || if_addrs[if_cnt].is_loopback ())
continue;
char addr_buf[INET6_ADDRSTRLEN];
if (this->leave (mcast_addr,
ACE_TEXT_CHAR_TO_TCHAR
(if_addrs[if_cnt].get_host_addr (addr_buf, INET6_ADDRSTRLEN))) == 0)
++nr_unsubscribed;
}
}
delete [] if_addrs;
if (nr_unsubscribed == 0)
{
errno = ENODEV;
return -1;
}
return 1;
}
#else /* ACE_HAS_IPV6 */
// Unsubscribe on all local multicast-capable network interfaces, by
// doing recursive calls with specific interfaces.
ACE_INET_Addr *if_addrs = 0;
size_t if_cnt;
// NOTE - <get_ip_interfaces> doesn't always get all of the
// interfaces. In particular, it may not get a PPP interface. This
// is a limitation of the way <get_ip_interfaces> works with
// old versions of MSVC. The reliable way of getting the interface list
// is available only with MSVC 5 and newer.
if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
return -1;
size_t nr_unsubscribed = 0;
if (if_cnt < 2)
{
if (this->leave (mcast_addr,
ACE_TEXT ("0.0.0.0")) == 0)
++nr_unsubscribed;
}
else
{
while (if_cnt > 0)
{
--if_cnt;
// Convert to 0-based for indexing, next loop check
if (if_addrs[if_cnt].is_loopback ())
continue;
char addr_buf[INET6_ADDRSTRLEN];
if (this->leave (mcast_addr,
ACE_TEXT_CHAR_TO_TCHAR
(if_addrs[if_cnt].get_host_addr (addr_buf, INET6_ADDRSTRLEN))) == 0)
++nr_unsubscribed;
}
}
delete [] if_addrs;
if (nr_unsubscribed == 0)
{
errno = ENODEV;
return -1;
}
return 1;
#endif /* !ACE_HAS_IPV6 */
}
return 0;
}
Declare the dynamic allocation hooks.
Reimplemented from ACE_SOCK_Dgram.
Reimplemented in ACE_SOCK_Dgram_Mcast_QoS.
Definition at line 319 of file SOCK_Dgram_Mcast.h.
int ACE_SOCK_Dgram_Mcast::opts_ [private] |
Per-instance options..
Definition at line 358 of file SOCK_Dgram_Mcast.h.
Multicast address to which local <send> methods send datagrams.
Definition at line 361 of file SOCK_Dgram_Mcast.h.
ACE_TCHAR* ACE_SOCK_Dgram_Mcast::send_net_if_ [private] |
Network interface to which all <send> methods send multicast datagrams.
Definition at line 363 of file SOCK_Dgram_Mcast.h.
1.7.0