Call WSASetLastError() instead of SetLastError()
[mod_fastcgi.git] / fcgi_buf.c
blob462a342f30e9dd53d2bb2a3d5fbfc84cb0415e26
1 /*
2 * $Id: fcgi_buf.c,v 1.14 2002/03/04 22:20:57 robs Exp $
3 */
5 #include "fcgi.h"
7 #ifdef WIN32
8 #pragma warning( disable : 4127 )
9 #endif
11 /*******************************************************************************
12 * Check buffer consistency with assertions.
14 void fcgi_buf_check(Buffer *buf)
16 ap_assert(buf->size > 0);
17 ap_assert(buf->length >= 0);
18 ap_assert(buf->length <= buf->size);
20 ap_assert(buf->begin >= buf->data);
21 ap_assert(buf->begin < buf->data + buf->size);
22 ap_assert(buf->end >= buf->data);
23 ap_assert(buf->end < buf->data + buf->size);
25 ap_assert(((buf->end - buf->begin + buf->size) % buf->size)
26 == (buf->length % buf->size));
29 /*******************************************************************************
30 * Reset buffer, losing any data that's in it.
32 void fcgi_buf_reset(Buffer *buf)
34 buf->length = 0;
35 buf->begin = buf->end = buf->data;
38 /*******************************************************************************
39 * Allocate and intialize a new buffer of the specified size.
41 Buffer *fcgi_buf_new(pool *p, int size)
43 Buffer *buf;
45 buf = (Buffer *)ap_pcalloc(p, sizeof(Buffer) + size);
46 buf->size = size;
47 fcgi_buf_reset(buf);
48 return buf;
51 #ifdef WIN32
53 static int fd_read(SOCKET fd, char *buf, int len)
55 DWORD bytes_read;
57 ap_assert(len);
59 // HACK - we don't know if its a pipe or socket..
60 if (ReadFile((HANDLE) fd, buf, len, &bytes_read, NULL))
62 return (int) bytes_read;
64 else
66 int rv = GetLastError();
68 if (rv == ERROR_PIPE_NOT_CONNECTED)
70 return 0;
72 else if (rv == ERROR_INVALID_PARAMETER)
74 // Then it must be a real socket
76 WSASetLastError(ERROR_SUCCESS);
78 rv = recv(fd, buf, len, 0);
79 if (rv == SOCKET_ERROR)
81 errno = WSAGetLastError();
82 return -1;
85 return rv;
87 else
89 errno = rv;
90 return -1;
95 #else
97 static int fd_read(int fd, char * buf, int len)
99 int bytes_read;
101 ap_assert(len);
103 do {
104 bytes_read = read(fd, buf, len);
105 } while (bytes_read == -1 && errno == EINTR);
106 return bytes_read;
109 #endif
111 /*******************************************************************************
112 * Read from an open file descriptor into buffer.
114 * The caller should disable the default Apache SIGPIPE handler,
115 * otherwise a bad script could cause the request to abort and appear
116 * as though the client's fd caused it.
118 * Results:
119 * <0 error, errno is set
120 * =0 EOF reached
121 * >0 successful read or no room in buffer (NOT # of bytes read)
123 #ifdef WIN32
124 int fcgi_buf_add_fd(Buffer *buf, SOCKET fd)
125 #else
126 int fcgi_buf_add_fd(Buffer *buf, int fd)
127 #endif
129 int len;
131 fcgi_buf_check(buf);
133 if (buf->length == buf->size)
134 /* there's no room in the buffer, return "success" */
135 return 1;
137 if (buf->length == 0)
138 /* the buffer is empty so defrag */
139 buf->begin = buf->end = buf->data;
141 len = min(buf->size - buf->length, buf->data + buf->size - buf->end);
143 #ifndef NO_WRITEV
144 /* assume there is a readv() if there is a writev() */
145 if (len == buf->size - buf->length) {
146 /* its not wrapped, use read() instead of readv() */
147 #endif
149 len = fd_read(fd, buf->end, len);
151 if (len <= 0)
152 return len;
154 buf->end += len;
155 buf->length += len;
157 if (buf->end == (buf->data + buf->size)) {
158 /* the buffer needs to be wrapped */
159 buf->end = buf->data;
160 #ifndef NO_WRITEV
162 } else {
163 /* the buffer is wrapped, use readv() */
164 struct iovec vec[2];
166 vec[0].iov_base = buf->end;
167 vec[0].iov_len = len;
168 vec[1].iov_base = buf->data;
169 vec[1].iov_len = buf->size - buf->length - len;
171 ap_assert(len);
172 ap_assert(vec[1].iov_len);
175 len = readv(fd, vec, 2);
176 while (len == -1 && errno == EINTR);
178 if (len <= 0)
179 return len;
181 buf->end += len;
182 if (buf->end >= (buf->data + buf->size))
183 buf->end -= buf->size;
185 buf->length += len;
188 #else
189 if (buf->length < buf->size) {
190 /* There's still more buffer space to read into. */
192 fd_set read_set;
193 int status;
194 int numFDs = fd + 1;
195 struct timeval timeOut;
197 FD_ZERO(&read_set);
198 FD_SET(fd, &read_set);
200 timeOut.tv_sec = 0;
201 timeOut.tv_usec = 0;
203 status = ap_select(numFDs, &read_set, NULL, NULL, &timeOut);
205 if (status < 0) {
206 #ifdef WIN32
207 // More hackery
208 if (WSAGetLastError() == WSAENOTSOCK)
210 DWORD bytesavail=0;
211 if (PeekNamedPipe((HANDLE) fd, NULL, 0, NULL, &bytesavail, NULL))
213 if (bytesavail > 0)
215 len = fd_read(fd, buf->end, buf->size - buf->length);
217 if (len <= 0)
218 return len;
220 buf->end += len;
221 buf->length += len;
223 return len;
226 #endif
227 return status; /* error, errno is set */
230 if (status > 0 && FD_ISSET(fd, &read_set)) {
232 len = fd_read(fd, buf->end, buf->size - buf->length);
234 if (len <= 0)
235 return len;
237 buf->end += len;
238 buf->length += len;
242 #endif
244 return len; /* this may not contain the number of bytes read */
247 #ifdef WIN32
249 static int fd_write(SOCKET fd, char * buf, int len)
251 DWORD bytes_sent;
253 // HACK - We don't know if its a pipe or socket..
254 if (WriteFile((HANDLE) fd, buf, len, &bytes_sent, NULL))
256 return (int) bytes_sent;
258 else
260 int rv = GetLastError();
262 if (rv == ERROR_INVALID_PARAMETER)
264 // Then it must be a real socket..
266 SetLastError(ERROR_SUCCESS);
268 rv = send(fd, buf, len, 0);
270 if (rv == SOCKET_ERROR)
272 rv = WSAGetLastError();
273 if (rv == WSAEWOULDBLOCK)
275 return 0;;
277 else
279 errno = rv;
280 return -1;
284 return rv;
286 else if (rv == WSAEWOULDBLOCK)
288 return 0;
290 else
292 errno = rv;
293 return -1;
298 #else
300 static int fd_write(int fd, char * buf, int len)
302 int bytes_sent;
304 do {
305 bytes_sent = write(fd, buf, len);
307 #ifdef EWOULDBLOCK
308 if (bytes_sent == -1 && errno == EWOULDBLOCK) {
309 bytes_sent = 0;
311 #endif
312 } while (bytes_sent == -1 && errno == EINTR);
314 return bytes_sent;
317 #endif
319 /*******************************************************************************
320 * Write from the buffer to an open file descriptor.
322 * The caller should disable the default Apache SIGPIPE handler,
323 * otherwise a bad script could cause the request to abort appearing
324 * as though the client's fd caused it.
326 * Results:
327 * <0 if an error occured (bytes may or may not have been written)
328 * =0 if no bytes were written
329 * >0 successful write
331 #ifdef WIN32
332 int fcgi_buf_get_to_fd(Buffer *buf, SOCKET fd)
333 #else
334 int fcgi_buf_get_to_fd(Buffer *buf, int fd)
335 #endif
337 int len;
339 fcgi_buf_check(buf);
341 if (buf->length == 0)
342 return 0;
344 len = min(buf->length, buf->data + buf->size - buf->begin);
346 #ifndef NO_WRITEV
347 if (len == buf->length) {
348 /* the buffer is not wrapped, we don't need to use writev() */
349 #endif
351 len = fd_write(fd, buf->begin, len);
353 if (len <= 0)
354 goto Return;
356 buf->begin += len;
357 buf->length -= len;
359 if (buf->begin == buf->data + buf->size) {
360 /* the buffer needs to be wrapped */
361 buf->begin = buf->data;
363 #ifndef NO_WRITEV
365 } else {
366 /* the buffer is wrapped, use writev() */
367 struct iovec vec[2];
369 vec[0].iov_base = buf->begin;
370 vec[0].iov_len = len;
371 vec[1].iov_base = buf->data;
372 vec[1].iov_len = buf->length - len;
375 len = writev(fd, vec, 2);
376 while (len == -1 && errno == EINTR);
378 if (len <= 0)
379 goto Return;
381 buf->begin += len;
382 buf->length -= len;
384 if (buf->begin >= buf->data + buf->size)
385 buf->begin -= buf->size;
387 #else
388 if (buf->length > 0) {
389 /* there's still more data to write */
391 fd_set write_set;
392 int status;
393 int numFDs = fd + 1;
394 struct timeval timeOut;
396 FD_ZERO(&write_set);
397 FD_SET(fd, &write_set);
399 timeOut.tv_sec = 0;
400 timeOut.tv_usec = 0;
402 status = ap_select(numFDs, NULL, &write_set, NULL, &timeOut);
404 if (status < 0) {
405 len = status; /* error, errno is set */
406 goto Return;
409 if (status > 0 && FD_ISSET(fd, &write_set)) {
410 int len2;
412 len2 = fd_write(fd, buf->begin, buf->length);
414 if (len2 < 0) {
415 len = len2;
416 goto Return;
419 if (len2 > 0) {
420 buf->begin += len2;
421 buf->length -= len2;
422 len += len2;
427 #endif
429 Return:
430 if (buf->length == 0)
431 buf->begin = buf->end = buf->data;
433 return len;
436 /*******************************************************************************
437 * Return the data block start address and the length of the block.
439 void fcgi_buf_get_block_info(Buffer *buf, char **beginPtr, int *countPtr)
441 fcgi_buf_check(buf);
443 *beginPtr = buf->begin;
444 *countPtr = min(buf->length, buf->data + buf->size - buf->begin);
447 /*******************************************************************************
448 * Throw away bytes from buffer.
450 void fcgi_buf_toss(Buffer *buf, int count)
452 fcgi_buf_check(buf);
453 ap_assert(count >= 0);
454 ap_assert(count <= buf->length);
456 buf->length -= count;
457 buf->begin += count;
458 if(buf->begin >= buf->data + buf->size) {
459 buf->begin -= buf->size;
463 /*******************************************************************************
464 * Return the free data block start address and the length of the block.
466 void fcgi_buf_get_free_block_info(Buffer *buf, char **endPtr, int *countPtr)
468 fcgi_buf_check(buf);
470 *endPtr = buf->end;
471 *countPtr = min(buf->size - buf->length,
472 buf->data + buf->size - buf->end);
475 /*******************************************************************************
476 * Updates the buf to reflect recently added data.
478 void fcgi_buf_add_update(Buffer *buf, int count)
480 fcgi_buf_check(buf);
481 ap_assert(count >= 0);
482 ap_assert(count <= BufferFree(buf));
484 buf->length += count;
485 buf->end += count;
486 if(buf->end >= buf->data + buf->size) {
487 buf->end -= buf->size;
490 fcgi_buf_check(buf);
493 /*******************************************************************************
494 * Adds a block of data to a buffer, returning the number of bytes added.
496 int fcgi_buf_add_block(Buffer *buf, char *data, int datalen)
498 char *end;
499 int copied = 0; /* Number of bytes actually copied. */
500 int canCopy; /* Number of bytes to copy in a given op. */
502 ap_assert(data != NULL);
503 ap_assert(datalen >= 0);
505 if(datalen == 0) {
506 return 0;
509 ap_assert(datalen > 0);
510 fcgi_buf_check(buf);
511 end = buf->data + buf->size;
514 * Copy the first part of the data: from here to the end of the
515 * buffer, or the end of the data, whichever comes first.
517 datalen = min(BufferFree(buf), datalen);
518 canCopy = min(datalen, end - buf->end);
519 memcpy(buf->end, data, canCopy);
520 buf->length += canCopy;
521 buf->end += canCopy;
522 copied += canCopy;
523 if (buf->end >= end) {
524 buf->end = buf->data;
526 datalen -= canCopy;
529 * If there's more to go, copy the second part starting from the
530 * beginning of the buffer.
532 if (datalen > 0) {
533 data += canCopy;
534 memcpy(buf->end, data, datalen);
535 buf->length += datalen;
536 buf->end += datalen;
537 copied += datalen;
539 return(copied);
542 /*******************************************************************************
543 * Add a string to a buffer, returning the number of bytes added.
545 int fcgi_buf_add_string(Buffer *buf, char *str)
547 return fcgi_buf_add_block(buf, str, strlen(str));
550 /*******************************************************************************
551 * Gets a data block from a buffer, returning the number of bytes copied.
553 int fcgi_buf_get_to_block(Buffer *buf, char *data, int datalen)
555 char *end;
556 int copied = 0; /* Number of bytes actually copied. */
557 int canCopy; /* Number of bytes to copy in a given op. */
559 ap_assert(data != NULL);
560 ap_assert(datalen > 0);
561 fcgi_buf_check(buf);
563 end = buf->data + buf->size;
566 * Copy the first part out of the buffer: from here to the end
567 * of the buffer, or all of the requested data.
569 canCopy = min(buf->length, datalen);
570 canCopy = min(canCopy, end - buf->begin);
572 memcpy(data, buf->begin, canCopy);
574 buf->length -= canCopy;
575 buf->begin += canCopy;
576 copied += canCopy;
577 if (buf->begin >= end) {
578 buf->begin = buf->data;
582 * If there's more to go, copy the second part starting from the
583 * beginning of the buffer.
585 if (copied < datalen && buf->length > 0) {
586 data += copied;
587 canCopy = min(buf->length, datalen - copied);
589 memcpy(data, buf->begin, canCopy);
591 buf->length -= canCopy;
592 buf->begin += canCopy;
593 copied += canCopy;
596 fcgi_buf_check(buf);
597 return(copied);
600 /*******************************************************************************
601 * Move 'len' bytes from 'src' buffer to 'dest' buffer. There must be at
602 * least 'len' bytes available in the source buffer and space for 'len'
603 * bytes in the destination buffer.
605 void fcgi_buf_get_to_buf(Buffer *dest, Buffer *src, int len)
607 char *dest_end, *src_begin;
608 int dest_len, src_len, move_len;
610 ap_assert(len > 0);
611 ap_assert(BufferLength(src) >= len);
612 ap_assert(BufferFree(dest) >= len);
614 fcgi_buf_check(src);
615 fcgi_buf_check(dest);
617 for (;;) {
618 if (len == 0)
619 return;
621 fcgi_buf_get_free_block_info(dest, &dest_end, &dest_len);
622 fcgi_buf_get_block_info(src, &src_begin, &src_len);
624 move_len = min(dest_len, src_len);
625 move_len = min(move_len, len);
627 if (move_len == 0)
628 return;
630 memcpy(dest_end, src_begin, move_len);
631 fcgi_buf_toss(src, move_len);
632 fcgi_buf_add_update(dest, move_len);
633 len -= move_len;
637 static void array_grow(array_header *arr, int n)
639 if (n <= 0)
640 return;
642 if (arr->nelts + n > arr->nalloc) {
643 char *new_elts;
644 int new_nalloc = (arr->nalloc <= 0) ? n : arr->nelts + n;
646 new_elts = ap_pcalloc(arr->pool, arr->elt_size * new_nalloc);
647 memcpy(new_elts, arr->elts, arr->nelts * arr->elt_size);
649 arr->elts = new_elts;
650 arr->nalloc = new_nalloc;
654 static void array_cat_block(array_header *arr, void *block, int n)
656 array_grow(arr, n);
657 memcpy(arr->elts + arr->nelts * arr->elt_size, block, n * arr->elt_size);
658 arr->nelts += n;
661 /*----------------------------------------------------------------------
662 * Append "len" bytes from "buf" into "arr". Apache arrays are used
663 * whenever the data being handled is binary (may contain null chars).
665 void fcgi_buf_get_to_array(Buffer *buf, array_header *arr, int len)
667 int len1 = min(buf->length, buf->data + buf->size - buf->begin);
669 fcgi_buf_check(buf);
670 ap_assert(len > 0);
671 ap_assert(len <= BufferLength(buf));
673 array_grow(arr, len);
675 len1 = min(len1, len);
676 array_cat_block(arr, buf->begin, len1);
678 if (len1 < len)
679 array_cat_block(arr, buf->data, len - len1);
681 fcgi_buf_toss(buf, len);