2 * $Id: fcgi_buf.c,v 1.10 2001/03/06 12:57:33 robs Exp $
7 /*******************************************************************************
8 * Check buffer consistency with assertions.
10 void fcgi_buf_check(Buffer
*buf
)
12 ap_assert(buf
->size
> 0);
13 ap_assert(buf
->length
>= 0);
14 ap_assert(buf
->length
<= buf
->size
);
16 ap_assert(buf
->begin
>= buf
->data
);
17 ap_assert(buf
->begin
< buf
->data
+ buf
->size
);
18 ap_assert(buf
->end
>= buf
->data
);
19 ap_assert(buf
->end
< buf
->data
+ buf
->size
);
21 ap_assert(((buf
->end
- buf
->begin
+ buf
->size
) % buf
->size
)
22 == (buf
->length
% buf
->size
));
25 /*******************************************************************************
26 * Reset buffer, losing any data that's in it.
28 void fcgi_buf_reset(Buffer
*buf
)
31 buf
->begin
= buf
->end
= buf
->data
;
34 /*******************************************************************************
35 * Allocate and intialize a new buffer of the specified size.
37 Buffer
*fcgi_buf_new(pool
*p
, int size
)
41 buf
= (Buffer
*)ap_pcalloc(p
, sizeof(Buffer
) + size
);
49 static int fd_read(SOCKET fd
, char *buf
, int len
)
53 // HACK - we don't know if its a pipe or socket..
54 if (!ReadFile((HANDLE
) fd
, buf
, len
, (unsigned long *) &bytes_read
, NULL
)) {
56 int rv
= GetLastError();
58 if (rv
== ERROR_PIPE_NOT_CONNECTED
) {
61 else if (rv
== ERROR_INVALID_PARAMETER
) {
63 SetLastError(ERROR_SUCCESS
);
65 // Then it must be a real socket
67 bytes_read
= recv(fd
, buf
, len
, 0);
68 if (bytes_read
== SOCKET_ERROR
) {
69 errno
= WSAGetLastError();
83 static int fd_read(int fd
, char * buf
, int len
)
87 bytes_read
= read(fd
, buf
, len
);
88 } while (bytes_read
== -1 && errno
== EINTR
);
94 /*******************************************************************************
95 * Read from an open file descriptor into buffer.
97 * The caller should disable the default Apache SIGPIPE handler,
98 * otherwise a bad script could cause the request to abort and appear
99 * as though the client's fd caused it.
102 * <0 error, errno is set
104 * >0 successful read or no room in buffer (NOT # of bytes read)
107 int fcgi_buf_add_fd(Buffer
*buf
, SOCKET fd
)
109 int fcgi_buf_add_fd(Buffer
*buf
, int fd
)
120 if (buf
->length
== buf
->size
)
121 /* there's no room in the buffer, return "success" */
124 if (buf
->length
== 0)
125 /* the buffer is empty so defrag */
126 buf
->begin
= buf
->end
= buf
->data
;
128 len
= min(buf
->size
- buf
->length
, buf
->data
+ buf
->size
- buf
->end
);
131 /* assume there is a readv() if there is a writev() */
132 if (len
== buf
->size
- buf
->length
) {
133 /* its not wrapped, use read() instead of readv() */
136 len
= fd_read(fd
, buf
->end
, len
);
144 if (buf
->end
== (buf
->data
+ buf
->size
)) {
145 /* the buffer needs to be wrapped */
146 buf
->end
= buf
->data
;
150 /* the buffer is wrapped, use readv() */
153 vec
[0].iov_base
= buf
->end
;
154 vec
[0].iov_len
= len
;
155 vec
[1].iov_base
= buf
->data
;
156 vec
[1].iov_len
= buf
->size
- buf
->length
- len
;
159 len
= readv(fd
, vec
, 2);
160 while (len
== -1 && errno
== EINTR
);
166 if (buf
->end
>= (buf
->data
+ buf
->size
))
167 buf
->end
-= buf
->size
;
173 if (buf
->length
< buf
->size
) {
174 /* There's still more buffer space to read into. */
179 struct timeval timeOut
;
182 FD_SET(fd
, &read_set
);
187 status
= ap_select(numFDs
, &read_set
, NULL
, NULL
, &timeOut
);
192 if (WSAGetLastError() == WSAENOTSOCK
)
195 if (PeekNamedPipe((HANDLE
) fd
, NULL
, 0, NULL
, &bytesavail
, NULL
))
199 len
= fd_read(fd
, buf
->end
, buf
->size
- buf
->length
);
211 return status
; /* error, errno is set */
214 if (status
> 0 && FD_ISSET(fd
, &read_set
)) {
216 len
= fd_read(fd
, buf
->end
, buf
->size
- buf
->length
);
228 return len
; /* this may not contain the number of bytes read */
233 static int fd_write(SOCKET fd
, char * buf
, int len
)
237 // HACK - We don't know if its a pipe or socket..
238 if (!WriteFile((HANDLE
) fd
, (LPVOID
) buf
, len
, (unsigned long *) &bytes_sent
, NULL
)) {
240 int rv
= GetLastError();
242 if (rv
== ERROR_INVALID_PARAMETER
) {
244 SetLastError(ERROR_SUCCESS
);
246 // Then it must be a real socket..
247 bytes_sent
= send(fd
, buf
, len
, 0);
248 if (bytes_sent
== SOCKET_ERROR
) {
249 rv
= WSAGetLastError();
250 if (rv
== WSAEWOULDBLOCK
) {
259 else if (rv
== WSAEWOULDBLOCK
) {
273 static int fd_write(int fd
, char * buf
, int len
)
278 bytes_sent
= write(fd
, buf
, len
);
281 if (bytes_sent
== -1 && errno
== EWOULDBLOCK
) {
285 } while (bytes_sent
== -1 && errno
== EINTR
);
292 /*******************************************************************************
293 * Write from the buffer to an open file descriptor.
295 * The caller should disable the default Apache SIGPIPE handler,
296 * otherwise a bad script could cause the request to abort appearing
297 * as though the client's fd caused it.
300 * <0 if an error occured (bytes may or may not have been written)
301 * =0 if no bytes were written
302 * >0 successful write
305 int fcgi_buf_get_to_fd(Buffer
*buf
, SOCKET fd
)
309 int fcgi_buf_get_to_fd(Buffer
*buf
, int fd
)
316 if (buf
->length
== 0)
319 len
= min(buf
->length
, buf
->data
+ buf
->size
- buf
->begin
);
322 if (len
== buf
->length
) {
323 /* the buffer is not wrapped, we don't need to use writev() */
326 len
= fd_write(fd
, buf
->begin
, len
);
334 if (buf
->begin
== buf
->data
+ buf
->size
) {
335 /* the buffer needs to be wrapped */
336 buf
->begin
= buf
->data
;
341 /* the buffer is wrapped, use writev() */
344 vec
[0].iov_base
= buf
->begin
;
345 vec
[0].iov_len
= len
;
346 vec
[1].iov_base
= buf
->data
;
347 vec
[1].iov_len
= buf
->length
- len
;
350 len
= writev(fd
, vec
, 2);
351 while (len
== -1 && errno
== EINTR
);
359 if (buf
->begin
>= buf
->data
+ buf
->size
)
360 buf
->begin
-= buf
->size
;
363 if (buf
->length
> 0) {
364 /* there's still more data to write */
369 struct timeval timeOut
;
372 FD_SET(fd
, &write_set
);
377 status
= ap_select(numFDs
, NULL
, &write_set
, NULL
, &timeOut
);
380 len
= status
; /* error, errno is set */
384 if (status
> 0 && FD_ISSET(fd
, &write_set
)) {
387 len2
= fd_write(fd
, buf
->begin
, buf
->length
);
405 if (buf
->length
== 0)
406 buf
->begin
= buf
->end
= buf
->data
;
411 /*******************************************************************************
412 * Return the data block start address and the length of the block.
414 void fcgi_buf_get_block_info(Buffer
*buf
, char **beginPtr
, size_t *countPtr
)
417 *beginPtr
= buf
->begin
;
418 *countPtr
= min(buf
->length
,
419 buf
->data
+ buf
->size
- buf
->begin
);
422 /*******************************************************************************
423 * Throw away bytes from buffer.
425 void fcgi_buf_toss(Buffer
*buf
, size_t count
)
428 ap_assert(count
>= 0 && (int) count
<= buf
->length
);
430 buf
->length
-= count
;
432 if(buf
->begin
>= buf
->data
+ buf
->size
) {
433 buf
->begin
-= buf
->size
;
437 /*******************************************************************************
438 * Return the free data block start address and the length of the block.
440 void fcgi_buf_get_free_block_info(Buffer
*buf
, char **endPtr
, size_t *countPtr
)
444 *countPtr
= min(buf
->size
- buf
->length
,
445 buf
->data
+ buf
->size
- buf
->end
);
448 /*******************************************************************************
449 * Updates the buf to reflect recently added data.
451 void fcgi_buf_add_update(Buffer
*buf
, size_t count
)
454 ap_assert(count
>= 0 && (int) count
<= BufferFree(buf
));
456 buf
->length
+= count
;
458 if(buf
->end
>= buf
->data
+ buf
->size
) {
459 buf
->end
-= buf
->size
;
465 /*******************************************************************************
466 * Adds a block of data to a buffer, returning the number of bytes added.
468 int fcgi_buf_add_block(Buffer
*buf
, char *data
, size_t datalen
)
471 int copied
= 0; /* Number of bytes actually copied. */
472 size_t canCopy
; /* Number of bytes to copy in a given op. */
474 ap_assert(data
!= NULL
);
479 ap_assert(datalen
> 0);
481 end
= buf
->data
+ buf
->size
;
484 * Copy the first part of the data: from here to the end of the
485 * buffer, or the end of the data, whichever comes first.
487 datalen
= min(BufferFree(buf
), (int) datalen
);
488 canCopy
= min((int) datalen
, end
- buf
->end
);
489 memcpy(buf
->end
, data
, canCopy
);
490 buf
->length
+= canCopy
;
493 if (buf
->end
>= end
) {
494 buf
->end
= buf
->data
;
499 * If there's more to go, copy the second part starting from the
500 * beginning of the buffer.
504 memcpy(buf
->end
, data
, datalen
);
505 buf
->length
+= datalen
;
512 /*******************************************************************************
513 * Add a string to a buffer, returning the number of bytes added.
515 int fcgi_buf_add_string(Buffer
*buf
, char *str
)
517 return fcgi_buf_add_block(buf
, str
, strlen(str
));
520 /*******************************************************************************
521 * Gets a data block from a buffer, returning the number of bytes copied.
523 int fcgi_buf_get_to_block(Buffer
*buf
, char *data
, int datalen
)
526 int copied
= 0; /* Number of bytes actually copied. */
527 size_t canCopy
; /* Number of bytes to copy in a given op. */
529 ap_assert(data
!= NULL
);
530 ap_assert(datalen
> 0);
532 end
= buf
->data
+ buf
->size
;
535 * Copy the first part out of the buffer: from here to the end
536 * of the buffer, or all of the requested data.
538 canCopy
= min(buf
->length
, datalen
);
539 canCopy
= min((int) canCopy
, end
- buf
->begin
);
540 memcpy(data
, buf
->begin
, canCopy
);
541 buf
->length
-= canCopy
;
542 buf
->begin
+= canCopy
;
544 if (buf
->begin
>= end
) {
545 buf
->begin
= buf
->data
;
549 * If there's more to go, copy the second part starting from the
550 * beginning of the buffer.
552 if (copied
< datalen
&& buf
->length
> 0) {
554 canCopy
= min(buf
->length
, datalen
- copied
);
555 memcpy(data
, buf
->begin
, canCopy
);
556 buf
->length
-= canCopy
;
557 buf
->begin
+= canCopy
;
564 /*******************************************************************************
565 * Move 'len' bytes from 'src' buffer to 'dest' buffer. There must be at
566 * least 'len' bytes available in the source buffer and space for 'len'
567 * bytes in the destination buffer.
569 void fcgi_buf_get_to_buf(Buffer
*dest
, Buffer
*src
, int len
)
571 char *dest_end
, *src_begin
;
572 size_t dest_len
, src_len
, move_len
;
575 ap_assert(BufferLength(src
) >= len
);
576 ap_assert(BufferFree(dest
) >= len
);
579 fcgi_buf_check(dest
);
585 fcgi_buf_get_free_block_info(dest
, &dest_end
, &dest_len
);
586 fcgi_buf_get_block_info(src
, &src_begin
, &src_len
);
588 move_len
= min(dest_len
, src_len
);
589 move_len
= min((int) move_len
, len
);
594 memcpy(dest_end
, src_begin
, move_len
);
595 fcgi_buf_toss(src
, move_len
);
596 fcgi_buf_add_update(dest
, move_len
);
601 static void array_grow(array_header
*arr
, size_t n
)
606 if ((int) (arr
->nelts
+ n
) > arr
->nalloc
) {
608 int new_nalloc
= (arr
->nalloc
<= 0) ? n
: arr
->nelts
+ n
;
610 new_elts
= ap_pcalloc(arr
->pool
, arr
->elt_size
* new_nalloc
);
611 memcpy(new_elts
, arr
->elts
, arr
->nelts
* arr
->elt_size
);
613 arr
->elts
= new_elts
;
614 arr
->nalloc
= new_nalloc
;
618 static void array_cat_block(array_header
*arr
, void *block
, size_t n
)
621 memcpy(arr
->elts
+ arr
->nelts
* arr
->elt_size
, block
, n
* arr
->elt_size
);
625 /*----------------------------------------------------------------------
626 * Append "len" bytes from "buf" into "arr". Apache arrays are used
627 * whenever the data being handled is binary (may contain null chars).
629 void fcgi_buf_get_to_array(Buffer
*buf
, array_header
*arr
, size_t len
)
631 int len1
= min(buf
->length
, buf
->data
+ buf
->size
- buf
->begin
);
635 ap_assert((int) len
<= BufferLength(buf
));
637 array_grow(arr
, len
);
639 len1
= min(len1
, (int) len
);
640 array_cat_block(arr
, buf
->begin
, len1
);
642 if (len1
< (int) len
)
643 array_cat_block(arr
, buf
->data
, len
- len1
);
645 fcgi_buf_toss(buf
, len
);