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 85421 2009-05-22 11:12:30Z 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->join (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 char addr_buf[INET6_ADDRSTRLEN];
00367 if (this->join (mcast_addr,
00368 reuse_addr,
00369 ACE_TEXT_CHAR_TO_TCHAR
00370 (if_addrs[if_cnt].get_host_addr (addr_buf, INET6_ADDRSTRLEN))) == 0)
00371 ++nr_subscribed;
00372 }
00373 }
00374
00375 delete [] if_addrs;
00376
00377 if (nr_subscribed == 0)
00378 {
00379 errno = ENODEV;
00380 return -1;
00381 }
00382
00383
00384
00385 return 1;
00386
00387 }
00388 #else
00389
00390
00391
00392 ACE_INET_Addr *if_addrs = 0;
00393 size_t if_cnt;
00394
00395 if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00396 return -1;
00397
00398 size_t nr_subscribed = 0;
00399
00400 if (if_cnt < 2)
00401 {
00402 if (this->join (mcast_addr,
00403 reuse_addr,
00404 ACE_TEXT ("0.0.0.0")) == 0)
00405 ++nr_subscribed;
00406 }
00407 else
00408 {
00409
00410
00411 while (if_cnt > 0)
00412 {
00413 --if_cnt;
00414
00415
00416 if (if_addrs[if_cnt].is_loopback ())
00417 continue;
00418 char addr_buf[INET6_ADDRSTRLEN];
00419 if (this->join (mcast_addr,
00420 reuse_addr,
00421 ACE_TEXT_CHAR_TO_TCHAR
00422 (if_addrs[if_cnt].get_host_addr (addr_buf, INET6_ADDRSTRLEN))) == 0)
00423 ++nr_subscribed;
00424 }
00425 }
00426
00427 delete [] if_addrs;
00428
00429 if (nr_subscribed == 0)
00430 {
00431 errno = ENODEV;
00432 return -1;
00433 }
00434
00435
00436
00437 return 1;
00438 #endif
00439 }
00440
00441 #if defined (ACE_HAS_IPV6)
00442 if (mcast_addr.get_type () == AF_INET6)
00443 {
00444 if (this->make_multicast_ifaddr6 (0, mcast_addr, net_if) == -1)
00445 return -1;
00446 }
00447 else
00448 {
00449
00450 if (this->make_multicast_ifaddr (0,
00451 mcast_addr,
00452 net_if) == -1)
00453 return -1;
00454 }
00455 #else
00456
00457 if (this->make_multicast_ifaddr (0,
00458 mcast_addr,
00459 net_if) == -1)
00460 return -1;
00461 #endif
00462
00463 return 0;
00464
00465 }
00466
00467 int
00468 ACE_SOCK_Dgram_Mcast::join (const ACE_INET_Addr &mcast_addr,
00469 int reuse_addr,
00470 const ACE_TCHAR *net_if)
00471 {
00472 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::join");
00473 ACE_INET_Addr subscribe_addr = mcast_addr;
00474
00475
00476
00477 u_short def_port_number = this->send_addr_.get_port_number ();
00478 if (subscribe_addr.get_port_number () == 0
00479 && def_port_number != 0)
00480 {
00481 subscribe_addr.set_port_number (def_port_number);
00482 }
00483
00484
00485 u_short sub_port_number = mcast_addr.get_port_number ();
00486 if (sub_port_number != 0
00487 && def_port_number != 0
00488 && sub_port_number != def_port_number)
00489 {
00490 ACE_ERROR ((LM_ERROR,
00491 ACE_TEXT ("Subscribed port# (%u) different than bound ")
00492 ACE_TEXT ("port# (%u).\n"),
00493 (u_int) sub_port_number,
00494 (u_int) def_port_number));
00495 errno = ENXIO;
00496 return -1;
00497 }
00498
00499
00500
00501 ACE_INET_Addr tmp_addr (this->send_addr_);
00502 tmp_addr.set_port_number (mcast_addr.get_port_number ());
00503 if (ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES)
00504 && !this->send_addr_.is_any ()
00505 && this->send_addr_ != mcast_addr)
00506 {
00507 ACE_TCHAR sub_addr_string[MAXNAMELEN + 1];
00508 ACE_TCHAR bound_addr_string[MAXNAMELEN + 1];
00509 ACE_SDM_helpers::addr_to_string (mcast_addr, sub_addr_string,
00510 sizeof sub_addr_string, 1);
00511 ACE_SDM_helpers::addr_to_string (this->send_addr_, bound_addr_string,
00512 sizeof bound_addr_string, 1);
00513 ACE_ERROR ((LM_ERROR,
00514 ACE_TEXT ("Subscribed address (%s) different than ")
00515 ACE_TEXT ("bound address (%s).\n"),
00516 sub_addr_string,
00517 bound_addr_string));
00518 errno = ENXIO;
00519 return -1;
00520 }
00521
00522
00523 int result = this->subscribe_i (subscribe_addr, reuse_addr, net_if);
00524
00525 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00526 if (result == 0)
00527 {
00528
00529
00530
00531 ip_mreq *pmreq = new ip_mreq;
00532
00533 if (this->make_multicast_ifaddr (pmreq, subscribe_addr, net_if) != -1)
00534 {
00535 ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00536 this->subscription_list_lock_, -1));
00537 this->subscription_list_.insert_tail (pmreq);
00538 return 0;
00539 }
00540
00541
00542 delete pmreq;
00543 }
00544 #endif
00545
00546 return result >= 0 ? 0 : result;
00547 }
00548
00549
00550 int
00551 ACE_SOCK_Dgram_Mcast::subscribe_i (const ACE_INET_Addr &mcast_addr,
00552 int reuse_addr,
00553 const ACE_TCHAR *net_if)
00554 {
00555 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_i");
00556 ip_mreq mreq;
00557 #if defined (ACE_HAS_IPV6)
00558 ipv6_mreq mreq6;
00559 #endif
00560
00561
00562
00563 if (this->open (mcast_addr,
00564 net_if,
00565 reuse_addr) == -1)
00566 return -1;
00567
00568
00569 if (net_if == 0)
00570 {
00571 int result = this->subscribe_ifs (mcast_addr,
00572 net_if,
00573 reuse_addr);
00574
00575 if (result != 0)
00576 return result;
00577 }
00578
00579 #if defined (ACE_HAS_IPV6)
00580 if (mcast_addr.get_type () == AF_INET6)
00581 {
00582 if (this->make_multicast_ifaddr6 (&mreq6, mcast_addr, net_if) == -1)
00583 return -1;
00584
00585 else if (this->ACE_SOCK::set_option (IPPROTO_IPV6,
00586 IPV6_JOIN_GROUP,
00587 &mreq6,
00588 sizeof mreq6) == -1)
00589 return -1;
00590
00591 return 0;
00592 }
00593
00594 #endif
00595
00596
00597 if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00598 return -1;
00599
00600 else if (this->ACE_SOCK::set_option (IPPROTO_IP,
00601 IP_ADD_MEMBERSHIP,
00602 &mreq,
00603 sizeof mreq) == -1)
00604 return -1;
00605
00606 return 0;
00607 }
00608
00609 int
00610 ACE_SOCK_Dgram_Mcast::unsubscribe_ifs (const ACE_INET_Addr &mcast_addr,
00611 const ACE_TCHAR *net_if)
00612 {
00613 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_ifs");
00614
00615
00616 if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
00617 && net_if == 0)
00618 {
00619 #if defined (ACE_HAS_IPV6)
00620 if (mcast_addr.get_type () == AF_INET6)
00621 {
00622 size_t nr_unsubscribed = 0;
00623 # if defined(__linux__)
00624
00625 struct if_nameindex *intf;
00626
00627 intf = ACE_OS::if_nameindex ();
00628
00629 if (intf == 0)
00630 return -1;
00631
00632 int index = 0;
00633 while (intf[index].if_index != 0 || intf[index].if_name != 0)
00634 {
00635 if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(intf[index].if_name)) == 0)
00636 ++nr_unsubscribed;
00637
00638 ++index;
00639 }
00640
00641 ACE_OS::if_freenameindex (intf);
00642
00643 # elif defined (ACE_WIN32)
00644
00645 IP_ADAPTER_ADDRESSES tmp_addrs;
00646
00647 DWORD dwRetVal;
00648 ULONG bufLen = 0;
00649 if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00650 0,
00651 0,
00652 &tmp_addrs,
00653 &bufLen)) != ERROR_BUFFER_OVERFLOW)
00654 return -1;
00655
00656
00657 PIP_ADAPTER_ADDRESSES pAddrs;
00658 char *buf;
00659 ACE_NEW_RETURN (buf,
00660 char[bufLen],
00661 -1);
00662 pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
00663 if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00664 0,
00665 0,
00666 pAddrs,
00667 &bufLen)) != NO_ERROR)
00668 {
00669 delete[] buf;
00670 return -1;
00671 }
00672
00673 while (pAddrs)
00674 {
00675 if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
00676 ++nr_unsubscribed;
00677
00678 pAddrs = pAddrs->Next;
00679 }
00680
00681 delete[] buf;
00682
00683 # endif
00684
00685 if (nr_unsubscribed == 0)
00686 {
00687 errno = ENODEV;
00688 return -1;
00689 }
00690
00691 return 1;
00692
00693
00694 }
00695 else
00696 {
00697
00698
00699
00700 ACE_INET_Addr *if_addrs = 0;
00701 size_t if_cnt;
00702
00703
00704
00705
00706
00707
00708 if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00709 return -1;
00710
00711 size_t nr_unsubscribed = 0;
00712
00713 if (if_cnt < 2)
00714 {
00715 if (this->leave (mcast_addr,
00716 ACE_TEXT ("0.0.0.0")) == 0)
00717 ++nr_unsubscribed;
00718 }
00719 else
00720 {
00721 while (if_cnt > 0)
00722 {
00723 --if_cnt;
00724
00725 if (if_addrs[if_cnt].get_type () != AF_INET || if_addrs[if_cnt].is_loopback ())
00726 continue;
00727 char addr_buf[INET6_ADDRSTRLEN];
00728 if (this->leave (mcast_addr,
00729 ACE_TEXT_CHAR_TO_TCHAR
00730 (if_addrs[if_cnt].get_host_addr (addr_buf, INET6_ADDRSTRLEN))) == 0)
00731 ++nr_unsubscribed;
00732 }
00733 }
00734
00735 delete [] if_addrs;
00736
00737 if (nr_unsubscribed == 0)
00738 {
00739 errno = ENODEV;
00740 return -1;
00741 }
00742
00743 return 1;
00744
00745 }
00746 #else
00747
00748
00749
00750 ACE_INET_Addr *if_addrs = 0;
00751 size_t if_cnt;
00752
00753
00754
00755
00756
00757
00758 if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00759 return -1;
00760
00761 size_t nr_unsubscribed = 0;
00762
00763 if (if_cnt < 2)
00764 {
00765 if (this->leave (mcast_addr,
00766 ACE_TEXT ("0.0.0.0")) == 0)
00767 ++nr_unsubscribed;
00768 }
00769 else
00770 {
00771 while (if_cnt > 0)
00772 {
00773 --if_cnt;
00774
00775 if (if_addrs[if_cnt].is_loopback ())
00776 continue;
00777 char addr_buf[INET6_ADDRSTRLEN];
00778 if (this->leave (mcast_addr,
00779 ACE_TEXT_CHAR_TO_TCHAR
00780 (if_addrs[if_cnt].get_host_addr (addr_buf, INET6_ADDRSTRLEN))) == 0)
00781 ++nr_unsubscribed;
00782 }
00783 }
00784
00785 delete [] if_addrs;
00786
00787 if (nr_unsubscribed == 0)
00788 {
00789 errno = ENODEV;
00790 return -1;
00791 }
00792
00793 return 1;
00794 #endif
00795 }
00796
00797 return 0;
00798 }
00799
00800
00801 int
00802 ACE_SOCK_Dgram_Mcast::leave (const ACE_INET_Addr &mcast_addr,
00803 const ACE_TCHAR *net_if)
00804 {
00805 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::leave");
00806
00807 int result = this->unsubscribe_i (mcast_addr,
00808 net_if);
00809
00810 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00811
00812
00813 ip_mreq tgt_mreq;
00814 if (this->make_multicast_ifaddr (&tgt_mreq,
00815 mcast_addr,
00816 net_if) != -1)
00817 {
00818 ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00819 this->subscription_list_lock_, -1));
00820 subscription_list_iter_t iter (this->subscription_list_);
00821 for (; !iter.done (); iter.advance ())
00822 {
00823 ip_mreq *pm = iter.next ();
00824 if (ACE_SDM_helpers::is_equal (*pm, tgt_mreq))
00825 {
00826 iter.remove ();
00827 delete pm;
00828 break;
00829 }
00830 }
00831 }
00832 #endif
00833
00834 return result >= 0 ? 0 : result;
00835 }
00836
00837
00838 int
00839 ACE_SOCK_Dgram_Mcast::unsubscribe_i (const ACE_INET_Addr &mcast_addr,
00840 const ACE_TCHAR *net_if)
00841 {
00842 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_i");
00843
00844 int result = this->unsubscribe_ifs (mcast_addr,
00845 net_if);
00846
00847
00848 if (result != 0)
00849 return result;
00850
00851 #if defined (ACE_HAS_IPV6)
00852 if (mcast_addr.get_type () == AF_INET6)
00853 {
00854
00855 ipv6_mreq mreq;
00856 if (this->make_multicast_ifaddr6 (&mreq, mcast_addr, net_if) == -1)
00857 {
00858 return -1;
00859 }
00860
00861
00862 else if (ACE_SOCK::set_option (IPPROTO_IPV6,
00863 IPV6_LEAVE_GROUP,
00864 &mreq,
00865 sizeof mreq) == -1)
00866 {
00867 return -1;
00868 }
00869
00870 }
00871 else
00872 {
00873
00874 ip_mreq mreq;
00875 if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00876 {
00877 return -1;
00878 }
00879
00880
00881 else if (ACE_SOCK::set_option (IPPROTO_IP,
00882 IP_DROP_MEMBERSHIP,
00883 &mreq,
00884 sizeof mreq) == -1)
00885 {
00886 return -1;
00887 }
00888
00889 }
00890 #else
00891
00892 ip_mreq mreq;
00893 if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00894 {
00895 return -1;
00896 }
00897
00898
00899
00900 else if (ACE_SOCK::set_option (IPPROTO_IP,
00901 IP_DROP_MEMBERSHIP,
00902 &mreq,
00903 sizeof mreq) == -1)
00904 {
00905 return -1;
00906 }
00907 #endif
00908
00909 return 0;
00910 }
00911
00912 int
00913 ACE_SOCK_Dgram_Mcast::clear_subs_list (void)
00914 {
00915 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::clear_subs_list");
00916 int result = 0;
00917
00918 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00919 ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00920 this->subscription_list_lock_, -1));
00921 subscription_list_iter_t iter (this->subscription_list_);
00922 for (; !iter.done (); )
00923 {
00924 ip_mreq *pm = iter.next ();
00925 iter.remove ();
00926 delete pm;
00927 }
00928 #endif
00929 return result;
00930 }
00931
00932 ACE_END_VERSIONED_NAMESPACE_DECL