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