Index: include/apr_network_io.h
===================================================================
--- include/apr_network_io.h    (revision 572605)
+++ include/apr_network_io.h    (working copy)
@@ -508,6 +508,33 @@
                                             apr_size_t *len);
 
 /**
+ * Send multiple packets of data over a network.
+ * @param sock The socket to send the data over.
+ * @param where The apr_sockaddr_t describing where to send the data
+ * @param flags The flags to use
+ * @param vec The array of iovec structs containing the data to send 
+ * @param nvec The number of iovec structs in the array
+ * @param len Receives the number of bytes actually written
+ * @remark
+ * <PRE>
+ * This functions acts like a blocking write by default.  To change 
+ * this behavior, use apr_socket_timeout_set() or the APR_SO_NONBLOCK
+ * socket option.
+ * The number of bytes actually sent is stored in argument 3.
+ *
+ * It is possible for both bytes to be sent and an error to be returned.
+ *
+ * APR_EINTR is never returned.
+ * </PRE>
+ */
+APR_DECLARE(apr_status_t) apr_socket_sendtov(apr_socket_t *sock,
+                                             apr_sockaddr_t *where,
+                                             apr_int32_t flags,
+                                             const struct iovec *vec,
+                                             apr_int32_t nvec,
+                                             apr_size_t *len);
+
+/**
  * Read data from a socket.  On success, the address of the peer from
  * which the data was sent is copied into the @param from parameter,
  * and the @param len parameter is updated to give the number of bytes
 
Index: network_io/unix/sendrecv.c
===================================================================
--- network_io/unix/sendrecv.c  (revision 572605)
+++ network_io/unix/sendrecv.c  (working copy)
@@ -184,7 +184,15 @@
     return APR_SUCCESS;
 }
 
-apr_status_t apr_socket_sendv(apr_socket_t * sock, const struct iovec *vec,
+apr_status_t apr_socket_sendtov(apr_socket_t *sock, apr_sockaddr_t *where,
+                                apr_int32_t flags, const struct iovec *vec,
+                                apr_int32_t nvec, apr_size_t *len)
+{
+    *len = vec[0].iov_len;
+    return apr_socket_sendto(sock, where, flags, vec[0].iov_base, len);
+}
+
+apr_status_t apr_socket_sendv(apr_socket_t *sock, const struct iovec *vec,
                               apr_int32_t nvec, apr_size_t *len)
 {
 #ifdef HAVE_WRITEV
Index: network_io/win32/sendrecv.c
===================================================================
--- network_io/win32/sendrecv.c (revision 573953)
+++ network_io/win32/sendrecv.c (working copy)
@@ -93,7 +93,75 @@
     return dwBytes == 0 ? APR_EOF : APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_socket_sendtov(apr_socket_t *sock, 
+                                             apr_sockaddr_t *where,
+                                             apr_int32_t flags,
+                                             const struct iovec *vec,
+                                             apr_int32_t in_vec,
+                                             apr_size_t *nbytes)
+{
 
+    apr_status_t rc = APR_SUCCESS;
+    apr_ssize_t rv;
+    apr_size_t cur_len;
+    apr_int32_t nvec = 0;
+    int i, j = 0;
+    DWORD dwBytes = 0;
+    WSABUF *pWsaBuf;
+
+    for (i = 0; i < in_vec; i++) {
+        cur_len = vec[i].iov_len;
+        nvec++;
+        while (cur_len > APR_DWORD_MAX) {
+            nvec++;
+            cur_len -= APR_DWORD_MAX;
+        } 
+    }
+
+    pWsaBuf = (nvec <= WSABUF_ON_STACK) ? _alloca(sizeof(WSABUF) * (nvec))
+                                         : malloc(sizeof(WSABUF) * (nvec));
+    if (!pWsaBuf)
+        return APR_ENOMEM;
+
+    for (i = 0; i < in_vec; i++) {
+        char * base = vec[i].iov_base;
+        cur_len = vec[i].iov_len;
+        
+        do {
+            if (cur_len > APR_DWORD_MAX) {
+                pWsaBuf[j].buf = base;
+                pWsaBuf[j].len = APR_DWORD_MAX;
+                cur_len -= APR_DWORD_MAX;
+                base += APR_DWORD_MAX;
+            }
+            else {
+                pWsaBuf[j].buf = base;
+                pWsaBuf[j].len = (DWORD)cur_len;
+                cur_len = 0;
+            }
+            j++;
+
+        } while (cur_len > 0);
+    }
+
+    for (i = 0; i < nvec; i++) {
+        rv = sendto(sock->socketdes, pWsaBuf[i].buf, pWsaBuf[i].len, flags,
+                    (const struct sockaddr*)&where->sa, 
+                    where->salen);
+        if (rv == SOCKET_ERROR) {
+            rc = apr_get_netos_error();
+            break;
+        }
+        dwBytes += rv;
+    }
+
+    if (nvec > WSABUF_ON_STACK) 
+        free(pWsaBuf);
+
+    *nbytes = dwBytes;
+    return rc;
+}
+
 APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock,
                                            const struct iovec *vec,
                                            apr_int32_t in_vec, apr_size_t 
*nbytes)
Index: network_io/beos/sendrecv.c
===================================================================
--- network_io/beos/sendrecv.c  (revision 573953)
+++ network_io/beos/sendrecv.c  (working copy)
@@ -122,6 +122,18 @@
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_socket_sendtov(apr_socket_t *sock, 
+                                             apr_sockaddr_t *where,
+                                             apr_int32_t flags,
+                                             const struct iovec *vec,
+                                             apr_int32_t nvec,
+                                             apr_size_t *len)
+{
+    *len = vec[0].iov_len;
+    return apr_socket_sendto(sock, where, flags, vec[0].iov_base, len);
+}
+
+
 /* BeOS doesn't have writev for sockets so we use the following instead...
  */
 APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t * sock, 

Reply via email to