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 85421 2009-05-22 11:12:30Z johnnyw $")
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 # if defined (ACE_WIN32)
00064
00065
00066 int select_width = 0;
00067 # else
00068 int select_width = int (this->get_handle ()) + 1;
00069 # endif
00070 switch (ACE_OS::select (select_width,
00071 handle_set,
00072 0, 0,
00073 timeout))
00074 {
00075 case -1:
00076 return -1;
00077
00078 case 0:
00079 errno = ETIME;
00080 return -1;
00081
00082 default:
00083
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 ssize_t rcv_len = ACE_OS::recvfrom (this->get_handle (),
00101 (char *) io_vec->iov_base,
00102 inlen,
00103 flags,
00104 (sockaddr *) saddr,
00105 &addr_len);
00106 if (rcv_len < 0)
00107 {
00108 delete [] (char *)io_vec->iov_base;
00109 io_vec->iov_base = 0;
00110 }
00111 else
00112 {
00113 io_vec->iov_len = ACE_Utils::truncate_cast<u_long> (rcv_len);
00114 addr.set_size (addr_len);
00115 }
00116 return rcv_len;
00117 }
00118 else
00119 return 0;
00120 #else
00121 ACE_UNUSED_ARG (flags);
00122 ACE_UNUSED_ARG (addr);
00123 ACE_UNUSED_ARG (io_vec);
00124 ACE_UNUSED_ARG (timeout);
00125 ACE_NOTSUP_RETURN (-1);
00126 #endif
00127 }
00128
00129
00130
00131
00132
00133
00134 int
00135 ACE_SOCK_Dgram::shared_open (const ACE_Addr &local,
00136 int protocol_family)
00137 {
00138 ACE_TRACE ("ACE_SOCK_Dgram::shared_open");
00139 bool error = false;
00140
00141 if (local == ACE_Addr::sap_any)
00142 {
00143 if (protocol_family == PF_INET
00144 #if defined (ACE_HAS_IPV6)
00145 || protocol_family == PF_INET6
00146 #endif
00147 )
00148 {
00149 if (ACE::bind_port (this->get_handle (),
00150 INADDR_ANY,
00151 protocol_family) == -1)
00152 error = true;
00153 }
00154 }
00155 else if (ACE_OS::bind (this->get_handle (),
00156 reinterpret_cast<sockaddr *> (local.get_addr ()),
00157 local.get_size ()) == -1)
00158 error = true;
00159
00160 if (error)
00161 this->close ();
00162
00163 return error ? -1 : 0;
00164 }
00165
00166 int
00167 ACE_SOCK_Dgram::open (const ACE_Addr &local,
00168 int protocol_family,
00169 int protocol,
00170 ACE_Protocol_Info *protocolinfo,
00171 ACE_SOCK_GROUP g,
00172 u_long flags,
00173 int reuse_addr)
00174 {
00175 if (ACE_SOCK::open (SOCK_DGRAM,
00176 protocol_family,
00177 protocol,
00178 protocolinfo,
00179 g,
00180 flags,
00181 reuse_addr) == -1)
00182 return -1;
00183 else if (this->shared_open (local,
00184 protocol_family) == -1)
00185 return -1;
00186 else
00187 return 0;
00188 }
00189
00190
00191
00192 int
00193 ACE_SOCK_Dgram::open (const ACE_Addr &local,
00194 int protocol_family,
00195 int protocol,
00196 int reuse_addr)
00197 {
00198 ACE_TRACE ("ACE_SOCK_Dgram::open");
00199
00200 if (local != ACE_Addr::sap_any)
00201 protocol_family = local.get_type ();
00202 else if (protocol_family == PF_UNSPEC)
00203 {
00204 #if defined (ACE_HAS_IPV6)
00205 protocol_family = ACE::ipv6_enabled () ? PF_INET6 : PF_INET;
00206 #else
00207 protocol_family = PF_INET;
00208 #endif
00209 }
00210
00211 if (ACE_SOCK::open (SOCK_DGRAM,
00212 protocol_family,
00213 protocol,
00214 reuse_addr) == -1)
00215 return -1;
00216 else
00217 return this->shared_open (local,
00218 protocol_family);
00219 }
00220
00221
00222
00223
00224 ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local,
00225 int protocol_family,
00226 int protocol,
00227 int reuse_addr)
00228 {
00229 ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram");
00230
00231 if (this->open (local,
00232 protocol_family,
00233 protocol,
00234 reuse_addr) == -1)
00235 ACE_ERROR ((LM_ERROR,
00236 ACE_TEXT ("%p\n"),
00237 ACE_TEXT ("ACE_SOCK_Dgram")));
00238 }
00239
00240 ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local,
00241 int protocol_family,
00242 int protocol,
00243 ACE_Protocol_Info *protocolinfo,
00244 ACE_SOCK_GROUP g,
00245 u_long flags,
00246 int reuse_addr)
00247 {
00248 ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram");
00249 if (this->open (local,
00250 protocol_family,
00251 protocol,
00252 protocolinfo,
00253 g,
00254 flags,
00255 reuse_addr) == -1)
00256 ACE_ERROR ((LM_ERROR,
00257 ACE_TEXT ("%p\n"),
00258 ACE_TEXT ("ACE_SOCK_Dgram")));
00259 }
00260
00261 #if defined (ACE_HAS_MSG)
00262
00263
00264
00265 ssize_t
00266 ACE_SOCK_Dgram::send (const iovec iov[],
00267 int n,
00268 const ACE_Addr &addr,
00269 int flags) const
00270 {
00271 ACE_TRACE ("ACE_SOCK_Dgram::send");
00272 msghdr send_msg;
00273
00274 send_msg.msg_iov = (iovec *) iov;
00275 send_msg.msg_iovlen = n;
00276 #if defined (ACE_HAS_SOCKADDR_MSG_NAME)
00277 send_msg.msg_name = (struct sockaddr *) addr.get_addr ();
00278 #else
00279 send_msg.msg_name = (char *) addr.get_addr ();
00280 #endif
00281 send_msg.msg_namelen = addr.get_size ();
00282
00283 #if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
00284 send_msg.msg_control = 0;
00285 send_msg.msg_controllen = 0;
00286 send_msg.msg_flags = 0;
00287 #else
00288 send_msg.msg_accrights = 0;
00289 send_msg.msg_accrightslen = 0;
00290 #endif
00291
00292 return ACE_OS::sendmsg (this->get_handle (),
00293 &send_msg,
00294 flags);
00295 }
00296
00297
00298
00299
00300 ssize_t
00301 ACE_SOCK_Dgram::recv (iovec iov[],
00302 int n,
00303 ACE_Addr &addr,
00304 int flags) const
00305 {
00306 ACE_TRACE ("ACE_SOCK_Dgram::recv");
00307 msghdr recv_msg;
00308
00309 recv_msg.msg_iov = (iovec *) iov;
00310 recv_msg.msg_iovlen = n;
00311 #if defined (ACE_HAS_SOCKADDR_MSG_NAME)
00312 recv_msg.msg_name = (struct sockaddr *) addr.get_addr ();
00313 #else
00314 recv_msg.msg_name = (char *) addr.get_addr ();
00315 #endif
00316 recv_msg.msg_namelen = addr.get_size ();
00317
00318 #if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
00319 recv_msg.msg_control = 0 ;
00320 recv_msg.msg_controllen = 0 ;
00321 #else
00322 recv_msg.msg_accrights = 0;
00323 recv_msg.msg_accrightslen = 0;
00324 #endif
00325
00326 ssize_t status = ACE_OS::recvmsg (this->get_handle (),
00327 &recv_msg,
00328 flags);
00329 addr.set_size (recv_msg.msg_namelen);
00330 addr.set_type (((sockaddr_in *) addr.get_addr())->sin_family);
00331 return status;
00332 }
00333
00334 #else
00335
00336
00337
00338
00339 ssize_t
00340 ACE_SOCK_Dgram::send (const iovec iov[],
00341 int n,
00342 const ACE_Addr &addr,
00343 int flags) const
00344 {
00345 ACE_TRACE ("ACE_SOCK_Dgram::send");
00346
00347 size_t length = 0;
00348 int i;
00349
00350
00351 for (i = 0; i < n; i++)
00352 #if ! (defined(__BORLANDC__) || defined(linux) || defined(ACE_HAS_RTEMS))
00353
00354
00355 if (iov[i].iov_len < 0)
00356 return -1;
00357 else
00358 #endif
00359 length += iov[i].iov_len;
00360
00361 char *buf = 0;
00362
00363 #if defined (ACE_HAS_ALLOCA)
00364 buf = alloca (length);
00365 #else
00366 ACE_NEW_RETURN (buf,
00367 char[length],
00368 -1);
00369 #endif
00370
00371 char *ptr = buf;
00372
00373 for (i = 0; i < n; i++)
00374 {
00375 ACE_OS::memcpy (ptr, iov[i].iov_base, iov[i].iov_len);
00376 ptr += iov[i].iov_len;
00377 }
00378
00379 ssize_t result = ACE_SOCK_Dgram::send (buf, length, addr, flags);
00380 #if !defined (ACE_HAS_ALLOCA)
00381 delete [] buf;
00382 #endif
00383 return result;
00384 }
00385
00386
00387
00388
00389 ssize_t
00390 ACE_SOCK_Dgram::recv (iovec iov[],
00391 int n,
00392 ACE_Addr &addr,
00393 int flags) const
00394 {
00395 ACE_TRACE ("ACE_SOCK_Dgram::recv");
00396
00397 ssize_t length = 0;
00398 int i;
00399
00400 for (i = 0; i < n; i++)
00401 #if ! (defined(__BORLANDC__) || defined(linux) || defined(ACE_HAS_RTEMS))
00402
00403
00404 if (iov[i].iov_len < 0)
00405 return -1;
00406 else
00407 #endif
00408 length += iov[i].iov_len;
00409
00410 char *buf = 0;
00411
00412 #if defined (ACE_HAS_ALLOCA)
00413 buf = alloca (length);
00414 #else
00415 ACE_NEW_RETURN (buf,
00416 char[length],
00417 -1);
00418 #endif
00419
00420 length = ACE_SOCK_Dgram::recv (buf, length, addr, flags);
00421
00422 if (length != -1)
00423 {
00424 char *ptr = buf;
00425 int copyn = length;
00426
00427 for (i = 0;
00428 i < n && copyn > 0;
00429 i++)
00430 {
00431 ACE_OS::memcpy (iov[i].iov_base, ptr,
00432
00433 copyn > (int) iov[i].iov_len
00434 ? (size_t) iov[i].iov_len
00435 : (size_t) copyn);
00436 ptr += iov[i].iov_len;
00437 copyn -= iov[i].iov_len;
00438 }
00439 }
00440
00441 #if !defined (ACE_HAS_ALLOCA)
00442 delete [] buf;
00443 #endif
00444 return length;
00445 }
00446
00447 #endif
00448
00449 ssize_t
00450 ACE_SOCK_Dgram::recv (void *buf,
00451 size_t n,
00452 ACE_Addr &addr,
00453 int flags,
00454 const ACE_Time_Value *timeout) const
00455 {
00456 ACE_Handle_Set handle_set;
00457 handle_set.reset ();
00458 handle_set.set_bit (this->get_handle ());
00459
00460
00461 #if defined (ACE_WIN32)
00462
00463
00464 int select_width = 0;
00465 #else
00466 int select_width = int (this->get_handle ()) + 1;
00467 #endif
00468 switch (ACE_OS::select (select_width,
00469 handle_set,
00470 0,
00471 0,
00472 timeout))
00473 {
00474 case -1:
00475 return -1;
00476
00477 case 0:
00478 errno = ETIME;
00479 return -1;
00480
00481 default:
00482
00483 return this->recv (buf, n, addr, flags);
00484 }
00485 }
00486
00487 ssize_t
00488 ACE_SOCK_Dgram::send (const void *buf,
00489 size_t n,
00490 const ACE_Addr &addr,
00491 int flags,
00492 const ACE_Time_Value *timeout) const
00493 {
00494 ACE_Handle_Set handle_set;
00495 handle_set.reset ();
00496 handle_set.set_bit (this->get_handle ());
00497
00498
00499 #if defined (ACE_WIN32)
00500
00501
00502 int select_width = 0;
00503 #else
00504 int select_width = int (this->get_handle ()) + 1;
00505 #endif
00506 switch (ACE_OS::select (select_width,
00507 0,
00508 handle_set,
00509 0,
00510 timeout))
00511 {
00512 case -1:
00513 return -1;
00514
00515 case 0:
00516 errno = ETIME;
00517 return -1;
00518
00519 default:
00520
00521 return this->send (buf, n, addr, flags);
00522 }
00523 }
00524
00525 int
00526 ACE_SOCK_Dgram::set_nic (const ACE_TCHAR *net_if,
00527 int addr_family)
00528 {
00529 #if defined (IP_MULTICAST_IF) && (IP_MULTICAST_IF != 0)
00530 # if defined (ACE_HAS_IPV6)
00531 bool ipv6_mif_set = false;
00532 if (addr_family == AF_INET6 || addr_family == AF_UNSPEC)
00533 {
00534 ACE_INET_Addr addr;
00535 addr.set (static_cast<u_short> (0), ACE_IPV6_ANY);
00536 ipv6_mreq send_mreq;
00537 if (this->make_multicast_ifaddr6 (&send_mreq,
00538 addr,
00539 net_if) == -1)
00540 return -1;
00541
00542
00543
00544 if (send_mreq.ipv6mr_interface != 0 || addr_family == AF_INET6)
00545 {
00546 if (this->ACE_SOCK::set_option
00547 (IPPROTO_IPV6, IPV6_MULTICAST_IF,
00548 &(send_mreq.ipv6mr_interface),
00549 sizeof send_mreq.ipv6mr_interface) == -1)
00550 return -1;
00551 }
00552 ipv6_mif_set = send_mreq.ipv6mr_interface != 0;
00553 }
00554
00555 # if defined (ACE_WIN32)
00556
00557
00558 if (!ipv6_mif_set && (addr_family == AF_INET || addr_family == AF_UNSPEC))
00559 # else
00560 if (addr_family == AF_INET || addr_family == AF_UNSPEC)
00561 # endif
00562 {
00563 ACE_INET_Addr addr (static_cast<u_short> (0));
00564 ip_mreq send_mreq;
00565 if (this->make_multicast_ifaddr (&send_mreq,
00566 addr,
00567 net_if) == -1)
00568 {
00569 if (!ipv6_mif_set)
00570 return -1;
00571 }
00572 else if (this->ACE_SOCK::set_option (IPPROTO_IP,
00573 IP_MULTICAST_IF,
00574 &(send_mreq.imr_interface),
00575 sizeof send_mreq.imr_interface) == -1)
00576 {
00577 if (!ipv6_mif_set)
00578 return -1;
00579 }
00580 }
00581 # else
00582 ACE_UNUSED_ARG (addr_family);
00583 ACE_INET_Addr addr (static_cast<u_short> (0));
00584 ip_mreq send_mreq;
00585 if (this->make_multicast_ifaddr (&send_mreq,
00586 addr,
00587 net_if) == -1)
00588 return -1;
00589 if (this->ACE_SOCK::set_option (IPPROTO_IP,
00590 IP_MULTICAST_IF,
00591 &(send_mreq.imr_interface),
00592 sizeof send_mreq.imr_interface) == -1)
00593 return -1;
00594 # endif
00595 #else
00596
00597
00598
00599 ACE_UNUSED_ARG (net_if);
00600 ACE_UNUSED_ARG (addr_family);
00601 ACE_DEBUG ((LM_DEBUG,
00602 ACE_TEXT ("Send interface specification not ")
00603 ACE_TEXT ("supported - IGNORED.\n")));
00604 #endif
00605
00606 return 0;
00607 }
00608
00609 int
00610 ACE_SOCK_Dgram::make_multicast_ifaddr (ip_mreq *ret_mreq,
00611 const ACE_INET_Addr &mcast_addr,
00612 const ACE_TCHAR *net_if)
00613 {
00614 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::make_multicast_ifaddr");
00615 ip_mreq lmreq;
00616 if (net_if != 0)
00617 {
00618 #if defined (ACE_WIN32) || defined(__INTERIX)
00619
00620 ACE_INET_Addr interface_addr;
00621 if (interface_addr.set (mcast_addr.get_port_number (), net_if) == -1)
00622 return -1;
00623 lmreq.imr_interface.s_addr =
00624 ACE_HTONL (interface_addr.get_ip_address ());
00625 #else
00626 ifreq if_address;
00627
00628 ACE_OS::strcpy (if_address.ifr_name, ACE_TEXT_ALWAYS_CHAR (net_if));
00629
00630 if (ACE_OS::ioctl (this->get_handle (),
00631 SIOCGIFADDR,
00632 &if_address) == -1)
00633 return -1;
00634
00635 sockaddr_in *socket_address =
00636 reinterpret_cast<sockaddr_in*> (&if_address.ifr_addr);
00637 lmreq.imr_interface.s_addr = socket_address->sin_addr.s_addr;
00638 #endif
00639 }
00640 else
00641 lmreq.imr_interface.s_addr = INADDR_ANY;
00642
00643 lmreq.IMR_MULTIADDR.s_addr = ACE_HTONL (mcast_addr.get_ip_address ());
00644
00645
00646 if (ret_mreq)
00647 *ret_mreq = lmreq;
00648
00649 return 0;
00650 }
00651
00652 #if defined (ACE_HAS_IPV6)
00653
00654
00655 int
00656 ACE_SOCK_Dgram::make_multicast_ifaddr6 (ipv6_mreq *ret_mreq,
00657 const ACE_INET_Addr &mcast_addr,
00658 const ACE_TCHAR *net_if)
00659 {
00660 ACE_TRACE ("ACE_SOCK_Dgram_Mcast::make_multicast_ifaddr6");
00661 ipv6_mreq lmreq;
00662
00663 ACE_OS::memset (&lmreq,
00664 0,
00665 sizeof (lmreq));
00666
00667 #if defined(__linux__)
00668 if (net_if != 0)
00669 {
00670 lmreq.ipv6mr_interface = ACE_OS::if_nametoindex (ACE_TEXT_ALWAYS_CHAR(net_if));
00671 }
00672 else
00673 #elif defined (ACE_WIN32)
00674 if (net_if != 0)
00675 {
00676 int if_ix = 0;
00677 bool num_if =
00678 ACE_OS::ace_isdigit (net_if[0]) &&
00679 (if_ix = ACE_OS::atoi (net_if)) > 0;
00680
00681 IP_ADAPTER_ADDRESSES tmp_addrs;
00682
00683 DWORD dwRetVal;
00684 ULONG bufLen = 0;
00685 if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00686 0,
00687 0,
00688 &tmp_addrs,
00689 &bufLen)) != ERROR_BUFFER_OVERFLOW)
00690 return -1;
00691
00692
00693 PIP_ADAPTER_ADDRESSES pAddrs;
00694 char *buf;
00695 ACE_NEW_RETURN (buf,
00696 char[bufLen],
00697 -1);
00698 pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
00699 if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
00700 0,
00701 0,
00702 pAddrs,
00703 &bufLen)) != NO_ERROR)
00704 {
00705 delete[] buf;
00706 return -1;
00707 }
00708
00709 lmreq.ipv6mr_interface = 0;
00710 while (pAddrs)
00711 {
00712 if ((num_if && pAddrs->Ipv6IfIndex == static_cast<unsigned int>(if_ix))
00713 || (!num_if &&
00714 (ACE_OS::strcmp (ACE_TEXT_ALWAYS_CHAR (net_if),
00715 pAddrs->AdapterName) == 0
00716 || ACE_OS::strcmp (ACE_TEXT_ALWAYS_CHAR (net_if),
00717 ACE_Wide_To_Ascii (pAddrs->FriendlyName).char_rep()) == 0)))
00718 {
00719 lmreq.ipv6mr_interface = pAddrs->Ipv6IfIndex;
00720 break;
00721 }
00722
00723 pAddrs = pAddrs->Next;
00724 }
00725
00726 delete[] buf;
00727 }
00728 else
00729 #else
00730 ACE_UNUSED_ARG(net_if);
00731 #endif
00732 lmreq.ipv6mr_interface = 0;
00733
00734
00735 ACE_OS::memcpy (&lmreq.ipv6mr_multiaddr,
00736 &((sockaddr_in6 *) mcast_addr.get_addr ())->sin6_addr,
00737 sizeof (in6_addr));
00738
00739
00740 if (ret_mreq)
00741 *ret_mreq = lmreq;
00742
00743 return 0;
00744 }
00745 #endif
00746
00747 ACE_END_VERSIONED_NAMESPACE_DECL