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 "SOCK_Dgram_Mcast.cpp,v 4.86 2006/03/14 21:15:49 sjiang Exp")
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_LIB_TEXT ("<?>"));
00050 else
00051 {
00052 ACE_TCHAR *pc = ACE_OS::strrchr (ret_string, ACE_LIB_TEXT (':'));
00053 if (clip_portnum && pc)
00054 *pc = ACE_LIB_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_LIB_TEXT ("\nOptions: bindaddr=%s, nulliface=%s\n"),
00080 ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES) ?
00081 ACE_LIB_TEXT ("<Bound>") : ACE_LIB_TEXT ("<Not Bound>"),
00082 ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL) ?
00083 ACE_LIB_TEXT ("<All Ifaces>") : ACE_LIB_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_LIB_TEXT ("Send addr=%s iface=%s\n"),
00090 addr_string,
00091 this->send_net_if_ ? this->send_net_if_
00092 : ACE_LIB_TEXT ("<default>")));
00093
00094
00095 ACE_DEBUG ((LM_DEBUG, ACE_LIB_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_LIB_TEXT ("0.0.0.0")) == 0)
00116
00117
00118 ACE_OS::strcpy (iface_string, ACE_LIB_TEXT ("<default>"));
00119
00120
00121 ACE_DEBUG ((LM_DEBUG,
00122 ACE_LIB_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 NULL,
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 NULL,
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_LIB_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_LIB_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_LIB_TEXT ("Subscribed port# (%u) different than bound ")
00506 ACE_LIB_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_LIB_TEXT ("Subscribed address (%s) different than ")
00529 ACE_LIB_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 else
00606 {
00607
00608 if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00609 return -1;
00610
00611 else if (this->ACE_SOCK::set_option (IPPROTO_IP,
00612 IP_ADD_MEMBERSHIP,
00613 &mreq,
00614 sizeof mreq) == -1)
00615 return -1;
00616
00617 }
00618 #else
00619 if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00620 return -1;
00621
00622
00623 else if (this->ACE_SOCK::set_option (IPPROTO_IP,
00624 IP_ADD_MEMBERSHIP,
00625 &mreq,
00626 sizeof mreq) == -1)
00627 return -1;
00628
00629 #endif
00630
00631 return 0;
00632 }
00633
00634 int
00635 ACE_SOCK_Dgram_Mcast::unsubscribe_ifs (const ACE_INET_Addr &mcast_addr,
00636 const ACE_TCHAR *net_if)
00637 {
00638 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_ifs");
00639
00640
00641 if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
00642 && net_if == 0)
00643 {
00644 #if defined (ACE_HAS_IPV6)
00645 if (mcast_addr.get_type () == AF_INET6)
00646 {
00647 size_t nr_unsubscribed = 0;
00648 # if defined(__linux__)
00649
00650 struct if_nameindex *intf;
00651
00652 intf = ACE_OS::if_nameindex ();
00653
00654 if (intf == 0)
00655 return -1;
00656
00657 int index = 0;
00658 while (intf[index].if_index != 0 || intf[index].if_name != 0)
00659 {
00660 if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(intf[index].if_name)) == 0)
00661 ++nr_unsubscribed;
00662
00663 ++index;
00664 }
00665
00666 ACE_OS::if_freenameindex (intf);
00667
00668 # elif defined (ACE_WIN32)
00669
00670 IP_ADAPTER_ADDRESSES tmp_addrs;
00671
00672 DWORD dwRetVal;
00673 ULONG bufLen = 0;
00674 if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00675 0,
00676 NULL,
00677 &tmp_addrs,
00678 &bufLen)) != ERROR_BUFFER_OVERFLOW)
00679 return -1;
00680
00681
00682 PIP_ADAPTER_ADDRESSES pAddrs;
00683 char *buf;
00684 ACE_NEW_RETURN (buf,
00685 char[bufLen],
00686 -1);
00687 pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
00688 if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00689 0,
00690 NULL,
00691 pAddrs,
00692 &bufLen)) != NO_ERROR)
00693 {
00694 delete[] buf;
00695 return -1;
00696 }
00697
00698 while (pAddrs)
00699 {
00700 if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
00701 ++nr_unsubscribed;
00702
00703 pAddrs = pAddrs->Next;
00704 }
00705
00706 delete[] buf;
00707
00708 # endif
00709
00710 if (nr_unsubscribed == 0)
00711 {
00712 errno = ENODEV;
00713 return -1;
00714 }
00715
00716 return 1;
00717
00718
00719 }
00720 else
00721 {
00722
00723
00724
00725 ACE_INET_Addr *if_addrs = 0;
00726 size_t if_cnt;
00727
00728
00729
00730
00731
00732
00733 if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00734 return -1;
00735
00736 size_t nr_unsubscribed = 0;
00737
00738 if (if_cnt < 2)
00739 {
00740 if (this->leave (mcast_addr,
00741 ACE_LIB_TEXT ("0.0.0.0")) == 0)
00742 ++nr_unsubscribed;
00743 }
00744 else
00745 {
00746 while (if_cnt > 0)
00747 {
00748 --if_cnt;
00749
00750 if (if_addrs[if_cnt].get_type () != AF_INET || if_addrs[if_cnt].is_loopback ())
00751 continue;
00752 if (this->leave (mcast_addr,
00753 ACE_TEXT_CHAR_TO_TCHAR
00754 (if_addrs[if_cnt].get_host_addr ())) == 0)
00755 ++nr_unsubscribed;
00756 }
00757 }
00758
00759 delete [] if_addrs;
00760
00761 if (nr_unsubscribed == 0)
00762 {
00763 errno = ENODEV;
00764 return -1;
00765 }
00766
00767 return 1;
00768
00769 }
00770 #else
00771
00772
00773
00774 ACE_INET_Addr *if_addrs = 0;
00775 size_t if_cnt;
00776
00777
00778
00779
00780
00781
00782 if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
00783 return -1;
00784
00785 size_t nr_unsubscribed = 0;
00786
00787 if (if_cnt < 2)
00788 {
00789 if (this->leave (mcast_addr,
00790 ACE_LIB_TEXT ("0.0.0.0")) == 0)
00791 ++nr_unsubscribed;
00792 }
00793 else
00794 {
00795 while (if_cnt > 0)
00796 {
00797 --if_cnt;
00798
00799 if (if_addrs[if_cnt].is_loopback ())
00800 continue;
00801 if (this->leave (mcast_addr,
00802 ACE_TEXT_CHAR_TO_TCHAR
00803 (if_addrs[if_cnt].get_host_addr ())) == 0)
00804 ++nr_unsubscribed;
00805 }
00806 }
00807
00808 delete [] if_addrs;
00809
00810 if (nr_unsubscribed == 0)
00811 {
00812 errno = ENODEV;
00813 return -1;
00814 }
00815
00816 return 1;
00817 #endif
00818 }
00819
00820 return 0;
00821 }
00822
00823
00824
00825
00826
00827
00828 int
00829 ACE_SOCK_Dgram_Mcast::unsubscribe (const ACE_INET_Addr &mcast_addr,
00830 const ACE_TCHAR *net_if,
00831 int protocol_family,
00832 int protocol)
00833 {
00834 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe");
00835
00836 ACE_UNUSED_ARG (protocol_family);
00837 ACE_UNUSED_ARG (protocol);
00838
00839 return this->leave (mcast_addr, net_if);
00840 }
00841
00842 int
00843 ACE_SOCK_Dgram_Mcast::leave (const ACE_INET_Addr &mcast_addr,
00844 const ACE_TCHAR *net_if)
00845 {
00846 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::leave");
00847
00848 int result = this->unsubscribe_i (mcast_addr,
00849 net_if);
00850
00851 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00852
00853
00854 ip_mreq tgt_mreq;
00855 if (this->make_multicast_ifaddr (&tgt_mreq,
00856 mcast_addr,
00857 net_if) != -1)
00858 {
00859 ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00860 this->subscription_list_lock_, -1));
00861 subscription_list_iter_t iter (this->subscription_list_);
00862 for (; !iter.done (); iter.advance ())
00863 {
00864 ip_mreq *pm = iter.next ();
00865 if (ACE_SDM_helpers::is_equal (*pm, tgt_mreq))
00866 {
00867 iter.remove ();
00868 delete pm;
00869 break;
00870 }
00871 }
00872 }
00873 #endif
00874
00875 return result >= 0 ? 0 : result;
00876 }
00877
00878
00879 int
00880 ACE_SOCK_Dgram_Mcast::unsubscribe_i (const ACE_INET_Addr &mcast_addr,
00881 const ACE_TCHAR *net_if)
00882 {
00883 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_i");
00884
00885 int result = this->unsubscribe_ifs (mcast_addr,
00886 net_if);
00887
00888
00889 if (result != 0)
00890 return result;
00891
00892 #if defined (ACE_HAS_IPV6)
00893 if (mcast_addr.get_type () == AF_INET6)
00894 {
00895
00896 ipv6_mreq mreq;
00897 if (this->make_multicast_ifaddr6 (&mreq, mcast_addr, net_if) == -1)
00898 {
00899 return -1;
00900 }
00901
00902
00903 else if (ACE_SOCK::set_option (IPPROTO_IPV6,
00904 IPV6_LEAVE_GROUP,
00905 &mreq,
00906 sizeof mreq) == -1)
00907 {
00908 return -1;
00909 }
00910
00911 }
00912 else
00913 {
00914
00915 ip_mreq mreq;
00916 if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00917 {
00918 return -1;
00919 }
00920
00921
00922 else if (ACE_SOCK::set_option (IPPROTO_IP,
00923 IP_DROP_MEMBERSHIP,
00924 &mreq,
00925 sizeof mreq) == -1)
00926 {
00927 return -1;
00928 }
00929
00930 }
00931 #else
00932
00933 ip_mreq mreq;
00934 if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00935 {
00936 return -1;
00937 }
00938
00939
00940
00941 else if (ACE_SOCK::set_option (IPPROTO_IP,
00942 IP_DROP_MEMBERSHIP,
00943 &mreq,
00944 sizeof mreq) == -1)
00945 {
00946 return -1;
00947 }
00948 #endif
00949
00950 return 0;
00951 }
00952
00953 int
00954 ACE_SOCK_Dgram_Mcast::unsubscribe (void)
00955 {
00956 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe");
00957
00958
00959
00960
00961
00962
00963
00964
00965 ACE_ERROR_RETURN ((LM_INFO,
00966 ACE_LIB_TEXT ("ACE_SOCK_Dgram_Mcast::unsubscribe (void) ")
00967 ACE_LIB_TEXT ("has been deprecated. You must either ")
00968 ACE_LIB_TEXT ("close to socket to unsubscribe to all ")
00969 ACE_LIB_TEXT ("or unsubscribe to each individually.\n")),
00970 0);
00971 }
00972
00973 int
00974 ACE_SOCK_Dgram_Mcast::clear_subs_list (void)
00975 {
00976 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::clear_subs_list");
00977 int result = 0;
00978
00979 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00980 ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00981 this->subscription_list_lock_, -1));
00982 subscription_list_iter_t iter (this->subscription_list_);
00983 for (; !iter.done (); )
00984 {
00985 ip_mreq *pm = iter.next ();
00986 iter.remove ();
00987 delete pm;
00988 }
00989 #endif
00990 return result;
00991 }
00992
00993 ACE_END_VERSIONED_NAMESPACE_DECL