Eliminate the logging of "incomplete headers (0 bytes) received from
[mod_fastcgi.git] / fcgi_buf.c
blob1aedac197c86e3c9811b3dfcc6e62e4c403cb58c
1 /*
2 * $Id: fcgi_buf.c,v 1.16 2002/10/22 01:02:18 robs Exp $
3 */
5 #include "fcgi.h"
7 #ifdef WIN32
8 #pragma warning( disable : 4127 )
9 #else
10 #ifdef APACHE2
11 #include <unistd.h>
12 #endif
13 #endif
15 /*******************************************************************************
16 * Check buffer consistency with assertions.
18 void fcgi_buf_check(Buffer *buf)
20 ap_assert(buf->size > 0);
21 ap_assert(buf->length >= 0);
22 ap_assert(buf->length <= buf->size);
24 ap_assert(buf->begin >= buf->data);
25 ap_assert(buf->begin < buf->data + buf->size);
26 ap_assert(buf->end >= buf->data);
27 ap_assert(buf->end < buf->data + buf->size);
29 ap_assert(((buf->end - buf->begin + buf->size) % buf->size)
30 == (buf->length % buf->size));
33 /*******************************************************************************
34 * Reset buffer, losing any data that's in it.
36 void fcgi_buf_reset(Buffer *buf)
38 buf->length = 0;
39 buf->begin = buf->end = buf->data;
42 /*******************************************************************************
43 * Allocate and intialize a new buffer of the specified size.
45 Buffer *fcgi_buf_new(pool *p, int size)
47 Buffer *buf;
49 buf = (Buffer *)ap_pcalloc(p, sizeof(Buffer) + size);
50 buf->size = size;
51 fcgi_buf_reset(buf);
52 return buf;
55 void fcgi_buf_removed(Buffer * const b, unsigned int len)
57 b->length -= len;
58 b->begin += len;
60 if (b->length == 0)
62 b->begin = b->end = b->data;
64 else if (b->begin >= b->data + b->size)
66 b->begin -= b->size;
70 void fcgi_buf_added(Buffer * const b, const unsigned int len)
72 b->length += len;
73 b->end += len;
75 if (b->end >= b->data + b->size)
77 b->end -= b->size;
81 #ifdef WIN32
83 static int socket_recv(SOCKET fd, char *buf, int len)
85 int bytes_read = recv(fd, buf, len, 0);
87 if (bytes_read == SOCKET_ERROR)
89 return -1;
91 return bytes_read;
94 static int socket_send(SOCKET fd, char * buf, int len)
96 int bytes_sent = send(fd, buf, len, 0);
98 if (bytes_sent == SOCKET_ERROR)
100 return -1;
102 return bytes_sent;
105 #else /* !WIN32 */
107 static int socket_recv(int fd, char * buf, int len)
109 int bytes_read;
111 do {
112 bytes_read = read(fd, buf, len);
114 if (bytes_read < 0)
116 #ifdef EWOULDBLOCK
117 ap_assert(errno != EWOULDBLOCK);
118 #endif
119 #ifdef EAGAIN
120 ap_assert(errno != EAGAIN);
121 #endif
123 } while (bytes_read == -1 && errno == EINTR);
125 return bytes_read;
128 static int socket_send(int fd, char * buf, int len)
130 int bytes_sent;
132 do {
133 bytes_sent = write(fd, buf, len);
135 if (bytes_sent < 0)
137 #ifdef EWOULDBLOCK
138 ap_assert(errno != EWOULDBLOCK);
139 #endif
140 #ifdef EAGAIN
141 ap_assert(errno != EAGAIN);
142 #endif
145 while (bytes_sent == -1 && errno == EINTR);
147 return bytes_sent;
150 #endif /* !WIN32 */
152 /*******************************************************************************
153 * Read from an open file descriptor into buffer.
155 * The caller should disable the default Apache SIGPIPE handler,
156 * otherwise a bad script could cause the request to abort and appear
157 * as though the client's fd caused it.
159 * Results:
160 * <0 error, errno is set
161 * =0 EOF reached
162 * >0 successful read or no room in buffer (NOT # of bytes read)
164 int fcgi_buf_socket_recv(Buffer *buf, SOCKET fd)
166 int len;
168 fcgi_buf_check(buf);
170 if (buf->length == buf->size)
171 /* there's no room in the buffer, return "success" */
172 return 1;
174 if (buf->length == 0)
175 /* the buffer is empty so defrag */
176 buf->begin = buf->end = buf->data;
178 len = min(buf->size - buf->length, buf->data + buf->size - buf->end);
180 #ifndef NO_WRITEV
182 /* assume there is a readv() since there is a writev() */
183 if (len == buf->size - buf->length)
185 #endif
187 len = socket_recv(fd, buf->end, len);
189 #ifndef NO_WRITEV
191 else
193 /* the buffer is wrapped, use readv() */
194 struct iovec vec[2];
196 vec[0].iov_base = buf->end;
197 vec[0].iov_len = len;
198 vec[1].iov_base = buf->data;
199 vec[1].iov_len = buf->size - buf->length - len;
201 ap_assert(len);
202 ap_assert(vec[1].iov_len);
206 len = readv(fd, vec, 2);
208 while (len == -1 && errno == EINTR);
210 #endif
212 if (len <= 0) return len;
214 fcgi_buf_added(buf, len);
216 return len; /* this may not contain the number of bytes read */
220 /*******************************************************************************
221 * Write from the buffer to an open file descriptor.
223 * The caller should disable the default Apache SIGPIPE handler,
224 * otherwise a bad script could cause the request to abort appearing
225 * as though the client's fd caused it.
227 * Results:
228 * <0 if an error occured (bytes may or may not have been written)
229 * =0 if no bytes were written
230 * >0 successful write
232 int fcgi_buf_socket_send(Buffer *buf, SOCKET fd)
234 int len;
236 fcgi_buf_check(buf);
238 if (buf->length == 0)
239 return 0;
241 len = min(buf->length, buf->data + buf->size - buf->begin);
243 #ifndef NO_WRITEV
244 if (len == buf->length)
246 #endif
248 len = socket_send(fd, buf->begin, len);
250 #ifndef NO_WRITEV
252 else
254 struct iovec vec[2];
256 vec[0].iov_base = buf->begin;
257 vec[0].iov_len = len;
258 vec[1].iov_base = buf->data;
259 vec[1].iov_len = buf->length - len;
263 len = writev(fd, vec, 2);
265 while (len == -1 && errno == EINTR);
267 #endif
269 if (len <= 0) return len;
271 fcgi_buf_removed(buf, len);
273 return len;
276 /*******************************************************************************
277 * Return the data block start address and the length of the block.
279 void fcgi_buf_get_block_info(Buffer *buf, char **beginPtr, int *countPtr)
281 fcgi_buf_check(buf);
283 *beginPtr = buf->begin;
284 *countPtr = min(buf->length, buf->data + buf->size - buf->begin);
287 /*******************************************************************************
288 * Throw away bytes from buffer.
290 void fcgi_buf_toss(Buffer *buf, int count)
292 fcgi_buf_check(buf);
293 ap_assert(count >= 0);
294 ap_assert(count <= buf->length);
296 buf->length -= count;
297 buf->begin += count;
298 if(buf->begin >= buf->data + buf->size) {
299 buf->begin -= buf->size;
303 /*******************************************************************************
304 * Return the free data block start address and the length of the block.
306 void fcgi_buf_get_free_block_info(Buffer *buf, char **endPtr, int *countPtr)
308 fcgi_buf_check(buf);
310 *endPtr = buf->end;
311 *countPtr = min(buf->size - buf->length,
312 buf->data + buf->size - buf->end);
315 /*******************************************************************************
316 * Updates the buf to reflect recently added data.
318 void fcgi_buf_add_update(Buffer *buf, int count)
320 fcgi_buf_check(buf);
321 ap_assert(count >= 0);
322 ap_assert(count <= BufferFree(buf));
324 buf->length += count;
325 buf->end += count;
326 if(buf->end >= buf->data + buf->size) {
327 buf->end -= buf->size;
330 fcgi_buf_check(buf);
333 /*******************************************************************************
334 * Adds a block of data to a buffer, returning the number of bytes added.
336 int fcgi_buf_add_block(Buffer *buf, char *data, int datalen)
338 char *end;
339 int copied = 0; /* Number of bytes actually copied. */
340 int canCopy; /* Number of bytes to copy in a given op. */
342 ap_assert(data != NULL);
343 ap_assert(datalen >= 0);
345 if(datalen == 0) {
346 return 0;
349 ap_assert(datalen > 0);
350 fcgi_buf_check(buf);
351 end = buf->data + buf->size;
354 * Copy the first part of the data: from here to the end of the
355 * buffer, or the end of the data, whichever comes first.
357 datalen = min(BufferFree(buf), datalen);
358 canCopy = min(datalen, end - buf->end);
359 memcpy(buf->end, data, canCopy);
360 buf->length += canCopy;
361 buf->end += canCopy;
362 copied += canCopy;
363 if (buf->end >= end) {
364 buf->end = buf->data;
366 datalen -= canCopy;
369 * If there's more to go, copy the second part starting from the
370 * beginning of the buffer.
372 if (datalen > 0) {
373 data += canCopy;
374 memcpy(buf->end, data, datalen);
375 buf->length += datalen;
376 buf->end += datalen;
377 copied += datalen;
379 return(copied);
382 /*******************************************************************************
383 * Add a string to a buffer, returning the number of bytes added.
385 int fcgi_buf_add_string(Buffer *buf, char *str)
387 return fcgi_buf_add_block(buf, str, strlen(str));
390 /*******************************************************************************
391 * Gets a data block from a buffer, returning the number of bytes copied.
393 int fcgi_buf_get_to_block(Buffer *buf, char *data, int datalen)
395 char *end;
396 int copied = 0; /* Number of bytes actually copied. */
397 int canCopy; /* Number of bytes to copy in a given op. */
399 ap_assert(data != NULL);
400 ap_assert(datalen > 0);
401 fcgi_buf_check(buf);
403 end = buf->data + buf->size;
406 * Copy the first part out of the buffer: from here to the end
407 * of the buffer, or all of the requested data.
409 canCopy = min(buf->length, datalen);
410 canCopy = min(canCopy, end - buf->begin);
412 memcpy(data, buf->begin, canCopy);
414 buf->length -= canCopy;
415 buf->begin += canCopy;
416 copied += canCopy;
417 if (buf->begin >= end) {
418 buf->begin = buf->data;
422 * If there's more to go, copy the second part starting from the
423 * beginning of the buffer.
425 if (copied < datalen && buf->length > 0) {
426 data += copied;
427 canCopy = min(buf->length, datalen - copied);
429 memcpy(data, buf->begin, canCopy);
431 buf->length -= canCopy;
432 buf->begin += canCopy;
433 copied += canCopy;
436 fcgi_buf_check(buf);
437 return(copied);
440 /*******************************************************************************
441 * Move 'len' bytes from 'src' buffer to 'dest' buffer. There must be at
442 * least 'len' bytes available in the source buffer and space for 'len'
443 * bytes in the destination buffer.
445 void fcgi_buf_get_to_buf(Buffer *dest, Buffer *src, int len)
447 char *dest_end, *src_begin;
448 int dest_len, src_len, move_len;
450 ap_assert(len > 0);
451 ap_assert(BufferLength(src) >= len);
452 ap_assert(BufferFree(dest) >= len);
454 fcgi_buf_check(src);
455 fcgi_buf_check(dest);
457 for (;;) {
458 if (len == 0)
459 return;
461 fcgi_buf_get_free_block_info(dest, &dest_end, &dest_len);
462 fcgi_buf_get_block_info(src, &src_begin, &src_len);
464 move_len = min(dest_len, src_len);
465 move_len = min(move_len, len);
467 if (move_len == 0)
468 return;
470 memcpy(dest_end, src_begin, move_len);
471 fcgi_buf_toss(src, move_len);
472 fcgi_buf_add_update(dest, move_len);
473 len -= move_len;
477 static void array_grow(array_header *arr, int n)
479 if (n <= 0)
480 return;
482 if (arr->nelts + n > arr->nalloc) {
483 char *new_elts;
484 int new_nalloc = (arr->nalloc <= 0) ? n : arr->nelts + n;
486 new_elts = ap_pcalloc(arr->pool, arr->elt_size * new_nalloc);
487 memcpy(new_elts, arr->elts, arr->nelts * arr->elt_size);
489 arr->elts = new_elts;
490 arr->nalloc = new_nalloc;
494 static void array_cat_block(array_header *arr, void *block, int n)
496 array_grow(arr, n);
497 memcpy(arr->elts + arr->nelts * arr->elt_size, block, n * arr->elt_size);
498 arr->nelts += n;
501 /*----------------------------------------------------------------------
502 * Append "len" bytes from "buf" into "arr". Apache arrays are used
503 * whenever the data being handled is binary (may contain null chars).
505 void fcgi_buf_get_to_array(Buffer *buf, array_header *arr, int len)
507 int len1 = min(buf->length, buf->data + buf->size - buf->begin);
509 fcgi_buf_check(buf);
510 ap_assert(len > 0);
511 ap_assert(len <= BufferLength(buf));
513 array_grow(arr, len);
515 len1 = min(len1, len);
516 array_cat_block(arr, buf->begin, len1);
518 if (len1 < len)
519 array_cat_block(arr, buf->data, len - len1);
521 fcgi_buf_toss(buf, len);