Add discussion of signals.
[mod_fastcgi.git] / fcgi_buf.c
blob8f0021c6878d077fdb8c17f8ce9f7efe8de0e1c2
1 /*
2 * $Id: fcgi_buf.c,v 1.11 2001/03/26 15:23:02 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 long bytes_read;
57 // HACK - we don't know if its a pipe or socket..
58 if (!ReadFile((HANDLE) fd, buf, len, (unsigned long *) &bytes_read, NULL)) {
60 int rv = GetLastError();
62 if (rv == ERROR_PIPE_NOT_CONNECTED) {
63 bytes_read = 0;
65 else if (rv == ERROR_INVALID_PARAMETER) {
67 SetLastError(ERROR_SUCCESS);
69 // Then it must be a real socket
71 bytes_read = recv(fd, buf, len, 0);
72 if (bytes_read == SOCKET_ERROR) {
73 errno = WSAGetLastError();
74 bytes_read = -1;
77 else {
78 errno = rv;
79 bytes_read = -1;
82 return bytes_read;
85 #else
87 static int fd_read(int fd, char * buf, int len)
89 int bytes_read;
90 do {
91 bytes_read = read(fd, buf, len);
92 } while (bytes_read == -1 && errno == EINTR);
93 return bytes_read;
96 #endif
98 /*******************************************************************************
99 * Read from an open file descriptor into buffer.
101 * The caller should disable the default Apache SIGPIPE handler,
102 * otherwise a bad script could cause the request to abort and appear
103 * as though the client's fd caused it.
105 * Results:
106 * <0 error, errno is set
107 * =0 EOF reached
108 * >0 successful read or no room in buffer (NOT # of bytes read)
110 #ifdef WIN32
111 int fcgi_buf_add_fd(Buffer *buf, SOCKET fd)
112 #else
113 int fcgi_buf_add_fd(Buffer *buf, int fd)
114 #endif
116 #ifdef WIN32
117 DWORD len;
118 #else
119 size_t len;
120 #endif
122 fcgi_buf_check(buf);
124 if (buf->length == buf->size)
125 /* there's no room in the buffer, return "success" */
126 return 1;
128 if (buf->length == 0)
129 /* the buffer is empty so defrag */
130 buf->begin = buf->end = buf->data;
132 len = min(buf->size - buf->length, buf->data + buf->size - buf->end);
134 #ifndef NO_WRITEV
135 /* assume there is a readv() if there is a writev() */
136 if (len == buf->size - buf->length) {
137 /* its not wrapped, use read() instead of readv() */
138 #endif
140 len = fd_read(fd, buf->end, len);
142 if (len <= 0)
143 return len;
145 buf->end += len;
146 buf->length += len;
148 if (buf->end == (buf->data + buf->size)) {
149 /* the buffer needs to be wrapped */
150 buf->end = buf->data;
151 #ifndef NO_WRITEV
153 } else {
154 /* the buffer is wrapped, use readv() */
155 struct iovec vec[2];
157 vec[0].iov_base = buf->end;
158 vec[0].iov_len = len;
159 vec[1].iov_base = buf->data;
160 vec[1].iov_len = buf->size - buf->length - len;
163 len = readv(fd, vec, 2);
164 while (len == -1 && errno == EINTR);
166 if (len <= 0)
167 return len;
169 buf->end += len;
170 if (buf->end >= (buf->data + buf->size))
171 buf->end -= buf->size;
173 buf->length += len;
176 #else
177 if (buf->length < buf->size) {
178 /* There's still more buffer space to read into. */
180 fd_set read_set;
181 int status;
182 int numFDs = fd + 1;
183 struct timeval timeOut;
185 FD_ZERO(&read_set);
186 FD_SET(fd, &read_set);
188 timeOut.tv_sec = 0;
189 timeOut.tv_usec = 0;
191 status = ap_select(numFDs, &read_set, NULL, NULL, &timeOut);
193 if (status < 0) {
194 #ifdef WIN32
195 // More hackery
196 if (WSAGetLastError() == WSAENOTSOCK)
198 DWORD bytesavail=0;
199 if (PeekNamedPipe((HANDLE) fd, NULL, 0, NULL, &bytesavail, NULL))
201 if (bytesavail > 0)
203 len = fd_read(fd, buf->end, buf->size - buf->length);
205 if (len <= 0)
206 return len;
208 buf->end += len;
209 buf->length += len;
211 return len;
214 #endif
215 return status; /* error, errno is set */
218 if (status > 0 && FD_ISSET(fd, &read_set)) {
220 len = fd_read(fd, buf->end, buf->size - buf->length);
222 if (len <= 0)
223 return len;
225 buf->end += len;
226 buf->length += len;
230 #endif
232 return len; /* this may not contain the number of bytes read */
235 #ifdef WIN32
237 static int fd_write(SOCKET fd, char * buf, int len)
239 long bytes_sent;
241 // HACK - We don't know if its a pipe or socket..
242 if (!WriteFile((HANDLE) fd, (LPVOID) buf, len, (unsigned long *) &bytes_sent, NULL)) {
244 int rv = GetLastError();
246 if (rv == ERROR_INVALID_PARAMETER) {
248 SetLastError(ERROR_SUCCESS);
250 // Then it must be a real socket..
251 bytes_sent = send(fd, buf, len, 0);
252 if (bytes_sent == SOCKET_ERROR) {
253 rv = WSAGetLastError();
254 if (rv == WSAEWOULDBLOCK) {
255 bytes_sent = 0;
257 else {
258 bytes_sent = -1;
259 errno = rv;
263 else if (rv == WSAEWOULDBLOCK) {
264 bytes_sent = 0;
266 else {
267 bytes_sent = -1;
268 errno = rv;
272 return bytes_sent;
275 #else
277 static int fd_write(int fd, char * buf, int len)
279 int bytes_sent;
281 do {
282 bytes_sent = write(fd, buf, len);
284 #ifdef EWOULDBLOCK
285 if (bytes_sent == -1 && errno == EWOULDBLOCK) {
286 bytes_sent = 0;
288 #endif
289 } while (bytes_sent == -1 && errno == EINTR);
291 return bytes_sent;
294 #endif
296 /*******************************************************************************
297 * Write from the buffer to an open file descriptor.
299 * The caller should disable the default Apache SIGPIPE handler,
300 * otherwise a bad script could cause the request to abort appearing
301 * as though the client's fd caused it.
303 * Results:
304 * <0 if an error occured (bytes may or may not have been written)
305 * =0 if no bytes were written
306 * >0 successful write
308 #ifdef WIN32
309 int fcgi_buf_get_to_fd(Buffer *buf, SOCKET fd)
311 DWORD len;
312 #else
313 int fcgi_buf_get_to_fd(Buffer *buf, int fd)
315 size_t len;
316 #endif
318 fcgi_buf_check(buf);
320 if (buf->length == 0)
321 return 0;
323 len = min(buf->length, buf->data + buf->size - buf->begin);
325 #ifndef NO_WRITEV
326 if (len == buf->length) {
327 /* the buffer is not wrapped, we don't need to use writev() */
328 #endif
330 len = fd_write(fd, buf->begin, len);
332 if (len <= 0)
333 goto Return;
335 buf->begin += len;
336 buf->length -= len;
338 if (buf->begin == buf->data + buf->size) {
339 /* the buffer needs to be wrapped */
340 buf->begin = buf->data;
342 #ifndef NO_WRITEV
344 } else {
345 /* the buffer is wrapped, use writev() */
346 struct iovec vec[2];
348 vec[0].iov_base = buf->begin;
349 vec[0].iov_len = len;
350 vec[1].iov_base = buf->data;
351 vec[1].iov_len = buf->length - len;
354 len = writev(fd, vec, 2);
355 while (len == -1 && errno == EINTR);
357 if (len <= 0)
358 goto Return;
360 buf->begin += len;
361 buf->length -= len;
363 if (buf->begin >= buf->data + buf->size)
364 buf->begin -= buf->size;
366 #else
367 if (buf->length > 0) {
368 /* there's still more data to write */
370 fd_set write_set;
371 int status;
372 int numFDs = fd + 1;
373 struct timeval timeOut;
375 FD_ZERO(&write_set);
376 FD_SET(fd, &write_set);
378 timeOut.tv_sec = 0;
379 timeOut.tv_usec = 0;
381 status = ap_select(numFDs, NULL, &write_set, NULL, &timeOut);
383 if (status < 0) {
384 len = status; /* error, errno is set */
385 goto Return;
388 if (status > 0 && FD_ISSET(fd, &write_set)) {
389 int len2;
391 len2 = fd_write(fd, buf->begin, buf->length);
393 if (len2 < 0) {
394 len = len2;
395 goto Return;
398 if (len2 > 0) {
399 buf->begin += len2;
400 buf->length -= len2;
401 len += len2;
406 #endif
408 Return:
409 if (buf->length == 0)
410 buf->begin = buf->end = buf->data;
412 return len;
415 /*******************************************************************************
416 * Return the data block start address and the length of the block.
418 void fcgi_buf_get_block_info(Buffer *buf, char **beginPtr, size_t *countPtr)
420 fcgi_buf_check(buf);
421 *beginPtr = buf->begin;
422 *countPtr = min(buf->length,
423 buf->data + buf->size - buf->begin);
426 /*******************************************************************************
427 * Throw away bytes from buffer.
429 void fcgi_buf_toss(Buffer *buf, size_t count)
431 fcgi_buf_check(buf);
432 ap_assert(count >= 0 && (int) count <= buf->length);
434 buf->length -= count;
435 buf->begin += count;
436 if(buf->begin >= buf->data + buf->size) {
437 buf->begin -= buf->size;
441 /*******************************************************************************
442 * Return the free data block start address and the length of the block.
444 void fcgi_buf_get_free_block_info(Buffer *buf, char **endPtr, size_t *countPtr)
446 fcgi_buf_check(buf);
447 *endPtr = buf->end;
448 *countPtr = min(buf->size - buf->length,
449 buf->data + buf->size - buf->end);
452 /*******************************************************************************
453 * Updates the buf to reflect recently added data.
455 void fcgi_buf_add_update(Buffer *buf, size_t count)
457 fcgi_buf_check(buf);
458 ap_assert(count >= 0 && (int) count <= BufferFree(buf));
460 buf->length += count;
461 buf->end += count;
462 if(buf->end >= buf->data + buf->size) {
463 buf->end -= buf->size;
466 fcgi_buf_check(buf);
469 /*******************************************************************************
470 * Adds a block of data to a buffer, returning the number of bytes added.
472 int fcgi_buf_add_block(Buffer *buf, char *data, size_t datalen)
474 char *end;
475 int copied = 0; /* Number of bytes actually copied. */
476 size_t canCopy; /* Number of bytes to copy in a given op. */
478 ap_assert(data != NULL);
479 if(datalen == 0) {
480 return 0;
483 ap_assert(datalen > 0);
484 fcgi_buf_check(buf);
485 end = buf->data + buf->size;
488 * Copy the first part of the data: from here to the end of the
489 * buffer, or the end of the data, whichever comes first.
491 datalen = min(BufferFree(buf), (int) datalen);
492 canCopy = min((int) datalen, end - buf->end);
493 memcpy(buf->end, data, canCopy);
494 buf->length += canCopy;
495 buf->end += canCopy;
496 copied += canCopy;
497 if (buf->end >= end) {
498 buf->end = buf->data;
500 datalen -= canCopy;
503 * If there's more to go, copy the second part starting from the
504 * beginning of the buffer.
506 if (datalen > 0) {
507 data += canCopy;
508 memcpy(buf->end, data, datalen);
509 buf->length += datalen;
510 buf->end += datalen;
511 copied += datalen;
513 return(copied);
516 /*******************************************************************************
517 * Add a string to a buffer, returning the number of bytes added.
519 int fcgi_buf_add_string(Buffer *buf, char *str)
521 return fcgi_buf_add_block(buf, str, strlen(str));
524 /*******************************************************************************
525 * Gets a data block from a buffer, returning the number of bytes copied.
527 int fcgi_buf_get_to_block(Buffer *buf, char *data, int datalen)
529 char *end;
530 int copied = 0; /* Number of bytes actually copied. */
531 size_t canCopy; /* Number of bytes to copy in a given op. */
533 ap_assert(data != NULL);
534 ap_assert(datalen > 0);
535 fcgi_buf_check(buf);
536 end = buf->data + buf->size;
539 * Copy the first part out of the buffer: from here to the end
540 * of the buffer, or all of the requested data.
542 canCopy = min(buf->length, datalen);
543 canCopy = min((int) canCopy, end - buf->begin);
544 memcpy(data, buf->begin, canCopy);
545 buf->length -= canCopy;
546 buf->begin += canCopy;
547 copied += canCopy;
548 if (buf->begin >= end) {
549 buf->begin = buf->data;
553 * If there's more to go, copy the second part starting from the
554 * beginning of the buffer.
556 if (copied < datalen && buf->length > 0) {
557 data += copied;
558 canCopy = min(buf->length, datalen - copied);
559 memcpy(data, buf->begin, canCopy);
560 buf->length -= canCopy;
561 buf->begin += canCopy;
562 copied += canCopy;
564 fcgi_buf_check(buf);
565 return(copied);
568 /*******************************************************************************
569 * Move 'len' bytes from 'src' buffer to 'dest' buffer. There must be at
570 * least 'len' bytes available in the source buffer and space for 'len'
571 * bytes in the destination buffer.
573 void fcgi_buf_get_to_buf(Buffer *dest, Buffer *src, int len)
575 char *dest_end, *src_begin;
576 size_t dest_len, src_len, move_len;
578 ap_assert(len > 0);
579 ap_assert(BufferLength(src) >= len);
580 ap_assert(BufferFree(dest) >= len);
582 fcgi_buf_check(src);
583 fcgi_buf_check(dest);
585 for (;;) {
586 if (len == 0)
587 return;
589 fcgi_buf_get_free_block_info(dest, &dest_end, &dest_len);
590 fcgi_buf_get_block_info(src, &src_begin, &src_len);
592 move_len = min(dest_len, src_len);
593 move_len = min((int) move_len, len);
595 if (move_len == 0)
596 return;
598 memcpy(dest_end, src_begin, move_len);
599 fcgi_buf_toss(src, move_len);
600 fcgi_buf_add_update(dest, move_len);
601 len -= move_len;
605 static void array_grow(array_header *arr, size_t n)
607 if (n <= 0)
608 return;
610 if ((int) (arr->nelts + n) > arr->nalloc) {
611 char *new_elts;
612 int new_nalloc = (arr->nalloc <= 0) ? n : arr->nelts + n;
614 new_elts = ap_pcalloc(arr->pool, arr->elt_size * new_nalloc);
615 memcpy(new_elts, arr->elts, arr->nelts * arr->elt_size);
617 arr->elts = new_elts;
618 arr->nalloc = new_nalloc;
622 static void array_cat_block(array_header *arr, void *block, size_t n)
624 array_grow(arr, n);
625 memcpy(arr->elts + arr->nelts * arr->elt_size, block, n * arr->elt_size);
626 arr->nelts += n;
629 /*----------------------------------------------------------------------
630 * Append "len" bytes from "buf" into "arr". Apache arrays are used
631 * whenever the data being handled is binary (may contain null chars).
633 void fcgi_buf_get_to_array(Buffer *buf, array_header *arr, size_t len)
635 int len1 = min(buf->length, buf->data + buf->size - buf->begin);
637 fcgi_buf_check(buf);
638 ap_assert(len > 0);
639 ap_assert((int) len <= BufferLength(buf));
641 array_grow(arr, len);
643 len1 = min(len1, (int) len);
644 array_cat_block(arr, buf->begin, len1);
646 if (len1 < (int) len)
647 array_cat_block(arr, buf->data, len - len1);
649 fcgi_buf_toss(buf, len);