00001
00002
00003 #include "ace/SOCK_Dgram_Mcast.h"
00004
00005 #include "ace/OS_Memory.h"
00006 #include "ace/OS_NS_string.h"
00007 #include "ace/OS_NS_errno.h"
00008 #include "ace/os_include/net/os_if.h"
00009 #include "ace/os_include/arpa/os_inet.h"
00010
00011 #if defined (__linux__) && defined (ACE_HAS_IPV6)
00012 #include "ace/OS_NS_sys_socket.h"
00013 #endif
00014
00015 #if defined (ACE_HAS_IPV6) && defined (ACE_WIN32)
00016 #include <Iphlpapi.h>
00017 #endif
00018
00019 #if !defined (__ACE_INLINE__)
00020 #include "ace/SOCK_Dgram_Mcast.inl"
00021 #endif
00022
00023 ACE_RCSID (ace,
00024 SOCK_Dgram_Mcast,
00025 "$Id: SOCK_Dgram_Mcast.cpp 79134 2007-07-31 18:23:50Z johnnyw $")
00026
00027 #include "ace/Log_Msg.h"
00028
00029
00030
00031 #if ! defined (IMR_MULTIADDR)
00032 #define IMR_MULTIADDR imr_multiaddr
00033 #endif
00034
00035 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00036
00037
00038 class ACE_SDM_helpers
00039 {
00040 public:
00041
00042
00043 static void addr_to_string (const ACE_INET_Addr &ip_addr,
00044 ACE_TCHAR *ret_string,
00045 size_t len,
00046 int clip_portnum)
00047 {
00048 if (ip_addr.addr_to_string (ret_string, len, 1) == -1)
00049 ACE_OS::strcpy (ret_string, ACE_TEXT ("<?>"));
00050 else
00051 {
00052 ACE_TCHAR *pc = ACE_OS::strrchr (ret_string, ACE_TEXT (':'));
00053 if (clip_portnum && pc)
00054 *pc = ACE_TEXT ('\0');
00055 }
00056 }
00057
00058 static int is_equal (const ip_mreq &m1, const ip_mreq &m2)
00059 {
00060 return m1.IMR_MULTIADDR.s_addr == m2.IMR_MULTIADDR.s_addr
00061 && m1.imr_interface.s_addr == m2.imr_interface.s_addr;
00062 }
00063 };
00064
00065 ACE_ALLOC_HOOK_DEFINE (ACE_SOCK_Dgram_Mcast)
00066
00067 void
00068 ACE_SOCK_Dgram_Mcast::dump (void) const
00069 {
00070 #if defined (ACE_HAS_DUMP)
00071 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::dump");
00072
00073 ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00074
00075 # if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00076 ACE_TCHAR addr_string[MAXNAMELEN + 1];
00077
00078 ACE_DEBUG ((LM_DEBUG,
00079 ACE_TEXT ("\nOptions: bindaddr=%s, nulliface=%s\n"),
00080 ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES) ?
00081 ACE_TEXT ("<Bound>") : ACE_TEXT ("<Not Bound>"),
00082 ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL) ?
00083 ACE_TEXT ("<All Ifaces>") : ACE_TEXT ("<Default Iface>")));
00084
00085
00086 ACE_SDM_helpers::addr_to_string (this->send_addr_, addr_string,
00087 sizeof addr_string, 0);
00088 ACE_DEBUG ((LM_DEBUG,
00089 ACE_TEXT ("Send addr=%s iface=%s\n"),
00090 addr_string,
00091 this->send_net_if_ ? this->send_net_if_
00092 : ACE_TEXT ("<default>")));
00093
00094
00095 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Subscription list:\n")));
00096
00097 ACE_MT (ACE_GUARD (ACE_SDM_LOCK, guard, this->subscription_list_lock_));
00098 subscription_list_iter_t iter (this->subscription_list_);
00099 for ( ; !iter.done (); iter.advance ())
00100 {
00101 ACE_TCHAR iface_string[MAXNAMELEN + 1];
00102 ip_mreq *pm = iter.next ();
00103
00104
00105 ACE_INET_Addr ip_addr (static_cast<u_short> (0),
00106 ACE_NTOHL (pm->IMR_MULTIADDR.s_addr));
00107 ACE_SDM_helpers::addr_to_string (ip_addr, addr_string,
00108 sizeof addr_string, 1);
00109
00110
00111 ACE_INET_Addr if_addr (static_cast<u_short> (0),
00112 ACE_NTOHL (pm->imr_interface.s_addr));
00113 ACE_SDM_helpers::addr_to_string (if_addr, iface_string,
00114 sizeof iface_string, 1);
00115 if (ACE_OS::strcmp (iface_string, ACE_TEXT ("0.0.0.0")) == 0)
00116
00117
00118 ACE_OS::strcpy (iface_string, ACE_TEXT ("<default>"));
00119
00120
00121 ACE_DEBUG ((LM_DEBUG,
00122 ACE_TEXT ("\taddr=%s iface=%s\n"),
00123 addr_string,
00124 iface_string));
00125 }
00126 # endif
00127 ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00128 #endif
00129 }
00130
00131
00132 ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast
00133 (ACE_SOCK_Dgram_Mcast::options opts)
00134 : opts_ (opts),
00135 send_net_if_ (0)
00136 {
00137 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast");
00138 }
00139
00140
00141 ACE_SOCK_Dgram_Mcast::~ACE_SOCK_Dgram_Mcast (void)
00142 {
00143 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::~ACE_SOCK_Dgram_Mcast");
00144
00145
00146 delete [] this->send_net_if_;
00147 this->clear_subs_list ();
00148 }
00149
00150 int
00151 ACE_SOCK_Dgram_Mcast::open (const ACE_INET_Addr &mcast_addr,
00152 const ACE_TCHAR *net_if,
00153 int reuse_addr)
00154 {
00155 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open");
00156
00157
00158
00159
00160
00161 if (this->get_handle () != ACE_INVALID_HANDLE)
00162 return 0;
00163
00164
00165 if (ACE_SOCK::open (SOCK_DGRAM,
00166 mcast_addr.get_type (),
00167 0,
00168 reuse_addr) == -1)
00169 return -1;
00170
00171 return this->open_i (mcast_addr, net_if, reuse_addr);
00172 }
00173
00174 int
00175 ACE_SOCK_Dgram_Mcast::open_i (const ACE_INET_Addr &mcast_addr,
00176 const ACE_TCHAR *net_if,
00177 int reuse_addr)
00178 {
00179 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open_i");
00180
00181
00182 if (reuse_addr)
00183 {
00184 #if defined (SO_REUSEPORT)
00185 int one = 1;
00186 if (this->ACE_SOCK::set_option (SOL_SOCKET,
00187 SO_REUSEPORT,
00188 &one,
00189 sizeof one) == -1)
00190 return -1;
00191 #endif
00192 }
00193
00194
00195
00196
00197
00198 ACE_INET_Addr bind_addy (mcast_addr);
00199 if (ACE_BIT_DISABLED (this->opts_, OPT_BINDADDR_YES))
00200 {
00201 #if defined (ACE_HAS_IPV6)
00202 if (mcast_addr.get_type () == PF_INET6)
00203 {
00204 if (bind_addy.set (mcast_addr.get_port_number (), "::",
00205 1, AF_INET6) == -1)
00206 return -1;
00207 }
00208 else
00209
00210 if (bind_addy.set (mcast_addr.get_port_number ()) == -1)
00211 return -1;
00212 #else
00213
00214 if (bind_addy.set (mcast_addr.get_port_number ()) == -1)
00215 return -1;
00216 #endif
00217 }
00218
00219
00220 if (ACE_SOCK_Dgram::shared_open (bind_addy, bind_addy.get_type ()) == -1)
00221 return -1;
00222
00223
00224
00225 ACE_INET_Addr bound_addy;
00226 if (this->get_local_addr (bound_addy) == -1)
00227 {
00228
00229 if (bound_addy.set (bind_addy) == -1)
00230 {
00231
00232 return -1;
00233 }
00234 }
00235
00236 this->send_addr_ = mcast_addr;
00237 this->send_addr_.set_port_number (bound_addy.get_port_number ());
00238 if (net_if)
00239 {
00240 if (this->set_nic (net_if, mcast_addr.get_type ()))
00241 return -1;
00242
00243 this->send_net_if_ = new ACE_TCHAR[ACE_OS::strlen (net_if) + 1];
00244 ACE_OS::strcpy (this->send_net_if_, net_if);
00245 }
00246
00247 return 0;
00248 }
00249
00250 int
00251 ACE_SOCK_Dgram_Mcast::subscribe_ifs (const ACE_INET_Addr &mcast_addr,
00252 const ACE_TCHAR *net_if,
00253 int reuse_addr)
00254 {
00255 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_ifs");
00256
00257 if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
00258 && net_if == 0)
00259 {
00260 #if defined (ACE_HAS_IPV6)
00261 if (mcast_addr.get_type () == AF_INET6)
00262 {
00263 size_t nr_subscribed = 0;
00264 # if defined(__linux__)
00265 struct if_nameindex *intf;
00266
00267 intf = ACE_OS::if_nameindex ();
00268
00269 if (intf == 0)
00270 return -1;
00271
00272 int index = 0;
00273 while (intf[index].if_index != 0 || intf[index].if_name != 0)
00274 {
00275 if (this->join (mcast_addr, reuse_addr,
00276 ACE_TEXT_CHAR_TO_TCHAR(intf[index].if_name)) == 0)
00277 ++nr_subscribed;
00278
00279 ++index;
00280 }
00281
00282 ACE_OS::if_freenameindex (intf);
00283
00284 # elif defined (ACE_WIN32)
00285
00286 IP_ADAPTER_ADDRESSES tmp_addrs;
00287
00288 DWORD dwRetVal;
00289 ULONG bufLen = 0;
00290 if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00291 0,
00292 0,
00293 &tmp_addrs,
00294 &bufLen)) != ERROR_BUFFER_OVERFLOW)
00295 return -1;
00296
00297
00298 PIP_ADAPTER_ADDRESSES pAddrs;
00299 char *buf;
00300 ACE_NEW_RETURN (buf,
00301 char[bufLen],
00302 -1);
00303 pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
00304 if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00305 0,
00306 0,
00307 pAddrs,
00308 &bufLen)) != NO_ERROR)
00309 {
00310 delete[] buf;
00311 return -1;
00312 }
00313
00314 while (pAddrs)
00315 {
00316 if (this->join (mcast_addr, reuse_addr,
00317 ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
00318 ++nr_subscribed;
00319
00320 pAddrs = pAddrs->Next;
00321 }
00322
00323 delete[] buf;
00324
00325 # endif
00326
00327 if (nr_subscribed == 0)
00328 {
00329 errno = ENODEV;
00330 return -1;
00331 }
00332
00333 return 1;
00334 }
00335 else
00336 {
00337
00338
00339
00340 ACE_INET_Addr *if_addrs = 0;
00341 size_t if_cnt;
00342
00343 if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00344 return -1;
00345
00346 size_t nr_subscribed = 0;
00347
00348 if (if_cnt < 2)
00349 {
00350 if (this->subscribe (mcast_addr,
00351 reuse_addr,
00352 ACE_TEXT ("0.0.0.0")) == 0)
00353 ++nr_subscribed;
00354 }
00355 else
00356 {
00357
00358
00359 while (if_cnt > 0)
00360 {
00361 --if_cnt;
00362
00363
00364 if (if_addrs[if_cnt].get_type () != AF_INET || if_addrs[if_cnt].is_loopback ())
00365 continue;
00366 if (this->subscribe (mcast_addr,
00367 reuse_addr,
00368 ACE_TEXT_CHAR_TO_TCHAR
00369 (if_addrs[if_cnt].get_host_addr ())) == 0)
00370 ++nr_subscribed;
00371 }
00372 }
00373
00374 delete [] if_addrs;
00375
00376 if (nr_subscribed == 0)
00377 {
00378 errno = ENODEV;
00379 return -1;
00380 }
00381
00382
00383
00384 return 1;
00385
00386 }
00387 #else
00388
00389
00390
00391 ACE_INET_Addr *if_addrs = 0;
00392 size_t if_cnt;
00393
00394 if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00395 return -1;
00396
00397 size_t nr_subscribed = 0;
00398
00399 if (if_cnt < 2)
00400 {
00401 if (this->subscribe (mcast_addr,
00402 reuse_addr,
00403 ACE_TEXT ("0.0.0.0")) == 0)
00404 ++nr_subscribed;
00405 }
00406 else
00407 {
00408
00409
00410 while (if_cnt > 0)
00411 {
00412 --if_cnt;
00413
00414
00415 if (if_addrs[if_cnt].is_loopback ())
00416 continue;
00417 if (this->subscribe (mcast_addr,
00418 reuse_addr,
00419 ACE_TEXT_CHAR_TO_TCHAR
00420 (if_addrs[if_cnt].get_host_addr ())) == 0)
00421 ++nr_subscribed;
00422 }
00423 }
00424
00425 delete [] if_addrs;
00426
00427 if (nr_subscribed == 0)
00428 {
00429 errno = ENODEV;
00430 return -1;
00431 }
00432
00433
00434
00435 return 1;
00436 #endif
00437 }
00438
00439 #if defined (ACE_HAS_IPV6)
00440 if (mcast_addr.get_type () == AF_INET6)
00441 {
00442 if (this->make_multicast_ifaddr6 (0, mcast_addr, net_if) == -1)
00443 return -1;
00444 }
00445 else
00446 {
00447
00448 if (this->make_multicast_ifaddr (0,
00449 mcast_addr,
00450 net_if) == -1)
00451 return -1;
00452 }
00453 #else
00454
00455 if (this->make_multicast_ifaddr (0,
00456 mcast_addr,
00457 net_if) == -1)
00458 return -1;
00459 #endif
00460
00461 return 0;
00462
00463 }
00464
00465
00466 int
00467 ACE_SOCK_Dgram_Mcast::subscribe (const ACE_INET_Addr &mcast_addr,
00468 int reuse_addr,
00469 const ACE_TCHAR *net_if,
00470 int protocol_family,
00471 int protocol)
00472 {
00473 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe");
00474
00475 ACE_UNUSED_ARG (protocol_family);
00476 ACE_UNUSED_ARG (protocol);
00477
00478 return this->join (mcast_addr,reuse_addr, net_if);
00479 }
00480
00481 int
00482 ACE_SOCK_Dgram_Mcast::join (const ACE_INET_Addr &mcast_addr,
00483 int reuse_addr,
00484 const ACE_TCHAR *net_if)
00485 {
00486 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::join");
00487 ACE_INET_Addr subscribe_addr = mcast_addr;
00488
00489
00490
00491 u_short def_port_number = this->send_addr_.get_port_number ();
00492 if (subscribe_addr.get_port_number () == 0
00493 && def_port_number != 0)
00494 {
00495 subscribe_addr.set_port_number (def_port_number);
00496 }
00497
00498
00499 u_short sub_port_number = mcast_addr.get_port_number ();
00500 if (sub_port_number != 0
00501 && def_port_number != 0
00502 && sub_port_number != def_port_number)
00503 {
00504 ACE_ERROR ((LM_ERROR,
00505 ACE_TEXT ("Subscribed port# (%u) different than bound ")
00506 ACE_TEXT ("port# (%u).\n"),
00507 (u_int) sub_port_number,
00508 (u_int) def_port_number));
00509 errno = ENXIO;
00510 return -1;
00511 }
00512
00513
00514
00515 ACE_INET_Addr tmp_addr (this->send_addr_);
00516 tmp_addr.set_port_number (mcast_addr.get_port_number ());
00517 if (ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES)
00518 && !this->send_addr_.is_any ()
00519 && this->send_addr_ != mcast_addr)
00520 {
00521 ACE_TCHAR sub_addr_string[MAXNAMELEN + 1];
00522 ACE_TCHAR bound_addr_string[MAXNAMELEN + 1];
00523 ACE_SDM_helpers::addr_to_string (mcast_addr, sub_addr_string,
00524 sizeof sub_addr_string, 1);
00525 ACE_SDM_helpers::addr_to_string (this->send_addr_, bound_addr_string,
00526 sizeof bound_addr_string, 1);
00527 ACE_ERROR ((LM_ERROR,
00528 ACE_TEXT ("Subscribed address (%s) different than ")
00529 ACE_TEXT ("bound address (%s).\n"),
00530 sub_addr_string,
00531 bound_addr_string));
00532 errno = ENXIO;
00533 return -1;
00534 }
00535
00536
00537 int result = this->subscribe_i (subscribe_addr, reuse_addr, net_if);
00538
00539 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00540 if (result == 0)
00541 {
00542
00543
00544
00545 ip_mreq *pmreq = new ip_mreq;
00546
00547 if (this->make_multicast_ifaddr (pmreq, subscribe_addr, net_if) != -1)
00548 {
00549 ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00550 this->subscription_list_lock_, -1));
00551 this->subscription_list_.insert_tail (pmreq);
00552 return 0;
00553 }
00554
00555
00556 delete pmreq;
00557 }
00558 #endif
00559
00560 return result >= 0 ? 0 : result;
00561 }
00562
00563
00564 int
00565 ACE_SOCK_Dgram_Mcast::subscribe_i (const ACE_INET_Addr &mcast_addr,
00566 int reuse_addr,
00567 const ACE_TCHAR *net_if)
00568 {
00569 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_i");
00570 ip_mreq mreq;
00571 #if defined (ACE_HAS_IPV6)
00572 ipv6_mreq mreq6;
00573 #endif
00574
00575
00576
00577 if (this->open (mcast_addr,
00578 net_if,
00579 reuse_addr) == -1)
00580 return -1;
00581
00582
00583 if (net_if == 0)
00584 {
00585 int result = this->subscribe_ifs (mcast_addr,
00586 net_if,
00587 reuse_addr);
00588
00589 if (result != 0)
00590 return result;
00591 }
00592
00593 #if defined (ACE_HAS_IPV6)
00594 if (mcast_addr.get_type () == AF_INET6)
00595 {
00596 if (this->make_multicast_ifaddr6 (&mreq6, mcast_addr, net_if) == -1)
00597 return -1;
00598
00599 else if (this->ACE_SOCK::set_option (IPPROTO_IPV6,
00600 IPV6_JOIN_GROUP,
00601 &mreq6,
00602 sizeof mreq6) == -1)
00603 return -1;
00604
00605 return 0;
00606 }
00607
00608 #endif
00609
00610
00611 if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00612 return -1;
00613
00614 else if (this->ACE_SOCK::set_option (IPPROTO_IP,
00615 IP_ADD_MEMBERSHIP,
00616 &mreq,
00617 sizeof mreq) == -1)
00618 return -1;
00619
00620 return 0;
00621 }
00622
00623 int
00624 ACE_SOCK_Dgram_Mcast::unsubscribe_ifs (const ACE_INET_Addr &mcast_addr,
00625 const ACE_TCHAR *net_if)
00626 {
00627 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_ifs");
00628
00629
00630 if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
00631 && net_if == 0)
00632 {
00633 #if defined (ACE_HAS_IPV6)
00634 if (mcast_addr.get_type () == AF_INET6)
00635 {
00636 size_t nr_unsubscribed = 0;
00637 # if defined(__linux__)
00638
00639 struct if_nameindex *intf;
00640
00641 intf = ACE_OS::if_nameindex ();
00642
00643 if (intf == 0)
00644 return -1;
00645
00646 int index = 0;
00647 while (intf[index].if_index != 0 || intf[index].if_name != 0)
00648 {
00649 if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(intf[index].if_name)) == 0)
00650 ++nr_unsubscribed;
00651
00652 ++index;
00653 }
00654
00655 ACE_OS::if_freenameindex (intf);
00656
00657 # elif defined (ACE_WIN32)
00658
00659 IP_ADAPTER_ADDRESSES tmp_addrs;
00660
00661 DWORD dwRetVal;
00662 ULONG bufLen = 0;
00663 if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00664 0,
00665 0,
00666 &tmp_addrs,
00667 &bufLen)) != ERROR_BUFFER_OVERFLOW)
00668 return -1;
00669
00670
00671 PIP_ADAPTER_ADDRESSES pAddrs;
00672 char *buf;
00673 ACE_NEW_RETURN (buf,
00674 char[bufLen],
00675 -1);
00676 pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
00677 if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00678 0,
00679 0,
00680 pAddrs,
00681 &bufLen)) != NO_ERROR)
00682 {
00683 delete[] buf;
00684 return -1;
00685 }
00686
00687 while (pAddrs)
00688 {
00689 if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
00690 ++nr_unsubscribed;
00691
00692 pAddrs = pAddrs->Next;
00693 }
00694
00695 delete[] buf;
00696
00697 # endif
00698
00699 if (nr_unsubscribed == 0)
00700 {
00701 errno = ENODEV;
00702 return -1;
00703 }
00704
00705 return 1;
00706
00707
00708 }
00709 else
00710 {
00711
00712
00713
00714 ACE_INET_Addr *if_addrs = 0;
00715 size_t if_cnt;
00716
00717
00718
00719
00720
00721
00722 if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00723 return -1;
00724
00725 size_t nr_unsubscribed = 0;
00726
00727 if (if_cnt < 2)
00728 {
00729 if (this->leave (mcast_addr,
00730 ACE_TEXT ("0.0.0.0")) == 0)
00731 ++nr_unsubscribed;
00732 }
00733 else
00734 {
00735 while (if_cnt > 0)
00736 {
00737 --if_cnt;
00738
00739 if (if_addrs[if_cnt].get_type () != AF_INET || if_addrs[if_cnt].is_loopback ())
00740 continue;
00741 if (this->leave (mcast_addr,
00742 ACE_TEXT_CHAR_TO_TCHAR
00743 (if_addrs[if_cnt].get_host_addr ())) == 0)
00744 ++nr_unsubscribed;
00745 }
00746 }
00747
00748 delete [] if_addrs;
00749
00750 if (nr_unsubscribed == 0)
00751 {
00752 errno = ENODEV;
00753 return -1;
00754 }
00755
00756 return 1;
00757
00758 }
00759 #else
00760
00761
00762
00763 ACE_INET_Addr *if_addrs = 0;
00764 size_t if_cnt;
00765
00766
00767
00768
00769
00770
00771 if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00772 return -1;
00773
00774 size_t nr_unsubscribed = 0;
00775
00776 if (if_cnt < 2)
00777 {
00778 if (this->leave (mcast_addr,
00779 ACE_TEXT ("0.0.0.0")) == 0)
00780 ++nr_unsubscribed;
00781 }
00782 else
00783 {
00784 while (if_cnt > 0)
00785 {
00786 --if_cnt;
00787
00788 if (if_addrs[if_cnt].is_loopback ())
00789 continue;
00790 if (this->leave (mcast_addr,
00791 ACE_TEXT_CHAR_TO_TCHAR
00792 (if_addrs[if_cnt].get_host_addr ())) == 0)
00793 ++nr_unsubscribed;
00794 }
00795 }
00796
00797 delete [] if_addrs;
00798
00799 if (nr_unsubscribed == 0)
00800 {
00801 errno = ENODEV;
00802 return -1;
00803 }
00804
00805 return 1;
00806 #endif
00807 }
00808
00809 return 0;
00810 }
00811
00812
00813
00814
00815
00816
00817 int
00818 ACE_SOCK_Dgram_Mcast::unsubscribe (const ACE_INET_Addr &mcast_addr,
00819 const ACE_TCHAR *net_if,
00820 int protocol_family,
00821 int protocol)
00822 {
00823 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe");
00824
00825 ACE_UNUSED_ARG (protocol_family);
00826 ACE_UNUSED_ARG (protocol);
00827
00828 return this->leave (mcast_addr, net_if);
00829 }
00830
00831 int
00832 ACE_SOCK_Dgram_Mcast::leave (const ACE_INET_Addr &mcast_addr,
00833 const ACE_TCHAR *net_if)
00834 {
00835 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::leave");
00836
00837 int result = this->unsubscribe_i (mcast_addr,
00838 net_if);
00839
00840 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00841
00842
00843 ip_mreq tgt_mreq;
00844 if (this->make_multicast_ifaddr (&tgt_mreq,
00845 mcast_addr,
00846 net_if) != -1)
00847 {
00848 ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00849 this->subscription_list_lock_, -1));
00850 subscription_list_iter_t iter (this->subscription_list_);
00851 for (; !iter.done (); iter.advance ())
00852 {
00853 ip_mreq *pm = iter.next ();
00854 if (ACE_SDM_helpers::is_equal (*pm, tgt_mreq))
00855 {
00856 iter.remove ();
00857 delete pm;
00858 break;
00859 }
00860 }
00861 }
00862 #endif
00863
00864 return result >= 0 ? 0 : result;
00865 }
00866
00867
00868 int
00869 ACE_SOCK_Dgram_Mcast::unsubscribe_i (const ACE_INET_Addr &mcast_addr,
00870 const ACE_TCHAR *net_if)
00871 {
00872 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_i");
00873
00874 int result = this->unsubscribe_ifs (mcast_addr,
00875 net_if);
00876
00877
00878 if (result != 0)
00879 return result;
00880
00881 #if defined (ACE_HAS_IPV6)
00882 if (mcast_addr.get_type () == AF_INET6)
00883 {
00884
00885 ipv6_mreq mreq;
00886 if (this->make_multicast_ifaddr6 (&mreq, mcast_addr, net_if) == -1)
00887 {
00888 return -1;
00889 }
00890
00891
00892 else if (ACE_SOCK::set_option (IPPROTO_IPV6,
00893 IPV6_LEAVE_GROUP,
00894 &mreq,
00895 sizeof mreq) == -1)
00896 {
00897 return -1;
00898 }
00899
00900 }
00901 else
00902 {
00903
00904 ip_mreq mreq;
00905 if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00906 {
00907 return -1;
00908 }
00909
00910
00911 else if (ACE_SOCK::set_option (IPPROTO_IP,
00912 IP_DROP_MEMBERSHIP,
00913 &mreq,
00914 sizeof mreq) == -1)
00915 {
00916 return -1;
00917 }
00918
00919 }
00920 #else
00921
00922 ip_mreq mreq;
00923 if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00924 {
00925 return -1;
00926 }
00927
00928
00929
00930 else if (ACE_SOCK::set_option (IPPROTO_IP,
00931 IP_DROP_MEMBERSHIP,
00932 &mreq,
00933 sizeof mreq) == -1)
00934 {
00935 return -1;
00936 }
00937 #endif
00938
00939 return 0;
00940 }
00941
00942 int
00943 ACE_SOCK_Dgram_Mcast::unsubscribe (void)
00944 {
00945 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe");
00946
00947
00948
00949
00950
00951
00952
00953
00954 ACE_ERROR_RETURN ((LM_INFO,
00955 ACE_TEXT ("ACE_SOCK_Dgram_Mcast::unsubscribe (void) ")
00956 ACE_TEXT ("has been deprecated. You must either ")
00957 ACE_TEXT ("close to socket to unsubscribe to all ")
00958 ACE_TEXT ("or unsubscribe to each individually.\n")),
00959 0);
00960 }
00961
00962 int
00963 ACE_SOCK_Dgram_Mcast::clear_subs_list (void)
00964 {
00965 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::clear_subs_list");
00966 int result = 0;
00967
00968 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00969 ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00970 this->subscription_list_lock_, -1));
00971 subscription_list_iter_t iter (this->subscription_list_);
00972 for (; !iter.done (); )
00973 {
00974 ip_mreq *pm = iter.next ();
00975 iter.remove ();
00976 delete pm;
00977 }
00978 #endif
00979 return result;
00980 }
00981
00982 ACE_END_VERSIONED_NAMESPACE_DECL