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,