summaryrefslogtreecommitdiff
path: root/ACE/ace/OS_NS_sys_socket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ace/OS_NS_sys_socket.cpp')
-rw-r--r--ACE/ace/OS_NS_sys_socket.cpp125
1 files changed, 122 insertions, 3 deletions
diff --git a/ACE/ace/OS_NS_sys_socket.cpp b/ACE/ace/OS_NS_sys_socket.cpp
index bbf468f4e63..014b8b1d6cf 100644
--- a/ACE/ace/OS_NS_sys_socket.cpp
+++ b/ACE/ace/OS_NS_sys_socket.cpp
@@ -2,19 +2,20 @@
#include "ace/OS_NS_sys_socket.h"
-ACE_RCSID(ace, OS_NS_sys_socket, "$Id$")
+
#if !defined (ACE_HAS_INLINED_OSCALLS)
# include "ace/OS_NS_sys_socket.inl"
#endif /* ACE_HAS_INLINED_OSCALLS */
+#include "ace/Containers_T.h"
+
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
#if defined (ACE_WIN32)
int ACE_OS::socket_initialized_;
#endif /* ACE_WIN32 */
-#if !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500))
ACE_HANDLE
ACE_OS::accept (ACE_HANDLE handle,
struct sockaddr *addr,
@@ -95,7 +96,6 @@ ACE_OS::join_leaf (ACE_HANDLE socket,
ACE_NOTSUP_RETURN (ACE_INVALID_HANDLE);
# endif /* ACE_HAS_WINSOCK2 */
}
-#endif /* !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500)) */
int
ACE_OS::socket_init (int version_high, int version_low)
@@ -158,4 +158,123 @@ ACE_OS::socket_fini (void)
return 0;
}
+ssize_t
+ACE_OS::sendv_partial_i (ACE_HANDLE handle,
+ const iovec *buffers,
+ int n)
+{
+ // the divide and conquer logic should remain consistent
+ // with send_partial_i
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ DWORD bytes_sent = 0;
+ int result = 1;
+ int simulated_n = n;
+ ACE_UINT64 buffer_size = 0;
+ ACE_Array<iovec> iovec_array(simulated_n);
+ int i = 0;
+ for ( ; i < simulated_n; ++i)
+ {
+ iovec_array[i].iov_base = buffers[i].iov_base;
+ iovec_array[i].iov_len = buffers[i].iov_len;
+ buffer_size += buffers[i].iov_len;
+ }
+ // keep dividing the current buffer_size in half and then
+ // attempt to send the modified iovec buffer until some
+ // data is sent, or we get an errno that is not ENOBUFS
+ while (true)
+ {
+ ACE_UINT64 remove_size = buffer_size / 2;
+ buffer_size -= remove_size;
+ for (i = simulated_n - 1; (i >= 0) && (remove_size > 0); --i)
+ {
+ // if the buffer division splits an iovec, we need
+ // to set its iov_len properly
+ if (iovec_array[i].iov_len > remove_size)
+ {
+ iovec_array[i].iov_len -= static_cast<u_long>(remove_size);
+ break;
+ }
+ remove_size -= iovec_array[i].iov_len;
+ }
+
+ simulated_n = i + 1;
+
+ result = ::WSASend ((SOCKET) handle,
+ (WSABUF *) &(iovec_array[0]),
+ simulated_n,
+ &bytes_sent,
+ 0,
+ 0,
+ 0);
+ if (result != SOCKET_ERROR)
+ break;
+
+ ACE_OS::set_errno_to_wsa_last_error ();
+ // if ENOBUFS is received, we apply a divide and
+ // conquer strategy, but if bytes are sent we
+ // cannot guarantee this is the same behavior
+ if ((errno != ENOBUFS) ||
+ (bytes_sent != 0))
+ {
+ return -1;
+ }
+ }
+
+ return (ssize_t) bytes_sent;
+# else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (buffers);
+ ACE_UNUSED_ARG (n);
+
+ return -1;
+# endif /* ACE_HAS_WINSOCK2 */
+}
+
+ssize_t
+ACE_OS::send_partial_i (ACE_HANDLE handle,
+ const char *buf,
+ size_t len,
+ int flags)
+{
+ // the divide and conquer logic should remain consistent
+ // with sendv_partial_i
+#if !defined (ACE_LACKS_SEND) && defined (ACE_WIN32)
+ DWORD bytes_sent = 0;
+ ssize_t result = 1;
+ // keep dividing the current buffer_size in half and then
+ // attempt to send the modified buffer until some data is
+ // sent, or we get an errno that is not ENOBUFS
+ while (true)
+ {
+ len -= len / 2;
+
+ result = (ssize_t) ::send ((SOCKET) handle,
+ buf,
+ static_cast<int> (len),
+ flags);
+ if (result != SOCKET_ERROR)
+ break;
+
+ ACE_OS::set_errno_to_wsa_last_error ();
+ // if ENOBUFS is received, we apply a divide and
+ // conquer strategy, but if bytes are sent we
+ // cannot guarantee this is the same behavior
+ if ((errno != ENOBUFS) ||
+ (bytes_sent != 0))
+ {
+ return -1;
+ }
+ }
+
+ return result;
+# else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (flags);
+
+ return -1;
+# endif /* ACE_LACKS_SEND && ACE_WIN32 */
+}
+
ACE_END_VERSIONED_NAMESPACE_DECL