Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

SOCK_Dgram_Mcast.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // SOCK_Dgram_Mcast.cpp
00003 
00004 #include "ace/SOCK_Dgram_Mcast.h"
00005 
00006 #if defined (ACE_LACKS_INLINE_FUNCTIONS)
00007 #include "ace/SOCK_Dgram_Mcast.i"
00008 #endif /* ACE_LACKS_INLINE_FUNCTIONS */
00009 
00010 ACE_RCSID (ace,
00011            SOCK_Dgram_Mcast,
00012            "$Id: SOCK_Dgram_Mcast.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $")
00013 
00014 #include "ace/Log_Msg.h"
00015 
00016 // This is a workaround for platforms with non-standard
00017 // definitions of the ip_mreq structure
00018 #if ! defined (IMR_MULTIADDR)
00019 #define IMR_MULTIADDR imr_multiaddr
00020 #endif /* ! defined (IMR_MULTIADDR) */
00021 
00022 // Helper (inline) functions.
00023 class ACE_SDM_helpers
00024 {
00025 public:
00026   // Convert ACE_INET_Addr to string, using local formatting rules.
00027 
00028   static void addr_to_string (const ACE_INET_Addr &ip_addr,
00029                               ACE_TCHAR *ret_string,  // results here.
00030                               size_t len,
00031                               int clip_portnum)       // clip port# info?
00032     {
00033       if (ip_addr.addr_to_string (ret_string, len, 1) == -1)
00034         {
00035           ACE_OS_String::strcpy (ret_string, ACE_LIB_TEXT ("<?>"));
00036         }
00037       else
00038         {
00039           ACE_TCHAR *pc;
00040           if (clip_portnum
00041               && (pc = ACE_OS_String::strchr (ret_string, ACE_LIB_TEXT (':'))))
00042             *pc = ACE_LIB_TEXT ('\0'); // clip port# info.
00043         }
00044     }
00045     // op== for ip_mreq structs.
00046     static int is_equal (const ip_mreq &m1, const ip_mreq &m2)
00047       {
00048         return m1.IMR_MULTIADDR.s_addr == m2.IMR_MULTIADDR.s_addr
00049           && m1.imr_interface.s_addr == m2.imr_interface.s_addr;
00050       }
00051 };
00052 
00053 ACE_ALLOC_HOOK_DEFINE (ACE_SOCK_Dgram_Mcast)
00054 
00055 void
00056 ACE_SOCK_Dgram_Mcast::dump (void) const
00057 {
00058   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::dump");
00059 
00060   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00061 
00062 # if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00063   ACE_TCHAR addr_string[MAXNAMELEN + 1];
00064 
00065   ACE_DEBUG ((LM_DEBUG, 
00066               ACE_LIB_TEXT ("\nOptions: bindaddr=%s, nulliface=%s\n"),
00067               ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES) ?
00068                 ACE_LIB_TEXT ("<Bound>") : ACE_LIB_TEXT ("<Not Bound>"),
00069               ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL) ? 
00070                 ACE_LIB_TEXT ("<All Ifaces>") : ACE_LIB_TEXT ("<Default Iface>")));
00071 
00072   // Show default send addr, port#, and interface.
00073   ACE_SDM_helpers::addr_to_string (this->send_addr_, addr_string, 
00074                                    sizeof addr_string, 0);
00075   ACE_DEBUG ((LM_DEBUG, 
00076               ACE_LIB_TEXT ("Send addr=%s iface=%s\n"),
00077               addr_string,
00078               this->send_net_if_ ? this->send_net_if_ 
00079                                  : ACE_LIB_TEXT ("<default>")));
00080 
00081   // Show list of subscribed addresses.
00082   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("Subscription list:\n")));
00083 
00084   ACE_MT (ACE_GUARD (ACE_SDM_LOCK, guard, this->subscription_list_lock_));
00085   subscription_list_iter_t  iter (this->subscription_list_);
00086   for ( ; !iter.done (); iter.advance ())
00087     {
00088       ACE_TCHAR iface_string[MAXNAMELEN + 1];
00089       ip_mreq *pm = iter.next ();
00090 
00091       // Get subscribed address (w/out port# info - not relevant).
00092       ACE_INET_Addr ip_addr (ACE_static_cast (u_short, 0),
00093                              ACE_NTOHL (pm->IMR_MULTIADDR.s_addr));
00094       ACE_SDM_helpers::addr_to_string (ip_addr, addr_string, 
00095                                        sizeof addr_string, 1);
00096 
00097       // Get interface address/specification.
00098       ACE_INET_Addr if_addr (ACE_static_cast (u_short, 0),
00099                              ACE_NTOHL (pm->imr_interface.s_addr));
00100       ACE_SDM_helpers::addr_to_string (if_addr, iface_string, 
00101                                        sizeof iface_string, 1);
00102       if (ACE_OS_String::strcmp (iface_string, ACE_LIB_TEXT ("0.0.0.0")) == 0)
00103         // Receives on system default iface. (Note that null_iface_opt_
00104         // option processing has already occurred.)
00105         ACE_OS_String::strcpy (iface_string, ACE_LIB_TEXT ("<default>"));
00106 
00107       // Dump info.
00108       ACE_DEBUG ((LM_DEBUG, 
00109                   ACE_LIB_TEXT ("\taddr=%s iface=%s\n"),
00110                   addr_string, 
00111                   iface_string));
00112     }
00113 # endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00114   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00115 }
00116 
00117 // Constructor.
00118 ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast
00119   (ACE_SOCK_Dgram_Mcast::options opts)
00120   :  opts_ (opts),
00121      send_net_if_ (0)
00122 {
00123   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast");
00124 }
00125 
00126 // Destructor.
00127 ACE_SOCK_Dgram_Mcast::~ACE_SOCK_Dgram_Mcast (void)
00128 {
00129   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::~ACE_SOCK_Dgram_Mcast");
00130 
00131   // Free memory and optionally unsubscribe from currently subscribed group(s).
00132   delete [] this->send_net_if_;
00133   this->clear_subs_list ();
00134 }
00135 
00136 int
00137 ACE_SOCK_Dgram_Mcast::open (const ACE_INET_Addr &mcast_addr,
00138                             const ACE_TCHAR *net_if,
00139                             int reuse_addr)
00140 {
00141   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open");
00142 
00143   // Only perform the <open> initialization if we haven't been opened
00144   // earlier.
00145   // No sanity check?  We should probably flag an error if the user 
00146   // makes multiple calls to open().
00147   if (this->get_handle () != ACE_INVALID_HANDLE)
00148     return 0;
00149 
00150   // Invoke lower-layer ::open.
00151   if (ACE_SOCK::open (SOCK_DGRAM,
00152                       mcast_addr.get_type (),
00153                       0, // always use 0
00154                       reuse_addr) == -1)
00155     return -1;
00156 
00157   return open_i (mcast_addr, net_if, reuse_addr);
00158 }
00159 
00160 int
00161 ACE_SOCK_Dgram_Mcast::open_i (const ACE_INET_Addr &mcast_addr,
00162                               const ACE_TCHAR *net_if,
00163                               int reuse_addr)
00164 {
00165   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open_i");
00166   // ACE_SOCK::open calls this if reuse_addr is set, so we only need to
00167   // process port reuse option.
00168   if (reuse_addr)
00169     {
00170 #if defined (SO_REUSEPORT)
00171       int one = 1;
00172       if (this->ACE_SOCK::set_option (SOL_SOCKET,
00173                                       SO_REUSEPORT,
00174                                       &one,
00175                                       sizeof one) == -1)
00176         return -1;
00177 #endif /* SO_REUSEPORT */
00178     }
00179 
00180   // Create an address/port# to bind the socket to. Use mcast_addr to
00181   // initialize bind_addy to pick up the correct protocol family. If
00182   // OPT_BINDADDR_YES is set, then we're done. Else use mcast_addr's
00183   // port number and use the "any" address.
00184   ACE_INET_Addr bind_addy (mcast_addr);
00185   if (ACE_BIT_DISABLED (this->opts_, OPT_BINDADDR_YES))
00186     {
00187       // Bind to "any" address and explicit port#.
00188       if (bind_addy.set (mcast_addr.get_port_number ()) == -1)
00189         return -1;
00190     }
00191 
00192   // Bind to the address (which may be INADDR_ANY) and port# (which may be 0)
00193   if (ACE_SOCK_Dgram::shared_open (bind_addy, bind_addy.get_type ()) == -1)
00194     return -1;
00195 
00196   // Cache the actual bound address (which may be INADDR_ANY)
00197   // and the actual bound port# (which will be a valid, non-zero port#).
00198   ACE_INET_Addr bound_addy;
00199   if (this->get_local_addr (bound_addy) == -1)
00200     {
00201       // (Unexpected failure - should be bound to something)
00202       if (bound_addy.set (bind_addy) == -1)
00203         {
00204           // (Shouldn't happen - bind_addy is a valid addy; punt.)
00205           return -1;
00206         }
00207     }
00208 
00209   this->send_addr_ = mcast_addr;
00210   this->send_addr_.set_port_number (bound_addy.get_port_number ());
00211   if (net_if)
00212     {
00213 #if defined (IP_MULTICAST_IF) && (IP_MULTICAST_IF != 0)
00214       ip_mreq  send_mreq;
00215       if (this->make_multicast_ifaddr (&send_mreq,
00216                                        mcast_addr,
00217                                        net_if) == -1)
00218         return -1;
00219       if (this->ACE_SOCK::set_option (IPPROTO_IP,
00220                                       IP_MULTICAST_IF,
00221                                       &(send_mreq.imr_interface),
00222                                       sizeof send_mreq.imr_interface) == -1)
00223         return -1;
00224       this->send_net_if_ = new ACE_TCHAR[ACE_OS_String::strlen (net_if) + 1];
00225       ACE_OS_String::strcpy (this->send_net_if_, net_if);
00226 #else
00227       // Send interface option not supported - ignore it.
00228       // (We may have been invoked by ::subscribe, so we have to allow
00229       // a non-null interface parameter in this function.)
00230       ACE_DEBUG ((LM_DEBUG, 
00231                   ACE_LIB_TEXT ("Send interface specification not ")
00232                   ACE_LIB_TEXT ("supported - IGNORED.\n")));
00233 #endif // IP_MULTICAST_IF
00234     }
00235 
00236   return 0;
00237 }
00238 
00239 int
00240 ACE_SOCK_Dgram_Mcast::subscribe_ifs (const ACE_INET_Addr &mcast_addr,
00241                                      const ACE_TCHAR *net_if,
00242                                      int reuse_addr)
00243 {
00244   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_ifs");
00245 
00246   if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
00247       && net_if == 0)
00248     {
00249       // Subscribe on all local multicast-capable network interfaces, by
00250       // doing recursive calls with specific interfaces.
00251 
00252       ACE_INET_Addr *if_addrs = 0;
00253       size_t if_cnt;
00254 
00255       if (ACE_Sock_Connect::get_ip_interfaces (if_cnt, if_addrs) != 0)
00256         return -1;
00257 
00258       size_t nr_subscribed = 0;
00259 
00260       if (if_cnt < 2)
00261         {
00262           if (this->subscribe (mcast_addr,
00263                                reuse_addr,
00264                                ACE_LIB_TEXT ("0.0.0.0")) == 0)
00265             ++nr_subscribed;
00266         }
00267       else
00268         {
00269           // Iterate through all the interfaces, figure out which ones
00270           // offer multicast service, and subscribe to them.
00271           while (if_cnt > 0)
00272             {
00273               --if_cnt;
00274 
00275               // Convert to 0-based for indexing, next loop check.
00276               if (if_addrs[if_cnt].get_ip_address () == INADDR_LOOPBACK)
00277                 continue;
00278               if (this->subscribe (mcast_addr,
00279                                    reuse_addr,
00280                                    ACE_TEXT_CHAR_TO_TCHAR
00281                                      (if_addrs[if_cnt].get_host_addr ())) == 0)
00282                 ++nr_subscribed;
00283             }
00284         }
00285 
00286       delete [] if_addrs;
00287 
00288       if (nr_subscribed == 0)
00289         {
00290           errno = ENODEV;
00291           return -1;
00292         }
00293 
00294       // 1 indicates a "short-circuit" return.  This handles the
00295       // recursive behavior of checking all the interfaces.
00296       return 1;
00297     }
00298 
00299   // Validate passed multicast addr and iface specifications.
00300   if (this->make_multicast_ifaddr (0,
00301                                    mcast_addr,
00302                                    net_if) == -1)
00303     return -1;
00304 
00305   return 0;
00306 }
00307 
00308 // Subscribe and add address/iface to subscription list if successful.
00309 int
00310 ACE_SOCK_Dgram_Mcast::subscribe (const ACE_INET_Addr &mcast_addr,
00311                                  int reuse_addr,
00312                                  const ACE_TCHAR *net_if,
00313                                  int protocol_family,
00314                                  int protocol)
00315 {
00316   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe");
00317 
00318   ACE_UNUSED_ARG (protocol_family);
00319   ACE_UNUSED_ARG (protocol);
00320 
00321   return this->join (mcast_addr,reuse_addr, net_if);
00322 }
00323 
00324 int
00325 ACE_SOCK_Dgram_Mcast::join (const ACE_INET_Addr &mcast_addr,
00326                             int reuse_addr,
00327                             const ACE_TCHAR *net_if)
00328 {
00329   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::join");
00330   ACE_INET_Addr subscribe_addr = mcast_addr;
00331 
00332   // If port# is 0, insert bound port# if it is set. (To satisfy lower-level
00333   // port# validation.)
00334   u_short def_port_number = this->send_addr_.get_port_number ();
00335   if (subscribe_addr.get_port_number () == 0 
00336       && def_port_number != 0)
00337     {
00338       subscribe_addr.set_port_number (def_port_number);
00339     }
00340 
00341   // Check for port# different than bound port#.
00342   u_short sub_port_number = mcast_addr.get_port_number ();
00343   if (sub_port_number != 0
00344       && def_port_number != 0
00345       && sub_port_number != def_port_number)
00346     {
00347       ACE_ERROR ((LM_ERROR,
00348                   ACE_LIB_TEXT ("Subscribed port# (%u) different than bound ")
00349                   ACE_LIB_TEXT ("port# (%u).\n"),
00350                   (u_int) sub_port_number,
00351                   (u_int) def_port_number));
00352       errno = ENXIO;
00353       return -1;
00354     }
00355 
00356   // If bind_addr_opt_ is enabled, check for address different than
00357   // bound address.
00358   if (ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES)
00359       && this->send_addr_.get_ip_address () != INADDR_ANY
00360       && this->send_addr_.get_ip_address () != mcast_addr.get_ip_address ())
00361     {
00362       ACE_TCHAR sub_addr_string[MAXNAMELEN + 1];
00363       ACE_TCHAR bound_addr_string[MAXNAMELEN + 1];
00364       ACE_SDM_helpers::addr_to_string (mcast_addr, sub_addr_string, 
00365                                        sizeof sub_addr_string, 1);
00366       ACE_SDM_helpers::addr_to_string (this->send_addr_, bound_addr_string, 
00367                                        sizeof bound_addr_string, 1);
00368       ACE_ERROR ((LM_ERROR,
00369                   ACE_LIB_TEXT ("Subscribed address (%s) different than ")
00370                   ACE_LIB_TEXT ("bound address (%s).\n"),
00371                   sub_addr_string,
00372                   bound_addr_string));
00373       errno = ENXIO;
00374       return -1;
00375     }
00376 
00377   // Attempt subscription.
00378   int  result = this->subscribe_i (subscribe_addr, reuse_addr, net_if);
00379 
00380 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00381   if (result == 0)
00382     {
00383       // Add this addr/iface info to the list of subscriptions.
00384       // (Assumes this is unique addr/iface combo - most systems don't allow
00385       // re-sub to same addr/iface.)
00386       ip_mreq  *pmreq = new ip_mreq;
00387       // (should not fail)
00388       if (this->make_multicast_ifaddr (pmreq, subscribe_addr, net_if) != -1)
00389         {
00390           ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00391                                     this->subscription_list_lock_, -1));
00392           this->subscription_list_.insert_tail (pmreq);
00393           return 0;
00394         }
00395       // this still isn't really right. If ACE_GUARD_RETURN fails, we leak.
00396       // Need to add one of Chris' fancy ace auto pointers (bound?).     
00397       delete pmreq;
00398     }
00399 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00400 
00401   return result >= 0 ? 0 : result;
00402 }
00403 
00404 // Attempt subscribe and return status.
00405 int
00406 ACE_SOCK_Dgram_Mcast::subscribe_i (const ACE_INET_Addr &mcast_addr,
00407                                    int reuse_addr,
00408                                    const ACE_TCHAR *net_if)
00409 {
00410   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_i");
00411   ip_mreq  mreq;
00412 
00413   // Open the socket IFF this is the first ::subscribe and ::open
00414   // was not explicitly invoked.
00415   if (this->open (mcast_addr,
00416                   net_if,
00417                   reuse_addr) == -1)
00418     return -1;
00419 
00420   // Only do this if net_if == 0, i.e., INADDR_ANY
00421   if (net_if == 0)
00422     {
00423       int result = this->subscribe_ifs (mcast_addr,
00424                                         net_if,
00425                                         reuse_addr);
00426       // Check for error or "short-circuit" return.
00427       if (result != 0)
00428         return result;
00429     }
00430 
00431   // Create multicast addr/if struct.
00432   if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00433     return -1;
00434 
00435   // Tell IP stack to pass messages sent to this group.
00436   // Note, this is not IPv6 compliant.
00437   else if (this->ACE_SOCK::set_option (IPPROTO_IP,
00438                                        IP_ADD_MEMBERSHIP,
00439                                        &mreq,
00440                                        sizeof mreq) == -1)
00441     return -1;
00442 
00443   return 0;
00444 }
00445 
00446 int
00447 ACE_SOCK_Dgram_Mcast::unsubscribe_ifs (const ACE_INET_Addr &mcast_addr,
00448                                        const ACE_TCHAR *net_if)
00449 {
00450   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_ifs");
00451 
00452 
00453   if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
00454       && net_if == 0)
00455     {
00456       // Unsubscribe on all local multicast-capable network interfaces, by
00457       // doing recursive calls with specific interfaces.
00458 
00459       ACE_INET_Addr *if_addrs = 0;
00460       size_t if_cnt;
00461 
00462       // NOTE - <get_ip_interfaces> doesn't always get all of the
00463       // interfaces.  In particular, it may not get a PPP interface.  This
00464       // is a limitation of the way <get_ip_interfaces> works with
00465       // old versions of MSVC.  The reliable way of getting the interface list
00466       // is available only with MSVC 5 and newer.
00467       if (ACE_Sock_Connect::get_ip_interfaces (if_cnt, if_addrs) != 0)
00468         return -1;
00469 
00470       size_t nr_unsubscribed = 0;
00471 
00472       if (if_cnt < 2)
00473         {
00474           if (this->leave (mcast_addr,
00475                            ACE_LIB_TEXT ("0.0.0.0")) == 0)
00476             ++nr_unsubscribed;
00477         }
00478       else
00479         {
00480           while (if_cnt > 0)
00481             {
00482               --if_cnt;
00483               // Convert to 0-based for indexing, next loop check
00484               if (if_addrs[if_cnt].get_ip_address () == INADDR_LOOPBACK)
00485                 continue;
00486               if (this->leave (mcast_addr,
00487                                ACE_TEXT_CHAR_TO_TCHAR
00488                                (if_addrs[if_cnt].get_host_addr ())) == 0)
00489                 ++nr_unsubscribed;
00490             }
00491         }
00492 
00493       delete [] if_addrs;
00494 
00495       if (nr_unsubscribed == 0)
00496         {
00497           errno = ENODEV;
00498           return -1;
00499         }
00500 
00501       return 1;
00502     }
00503 
00504   return 0;
00505 }
00506 
00507 
00508 // Unsubscribe, and remove address from subscription list.
00509 // Note: If there are duplicate entries, only finds the first in the list (this
00510 // is a defined restriction - most environments don't allow duplicates to be
00511 // created.)
00512 int
00513 ACE_SOCK_Dgram_Mcast::unsubscribe (const ACE_INET_Addr &mcast_addr,
00514                                    const ACE_TCHAR *net_if,
00515                                    int protocol_family,
00516                                    int protocol)
00517 {
00518   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe");
00519 
00520   ACE_UNUSED_ARG (protocol_family);
00521   ACE_UNUSED_ARG (protocol);
00522 
00523   return this->leave (mcast_addr, net_if);
00524 }
00525 
00526 int
00527 ACE_SOCK_Dgram_Mcast::leave (const ACE_INET_Addr &mcast_addr,
00528                              const ACE_TCHAR *net_if)
00529 {
00530   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::leave");
00531   // Unsubscribe.
00532   int result = this->unsubscribe_i (mcast_addr,
00533                                     net_if);
00534 
00535 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00536   // (Unconditionally) Remove this addr/if from subscription list.
00537   // (Addr/if is removed even if unsubscribe failed)
00538   ip_mreq  tgt_mreq;
00539   if (this->make_multicast_ifaddr (&tgt_mreq,
00540                                    mcast_addr,
00541                                    net_if) != -1)
00542     {
00543       ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00544                                 this->subscription_list_lock_, -1));
00545       subscription_list_iter_t iter (this->subscription_list_);
00546       for (; !iter.done (); iter.advance ())
00547         {
00548           ip_mreq  *pm = iter.next ();
00549           if (ACE_SDM_helpers::is_equal (*pm, tgt_mreq))
00550             {
00551               iter.remove ();
00552               delete pm;
00553               break;
00554             }
00555         }
00556     }
00557 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00558 
00559   return result >= 0 ? 0 : result;
00560 }
00561 
00562 // Attempt unsubscribe and return status.
00563 int
00564 ACE_SOCK_Dgram_Mcast::unsubscribe_i (const ACE_INET_Addr &mcast_addr,
00565                                      const ACE_TCHAR *net_if)
00566 {
00567   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_i");
00568 
00569   int result = this->unsubscribe_ifs (mcast_addr,
00570                                       net_if);
00571 
00572   // Check for error or "short-circuit" return.
00573   if (result != 0)
00574     return result;
00575 
00576   // Validate addr/if specifications and create addr/if struct.
00577   ip_mreq  mreq;
00578   if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
00579     {
00580       return -1;
00581     }
00582   // Tell network device driver to stop reading datagrams with the
00583   // <mcast_addr>.  
00584   // Note, this is not IPv6 friendly...
00585   else if (ACE_SOCK::set_option (IPPROTO_IP,
00586                                  IP_DROP_MEMBERSHIP,
00587                                  &mreq,
00588                                  sizeof mreq) == -1)
00589     {
00590       return -1;
00591     }
00592 
00593   return 0;
00594 }
00595 
00596 int
00597 ACE_SOCK_Dgram_Mcast::unsubscribe (void)
00598 {
00599   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe");
00600 
00601   // Can't implement this reliably without keeping an expensive list,
00602   // and can't close the socket since the caller may want to continue
00603   // using the socket to send() or join() new groups.  Even if we
00604   // wanted to be clever and reopen the socket, we'd need to know what
00605   // options had been set, and reset them--and we have no way of doing
00606   // that either. :-(
00607   // Should this return -1?
00608   ACE_ERROR_RETURN ((LM_INFO,
00609                      ACE_LIB_TEXT ("ACE_SOCK_Dgram_Mcast::unsubscribe (void) ")
00610                      ACE_LIB_TEXT ("has been deprecated. You must either ")
00611                      ACE_LIB_TEXT ("close to socket to unsubscribe to all ")
00612                      ACE_LIB_TEXT ("or unsubscribe to each individually.\n")),
00613                      0);
00614 }
00615 
00616 int
00617 ACE_SOCK_Dgram_Mcast::clear_subs_list (void)
00618 {
00619   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::clear_subs_list");
00620   int  result = 0;
00621 
00622 #if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
00623   ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
00624                             this->subscription_list_lock_, -1));
00625   subscription_list_iter_t iter (this->subscription_list_);
00626   for (; !iter.done (); /*Hack: Do _not_ ::advance after remove*/)
00627     {
00628       ip_mreq  *pm = iter.next ();
00629       iter.remove ();
00630       delete pm;
00631     }
00632 #endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
00633   return result;
00634 }
00635 
00636 int
00637 ACE_SOCK_Dgram_Mcast::make_multicast_ifaddr (ip_mreq *ret_mreq,
00638                                              const ACE_INET_Addr &mcast_addr,
00639                                              const ACE_TCHAR *net_if)
00640 {
00641   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::make_multicast_ifaddr");
00642   ip_mreq  lmreq;       // Scratch copy.
00643   if (net_if != 0)
00644     {
00645 #if defined (ACE_WIN32)
00646       // This port number is not necessary, just convenient
00647       ACE_INET_Addr interface_addr;
00648       if (interface_addr.set (mcast_addr.get_port_number (), net_if) == -1)
00649         return -1;
00650       lmreq.imr_interface.s_addr =
00651         ACE_HTONL (interface_addr.get_ip_address ());
00652 #else
00653       ifreq if_address;
00654 
00655 #if defined (ACE_PSOS)
00656       // Look up the interface by number, not name.
00657       if_address.ifr_ifno = ACE_OS::atoi (net_if);
00658 #else
00659       ACE_OS_String::strcpy (if_address.ifr_name, net_if);
00660 #endif /* defined (ACE_PSOS) */
00661 
00662       if (ACE_OS::ioctl (this->get_handle (),
00663                          SIOCGIFADDR,
00664                          &if_address) == -1)
00665         return -1;
00666 
00667       sockaddr_in *socket_address;
00668       socket_address = ACE_reinterpret_cast (sockaddr_in*,
00669                                              &if_address.ifr_addr);
00670       lmreq.imr_interface.s_addr = socket_address->sin_addr.s_addr;
00671 #endif /* ACE_WIN32 */
00672     }
00673   else
00674     lmreq.imr_interface.s_addr = INADDR_ANY;
00675 
00676   lmreq.IMR_MULTIADDR.s_addr = ACE_HTONL (mcast_addr.get_ip_address ());
00677 
00678   // Set return info, if requested.
00679   if (ret_mreq)
00680     *ret_mreq = lmreq;
00681 
00682   return 0;
00683 }
00684 

Generated on Mon Jun 16 11:21:20 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002