// -*- C++ -*- #include "ace/OS_NS_errno.h" #include "ace/OS_NS_macros.h" #include "ace/OS_NS_sys_uio.h" #include "ace/OS_NS_stdio.h" #include "ace/OS_QoS.h" #include "ace/Global_Macros.h" #include "ace/os_include/netinet/os_in.h" #if defined (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO) \ && (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO == 1) #include "ace/OS_NS_string.h" #endif ACE_BEGIN_VERSIONED_NAMESPACE_DECL #if defined (ACE_HAS_VOIDPTR_SOCKOPT) typedef void *ACE_SOCKOPT_TYPE1; #elif defined (ACE_HAS_CHARPTR_SOCKOPT) typedef char *ACE_SOCKOPT_TYPE1; #else typedef const char *ACE_SOCKOPT_TYPE1; #endif /* ACE_HAS_VOIDPTR_SOCKOPT */ ACE_INLINE ACE_HANDLE ACE_OS::accept (ACE_HANDLE handle, struct sockaddr *addr, int *addrlen) { ACE_OS_TRACE ("ACE_OS::accept"); // On a non-blocking socket with no connections to accept, this // system call will return EWOULDBLOCK or EAGAIN, depending on the // platform. UNIX 98 allows either errno, and they may be the same // numeric value. So to make life easier for upper ACE layers as // well as application programmers, always change EAGAIN to // EWOULDBLOCK. Rather than hack the ACE_OSCALL_RETURN macro, it's // handled explicitly here. If the ACE_OSCALL macro ever changes, // this function needs to be reviewed. On Win32, the regular macros // can be used, as this is not an issue. #if defined (ACE_LACKS_ACCEPT) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (addr); ACE_UNUSED_ARG (addrlen); ACE_NOTSUP_RETURN (ACE_INVALID_HANDLE); #elif defined (ACE_WIN32) ACE_SOCKCALL_RETURN (::accept ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN *) addrlen), ACE_HANDLE, ACE_INVALID_HANDLE); #else # if defined (ACE_HAS_BROKEN_ACCEPT_ADDR) // Apparently some platforms like VxWorks can't correctly deal with // a NULL addr. # if defined (ACE_HAS_IPV6) sockaddr_in6 fake_addr; # else sockaddr_in fake_addr; # endif /* ACE_HAS_IPV6 */ int fake_addrlen; if (addrlen == 0) addrlen = &fake_addrlen; if (addr == 0) { addr = (sockaddr *) &fake_addr; *addrlen = sizeof fake_addr; } # endif /* ACE_HAS_BROKEN_ACCEPT_ADDR */ ACE_HANDLE ace_result = ::accept ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN *) addrlen); # if !(defined (EAGAIN) && defined (EWOULDBLOCK) && EAGAIN == EWOULDBLOCK) // Optimize this code out if we can detect that EAGAIN == // EWOULDBLOCK at compile time. If we cannot detect equality at // compile-time (e.g. if EAGAIN or EWOULDBLOCK are not preprocessor // macros) perform the check at run-time. The goal is to avoid two // TSS accesses in the _REENTRANT case when EAGAIN == EWOULDBLOCK. if (ace_result == ACE_INVALID_HANDLE # if !defined (EAGAIN) || !defined (EWOULDBLOCK) && EAGAIN != EWOULDBLOCK # endif /* !EAGAIN || !EWOULDBLOCK */ && errno == EAGAIN) { errno = EWOULDBLOCK; } # endif /* EAGAIN != EWOULDBLOCK*/ return ace_result; #endif /* defined (ACE_WIN32) */ } ACE_INLINE int ACE_OS::bind (ACE_HANDLE handle, struct sockaddr *addr, int addrlen) { ACE_OS_TRACE ("ACE_OS::bind"); #if defined (ACE_LACKS_BIND) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (addr); ACE_UNUSED_ARG (addrlen); ACE_NOTSUP_RETURN (-1); #elif defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x640) // VxWorks clears the sin_port member after a successful bind when // sin_addr != INADDR_ANY, so after the bind we do retrieve the // original address so that user code can safely check the addr // after the bind. See bugzilla 3107 for more details int result; ACE_SOCKCALL (::bind ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN) addrlen), int, -1, result); if (result == -1) return -1; else return ACE_OS::getsockname (handle, addr, &addrlen); #else ACE_SOCKCALL_RETURN (::bind ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN) addrlen), int, -1); #endif } ACE_INLINE int ACE_OS::closesocket (ACE_HANDLE handle) { ACE_OS_TRACE ("ACE_OS::closesocket"); #if defined (ACE_WIN32) || defined (ACE_MQX) // @note Do not shutdown the write end here. Doing so will break // applications that duplicate a handle on fork(), for // example, and expect to continue writing in the fork()ed // process. ACE_SOCKCALL_RETURN (::closesocket ((SOCKET) handle), int, -1); #else //FUZZ: disable check_for_lack_ACE_OS return ::close (handle); //FUZZ: enable check_for_lack_ACE_OS #endif /* ACE_WIN32 */ } ACE_INLINE int ACE_OS::connect (ACE_HANDLE handle, struct sockaddr *addr, int addrlen) { ACE_OS_TRACE ("ACE_OS::connect"); #if defined (ACE_LACKS_CONNECT) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (addr); ACE_UNUSED_ARG (addrlen); ACE_NOTSUP_RETURN (-1); #else ACE_SOCKCALL_RETURN (::connect ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN) addrlen), int, -1); #endif /* ACE_LACKS_CONNECT */ } ACE_INLINE int ACE_OS::enum_protocols (int *protocols, ACE_Protocol_Info *protocol_buffer, u_long *buffer_length) { #if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) ACE_SOCKCALL_RETURN (::WSAEnumProtocols (protocols, protocol_buffer, buffer_length), int, SOCKET_ERROR); #else ACE_UNUSED_ARG (protocols); ACE_UNUSED_ARG (protocol_buffer); ACE_UNUSED_ARG (buffer_length); ACE_NOTSUP_RETURN (-1); #endif /* ACE_HAS_WINSOCK2 */ } ACE_INLINE int ACE_OS::getpeername (ACE_HANDLE handle, struct sockaddr *addr, int *addrlen) { ACE_OS_TRACE ("ACE_OS::getpeername"); #if defined (ACE_LACKS_GETPEERNAME) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (addr); ACE_UNUSED_ARG (addrlen); ACE_NOTSUP_RETURN (-1); #elif defined (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO) \ && (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO == 1) int result; ACE_SOCKCALL (::getpeername ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN *) addrlen), int, -1, result); // Some platforms, like older versions of the Linux kernel, do not // initialize the sin_zero field since that field is generally only // used for padding/alignment purposes. On those platforms // memcmp()-based comparisons of the sockaddr_in structure, such as // the one in the ACE_INET_Addr equality operator, may fail due to // random bytes in the sin_zero field even though that field is // unused. Prevent equality comparison of two different sockaddr_in // instances that refer to the same socket from failing by // explicitly initializing the sockaddr_in::sin_zero field to a // consistent value, e.g. zero. if (result != -1 && addr->sa_family == AF_INET) { ACE_OS::memset (reinterpret_cast (addr)->sin_zero, 0, sizeof (reinterpret_cast (addr)->sin_zero)); } return result; #else ACE_SOCKCALL_RETURN (::getpeername ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN *) addrlen), int, -1); #endif /* ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO */ } ACE_INLINE int ACE_OS::getsockname (ACE_HANDLE handle, struct sockaddr *addr, int *addrlen) { ACE_OS_TRACE ("ACE_OS::getsockname"); #if defined (ACE_LACKS_GETSOCKNAME) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (addr); ACE_UNUSED_ARG (addrlen); ACE_NOTSUP_RETURN (-1); #elif defined (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO) \ && (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO == 1) int result; ACE_SOCKCALL (::getsockname ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN *) addrlen), int, -1, result); // Some platforms, like older versions of the Linux kernel, do not // initialize the sin_zero field since that field is generally only // used for padding/alignment purposes. On those platforms // memcmp()-based comparisons of the sockaddr_in structure, such as // the one in the ACE_INET_Addr equality operator, may fail due to // random bytes in the sin_zero field even though that field is // unused. Prevent equality comparison of two different sockaddr_in // instances that refer to the same socket from failing by // explicitly initializing the sockaddr_in::sin_zero field to a // consistent value, e.g. zero. if (result != -1 && addr->sa_family == AF_INET) { ACE_OS::memset (reinterpret_cast (addr)->sin_zero, 0, sizeof (reinterpret_cast (addr)->sin_zero)); } return result; #else ACE_SOCKCALL_RETURN (::getsockname ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN *) addrlen), int, -1); #endif /* ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO */ } #if !defined(ACE_SOCKOPT_LEN) #define ACE_SOCKOPT_LEN ACE_SOCKET_LEN #endif ACE_INLINE int ACE_OS::getsockopt (ACE_HANDLE handle, int level, int optname, char *optval, int *optlen) { ACE_OS_TRACE ("ACE_OS::getsockopt"); #if defined (ACE_LACKS_GETSOCKOPT) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (level); ACE_UNUSED_ARG (optname); ACE_UNUSED_ARG (optval); ACE_UNUSED_ARG (optlen); ACE_NOTSUP_RETURN (-1); #else ACE_SOCKCALL_RETURN (::getsockopt ((ACE_SOCKET) handle, level, optname, optval, (ACE_SOCKOPT_LEN *) optlen), int, -1); #endif /* ACE_LACKS_GETSOCKOPT */ } ACE_INLINE int ACE_OS::listen (ACE_HANDLE handle, int backlog) { ACE_OS_TRACE ("ACE_OS::listen"); #if defined (ACE_LACKS_LISTEN) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (backlog); ACE_NOTSUP_RETURN (-1); #else ACE_SOCKCALL_RETURN (::listen ((ACE_SOCKET) handle, backlog), int, -1); #endif /* ACE_LACKS_LISTEN */ } ACE_INLINE ssize_t ACE_OS::recv (ACE_HANDLE handle, char *buf, size_t len, int flags) { ACE_OS_TRACE ("ACE_OS::recv"); // On UNIX, a non-blocking socket with no data to receive, this // system call will return EWOULDBLOCK or EAGAIN, depending on the // platform. UNIX 98 allows either errno, and they may be the same // numeric value. So to make life easier for upper ACE layers as // well as application programmers, always change EAGAIN to // EWOULDBLOCK. Rather than hack the ACE_OSCALL_RETURN macro, it's // handled explicitly here. If the ACE_OSCALL macro ever changes, // this function needs to be reviewed. On Win32, the regular macros // can be used, as this is not an issue. #if defined (ACE_LACKS_RECV) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (buf); ACE_UNUSED_ARG (len); ACE_UNUSED_ARG (flags); ACE_NOTSUP_RETURN (-1); #elif defined (ACE_WIN32) ACE_SOCKCALL_RETURN (::recv ((ACE_SOCKET) handle, buf, static_cast (len), flags), ssize_t, -1); #else ssize_t ace_result_; ace_result_ = ::recv ((ACE_SOCKET) handle, buf, len, flags); # if !(defined (EAGAIN) && defined (EWOULDBLOCK) && EAGAIN == EWOULDBLOCK) // Optimize this code out if we can detect that EAGAIN == // EWOULDBLOCK at compile time. If we cannot detect equality at // compile-time (e.g. if EAGAIN or EWOULDBLOCK are not preprocessor // macros) perform the check at run-time. The goal is to avoid two // TSS accesses in the _REENTRANT case when EAGAIN == EWOULDBLOCK. if (ace_result_ == -1 # if !defined (EAGAIN) || !defined (EWOULDBLOCK) && EAGAIN != EWOULDBLOCK # endif /* !EAGAIN || !EWOULDBLOCK */ && errno == EAGAIN) { errno = EWOULDBLOCK; } # endif /* EAGAIN != EWOULDBLOCK*/ return ace_result_; #endif /* ACE_LACKS_RECV */ } ACE_INLINE ssize_t ACE_OS::recvfrom (ACE_HANDLE handle, char *buf, size_t len, int flags, struct sockaddr *addr, int *addrlen) { ACE_OS_TRACE ("ACE_OS::recvfrom"); #if defined (ACE_LACKS_RECVFROM) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (buf); ACE_UNUSED_ARG (len); ACE_UNUSED_ARG (flags); ACE_UNUSED_ARG (addr); ACE_UNUSED_ARG (addrlen); ACE_NOTSUP_RETURN (-1); #elif defined (ACE_WIN32) int const shortened_len = static_cast (len); int const result = ::recvfrom ((ACE_SOCKET) handle, buf, shortened_len, flags, addr, (ACE_SOCKET_LEN *) addrlen); if (result == SOCKET_ERROR) { ACE_OS::set_errno_to_wsa_last_error (); if (errno == WSAEMSGSIZE && ACE_BIT_ENABLED (flags, MSG_PEEK)) return shortened_len; else return -1; } else { return result; } #else /* non Win32 */ ACE_SOCKCALL_RETURN (::recvfrom ((ACE_SOCKET) handle, buf, len, flags, addr, (ACE_SOCKET_LEN *) addrlen), ssize_t, -1); #endif /* ACE_LACKS_RECVFROM */ } ACE_INLINE ssize_t ACE_OS::recvfrom (ACE_HANDLE handle, iovec *buffers, int buffer_count, size_t &number_of_bytes_recvd, int &flags, struct sockaddr *addr, int *addrlen, ACE_OVERLAPPED *overlapped, ACE_OVERLAPPED_COMPLETION_FUNC func) { ACE_OS_TRACE ("ACE_OS::recvfrom"); #if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) DWORD bytes_recvd; DWORD the_flags = flags; int result = ::WSARecvFrom ((SOCKET) handle, (WSABUF*)buffers, buffer_count, &bytes_recvd, &the_flags, addr, addrlen, overlapped, func); if (result != 0) { ACE_OS::set_errno_to_wsa_last_error (); } flags = the_flags; number_of_bytes_recvd = static_cast (bytes_recvd); return result; #else ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (buffers); ACE_UNUSED_ARG (buffer_count); ACE_UNUSED_ARG (number_of_bytes_recvd); ACE_UNUSED_ARG (flags); ACE_UNUSED_ARG (addr); ACE_UNUSED_ARG (addrlen); ACE_UNUSED_ARG (overlapped); ACE_UNUSED_ARG (func); ACE_NOTSUP_RETURN (-1); #endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */ } ACE_INLINE ssize_t ACE_OS::recvmsg (ACE_HANDLE handle, struct msghdr *msg, int flags) { ACE_OS_TRACE ("ACE_OS::recvmsg"); #if !defined (ACE_LACKS_RECVMSG) # if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) DWORD bytes_received = 0; int const result = msg->msg_control ? recvmsg_win32_i (handle, msg, flags, bytes_received) : ::WSARecvFrom ((SOCKET) handle, (WSABUF *) msg->msg_iov, msg->msg_iovlen, &bytes_received, (DWORD *) &flags, msg->msg_name, &msg->msg_namelen, 0, 0); if (result != 0) { ACE_OS::set_errno_to_wsa_last_error (); return -1; } else return bytes_received; # else /* ACE_HAS_WINSOCK2 */ ACE_SOCKCALL_RETURN (::recvmsg (handle, msg, flags), ssize_t, -1); # endif /* ACE_HAS_WINSOCK2 */ #else ACE_UNUSED_ARG (flags); ACE_UNUSED_ARG (msg); ACE_UNUSED_ARG (handle); ACE_NOTSUP_RETURN (-1); #endif /* ACE_LACKS_RECVMSG */ } ACE_INLINE ssize_t ACE_OS::recvv (ACE_HANDLE handle, iovec *buffers, int n) { #if defined (ACE_HAS_WINSOCK2) DWORD bytes_received = 0; int result = 1; // Winsock 2 has WSARecv and can do this directly, but Winsock 1 needs // to do the recvs piece-by-piece. # if (ACE_HAS_WINSOCK2 != 0) DWORD flags = 0; result = ::WSARecv ((SOCKET) handle, (WSABUF *) buffers, n, &bytes_received, &flags, 0, 0); # else // Step through the buffers requested by caller; for each one, cycle // through reads until it's filled or an error occurs. for (int i = 0; i < n && result > 0; ++i) { char *chunkp = buffers[i].iov_base; // Point to part of chunk being read int chunklen = buffers[i].iov_len; // Track how much to read to chunk while (chunklen > 0 && result > 0) { result = ::recv ((SOCKET) handle, chunkp, chunklen, 0); if (result > 0) { chunkp += result; chunklen -= result; bytes_received += result; } } } # endif /* ACE_HAS_WINSOCK2 != 0 */ if (result == SOCKET_ERROR) { ACE_OS::set_errno_to_wsa_last_error (); return -1; } else return (ssize_t) bytes_received; #else return ACE_OS::readv (handle, buffers, n); #endif /* ACE_HAS_WINSOCK2 */ } ACE_INLINE ssize_t ACE_OS::send (ACE_HANDLE handle, const char *buf, size_t len, int flags) { ACE_OS_TRACE ("ACE_OS::send"); // On UNIX, a non-blocking socket with no data to receive, this // system call will return EWOULDBLOCK or EAGAIN, depending on the // platform. UNIX 98 allows either errno, and they may be the same // numeric value. So to make life easier for upper ACE layers as // well as application programmers, always change EAGAIN to // EWOULDBLOCK. Rather than hack the ACE_OSCALL_RETURN macro, it's // handled explicitly here. If the ACE_OSCALL macro ever changes, // this function needs to be reviewed. On Win32, the regular macros // can be used, as this is not an issue. #if defined (ACE_LACKS_SEND) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (buf); ACE_UNUSED_ARG (len); ACE_UNUSED_ARG (flags); ACE_NOTSUP_RETURN (-1); #elif defined (ACE_WIN32) ssize_t result = ::send ((ACE_SOCKET) handle, buf, static_cast (len), flags); if (result == -1) { ACE_OS::set_errno_to_wsa_last_error(); if (errno != ENOBUFS) return -1; ACE_SOCKCALL_RETURN(send_partial_i(handle, buf, len, flags), ssize_t, -1); } else return result; #else # if defined (ACE_MQX) ssize_t const ace_result_ = ::send ((ACE_SOCKET) handle, (void*)buf, len, flags); #else ssize_t const ace_result_ = ::send ((ACE_SOCKET) handle, buf, len, flags); #endif # if !(defined (EAGAIN) && defined (EWOULDBLOCK) && EAGAIN == EWOULDBLOCK) // Optimize this code out if we can detect that EAGAIN == // EWOULDBLOCK at compile time. If we cannot detect equality at // compile-time (e.g. if EAGAIN or EWOULDBLOCK are not preprocessor // macros) perform the check at run-time. The goal is to avoid two // TSS accesses in the _REENTRANT case when EAGAIN == EWOULDBLOCK. if (ace_result_ == -1 # if !defined (EAGAIN) || !defined (EWOULDBLOCK) && EAGAIN != EWOULDBLOCK # endif /* !EAGAIN || !EWOULDBLOCK */ && errno == EAGAIN) { errno = EWOULDBLOCK; } # endif /* EAGAIN != EWOULDBLOCK*/ return ace_result_; #endif /* defined (ACE_WIN32) */ } ACE_INLINE ssize_t ACE_OS::sendmsg (ACE_HANDLE handle, const struct msghdr *msg, int flags) { ACE_OS_TRACE ("ACE_OS::sendmsg"); #if !defined (ACE_LACKS_SENDMSG) # if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) DWORD bytes_sent = 0; int const result = msg->msg_control ? sendmsg_win32_i (handle, msg, flags, bytes_sent) : ::WSASendTo ((SOCKET) handle, (WSABUF *) msg->msg_iov, msg->msg_iovlen, &bytes_sent, flags, msg->msg_name, msg->msg_namelen, 0, 0); if (result != 0) { ACE_OS::set_errno_to_wsa_last_error (); return -1; } else return (ssize_t) bytes_sent; # elif defined (ACE_HAS_NONCONST_SENDMSG) ACE_SOCKCALL_RETURN (::sendmsg (handle, const_cast(msg), flags), ssize_t, -1); # else ACE_SOCKCALL_RETURN (::sendmsg (handle, msg, flags), ssize_t, -1); # endif #else ACE_UNUSED_ARG (flags); ACE_UNUSED_ARG (msg); ACE_UNUSED_ARG (handle); ACE_NOTSUP_RETURN (-1); #endif /* ACE_LACKS_SENDMSG */ } ACE_INLINE ssize_t ACE_OS::sendto (ACE_HANDLE handle, const char *buf, size_t len, int flags, const struct sockaddr *addr, int addrlen) { ACE_OS_TRACE ("ACE_OS::sendto"); #if defined (ACE_LACKS_SENDTO) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (buf); ACE_UNUSED_ARG (len); ACE_UNUSED_ARG (flags); ACE_UNUSED_ARG (addr); ACE_UNUSED_ARG (addrlen); ACE_NOTSUP_RETURN (-1); #elif defined (ACE_VXWORKS) ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle, const_cast (buf), len, flags, const_cast (addr), addrlen), ssize_t, -1); #elif defined (ACE_WIN32) ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle, buf, static_cast (len), flags, const_cast (addr), addrlen), ssize_t, -1); #elif defined (ACE_MQX) ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle, (void*)buf, len, flags, const_cast (addr), addrlen), ssize_t, -1); #else ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle, buf, len, flags, const_cast (addr), addrlen), ssize_t, -1); #endif /* ACE_LACKS_SENDTO */ } ACE_INLINE ssize_t ACE_OS::sendto (ACE_HANDLE handle, const iovec *buffers, int buffer_count, size_t &number_of_bytes_sent, int flags, const struct sockaddr *addr, int addrlen, ACE_OVERLAPPED *overlapped, ACE_OVERLAPPED_COMPLETION_FUNC func) { ACE_OS_TRACE ("ACE_OS::sendto"); #if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) DWORD bytes_sent = 0; int result = ::WSASendTo ((SOCKET) handle, (WSABUF*) buffers, buffer_count, &bytes_sent, flags, addr, addrlen, overlapped, func); if (result != 0) { ACE_OS::set_errno_to_wsa_last_error (); } number_of_bytes_sent = static_cast (bytes_sent); return (ssize_t) result; #else ACE_UNUSED_ARG (overlapped); ACE_UNUSED_ARG (func); number_of_bytes_sent = 0; ssize_t result = 0; for (int i = 0; i < buffer_count; ++i) { result = ACE_OS::sendto (handle, reinterpret_cast ( buffers[i].iov_base), buffers[i].iov_len, flags, addr, addrlen); if (result == -1) break; number_of_bytes_sent += static_cast (result); } return result; #endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */ } ACE_INLINE ssize_t ACE_OS::sendv (ACE_HANDLE handle, const iovec *buffers, int n) { #if defined (ACE_HAS_WINSOCK2) DWORD bytes_sent = 0; ssize_t result = 0; // Winsock 2 has WSASend and can do this directly, but Winsock 1 // needs to do the sends one-by-one. # if (ACE_HAS_WINSOCK2 != 0) && !defined (ACE_DONT_USE_WSASEND) result = ::WSASend ((SOCKET) handle, (WSABUF *) buffers, n, &bytes_sent, 0, 0, 0); if (result == SOCKET_ERROR) { ACE_OS::set_errno_to_wsa_last_error (); if ((errno != ENOBUFS) || (bytes_sent != 0)) { return -1; } result = sendv_partial_i(handle, buffers, n); if (result == SOCKET_ERROR) { ACE_OS::set_errno_to_wsa_last_error (); return -1; } bytes_sent = static_cast(result); } # else for (int i = 0; i < n; ++i) { result = ::send ((SOCKET) handle, buffers[i].iov_base, buffers[i].iov_len, 0); if (result == SOCKET_ERROR) { // There is a subtle difference in behaviour depending on // whether or not any data was sent. If no data was sent, // then always return -1. Otherwise return bytes_sent. // This gives the caller an opportunity to keep track of // bytes that have already been sent. if (bytes_sent > 0) break; else { ACE_OS::set_errno_to_wsa_last_error (); return -1; } } else { // Gets ignored on error anyway bytes_sent += result; // If the transfer isn't complete just drop out of the loop. if (result < (int)buffers[i].iov_len) break; } } # endif /* ACE_HAS_WINSOCK2 != 0 */ return (ssize_t) bytes_sent; #elif defined (ACE_MQX) ssize_t bytes_sent = 0; for (int i = 0; i < n; ++i) { ssize_t result = ACE_OS::send (handle, buffers[i].iov_base, buffers[i].iov_len, 0); if (result == -1) { // There is a subtle difference in behaviour depending on // whether or not any data was sent. If no data was sent, // then always return -1. Otherwise return bytes_sent. // This gives the caller an opportunity to keep track of // bytes that have already been sent. if (bytes_sent > 0) break; else { // errno should already be set from the ACE_OS::send call. return -1; } } else { // Gets ignored on error anyway bytes_sent += result; // If the transfer isn't complete just drop out of the loop. if (result < buffers[i].iov_len) break; } } return bytes_sent; #elif defined (ACE_HAS_SOCK_BUF_SIZE_MAX) // Platform limits the maximum socket message size. Pare down the // iovec, if necessary, to obey the limit. iovec local_iov[ACE_IOV_MAX]; long total = 0; long new_total = 0; for (int i = 0; i < n; i++) { local_iov[i].iov_base = buffers[i].iov_base; local_iov[i].iov_len = buffers[i].iov_len; new_total = total + buffers[i].iov_len; if (new_total >= ACE_HAS_SOCK_BUF_SIZE_MAX_VALUE) { local_iov[i].iov_len = ACE_HAS_SOCK_BUF_SIZE_MAX_VALUE - total; n = i+1; break; } total = new_total; } return ACE_OS::writev (handle, local_iov, n); #else return ACE_OS::writev (handle, buffers, n); #endif /* ACE_HAS_WINSOCK2 */ } ACE_INLINE int ACE_OS::setsockopt (ACE_HANDLE handle, int level, int optname, const char *optval, int optlen) { ACE_OS_TRACE ("ACE_OS::setsockopt"); #if defined (ACE_LACKS_SETSOCKOPT) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (level); ACE_UNUSED_ARG (optname); ACE_UNUSED_ARG (optval); ACE_UNUSED_ARG (optlen); ACE_NOTSUP_RETURN (-1); #else int result; ACE_SOCKCALL (::setsockopt ((ACE_SOCKET) handle, level, optname, (ACE_SOCKOPT_TYPE1) optval, optlen), int, -1, result); #if defined (WSAEOPNOTSUPP) if (result == -1 && (errno == WSAEOPNOTSUPP || errno == WSAENOPROTOOPT)) #else if (result == -1) #endif /* WSAEOPNOTSUPP */ errno = ENOTSUP; return result; #endif } ACE_INLINE int ACE_OS::shutdown (ACE_HANDLE handle, int how) { ACE_OS_TRACE ("ACE_OS::shutdown"); #if defined (ACE_LACKS_SHUTDOWN) ACE_UNUSED_ARG (handle); ACE_UNUSED_ARG (how); ACE_NOTSUP_RETURN (-1); #else ACE_SOCKCALL_RETURN (::shutdown ((ACE_SOCKET) handle, how), int, -1); #endif /* ACE_LACKS_SHUTDOWN */ } ACE_INLINE ACE_HANDLE ACE_OS::socket (int domain, int type, int proto) { ACE_OS_TRACE ("ACE_OS::socket"); #if defined (ACE_LACKS_SOCKET) ACE_UNUSED_ARG (domain); ACE_UNUSED_ARG (type); ACE_UNUSED_ARG (proto); ACE_NOTSUP_RETURN (ACE_INVALID_HANDLE); #else ACE_SOCKCALL_RETURN (::socket (domain, type, proto), ACE_HANDLE, ACE_INVALID_HANDLE); #endif /* ACE_LACKS_SOCKET */ } ACE_INLINE ACE_HANDLE ACE_OS::socket (int domain, int type, int proto, ACE_Protocol_Info *protocolinfo, ACE_SOCK_GROUP g, u_long flags) { ACE_OS_TRACE ("ACE_OS::socket"); #if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) ACE_SOCKCALL_RETURN (::WSASocket (domain, type, proto, protocolinfo, g, flags), ACE_HANDLE, ACE_INVALID_HANDLE); #else ACE_UNUSED_ARG (protocolinfo); ACE_UNUSED_ARG (g); ACE_UNUSED_ARG (flags); return ACE_OS::socket (domain, type, proto); #endif /* ACE_HAS_WINSOCK2 */ } ACE_INLINE int ACE_OS::socketpair (int domain, int type, int protocol, ACE_HANDLE sv[2]) { ACE_OS_TRACE ("ACE_OS::socketpair"); #if defined (ACE_LACKS_SOCKETPAIR) ACE_UNUSED_ARG (domain); ACE_UNUSED_ARG (type); ACE_UNUSED_ARG (protocol); ACE_UNUSED_ARG (sv); ACE_NOTSUP_RETURN (-1); #else return ::socketpair (domain, type, protocol, sv); #endif /* ACE_LACKS_SOCKETPAIR */ } ACE_INLINE unsigned int ACE_OS::if_nametoindex (const char *ifname) { ACE_OS_TRACE ("ACE_OS::if_nametoindex"); #ifdef ACE_LACKS_IF_NAMETOINDEX ACE_UNUSED_ARG (ifname); ACE_NOTSUP_RETURN (0); #else return ::if_nametoindex (ifname); #endif /* ACE_LACKS_IF_NAMETOINDEX */ } ACE_INLINE char * ACE_OS::if_indextoname (unsigned int ifindex, char *ifname) { ACE_OS_TRACE ("ACE_OS::if_indextoname"); #ifdef ACE_LACKS_IF_NAMETOINDEX ACE_UNUSED_ARG (ifindex); ACE_UNUSED_ARG (ifname); ACE_NOTSUP_RETURN (0); #else return ::if_indextoname (ifindex, ifname); #endif /* ACE_LACKS_IF_NAMETOINDEX */ } ACE_INLINE struct if_nameindex * ACE_OS::if_nameindex () { ACE_OS_TRACE ("ACE_OS::if_nameindex"); #ifdef ACE_LACKS_IF_NAMEINDEX ACE_NOTSUP_RETURN (0); #else return ::if_nameindex (); #endif /* ACE_LACKS_IF_NAMEINDEX */ } ACE_INLINE void ACE_OS::if_freenameindex (struct if_nameindex *ptr) { ACE_OS_TRACE ("ACE_OS::if_freenameindex"); #ifdef ACE_LACKS_IF_NAMEINDEX ACE_UNUSED_ARG (ptr); #else if (ptr) { ::if_freenameindex (ptr); } #endif /* ACE_LACKS_IF_NAMEINDEX */ } ACE_END_VERSIONED_NAMESPACE_DECL