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
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 79332 2007-08-13 20:30:44Z sowayaa $")
00025
00026
00027
00028 #if ! defined (IMR_MULTIADDR)
00029 #define IMR_MULTIADDR imr_multiaddr
00030 #endif
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
00042 }
00043
00044
00045
00046
00047
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
00062
00063 int select_width;
00064 # if defined (ACE_WIN32)
00065
00066
00067 select_width = 0;
00068 # else
00069 select_width = int (this->get_handle ()) + 1;
00070 # endif
00071 switch (ACE_OS::select (select_width,
00072 handle_set,
00073 0, 0,
00074 timeout))
00075 {
00076 case -1:
00077 return -1;
00078
00079 case 0:
00080 errno = ETIME;
00081 return -1;
00082
00083 default:
00084
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
00128 }
00129
00130
00131
00132
00133
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 int error = 0;
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
00148 )
00149 {
00150 if (ACE::bind_port (this->get_handle (),
00151 INADDR_ANY,
00152 protocol_family) == -1)
00153 error = 1;
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 = 1;
00160
00161 if (error != 0)
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
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
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
00223
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
00264
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
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
00292
00293 return ACE_OS::sendmsg (this->get_handle (),
00294 &send_msg,
00295 flags);
00296 }
00297
00298
00299
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
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
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
00336
00337
00338
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
00352 for (i = 0; i < n; i++)
00353 #if ! (defined(__BORLANDC__) || defined(linux) || defined(ACE_HAS_RTEMS))
00354
00355
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
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
00384 return result;
00385 }
00386
00387
00388
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
00404
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
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
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
00445 return length;
00446 }
00447
00448 #endif
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
00462 int select_width;
00463 #if defined (ACE_WIN32)
00464
00465
00466 select_width = 0;
00467 #else
00468 select_width = int (this->get_handle ()) + 1;
00469 #endif
00470 switch (ACE_OS::select (select_width,
00471 handle_set,
00472 0,
00473 0,
00474 timeout))
00475 {
00476 case -1:
00477 return -1;
00478
00479 case 0:
00480 errno = ETIME;
00481 return -1;
00482
00483 default:
00484
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
00501 int select_width;
00502 #if defined (ACE_WIN32)
00503
00504
00505 select_width = 0;
00506 #else
00507 select_width = int (this->get_handle ()) + 1;
00508 #endif
00509 switch (ACE_OS::select (select_width,
00510 0,
00511 handle_set,
00512 0,
00513 timeout))
00514 {
00515 case -1:
00516 return -1;
00517
00518 case 0:
00519 errno = ETIME;
00520 return -1;
00521
00522 default:
00523
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
00546
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
00560
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
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
00598 #else
00599
00600
00601
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
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;
00619 if (net_if != 0)
00620 {
00621 #if defined (ACE_WIN32) || defined(__INTERIX)
00622
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
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
00649 if (ret_mreq)
00650 *ret_mreq = lmreq;
00651
00652 return 0;
00653 }
00654
00655 #if defined (ACE_HAS_IPV6)
00656
00657
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;
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
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;
00694
00695
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;
00709 return -1;
00710 }
00711
00712 lmreq.ipv6mr_interface = 0;
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;
00730 }
00731 else
00732 #else
00733 ACE_UNUSED_ARG(net_if);
00734 #endif
00735 lmreq.ipv6mr_interface = 0;
00736
00737
00738 ACE_OS::memcpy (&lmreq.ipv6mr_multiaddr,
00739 &((sockaddr_in6 *) mcast_addr.get_addr ())->sin6_addr,
00740 sizeof (in6_addr));
00741
00742
00743 if (ret_mreq)
00744 *ret_mreq = lmreq;
00745
00746 return 0;
00747 }
00748 #endif
00749
00750 ACE_END_VERSIONED_NAMESPACE_DECL