SOCK_Dgram.cpp

Go to the documentation of this file.
00001 #include "ace/SOCK_Dgram.h"
00002 
00003 #include "ace/Handle_Set.h"
00004 #include "ace/Log_Msg.h"
00005 #include "ace/INET_Addr.h"
00006 #include "ace/ACE.h"
00007 #include "ace/OS_NS_string.h"
00008 #include "ace/OS_Memory.h"
00009 #include "ace/OS_NS_sys_select.h"
00010 #include "ace/OS_NS_ctype.h"
00011 #include "ace/os_include/net/os_if.h"
00012 
00013 #if !defined (__ACE_INLINE__)
00014 #  include "ace/SOCK_Dgram.inl"
00015 #endif /* __ACE_INLINE__ */
00016 
00017 #if defined (ACE_HAS_IPV6) && defined (ACE_WIN32)
00018 #include /**/ <Iphlpapi.h>
00019 #endif
00020 
00021 ACE_RCSID (ace,
00022            SOCK_Dgram,
00023            "SOCK_Dgram.cpp,v 4.75 2006/05/05 07:40:46 jwillemsen Exp")
00024 
00025 // This is a workaround for platforms with non-standard
00026 // definitions of the ip_mreq structure
00027 #if ! defined (IMR_MULTIADDR)
00028 #define IMR_MULTIADDR imr_multiaddr
00029 #endif /* ! defined (IMR_MULTIADDR) */
00030 
00031 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00032 
00033 ACE_ALLOC_HOOK_DEFINE (ACE_SOCK_Dgram)
00034 
00035 void
00036 ACE_SOCK_Dgram::dump (void) const
00037 {
00038 #if defined (ACE_HAS_DUMP)
00039   ACE_TRACE ("ACE_SOCK_Dgram::dump");
00040 #endif /* ACE_HAS_DUMP */
00041 }
00042 
00043 // Allows a client to read from a socket without having to provide a
00044 // buffer to read.  This method determines how much data is in the
00045 // socket, allocates a buffer of this size, reads in the data, and
00046 // returns the number of bytes read.
00047 
00048 ssize_t
00049 ACE_SOCK_Dgram::recv (iovec *io_vec,
00050                       ACE_Addr &addr,
00051                       int flags,
00052                       const ACE_Time_Value *timeout) const
00053 {
00054   ACE_TRACE ("ACE_SOCK_Dgram::recv");
00055 #if defined (FIONREAD)
00056   ACE_Handle_Set handle_set;
00057   handle_set.reset ();
00058   handle_set.set_bit (this->get_handle ());
00059 
00060   // Check the status of the current socket to make sure there's data
00061   // to recv (or time out).
00062   int select_width;
00063 #  if defined (ACE_WIN32)
00064   // This arg is ignored on Windows and causes pointer truncation
00065   // warnings on 64-bit compiles.
00066   select_width = 0;
00067 #  else
00068   select_width = int (this->get_handle ()) + 1;
00069 #  endif /* ACE_WIN32 */
00070   switch (ACE_OS::select (select_width,
00071                           handle_set,
00072                           0, 0,
00073                           timeout))
00074     {
00075     case -1:
00076       return -1;
00077       /* NOTREACHED */
00078     case 0:
00079       errno = ETIME;
00080       return -1;
00081       /* NOTREACHED */
00082     default:
00083       // Goes fine, fallthrough to get data
00084       break;
00085     }
00086 
00087   sockaddr *saddr = (sockaddr *) addr.get_addr ();
00088   int addr_len = addr.get_size ();
00089   int inlen;
00090 
00091   if (ACE_OS::ioctl (this->get_handle (),
00092                      FIONREAD,
00093                      &inlen) == -1)
00094     return -1;
00095   else if (inlen > 0)
00096     {
00097       ACE_NEW_RETURN (io_vec->iov_base,
00098                       char[inlen],
00099                       -1);
00100       io_vec->iov_len = ACE_OS::recvfrom (this->get_handle (),
00101                                           (char *) io_vec->iov_base,
00102                                           inlen,
00103                                           flags,
00104                                           (sockaddr *) saddr,
00105                                           &addr_len);
00106       addr.set_size (addr_len);
00107       return io_vec->iov_len;
00108     }
00109   else
00110     return 0;
00111 #else
00112   ACE_UNUSED_ARG (flags);
00113   ACE_UNUSED_ARG (addr);
00114   ACE_UNUSED_ARG (io_vec);
00115   ACE_UNUSED_ARG (timeout);
00116   ACE_NOTSUP_RETURN (-1);
00117 #endif /* FIONREAD */
00118 }
00119 
00120 // Here's the shared open function.  Note that if we are using the
00121 // PF_INET protocol family and the address of LOCAL == the address of
00122 // the special variable SAP_ANY then we are going to arbitrarily bind
00123 // to a portnumber.
00124 
00125 int
00126 ACE_SOCK_Dgram::shared_open (const ACE_Addr &local,
00127                              int protocol_family)
00128 {
00129   ACE_TRACE ("ACE_SOCK_Dgram::shared_open");
00130   int error = 0;
00131 
00132   if (local == ACE_Addr::sap_any)
00133     {
00134       if (protocol_family == PF_INET
00135 #if defined (ACE_HAS_IPV6)
00136           || protocol_family == PF_INET6
00137 #endif /* ACE_HAS_IPV6 */
00138           )
00139         {
00140           if (ACE::bind_port (this->get_handle (),
00141                               INADDR_ANY,
00142                               protocol_family) == -1)
00143             error = 1;
00144         }
00145     }
00146   else if (ACE_OS::bind (this->get_handle (),
00147                          reinterpret_cast<sockaddr *> (local.get_addr ()),
00148                          local.get_size ()) == -1)
00149     error = 1;
00150 
00151   if (error != 0)
00152     this->close ();
00153 
00154   return error ? -1 : 0;
00155 }
00156 
00157 int
00158 ACE_SOCK_Dgram::open (const ACE_Addr &local,
00159                       int protocol_family,
00160                       int protocol,
00161                       ACE_Protocol_Info *protocolinfo,
00162                       ACE_SOCK_GROUP g,
00163                       u_long flags,
00164                       int reuse_addr)
00165 {
00166   if (ACE_SOCK::open (SOCK_DGRAM,
00167                       protocol_family,
00168                       protocol,
00169                       protocolinfo,
00170                       g,
00171                       flags,
00172                       reuse_addr) == -1)
00173     return -1;
00174   else if (this->shared_open (local,
00175                               protocol_family) == -1)
00176     return -1;
00177   else
00178     return 0;
00179 }
00180 
00181 // Here's the general-purpose open routine.
00182 
00183 int
00184 ACE_SOCK_Dgram::open (const ACE_Addr &local,
00185                       int protocol_family,
00186                       int protocol,
00187                       int reuse_addr)
00188 {
00189   ACE_TRACE ("ACE_SOCK_Dgram::open");
00190 
00191   if (local != ACE_Addr::sap_any)
00192     protocol_family = local.get_type ();
00193   else if (protocol_family == PF_UNSPEC)
00194     {
00195 #if defined (ACE_HAS_IPV6)
00196       protocol_family = ACE::ipv6_enabled () ? PF_INET6 : PF_INET;
00197 #else
00198       protocol_family = PF_INET;
00199 #endif /* ACE_HAS_IPV6 */
00200     }
00201 
00202   if (ACE_SOCK::open (SOCK_DGRAM,
00203                       protocol_family,
00204                       protocol,
00205                       reuse_addr) == -1)
00206     return -1;
00207   else
00208     return this->shared_open (local,
00209                               protocol_family);
00210 }
00211 
00212 // Here's the general-purpose constructor used by a connectionless
00213 // datagram ``server''...
00214 
00215 ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local,
00216                                 int protocol_family,
00217                                 int protocol,
00218                                 int reuse_addr)
00219 {
00220   ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram");
00221 
00222   if (this->open (local,
00223                   protocol_family,
00224                   protocol,
00225                   reuse_addr) == -1)
00226     ACE_ERROR ((LM_ERROR,
00227                 ACE_LIB_TEXT ("%p\n"),
00228                 ACE_LIB_TEXT ("ACE_SOCK_Dgram")));
00229 }
00230 
00231 ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local,
00232                                 int protocol_family,
00233                                 int protocol,
00234                                 ACE_Protocol_Info *protocolinfo,
00235                                 ACE_SOCK_GROUP g,
00236                                 u_long flags,
00237                                 int reuse_addr)
00238 {
00239   ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram");
00240   if (this->open (local,
00241                   protocol_family,
00242                   protocol,
00243                   protocolinfo,
00244                   g,
00245                   flags,
00246                   reuse_addr) == -1)
00247     ACE_ERROR ((LM_ERROR,
00248                 ACE_LIB_TEXT ("%p\n"),
00249                 ACE_LIB_TEXT ("ACE_SOCK_Dgram")));
00250 }
00251 
00252 #if defined (ACE_HAS_MSG)
00253 // Send an iovec of size N to ADDR as a datagram (connectionless
00254 // version).
00255 
00256 ssize_t
00257 ACE_SOCK_Dgram::send (const iovec iov[],
00258                       int n,
00259                       const ACE_Addr &addr,
00260                       int flags) const
00261 {
00262   ACE_TRACE ("ACE_SOCK_Dgram::send");
00263   msghdr send_msg;
00264 
00265   send_msg.msg_iov = (iovec *) iov;
00266   send_msg.msg_iovlen = n;
00267 #if defined (ACE_HAS_SOCKADDR_MSG_NAME)
00268   send_msg.msg_name = (struct sockaddr *) addr.get_addr ();
00269 #else
00270   send_msg.msg_name = (char *) addr.get_addr ();
00271 #endif /* ACE_HAS_SOCKADDR_MSG_NAME */
00272   send_msg.msg_namelen = addr.get_size ();
00273 
00274 #if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
00275   send_msg.msg_control = 0;
00276   send_msg.msg_controllen = 0;
00277   send_msg.msg_flags = 0;
00278 #else
00279   send_msg.msg_accrights    = 0;
00280   send_msg.msg_accrightslen = 0;
00281 #endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
00282 
00283   return ACE_OS::sendmsg (this->get_handle (),
00284                           &send_msg,
00285                           flags);
00286 }
00287 
00288 // Recv an iovec of size N to ADDR as a datagram (connectionless
00289 // version).
00290 
00291 ssize_t
00292 ACE_SOCK_Dgram::recv (iovec iov[],
00293                       int n,
00294                       ACE_Addr &addr,
00295                       int flags) const
00296 {
00297   ACE_TRACE ("ACE_SOCK_Dgram::recv");
00298   msghdr recv_msg;
00299 
00300   recv_msg.msg_iov = (iovec *) iov;
00301   recv_msg.msg_iovlen = n;
00302 #if defined (ACE_HAS_SOCKADDR_MSG_NAME)
00303   recv_msg.msg_name = (struct sockaddr *) addr.get_addr ();
00304 #else
00305   recv_msg.msg_name = (char *) addr.get_addr ();
00306 #endif /* ACE_HAS_SOCKADDR_MSG_NAME */
00307   recv_msg.msg_namelen = addr.get_size ();
00308 
00309 #if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
00310   recv_msg.msg_control = 0 ;
00311   recv_msg.msg_controllen = 0 ;
00312 #else
00313   recv_msg.msg_accrights = 0;
00314   recv_msg.msg_accrightslen = 0;
00315 #endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
00316 
00317   ssize_t status = ACE_OS::recvmsg (this->get_handle (),
00318                                     &recv_msg,
00319                                     flags);
00320   addr.set_size (recv_msg.msg_namelen);
00321   addr.set_type (((sockaddr_in *) addr.get_addr())->sin_family);
00322   return status;
00323 }
00324 
00325 #else /* ACE_HAS_MSG */
00326 
00327 // Send an iovec of size N to ADDR as a datagram (connectionless
00328 // version).
00329 
00330 ssize_t
00331 ACE_SOCK_Dgram::send (const iovec iov[],
00332                       int n,
00333                       const ACE_Addr &addr,
00334                       int flags) const
00335 {
00336   ACE_TRACE ("ACE_SOCK_Dgram::send");
00337 
00338   size_t length = 0;
00339   int i;
00340 
00341   // Determine the total length of all the buffers in <iov>.
00342   for (i = 0; i < n; i++)
00343 #if ! (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0530))
00344     // The iov_len is unsigned in Borland. If we go ahead and try the
00345     // if, it will emit a warning.
00346     if (iov[i].iov_len < 0)
00347       return -1;
00348     else
00349 #endif
00350       length += iov[i].iov_len;
00351 
00352   char *buf;
00353 
00354 #if defined (ACE_HAS_ALLOCA)
00355   buf = alloca (length);
00356 #else
00357   ACE_NEW_RETURN (buf,
00358                   char[length],
00359                   -1);
00360 #endif /* !defined (ACE_HAS_ALLOCA) */
00361 
00362   char *ptr = buf;
00363 
00364   for (i = 0; i < n; i++)
00365     {
00366       ACE_OS::memcpy (ptr, iov[i].iov_base, iov[i].iov_len);
00367       ptr += iov[i].iov_len;
00368     }
00369 
00370   ssize_t result = ACE_SOCK_Dgram::send (buf, length, addr, flags);
00371 #if !defined (ACE_HAS_ALLOCA)
00372   delete [] buf;
00373 #endif /* !defined (ACE_HAS_ALLOCA) */
00374   return result;
00375 }
00376 
00377 // Recv an iovec of size N to ADDR as a datagram (connectionless
00378 // version).
00379 
00380 ssize_t
00381 ACE_SOCK_Dgram::recv (iovec iov[],
00382                       int n,
00383                       ACE_Addr &addr,
00384                       int flags) const
00385 {
00386   ACE_TRACE ("ACE_SOCK_Dgram::recv");
00387 
00388   ssize_t length = 0;
00389   int i;
00390 
00391   for (i = 0; i < n; i++)
00392 #if ! (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0530))
00393     // The iov_len is unsigned in Borland. If we go ahead and try the
00394     // if, it will emit a warning.
00395     if (iov[i].iov_len < 0)
00396       return -1;
00397     else
00398 #endif
00399       length += iov[i].iov_len;
00400 
00401   char *buf;
00402 
00403 #if defined (ACE_HAS_ALLOCA)
00404   buf = alloca (length);
00405 #else
00406   ACE_NEW_RETURN (buf,
00407                   char[length],
00408                   -1);
00409 #endif /* !defined (ACE_HAS_ALLOCA) */
00410 
00411   length = ACE_SOCK_Dgram::recv (buf, length, addr, flags);
00412 
00413   if (length != -1)
00414     {
00415       char *ptr = buf;
00416       int copyn = length;
00417 
00418       for (i = 0;
00419            i < n && copyn > 0;
00420            i++)
00421         {
00422           ACE_OS::memcpy (iov[i].iov_base, ptr,
00423                           // iov_len is int on some platforms, size_t on others
00424                           copyn > (int) iov[i].iov_len
00425                             ? (size_t) iov[i].iov_len
00426                             : (size_t) copyn);
00427           ptr += iov[i].iov_len;
00428           copyn -= iov[i].iov_len;
00429         }
00430     }
00431 
00432 #if !defined (ACE_HAS_ALLOCA)
00433   delete [] buf;
00434 #endif /* !defined (ACE_HAS_ALLOCA) */
00435   return length;
00436 }
00437 
00438 #endif /* ACE_HAS_MSG */
00439 
00440 ssize_t
00441 ACE_SOCK_Dgram::recv (void *buf,
00442                       size_t n,
00443                       ACE_Addr &addr,
00444                       int flags,
00445                       const ACE_Time_Value *timeout) const
00446 {
00447   ACE_Handle_Set handle_set;
00448   handle_set.reset ();
00449   handle_set.set_bit (this->get_handle ());
00450 
00451   // Check the status of the current socket.
00452   int select_width;
00453 #if defined (ACE_WIN32)
00454   // This arg is ignored on Windows and causes pointer truncation
00455   // warnings on 64-bit compiles.
00456   select_width = 0;
00457 #else
00458   select_width = int (this->get_handle ()) + 1;
00459 #endif /* ACE_WIN32 */
00460   switch (ACE_OS::select (select_width,
00461                           handle_set,
00462                           0,
00463                           0,
00464                           timeout))
00465     {
00466     case -1:
00467       return -1;
00468       /* NOTREACHED */
00469     case 0:
00470       errno = ETIME;
00471       return -1;
00472       /* NOTREACHED */
00473     default:
00474       // Goes fine, call <recv> to get data
00475       return this->recv (buf, n, addr, flags);
00476     }
00477 }
00478 
00479 ssize_t
00480 ACE_SOCK_Dgram::send (const void *buf,
00481                       size_t n,
00482                       const ACE_Addr &addr,
00483                       int flags,
00484                       const ACE_Time_Value *timeout) const
00485 {
00486   ACE_Handle_Set handle_set;
00487   handle_set.reset ();
00488   handle_set.set_bit (this->get_handle ());
00489 
00490   // Check the status of the current socket.
00491   int select_width;
00492 #if defined (ACE_WIN32)
00493   // This arg is ignored on Windows and causes pointer truncation
00494   // warnings on 64-bit compiles.
00495   select_width = 0;
00496 #else
00497   select_width = int (this->get_handle ()) + 1;
00498 #endif /* ACE_WIN32 */
00499   switch (ACE_OS::select (select_width,
00500                           0,
00501                           handle_set,
00502                           0,
00503                           timeout))
00504     {
00505     case -1:
00506       return -1;
00507       /* NOTREACHED */
00508     case 0:
00509       errno = ETIME;
00510       return -1;
00511       /* NOTREACHED */
00512     default:
00513       // Goes fine, call <send> to transmit the data.
00514       return this->send (buf, n, addr, flags);
00515     }
00516 }
00517 
00518 int
00519 ACE_SOCK_Dgram::set_nic (const ACE_TCHAR *net_if,
00520                          int addr_family)
00521 {
00522 #if defined (IP_MULTICAST_IF) && (IP_MULTICAST_IF != 0)
00523 # if defined (ACE_HAS_IPV6)
00524   bool ipv6_mif_set = false;
00525   if (addr_family == AF_INET6 || addr_family == AF_UNSPEC)
00526     {
00527       ACE_INET_Addr addr;
00528       addr.set (static_cast<u_short> (0), ACE_IPV6_ANY);
00529       ipv6_mreq send_mreq;
00530       if (this->make_multicast_ifaddr6 (&send_mreq,
00531                                         addr,
00532                                         net_if) == -1)
00533         return -1;
00534 
00535       // Only let this attempt to set unknown interface when INET6 is
00536       // specifically requested. Otherwise we will just try INET.
00537       if (send_mreq.ipv6mr_interface != 0 || addr_family == AF_INET6)
00538         {
00539           if (this->ACE_SOCK::set_option
00540                               (IPPROTO_IPV6, IPV6_MULTICAST_IF,
00541                                &(send_mreq.ipv6mr_interface),
00542                                sizeof send_mreq.ipv6mr_interface) == -1)
00543             return -1;
00544         }
00545       ipv6_mif_set = send_mreq.ipv6mr_interface != 0;
00546     }
00547 
00548 #   if defined (ACE_WIN32)
00549   // For Win32 net_if is distintly different between INET6 and INET
00550   // so it is always either an INET6 if or an INET if.
00551   if (!ipv6_mif_set && (addr_family == AF_INET || addr_family == AF_UNSPEC))
00552 #   else
00553   if (addr_family == AF_INET || addr_family == AF_UNSPEC)
00554 #   endif
00555     {
00556       ACE_INET_Addr addr (static_cast<u_short> (0));
00557       ip_mreq  send_mreq;
00558       if (this->make_multicast_ifaddr (&send_mreq,
00559                                        addr,
00560                                        net_if) == -1)
00561         {
00562           if (!ipv6_mif_set)
00563             return -1;
00564         }
00565       else if (this->ACE_SOCK::set_option (IPPROTO_IP,
00566                                            IP_MULTICAST_IF,
00567                                            &(send_mreq.imr_interface),
00568                                            sizeof send_mreq.imr_interface) == -1)
00569         {
00570           if (!ipv6_mif_set)
00571             return -1;
00572         }
00573     }
00574 # else /* ACE_HAS_IPV6 */
00575   ACE_UNUSED_ARG (addr_family);
00576   ACE_INET_Addr addr (static_cast<u_short> (0));
00577   ip_mreq  send_mreq;
00578   if (this->make_multicast_ifaddr (&send_mreq,
00579                                    addr,
00580                                    net_if) == -1)
00581     return -1;
00582   if (this->ACE_SOCK::set_option (IPPROTO_IP,
00583                                   IP_MULTICAST_IF,
00584                                   &(send_mreq.imr_interface),
00585                                   sizeof send_mreq.imr_interface) == -1)
00586     return -1;
00587 # endif /* !ACE_HAS_IPV6 */
00588 #else /* IP_MULTICAST_IF */
00589   // Send interface option not supported - ignore it.
00590   // (We may have been invoked by ::subscribe, so we have to allow
00591   // a non-null interface parameter in this function.)
00592   ACE_DEBUG ((LM_DEBUG,
00593               ACE_LIB_TEXT ("Send interface specification not ")
00594               ACE_LIB_TEXT ("supported - IGNORED.\n")));
00595 #endif /* !IP_MULTICAST_IF */
00596 
00597   return 0;
00598 }
00599 
00600 int
00601 ACE_SOCK_Dgram::make_multicast_ifaddr (ip_mreq *ret_mreq,
00602                                        const ACE_INET_Addr &mcast_addr,
00603                                        const ACE_TCHAR *net_if)
00604 {
00605   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::make_multicast_ifaddr");
00606   ip_mreq  lmreq;       // Scratch copy.
00607   if (net_if != 0)
00608     {
00609 #if defined (ACE_WIN32) || defined(__INTERIX)
00610       // This port number is not necessary, just convenient
00611       ACE_INET_Addr interface_addr;
00612       if (interface_addr.set (mcast_addr.get_port_number (), net_if) == -1)
00613         return -1;
00614       lmreq.imr_interface.s_addr =
00615         ACE_HTONL (interface_addr.get_ip_address ());
00616 #else
00617       ifreq if_address;
00618 
00619       ACE_OS::strcpy (if_address.ifr_name, ACE_TEXT_ALWAYS_CHAR (net_if));
00620 
00621       if (ACE_OS::ioctl (this->get_handle (),
00622                          SIOCGIFADDR,
00623                          &if_address) == -1)
00624         return -1;
00625 
00626       sockaddr_in *socket_address;
00627       socket_address = reinterpret_cast<sockaddr_in*> (&if_address.ifr_addr);
00628       lmreq.imr_interface.s_addr = socket_address->sin_addr.s_addr;
00629 #endif /* ACE_WIN32 || __INTERIX */
00630     }
00631   else
00632     lmreq.imr_interface.s_addr = INADDR_ANY;
00633 
00634   lmreq.IMR_MULTIADDR.s_addr = ACE_HTONL (mcast_addr.get_ip_address ());
00635 
00636   // Set return info, if requested.
00637   if (ret_mreq)
00638     *ret_mreq = lmreq;
00639 
00640   return 0;
00641 }
00642 
00643 #if defined (ACE_HAS_IPV6)
00644 // XXX: This will not work on any operating systems that do not support
00645 //      if_nametoindex or that is not Win32 >= Windows XP/Server 2003
00646 int
00647 ACE_SOCK_Dgram::make_multicast_ifaddr6 (ipv6_mreq *ret_mreq,
00648                                         const ACE_INET_Addr &mcast_addr,
00649                                         const ACE_TCHAR *net_if)
00650 {
00651   ACE_TRACE ("ACE_SOCK_Dgram_Mcast::make_multicast_ifaddr6");
00652   ipv6_mreq  lmreq;       // Scratch copy.
00653 
00654   ACE_OS::memset (&lmreq,
00655                   0,
00656                   sizeof (lmreq));
00657 
00658 #if defined(__linux__)
00659   if (net_if != 0)
00660     {
00661       lmreq.ipv6mr_interface = ACE_OS::if_nametoindex (ACE_TEXT_ALWAYS_CHAR(net_if));
00662     }
00663   else
00664 #elif defined (ACE_WIN32)
00665   if (net_if != 0)
00666     {
00667       int if_ix = 0;
00668       bool num_if =
00669         ACE_OS::ace_isdigit (net_if[0]) &&
00670         (if_ix = ACE_OS::atoi (net_if)) > 0;
00671 
00672       IP_ADAPTER_ADDRESSES tmp_addrs;
00673       // Initial call to determine actual memory size needed
00674       DWORD dwRetVal;
00675       ULONG bufLen = 0;
00676       if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00677                                               0,
00678                                               NULL,
00679                                               &tmp_addrs,
00680                                               &bufLen)) != ERROR_BUFFER_OVERFLOW)
00681         return -1; // With output bufferlength 0 this can't be right.
00682 
00683       // Get required output buffer and retrieve info for real.
00684       PIP_ADAPTER_ADDRESSES pAddrs;
00685       char *buf;
00686       ACE_NEW_RETURN (buf,
00687                       char[bufLen],
00688                       -1);
00689       pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
00690       if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00691                                               0,
00692                                               NULL,
00693                                               pAddrs,
00694                                               &bufLen)) != NO_ERROR)
00695         {
00696           delete[] buf; // clean up
00697           return -1;
00698         }
00699 
00700       lmreq.ipv6mr_interface = 0; // initialize
00701       while (pAddrs)
00702         {
00703           if ((num_if && pAddrs->Ipv6IfIndex == static_cast<unsigned int>(if_ix))
00704               || (!num_if &&
00705                   (ACE_OS::strcmp (ACE_TEXT_ALWAYS_CHAR (net_if),
00706                                    pAddrs->AdapterName) == 0
00707                    || ACE_OS::strcmp (ACE_TEXT_ALWAYS_CHAR (net_if),
00708                                       ACE_Wide_To_Ascii (pAddrs->FriendlyName).char_rep()) == 0)))
00709             {
00710               lmreq.ipv6mr_interface = pAddrs->Ipv6IfIndex;
00711               break;
00712             }
00713 
00714           pAddrs = pAddrs->Next;
00715         }
00716 
00717       delete[] buf; // clean up
00718     }
00719   else
00720 #endif /* ACE_WIN32 */
00721     lmreq.ipv6mr_interface = 0;
00722 
00723   // now set the multicast address
00724   ACE_OS::memcpy (&lmreq.ipv6mr_multiaddr,
00725                   &((sockaddr_in6 *) mcast_addr.get_addr ())->sin6_addr,
00726                   sizeof (in6_addr));
00727 
00728   // Set return info, if requested.
00729   if (ret_mreq)
00730     *ret_mreq = lmreq;
00731 
00732   return 0;
00733 }
00734 #endif /* __linux__ && ACE_HAS_IPV6 */
00735 
00736 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 09:42:04 2006 for ACE by doxygen 1.3.6