upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / network_io / win32 / sendrecv.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "apr_arch_networkio.h"
18 #include "apr_errno.h"
19 #include "apr_general.h"
20 #include "apr_network_io.h"
21 #include "apr_lib.h"
22 #include "apr_arch_file_io.h"
23 #if APR_HAVE_TIME_H
24 #include <time.h>
25 #endif
26
27 /* MAX_SEGMENT_SIZE is the maximum amount of data that will be sent to a client
28  * in one call of TransmitFile. This number must be small enough to give the 
29  * slowest client time to receive the data before the socket timeout triggers.
30  * The same problem can exist with apr_socket_send(). In that case, we rely on
31  * the application to adjust socket timeouts and max send segment 
32  * sizes appropriately.
33  * For example, Apache will in most cases call apr_socket_send() with less
34  * than 8193 bytes.
35  */
36 #define MAX_SEGMENT_SIZE 65536
37 #define WSABUF_ON_STACK 50
38
39 APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf,
40                                           apr_size_t *len)
41 {
42     apr_ssize_t rv;
43     WSABUF wsaData;
44     int lasterror;
45     DWORD dwBytes = 0;
46
47     wsaData.len = *len;
48     wsaData.buf = (char*) buf;
49
50 #ifndef _WIN32_WCE
51     rv = WSASend(sock->socketdes, &wsaData, 1, &dwBytes, 0, NULL, NULL);
52 #else
53     rv = send(sock->socketdes, wsaData.buf, wsaData.len, 0);
54     dwBytes = rv;
55 #endif
56     if (rv == SOCKET_ERROR) {
57         lasterror = apr_get_netos_error();
58         *len = 0;
59         return lasterror;
60     }
61
62     *len = dwBytes;
63
64     return APR_SUCCESS;
65 }
66
67
68 APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf,
69                                           apr_size_t *len) 
70 {
71     apr_ssize_t rv;
72     WSABUF wsaData;
73     int lasterror;
74     DWORD dwBytes = 0;
75     DWORD flags = 0;
76
77     wsaData.len = *len;
78     wsaData.buf = (char*) buf;
79
80 #ifndef _WIN32_WCE
81     rv = WSARecv(sock->socketdes, &wsaData, 1, &dwBytes, &flags, NULL, NULL);
82 #else
83     rv = recv(sock->socketdes, wsaData.buf, wsaData.len, 0);
84     dwBytes = rv;
85 #endif
86     if (rv == SOCKET_ERROR) {
87         lasterror = apr_get_netos_error();
88         *len = 0;
89         return lasterror;
90     }
91
92     *len = dwBytes;
93     return dwBytes == 0 ? APR_EOF : APR_SUCCESS;
94 }
95
96
97 APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock,
98                                            const struct iovec *vec,
99                                            apr_int32_t nvec, apr_size_t *nbytes)
100 {
101     apr_status_t rc = APR_SUCCESS;
102     apr_ssize_t rv;
103     int i;
104     DWORD dwBytes = 0;
105     WSABUF *pWsaBuf = (nvec <= WSABUF_ON_STACK) ? _alloca(sizeof(WSABUF) * (nvec))
106                                                 : malloc(sizeof(WSABUF) * (nvec));
107
108     if (!pWsaBuf)
109         return APR_ENOMEM;
110
111     for (i = 0; i < nvec; i++) {
112         pWsaBuf[i].buf = vec[i].iov_base;
113         pWsaBuf[i].len = vec[i].iov_len;
114     }
115 #ifndef _WIN32_WCE
116     rv = WSASend(sock->socketdes, pWsaBuf, nvec, &dwBytes, 0, NULL, NULL);
117     if (rv == SOCKET_ERROR) {
118         rc = apr_get_netos_error();
119     }
120 #else
121     for (i = 0; i < nvec; i++) {
122         rv = send(sock->socketdes, pWsaBuf[i].buf, pWsaBuf[i].len, 0);
123         if (rv == SOCKET_ERROR) {
124             rc = apr_get_netos_error();
125             break;
126         }
127         dwBytes += rv;
128     }
129 #endif
130     if (nvec > WSABUF_ON_STACK) 
131         free(pWsaBuf);
132
133     *nbytes = dwBytes;
134     return rc;
135 }
136
137
138 APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock,
139                                             apr_sockaddr_t *where,
140                                             apr_int32_t flags, const char *buf, 
141                                             apr_size_t *len)
142 {
143     apr_ssize_t rv;
144
145     rv = sendto(sock->socketdes, buf, (*len), flags, 
146                 (const struct sockaddr*)&where->sa, 
147                 where->salen);
148     if (rv == SOCKET_ERROR) {
149         *len = 0;
150         return apr_get_netos_error();
151     }
152
153     *len = rv;
154     return APR_SUCCESS;
155 }
156
157
158 APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, 
159                                               apr_socket_t *sock,
160                                               apr_int32_t flags, 
161                                               char *buf, apr_size_t *len)
162 {
163     apr_ssize_t rv;
164
165     rv = recvfrom(sock->socketdes, buf, (*len), flags, 
166                   (struct sockaddr*)&from->sa, &from->salen);
167     if (rv == SOCKET_ERROR) {
168         (*len) = 0;
169         return apr_get_netos_error();
170     }
171     (*len) = rv;
172     if (rv == 0 && sock->type == SOCK_STREAM)
173         return APR_EOF;
174
175     return APR_SUCCESS;
176 }
177
178
179 static apr_status_t collapse_iovec(char **off, apr_size_t *len, 
180                                    struct iovec *iovec, int numvec, 
181                                    char *buf, apr_size_t buflen)
182 {
183     if (numvec == 1) {
184         *off = iovec[0].iov_base;
185         *len = iovec[0].iov_len;
186     }
187     else {
188         int i;
189         for (i = 0; i < numvec; i++) {
190             *len += iovec[i].iov_len;
191         }
192
193         if (*len > buflen) {
194             *len = 0;
195             return APR_INCOMPLETE;
196         }
197
198         *off = buf;
199
200         for (i = 0; i < numvec; i++) {
201             memcpy(buf, iovec[i].iov_base, iovec[i].iov_len);
202             buf += iovec[i].iov_len;
203         }
204     }
205     return APR_SUCCESS;
206 }
207
208
209 #if APR_HAS_SENDFILE
210 /*
211  * apr_status_t apr_socket_sendfile(apr_socket_t *, apr_file_t *, apr_hdtr_t *, 
212  *                                 apr_off_t *, apr_size_t *, apr_int32_t flags)
213  *    Send a file from an open file descriptor to a socket, along with 
214  *    optional headers and trailers
215  * arg 1) The socket to which we're writing
216  * arg 2) The open file from which to read
217  * arg 3) A structure containing the headers and trailers to send
218  * arg 4) Offset into the file where we should begin writing
219  * arg 5) Number of bytes to send out of the file
220  * arg 6) APR flags that are mapped to OS specific flags
221  */
222 APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, 
223                                               apr_file_t *file,
224                                               apr_hdtr_t *hdtr,
225                                               apr_off_t *offset,
226                                               apr_size_t *len,
227                                               apr_int32_t flags) 
228 {
229     apr_status_t status = APR_SUCCESS;
230     apr_ssize_t rv;
231     apr_off_t curoff = *offset;
232     DWORD dwFlags = 0;
233     DWORD nbytes;
234     TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL;
235     int ptr = 0;
236     int bytes_to_send;   /* Bytes to send out of the file (not including headers) */
237     int disconnected = 0;
238     int sendv_trailers = 0;
239     char hdtrbuf[4096];
240
241     if (apr_os_level < APR_WIN_NT) {
242         return APR_ENOTIMPL;
243     }
244
245     /* Use len to keep track of number of total bytes sent (including headers) */
246     bytes_to_send = *len;
247     *len = 0;
248
249     /* Handle the goofy case of sending headers/trailers and a zero byte file */
250     if (!bytes_to_send && hdtr) {
251         if (hdtr->numheaders) {
252             rv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, 
253                                   &nbytes);
254             if (rv != APR_SUCCESS)
255                 return rv;
256             *len += nbytes;
257         }
258         if (hdtr->numtrailers) {
259             rv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers,
260                                   &nbytes);
261             if (rv != APR_SUCCESS)
262                 return rv;
263             *len += nbytes;
264         }
265         return APR_SUCCESS;
266     }
267
268     memset(&tfb, '\0', sizeof (tfb));
269     /* Collapse the headers into a single buffer */
270     if (hdtr && hdtr->numheaders) {
271         ptfb = &tfb;
272         nbytes = 0;
273         rv = collapse_iovec((char **)&ptfb->Head, &ptfb->HeadLength, 
274                             hdtr->headers, hdtr->numheaders, 
275                             hdtrbuf, sizeof(hdtrbuf));
276         /* If not enough buffer, punt to sendv */
277         if (rv == APR_INCOMPLETE) {
278             rv = apr_sendv(sock, hdtr->headers, hdtr->numheaders, &nbytes);
279             if (rv != APR_SUCCESS)
280                 return rv;
281             *len += nbytes;
282             ptfb = NULL;
283         }
284     }
285
286     /* Initialize the overlapped structure used on TransmitFile 
287      */
288     if (!sock->overlapped) {
289         sock->overlapped = apr_pcalloc(sock->cntxt, sizeof(OVERLAPPED));
290         sock->overlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
291     }
292     while (bytes_to_send) {
293         if (bytes_to_send > MAX_SEGMENT_SIZE) {
294             nbytes = MAX_SEGMENT_SIZE;
295         }
296         else {
297             /* Last call to TransmitFile() */
298             nbytes = bytes_to_send;
299             /* Collapse the trailers into a single buffer */
300             if (hdtr && hdtr->numtrailers) {
301                 ptfb = &tfb;
302                 rv = collapse_iovec((char**) &ptfb->Tail, &ptfb->TailLength,
303                                     hdtr->trailers, hdtr->numtrailers,
304                                     hdtrbuf + ptfb->HeadLength,
305                                     sizeof(hdtrbuf) - ptfb->HeadLength);
306                 if (rv == APR_INCOMPLETE) {
307                     /* If not enough buffer, punt to sendv, later */
308                     sendv_trailers = 1;
309                 }
310             }
311             /* Disconnect the socket after last send */
312             if ((flags & APR_SENDFILE_DISCONNECT_SOCKET)
313                     && !sendv_trailers) {
314                 dwFlags |= TF_REUSE_SOCKET;
315                 dwFlags |= TF_DISCONNECT;
316                 disconnected = 1;
317             }
318         }
319
320         sock->overlapped->Offset = (DWORD)(curoff);
321 #if APR_HAS_LARGE_FILES
322         sock->overlapped->OffsetHigh = (DWORD)(curoff >> 32);
323 #endif  
324         /* XXX BoundsChecker claims dwFlags must not be zero. */
325         rv = TransmitFile(sock->socketdes,  /* socket */
326                           file->filehand, /* open file descriptor of the file to be sent */
327                           nbytes,         /* number of bytes to send. 0=send all */
328                           0,              /* Number of bytes per send. 0=use default */
329                           sock->overlapped,    /* OVERLAPPED structure */
330                           ptfb,           /* header and trailer buffers */
331                           dwFlags);       /* flags to control various aspects of TransmitFile */
332         if (!rv) {
333             status = apr_get_netos_error();
334             if ((status == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) ||
335                 (status == APR_FROM_OS_ERROR(WSA_IO_PENDING))) 
336             {
337                 rv = WaitForSingleObject(sock->overlapped->hEvent, 
338                                          (DWORD)(sock->timeout >= 0 
339                                                  ? sock->timeout_ms : INFINITE));
340                 if (rv == WAIT_OBJECT_0) {
341                     status = APR_SUCCESS;
342                     if (!disconnected) {
343                         if (!WSAGetOverlappedResult(sock->socketdes,
344                                                     sock->overlapped,
345                                                     &nbytes,
346                                                     FALSE,
347                                                     &dwFlags)) {
348                             status = apr_get_netos_error();
349                         }
350                                                
351                         /* Ugly code alert: WSAGetOverlappedResult returns
352                          * a count of all bytes sent. This loop only
353                          * tracks bytes sent out of the file.
354                          */
355                         else if (ptfb) {
356                             nbytes -= (ptfb->HeadLength + ptfb->TailLength);
357                         }
358                     }
359                 }
360                 else if (rv == WAIT_TIMEOUT) {
361                     status = APR_FROM_OS_ERROR(WAIT_TIMEOUT);
362                 }
363                 else if (rv == WAIT_ABANDONED) {
364                     /* Hummm... WAIT_ABANDONDED is not an error code. It is
365                      * a return specific to the Win32 WAIT functions that
366                      * indicates that a thread exited while holding a
367                      * mutex. Should consider triggering an assert
368                      * to detect the condition...
369                      */
370                     status = APR_FROM_OS_ERROR(WAIT_TIMEOUT);
371                 }
372                 else
373                     status = apr_get_os_error();
374             }
375         }
376         if (status != APR_SUCCESS)
377             break;
378
379         bytes_to_send -= nbytes;
380         curoff += nbytes;
381         *len += nbytes;
382         /* Adjust len for any headers/trailers sent */
383         if (ptfb) {
384             *len += (ptfb->HeadLength + ptfb->TailLength);
385             memset(&tfb, '\0', sizeof (tfb));
386             ptfb = NULL;
387         }
388     }
389
390     if (status == APR_SUCCESS) {
391         if (sendv_trailers) {
392             rv = apr_sendv(sock, hdtr->trailers, hdtr->numtrailers, &nbytes);
393             if (rv != APR_SUCCESS)
394                 return rv;
395             *len += nbytes;
396         }
397
398     
399         /* Mark the socket as disconnected, but do not close it.
400          * Note: The application must have stored the socket prior to making
401          * the call to apr_socket_sendfile in order to either reuse it 
402          * or close it.
403          */
404         if (disconnected) {
405             sock->disconnected = 1;
406             sock->socketdes = INVALID_SOCKET;
407         }
408     }
409
410     return status;
411 }
412
413 /* Deprecated */
414 APR_DECLARE(apr_status_t) apr_sendfile(apr_socket_t *sock, apr_file_t *file,
415                                        apr_hdtr_t *hdtr, apr_off_t *offset,
416                                        apr_size_t *len, apr_int32_t flags) 
417 {
418     return apr_socket_sendfile(sock, file, hdtr, offset, len, flags);
419 }
420
421 #endif
422
423 /* Deprecated */
424 APR_DECLARE(apr_status_t) apr_send(apr_socket_t *sock, const char *buf,
425                                    apr_size_t *len)
426 {
427     return apr_socket_send(sock, buf, len);
428 }
429
430 /* Deprecated */
431 APR_DECLARE(apr_status_t) apr_sendv(apr_socket_t *sock,
432                                     const struct iovec *vec,
433                                     apr_int32_t nvec, apr_size_t *nbytes)
434 {
435     return apr_socket_sendv(sock, vec, nvec, nbytes);
436 }
437
438 /* Deprecated */
439 APR_DECLARE(apr_status_t) apr_sendto(apr_socket_t *sock, apr_sockaddr_t *where,
440                                      apr_int32_t flags, const char *buf, 
441                                      apr_size_t *len)
442 {
443     return apr_socket_sendto(sock, where, flags, buf, len);
444 }
445
446 /* Deprecated */
447 APR_DECLARE(apr_status_t) apr_recvfrom(apr_sockaddr_t *from, 
448                                        apr_socket_t *sock,
449                                        apr_int32_t flags, 
450                                        char *buf, apr_size_t *len)
451 {
452     return apr_socket_recvfrom(from, sock, flags, buf, len);
453 }
454
455 /* Deprecated */
456 APR_DECLARE(apr_status_t) apr_recv(apr_socket_t *sock, char *buf,
457                                    apr_size_t *len) 
458 {
459     return apr_socket_recv(sock, buf, len);
460 }