summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--network_io/win32/sendrecv.c51
1 files changed, 24 insertions, 27 deletions
diff --git a/network_io/win32/sendrecv.c b/network_io/win32/sendrecv.c
index 39746d9b7..06eec4989 100644
--- a/network_io/win32/sendrecv.c
+++ b/network_io/win32/sendrecv.c
@@ -66,8 +66,7 @@
* The same problem can exist with apr_send(). In that case, we rely on the
* application to adjust socket timeouts and max send segment sizes appropriately.
* For example, Apache will in most cases call apr_send() with less than 8193
- * bytes
- * of data.
+ * bytes.
*/
#define MAX_SEGMENT_SIZE 65536
apr_status_t apr_send(apr_socket_t *sock, const char *buf, apr_size_t *len)
@@ -122,6 +121,7 @@ apr_status_t apr_sendv(apr_socket_t *sock, const struct iovec *vec,
int lasterror;
DWORD dwBytes = 0;
+ /* Todo: Put the WSABUF array on the stack. */
LPWSABUF pWsaData = (LPWSABUF) malloc(sizeof(WSABUF) * nvec);
if (!pWsaData)
@@ -199,14 +199,10 @@ apr_status_t apr_sendfile(apr_socket_t * sock, apr_file_t * file,
DWORD nbytes;
OVERLAPPED overlapped;
TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL;
- int bytes_to_send;
int ptr = 0;
+ int bytes_to_send = *len; /* Bytes to send out of the file (not including headers) */
- /* Must pass in a valid length */
- if (len == 0) {
- return APR_EINVAL;
- }
- bytes_to_send = *len;
+ /* Use len to keep track of number of total bytes sent (including headers) */
*len = 0;
/* Initialize the overlapped structure */
@@ -218,26 +214,29 @@ apr_status_t apr_sendfile(apr_socket_t * sock, apr_file_t * file,
overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
#endif
- /* TransmitFile can only send one header and one footer */
- memset(&tfb, '\0', sizeof (tfb));
- if (hdtr && hdtr->numheaders) {
- ptfb = &tfb;
- collapse_iovec((char **)&ptfb->Head, &ptfb->HeadLength, hdtr->headers, hdtr->numheaders, sock->cntxt);
- }
-
- /* If we have more than MAX_SEGMENT_SIZE headers to send, send them
- * in segments.
- */
- if (ptfb && ptfb->HeadLength) {
- while (ptfb->HeadLength >= MAX_SEGMENT_SIZE) {
- nbytes = MAX_SEGMENT_SIZE;
- rv = apr_send(sock, ptfb->Head, &nbytes);
+ /* Handle the goofy case of sending headers/trailers and a zero byte file */
+ if (!bytes_to_send && hdtr) {
+ if (hdtr->numheaders) {
+ rv = apr_sendv(sock, hdtr->headers, hdtr->numheaders, &nbytes);
+ if (rv != APR_SUCCESS)
+ return rv;
+ *len += nbytes;
+ }
+ if (hdtr->numtrailers) {
+ rv = apr_sendv(sock, hdtr->trailers, hdtr->numtrailers, &nbytes);
if (rv != APR_SUCCESS)
return rv;
- (char*) ptfb->Head += nbytes;
- ptfb->HeadLength -= nbytes;
*len += nbytes;
}
+ return APR_SUCCESS;
+ }
+
+ /* Collapse the headers into a single buffer */
+ memset(&tfb, '\0', sizeof (tfb));
+ if (hdtr && hdtr->numheaders) {
+ ptfb = &tfb;
+ collapse_iovec((char **)&ptfb->Head, &ptfb->HeadLength, hdtr->headers,
+ hdtr->numheaders, sock->cntxt);
}
while (bytes_to_send) {
@@ -247,9 +246,7 @@ apr_status_t apr_sendfile(apr_socket_t * sock, apr_file_t * file,
else {
/* Last call to TransmitFile() */
nbytes = bytes_to_send;
- /* Send trailers on the last packet, even if the total size
- * exceeds MAX_SEGMENT_SIZE...
- */
+ /* Collapse the trailers into a single buffer */
if (hdtr && hdtr->numtrailers) {
ptfb = &tfb;
collapse_iovec((char**) &ptfb->Tail, &ptfb->TailLength,