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
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
00026
00027 #if ! defined (IMR_MULTIADDR)
00028 #define IMR_MULTIADDR imr_multiaddr
00029 #endif
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
00041 }
00042
00043
00044
00045
00046
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
00061
00062 int select_width;
00063 # if defined (ACE_WIN32)
00064
00065
00066 select_width = 0;
00067 # else
00068 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 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
00118 }
00119
00120
00121
00122
00123
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
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
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
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
00213
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
00254
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
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
00282
00283 return ACE_OS::sendmsg (this->get_handle (),
00284 &send_msg,
00285 flags);
00286 }
00287
00288
00289
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
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
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
00326
00327
00328
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
00342 for (i = 0; i < n; i++)
00343 #if ! (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0530))
00344
00345
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
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
00374 return result;
00375 }
00376
00377
00378
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
00394
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
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
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
00435 return length;
00436 }
00437
00438 #endif
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
00452 int select_width;
00453 #if defined (ACE_WIN32)
00454
00455
00456 select_width = 0;
00457 #else
00458 select_width = int (this->get_handle ()) + 1;
00459 #endif
00460 switch (ACE_OS::select (select_width,
00461 handle_set,
00462 0,
00463 0,
00464 timeout))
00465 {
00466 case -1:
00467 return -1;
00468
00469 case 0:
00470 errno = ETIME;
00471 return -1;
00472
00473 default:
00474
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
00491 int select_width;
00492 #if defined (ACE_WIN32)
00493
00494
00495 select_width = 0;
00496 #else
00497 select_width = int (this->get_handle ()) + 1;
00498 #endif
00499 switch (ACE_OS::select (select_width,
00500 0,
00501 handle_set,
00502 0,
00503 timeout))
00504 {
00505 case -1:
00506 return -1;
00507
00508 case 0:
00509 errno = ETIME;
00510 return -1;
00511
00512 default:
00513
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
00536
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
00550
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
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
00588 #else
00589
00590
00591
00592 ACE_DEBUG ((LM_DEBUG,
00593 ACE_LIB_TEXT ("Send interface specification not ")
00594 ACE_LIB_TEXT ("supported - IGNORED.\n")));
00595 #endif
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;
00607 if (net_if != 0)
00608 {
00609 #if defined (ACE_WIN32) || defined(__INTERIX)
00610
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
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
00637 if (ret_mreq)
00638 *ret_mreq = lmreq;
00639
00640 return 0;
00641 }
00642
00643 #if defined (ACE_HAS_IPV6)
00644
00645
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;
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
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;
00682
00683
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;
00697 return -1;
00698 }
00699
00700 lmreq.ipv6mr_interface = 0;
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;
00718 }
00719 else
00720 #endif
00721 lmreq.ipv6mr_interface = 0;
00722
00723
00724 ACE_OS::memcpy (&lmreq.ipv6mr_multiaddr,
00725 &((sockaddr_in6 *) mcast_addr.get_addr ())->sin6_addr,
00726 sizeof (in6_addr));
00727
00728
00729 if (ret_mreq)
00730 *ret_mreq = lmreq;
00731
00732 return 0;
00733 }
00734 #endif
00735
00736 ACE_END_VERSIONED_NAMESPACE_DECL