Reset LastError when we're doing "named pipe discovery"
[mod_fastcgi.git] / fcgi_buf.c
blob33cc072f85e0cc43e0e7eb07e0734079e687225a
1 /*
2 * $Id: fcgi_buf.c,v 1.10 2001/03/06 12:57:33 robs Exp $
3 */
5 #include "fcgi.h"
7 /*******************************************************************************
8 * Check buffer consistency with assertions.
9 */
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)
30 buf->length = 0;
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)
39 Buffer *buf;
41 buf = (Buffer *)ap_pcalloc(p, sizeof(Buffer) + size);
42 buf->size = size;
43 fcgi_buf_reset(buf);
44 return buf;
47 #ifdef WIN32
49 static int fd_read(SOCKET fd, char *buf, int len)
51 long bytes_read;
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) {
59 bytes_read = 0;
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();
70 bytes_read = -1;
73 else {
74 errno = rv;
75 bytes_read = -1;
78 return bytes_read;
81 #else
83 static int fd_read(int fd, char * buf, int len)
85 int bytes_read;
86 do {
87 bytes_read = read(fd, buf, len);
88 } while (bytes_read == -1 && errno == EINTR);
89 return bytes_read;
92 #endif
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.
101 * Results:
102 * <0 error, errno is set
103 * =0 EOF reached
104 * >0 successful read or no room in buffer (NOT # of bytes read)
106 #ifdef WIN32
107 int fcgi_buf_add_fd(Buffer *buf, SOCKET fd)
108 #else
109 int fcgi_buf_add_fd(Buffer *buf, int fd)
110 #endif
112 #ifdef WIN32
113 DWORD len;
114 #else
115 size_t len;
116 #endif
118 fcgi_buf_check(buf);
120 if (buf->length == buf->size)
121 /* there's no room in the buffer, return "success" */
122 return 1;
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);
130 #ifndef NO_WRITEV
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() */
134 #endif
136 len = fd_read(fd, buf->end, len);
138 if (len <= 0)
139 return len;
141 buf->end += len;
142 buf->length += len;
144 if (buf->end == (buf->data + buf->size)) {
145 /* the buffer needs to be wrapped */
146 buf->end = buf->data;
147 #ifndef NO_WRITEV
149 } else {
150 /* the buffer is wrapped, use readv() */
151 struct iovec vec[2];
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);
162 if (len <= 0)
163 return len;
165 buf->end += len;
166 if (buf->end >= (buf->data + buf->size))
167 buf->end -= buf->size;
169 buf->length += len;
172 #else
173 if (buf->length < buf->size) {
174 /* There's still more buffer space to read into. */
176 fd_set read_set;
177 int status;
178 int numFDs = fd + 1;
179 struct timeval timeOut;
181 FD_ZERO(&read_set);
182 FD_SET(fd, &read_set);
184 timeOut.tv_sec = 0;
185 timeOut.tv_usec = 0;
187 status = ap_select(numFDs, &read_set, NULL, NULL, &timeOut);
189 if (status < 0) {
190 #ifdef WIN32
191 // More hackery
192 if (WSAGetLastError() == WSAENOTSOCK)
194 DWORD bytesavail=0;
195 if (PeekNamedPipe((HANDLE) fd, NULL, 0, NULL, &bytesavail, NULL))
197 if (bytesavail > 0)
199 len = fd_read(fd, buf->end, buf->size - buf->length);
201 if (len <= 0)
202 return len;
204 buf->end += len;
205 buf->length += len;
207 return len;
210 #endif
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);
218 if (len <= 0)
219 return len;
221 buf->end += len;
222 buf->length += len;
226 #endif
228 return len; /* this may not contain the number of bytes read */
231 #ifdef WIN32
233 static int fd_write(SOCKET fd, char * buf, int len)
235 long bytes_sent;
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) {
251 bytes_sent = 0;
253 else {
254 bytes_sent = -1;
255 errno = rv;
259 else if (rv == WSAEWOULDBLOCK) {
260 bytes_sent = 0;
262 else {
263 bytes_sent = -1;
264 errno = rv;
268 return bytes_sent;
271 #else
273 static int fd_write(int fd, char * buf, int len)
275 int bytes_sent;
277 do {
278 bytes_sent = write(fd, buf, len);
280 #ifdef EWOULDBLOCK
281 if (bytes_sent == -1 && errno == EWOULDBLOCK) {
282 bytes_sent = 0;
284 #endif
285 } while (bytes_sent == -1 && errno == EINTR);
287 return bytes_sent;
290 #endif
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.
299 * Results:
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
304 #ifdef WIN32
305 int fcgi_buf_get_to_fd(Buffer *buf, SOCKET fd)
307 DWORD len;
308 #else
309 int fcgi_buf_get_to_fd(Buffer *buf, int fd)
311 size_t len;
312 #endif
314 fcgi_buf_check(buf);
316 if (buf->length == 0)
317 return 0;
319 len = min(buf->length, buf->data + buf->size - buf->begin);
321 #ifndef NO_WRITEV
322 if (len == buf->length) {
323 /* the buffer is not wrapped, we don't need to use writev() */
324 #endif
326 len = fd_write(fd, buf->begin, len);
328 if (len <= 0)
329 goto Return;
331 buf->begin += len;
332 buf->length -= len;
334 if (buf->begin == buf->data + buf->size) {
335 /* the buffer needs to be wrapped */
336 buf->begin = buf->data;
338 #ifndef NO_WRITEV
340 } else {
341 /* the buffer is wrapped, use writev() */
342 struct iovec vec[2];
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);
353 if (len <= 0)
354 goto Return;
356 buf->begin += len;
357 buf->length -= len;
359 if (buf->begin >= buf->data + buf->size)
360 buf->begin -= buf->size;
362 #else
363 if (buf->length > 0) {
364 /* there's still more data to write */
366 fd_set write_set;
367 int status;
368 int numFDs = fd + 1;
369 struct timeval timeOut;
371 FD_ZERO(&write_set);
372 FD_SET(fd, &write_set);
374 timeOut.tv_sec = 0;
375 timeOut.tv_usec = 0;
377 status = ap_select(numFDs, NULL, &write_set, NULL, &timeOut);
379 if (status < 0) {
380 len = status; /* error, errno is set */
381 goto Return;
384 if (status > 0 && FD_ISSET(fd, &write_set)) {
385 int len2;
387 len2 = fd_write(fd, buf->begin, buf->length);
389 if (len2 < 0) {
390 len = len2;
391 goto Return;
394 if (len2 > 0) {
395 buf->begin += len2;
396 buf->length -= len2;
397 len += len2;
402 #endif
404 Return:
405 if (buf->length == 0)
406 buf->begin = buf->end = buf->data;
408 return len;
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)
416 fcgi_buf_check(buf);
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)
427 fcgi_buf_check(buf);
428 ap_assert(count >= 0 && (int) count <= buf->length);
430 buf->length -= count;
431 buf->begin += 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)
442 fcgi_buf_check(buf);
443 *endPtr = buf->end;
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)
453 fcgi_buf_check(buf);
454 ap_assert(count >= 0 && (int) count <= BufferFree(buf));
456 buf->length += count;
457 buf->end += count;
458 if(buf->end >= buf->data + buf->size) {
459 buf->end -= buf->size;
462 fcgi_buf_check(buf);
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)
470 char *end;
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);
475 if(datalen == 0) {
476 return 0;
479 ap_assert(datalen > 0);
480 fcgi_buf_check(buf);
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;
491 buf->end += canCopy;
492 copied += canCopy;
493 if (buf->end >= end) {
494 buf->end = buf->data;
496 datalen -= canCopy;
499 * If there's more to go, copy the second part starting from the
500 * beginning of the buffer.
502 if (datalen > 0) {
503 data += canCopy;
504 memcpy(buf->end, data, datalen);
505 buf->length += datalen;
506 buf->end += datalen;
507 copied += datalen;
509 return(copied);
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)
525 char *end;
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);
531 fcgi_buf_check(buf);
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;
543 copied += 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) {
553 data += copied;
554 canCopy = min(buf->length, datalen - copied);
555 memcpy(data, buf->begin, canCopy);
556 buf->length -= canCopy;
557 buf->begin += canCopy;
558 copied += canCopy;
560 fcgi_buf_check(buf);
561 return(copied);
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;
574 ap_assert(len > 0);
575 ap_assert(BufferLength(src) >= len);
576 ap_assert(BufferFree(dest) >= len);
578 fcgi_buf_check(src);
579 fcgi_buf_check(dest);
581 for (;;) {
582 if (len == 0)
583 return;
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);
591 if (move_len == 0)
592 return;
594 memcpy(dest_end, src_begin, move_len);
595 fcgi_buf_toss(src, move_len);
596 fcgi_buf_add_update(dest, move_len);
597 len -= move_len;
601 static void array_grow(array_header *arr, size_t n)
603 if (n <= 0)
604 return;
606 if ((int) (arr->nelts + n) > arr->nalloc) {
607 char *new_elts;
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)
620 array_grow(arr, n);
621 memcpy(arr->elts + arr->nelts * arr->elt_size, block, n * arr->elt_size);
622 arr->nelts += n;
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);
633 fcgi_buf_check(buf);
634 ap_assert(len > 0);
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);