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

Generated on Tue Feb 2 17:18:42 2010 for ACE by  doxygen 1.4.7