]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/serf/buckets/buckets.c
Restore the dbus directory that was not meant to be deleted in r252729.
[FreeBSD/FreeBSD.git] / contrib / serf / buckets / buckets.c
1 /* Copyright 2002-2004 Justin Erenkrantz and Greg Stein
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <apr_pools.h>
17
18 #include "serf.h"
19 #include "serf_bucket_util.h"
20
21
22 serf_bucket_t *serf_bucket_create(
23     const serf_bucket_type_t *type,
24     serf_bucket_alloc_t *allocator,
25     void *data)
26 {
27     serf_bucket_t *bkt = serf_bucket_mem_alloc(allocator, sizeof(*bkt));
28
29     bkt->type = type;
30     bkt->data = data;
31     bkt->allocator = allocator;
32
33     return bkt;
34 }
35
36
37 apr_status_t serf_default_read_iovec(
38     serf_bucket_t *bucket,
39     apr_size_t requested,
40     int vecs_size,
41     struct iovec *vecs,
42     int *vecs_used)
43 {
44     const char *data;
45     apr_size_t len;
46
47     /* Read some data from the bucket.
48      *
49      * Because we're an internal 'helper' to the bucket, we can't call the
50      * normal serf_bucket_read() call because the debug allocator tracker will
51      * end up marking the bucket as read *twice* - once for us and once for
52      * our caller - which is reading the same bucket.  This leads to premature
53      * abort()s if we ever see EAGAIN.  Instead, we'll go directly to the
54      * vtable and bypass the debug tracker.
55      */
56     apr_status_t status = bucket->type->read(bucket, requested, &data, &len);
57
58     /* assert that vecs_size >= 1 ? */
59
60     /* Return that data as a single iovec. */
61     if (len) {
62         vecs[0].iov_base = (void *)data; /* loses the 'const' */
63         vecs[0].iov_len = len;
64         *vecs_used = 1;
65     }
66     else {
67         *vecs_used = 0;
68     }
69
70     return status;
71 }
72
73
74 apr_status_t serf_default_read_for_sendfile(
75     serf_bucket_t *bucket,
76     apr_size_t requested,
77     apr_hdtr_t *hdtr,
78     apr_file_t **file,
79     apr_off_t *offset,
80     apr_size_t *len)
81 {
82     /* Read a bunch of stuff into the headers.
83      *
84      * See serf_default_read_iovec as to why we call into the vtable
85      * directly.
86      */
87     apr_status_t status = bucket->type->read_iovec(bucket, requested,
88                                                    hdtr->numheaders,
89                                                    hdtr->headers,
90                                                    &hdtr->numheaders);
91
92     /* There isn't a file, and there are no trailers. */
93     *file = NULL;
94     hdtr->numtrailers = 0;
95
96     return status;
97 }
98
99
100 serf_bucket_t *serf_default_read_bucket(
101     serf_bucket_t *bucket,
102     const serf_bucket_type_t *type)
103 {
104     return NULL;
105 }
106
107
108 void serf_default_destroy(serf_bucket_t *bucket)
109 {
110 #ifdef SERF_DEBUG_BUCKET_USE
111     serf_debug__bucket_destroy(bucket);
112 #endif
113
114     serf_bucket_mem_free(bucket->allocator, bucket);
115 }
116
117
118 void serf_default_destroy_and_data(serf_bucket_t *bucket)
119 {
120     serf_bucket_mem_free(bucket->allocator, bucket->data);
121     serf_default_destroy(bucket);
122 }
123
124
125 /* ==================================================================== */
126
127
128 char *serf_bstrmemdup(serf_bucket_alloc_t *allocator,
129                       const char *str,
130                       apr_size_t size)
131 {
132     char *newstr = serf_bucket_mem_alloc(allocator, size + 1);
133     memcpy(newstr, str, size);
134     newstr[size] = '\0';
135     return newstr;
136 }
137
138
139 void *serf_bmemdup(serf_bucket_alloc_t *allocator,
140                    const void *mem,
141                    apr_size_t size)
142 {
143     void *newmem = serf_bucket_mem_alloc(allocator, size);
144     memcpy(newmem, mem, size);
145     return newmem;
146 }
147
148
149 char *serf_bstrdup(serf_bucket_alloc_t *allocator,
150                    const char *str)
151 {
152     apr_size_t size = strlen(str) + 1;
153     char *newstr = serf_bucket_mem_alloc(allocator, size);
154     memcpy(newstr, str, size);
155     return newstr;
156 }
157
158
159 /* ==================================================================== */
160
161
162 static void find_crlf(const char **data, apr_size_t *len, int *found)
163 {
164     const char *start = *data;
165     const char *end = start + *len;
166
167     while (start < end) {
168         const char *cr = memchr(start, '\r', *len);
169
170         if (cr == NULL) {
171             break;
172         }
173         ++cr;
174
175         if (cr < end && cr[0] == '\n') {
176             *len -= cr + 1 - start;
177             *data = cr + 1;
178             *found = SERF_NEWLINE_CRLF;
179             return;
180         }
181         if (cr == end) {
182             *len = 0;
183             *data = end;
184             *found = SERF_NEWLINE_CRLF_SPLIT;
185             return;
186         }
187
188         /* It was a bare CR without an LF. Just move past it. */
189         *len -= cr - start;
190         start = cr;
191     }
192
193     *data = start + *len;
194     *len -= *data - start;
195     *found = SERF_NEWLINE_NONE;
196 }
197
198
199 void serf_util_readline(
200     const char **data,
201     apr_size_t *len,
202     int acceptable,
203     int *found)
204 {
205     const char *start;
206     const char *cr;
207     const char *lf;
208     int want_cr;
209     int want_crlf;
210     int want_lf;
211
212     /* If _only_ CRLF is acceptable, then the scanning needs a loop to
213      * skip false hits on CR characters. Use a separate function.
214      */
215     if (acceptable == SERF_NEWLINE_CRLF) {
216         find_crlf(data, len, found);
217         return;
218     }
219
220     start = *data;
221     cr = lf = NULL;
222     want_cr = acceptable & SERF_NEWLINE_CR;
223     want_crlf = acceptable & SERF_NEWLINE_CRLF;
224     want_lf = acceptable & SERF_NEWLINE_LF;
225
226     if (want_cr || want_crlf) {
227         cr = memchr(start, '\r', *len);
228     }
229     if (want_lf) {
230         lf = memchr(start, '\n', *len);
231     }
232
233     if (cr != NULL) {
234         if (lf != NULL) {
235             if (cr + 1 == lf)
236                 *found = want_crlf ? SERF_NEWLINE_CRLF : SERF_NEWLINE_CR;
237             else if (want_cr && cr < lf)
238                 *found = SERF_NEWLINE_CR;
239             else
240                 *found = SERF_NEWLINE_LF;
241         }
242         else if (cr == start + *len - 1) {
243             /* the CR occurred in the last byte of the buffer. this could be
244              * a CRLF split across the data boundary.
245              * ### FIX THIS LOGIC? does caller need to detect?
246              */
247             *found = want_crlf ? SERF_NEWLINE_CRLF_SPLIT : SERF_NEWLINE_CR;
248         }
249         else if (want_cr)
250             *found = SERF_NEWLINE_CR;
251         else /* want_crlf */
252             *found = SERF_NEWLINE_NONE;
253     }
254     else if (lf != NULL)
255         *found = SERF_NEWLINE_LF;
256     else
257         *found = SERF_NEWLINE_NONE;
258
259     switch (*found) {
260       case SERF_NEWLINE_LF:
261         *data = lf + 1;
262         break;
263       case SERF_NEWLINE_CR:
264       case SERF_NEWLINE_CRLF:
265       case SERF_NEWLINE_CRLF_SPLIT:
266         *data = cr + 1 + (*found == SERF_NEWLINE_CRLF);
267         break;
268       case SERF_NEWLINE_NONE:
269         *data += *len;
270         break;
271       default:
272         /* Not reachable */
273         return;
274     }
275
276     *len -= *data - start;
277 }
278
279
280 /* ==================================================================== */
281
282
283 void serf_databuf_init(serf_databuf_t *databuf)
284 {
285     /* nothing is sitting in the buffer */
286     databuf->remaining = 0;
287
288     /* avoid thinking we have hit EOF */
289     databuf->status = APR_SUCCESS;
290 }
291
292 /* Ensure the buffer is prepared for reading. Will return APR_SUCCESS,
293  * APR_EOF, or some failure code. *len is only set for EOF. */
294 static apr_status_t common_databuf_prep(serf_databuf_t *databuf,
295                                         apr_size_t *len)
296 {
297     apr_size_t readlen;
298     apr_status_t status;
299
300     /* if there is data in the buffer, then we're happy. */
301     if (databuf->remaining > 0)
302         return APR_SUCCESS;
303
304     /* if we already hit EOF, then keep returning that. */
305     if (APR_STATUS_IS_EOF(databuf->status)) {
306         /* *data = NULL;   ?? */
307         *len = 0;
308         return APR_EOF;
309     }
310
311     /* refill the buffer */
312     status = (*databuf->read)(databuf->read_baton, sizeof(databuf->buf),
313                               databuf->buf, &readlen);
314     if (SERF_BUCKET_READ_ERROR(status)) {
315         return status;
316     }
317
318     databuf->current = databuf->buf;
319     databuf->remaining = readlen;
320     databuf->status = status;
321
322     return APR_SUCCESS;
323 }
324
325
326 apr_status_t serf_databuf_read(
327     serf_databuf_t *databuf,
328     apr_size_t requested,
329     const char **data,
330     apr_size_t *len)
331 {
332     apr_status_t status = common_databuf_prep(databuf, len);
333     if (status)
334         return status;
335
336     /* peg the requested amount to what we have remaining */
337     if (requested == SERF_READ_ALL_AVAIL || requested > databuf->remaining)
338         requested = databuf->remaining;
339
340     /* return the values */
341     *data = databuf->current;
342     *len = requested;
343
344     /* adjust our internal state to note we've consumed some data */
345     databuf->current += requested;
346     databuf->remaining -= requested;
347
348     /* If we read everything, then we need to return whatever the data
349      * read returned to us. This is going to be APR_EOF or APR_EGAIN.
350      * If we have NOT read everything, then return APR_SUCCESS to indicate
351      * that we're ready to return some more if asked.
352      */
353     return databuf->remaining ? APR_SUCCESS : databuf->status;
354 }
355
356
357 apr_status_t serf_databuf_readline(
358     serf_databuf_t *databuf,
359     int acceptable,
360     int *found,
361     const char **data,
362     apr_size_t *len)
363 {
364     apr_status_t status = common_databuf_prep(databuf, len);
365     if (status)
366         return status;
367
368     /* the returned line will start at the current position. */
369     *data = databuf->current;
370
371     /* read a line from the buffer, and adjust the various pointers. */
372     serf_util_readline(&databuf->current, &databuf->remaining, acceptable,
373                        found);
374
375     /* the length matches the amount consumed by the readline */
376     *len = databuf->current - *data;
377
378     /* see serf_databuf_read's return condition */
379     return databuf->remaining ? APR_SUCCESS : databuf->status;
380 }
381
382
383 apr_status_t serf_databuf_peek(
384     serf_databuf_t *databuf,
385     const char **data,
386     apr_size_t *len)
387 {
388     apr_status_t status = common_databuf_prep(databuf, len);
389     if (status)
390         return status;
391
392     /* return everything we have */
393     *data = databuf->current;
394     *len = databuf->remaining;
395
396     /* If the last read returned EOF, then the peek should return the same.
397      * The other possibility in databuf->status is APR_EAGAIN, which we
398      * should never return. Thus, just return APR_SUCCESS for non-EOF cases.
399      */
400     if (APR_STATUS_IS_EOF(databuf->status))
401         return APR_EOF;
402     return APR_SUCCESS;
403 }
404
405
406 /* ==================================================================== */
407
408
409 void serf_linebuf_init(serf_linebuf_t *linebuf)
410 {
411     linebuf->state = SERF_LINEBUF_EMPTY;
412     linebuf->used = 0;
413 }
414
415
416 apr_status_t serf_linebuf_fetch(
417     serf_linebuf_t *linebuf,
418     serf_bucket_t *bucket,
419     int acceptable)
420 {
421     /* If we had a complete line, then assume the caller has used it, so
422      * we can now reset the state.
423      */
424     if (linebuf->state == SERF_LINEBUF_READY) {
425         linebuf->state = SERF_LINEBUF_EMPTY;
426
427         /* Reset the line_used, too, so we don't have to test the state
428          * before using this value.
429          */
430         linebuf->used = 0;
431     }
432
433     while (1) {
434         apr_status_t status;
435         const char *data;
436         apr_size_t len;
437
438         if (linebuf->state == SERF_LINEBUF_CRLF_SPLIT) {
439             /* On the previous read, we received just a CR. The LF might
440              * be present, but the bucket couldn't see it. We need to
441              * examine a single character to determine how to handle the
442              * split CRLF.
443              */
444
445             status = serf_bucket_peek(bucket, &data, &len);
446             if (SERF_BUCKET_READ_ERROR(status))
447                 return status;
448
449             if (len > 0) {
450                 if (*data == '\n') {
451                     /* We saw the second part of CRLF. We don't need to
452                      * save that character, so do an actual read to suck
453                      * up that character.
454                      */
455                     /* ### check status */
456                     (void) serf_bucket_read(bucket, 1, &data, &len);
457                 }
458                 /* else:
459                  *   We saw the first character of the next line. Thus,
460                  *   the current line is terminated by the CR. Just
461                  *   ignore whatever we peeked at. The next reader will
462                  *   see it and handle it as appropriate.
463                  */
464
465                 /* Whatever was read, the line is now ready for use. */
466                 linebuf->state = SERF_LINEBUF_READY;
467             } else {
468                 /* no data available, try again later. */
469                 return APR_EAGAIN;
470             }
471         }
472         else {
473             int found;
474
475             status = serf_bucket_readline(bucket, acceptable, &found,
476                                           &data, &len);
477             if (SERF_BUCKET_READ_ERROR(status)) {
478                 return status;
479             }
480             /* Some bucket types (socket) might need an extra read to find
481                out EOF state, so they'll return no data in that read. This
482                means we're done reading, return what we got. */
483             if (APR_STATUS_IS_EOF(status) && len == 0) {
484                 return status;
485             }
486             if (linebuf->used + len > sizeof(linebuf->line)) {
487                 /* ### need a "line too long" error */
488                 return APR_EGENERAL;
489             }
490
491             /* Note: our logic doesn't change for SERF_LINEBUF_PARTIAL. That
492              * only affects how we fill the buffer. It is a communication to
493              * our caller on whether the line is ready or not.
494              */
495
496             /* If we didn't see a newline, then we should mark the line
497              * buffer as partially complete.
498              */
499             if (found == SERF_NEWLINE_NONE) {
500                 linebuf->state = SERF_LINEBUF_PARTIAL;
501             }
502             else if (found == SERF_NEWLINE_CRLF_SPLIT) {
503                 linebuf->state = SERF_LINEBUF_CRLF_SPLIT;
504
505                 /* Toss the partial CR. We won't ever need it. */
506                 --len;
507             }
508             else {
509                 /* We got a newline (of some form). We don't need it
510                  * in the line buffer, so back up the length. Then
511                  * mark the line as ready.
512                  */
513                 len -= 1 + (found == SERF_NEWLINE_CRLF);
514
515                 linebuf->state = SERF_LINEBUF_READY;
516             }
517
518             /* ### it would be nice to avoid this copy if at all possible,
519                ### and just return the a data/len pair to the caller. we're
520                ### keeping it simple for now. */
521             memcpy(&linebuf->line[linebuf->used], data, len);
522             linebuf->used += len;
523         }
524
525         /* If we saw anything besides "success. please read again", then
526          * we should return that status. If the line was completed, then
527          * we should also return.
528          */
529         if (status || linebuf->state == SERF_LINEBUF_READY)
530             return status;
531
532         /* We got APR_SUCCESS and the line buffer is not complete. Let's
533          * loop to read some more data.
534          */
535     }
536     /* NOTREACHED */
537 }
538
539 /* Logging functions.
540    Use with one of the [COMP]_VERBOSE defines so that the compiler knows to
541    optimize this code out when no logging is needed. */
542 static void log_time()
543 {
544     apr_time_exp_t tm;
545
546     apr_time_exp_lt(&tm, apr_time_now());
547     fprintf(stderr, "[%d-%02d-%02dT%02d:%02d:%02d.%06d%+03d] ",
548             1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday,
549             tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
550             tm.tm_gmtoff/3600);
551 }
552
553 void serf__log(int verbose_flag, const char *filename, const char *fmt, ...)
554 {
555     va_list argp;
556
557     if (verbose_flag) {
558         log_time();
559
560         if (filename)
561             fprintf(stderr, "%s: ", filename);
562
563         va_start(argp, fmt);
564         vfprintf(stderr, fmt, argp);
565         va_end(argp);
566     }
567 }
568
569 void serf__log_nopref(int verbose_flag, const char *fmt, ...)
570 {
571     va_list argp;
572
573     if (verbose_flag) {
574         va_start(argp, fmt);
575         vfprintf(stderr, fmt, argp);
576         va_end(argp);
577     }
578 }
579
580 void serf__log_skt(int verbose_flag, const char *filename, apr_socket_t *skt,
581                    const char *fmt, ...)
582 {
583     va_list argp;
584
585     if (verbose_flag) {
586         apr_sockaddr_t *sa;
587         log_time();
588
589         if (skt) {
590             /* Log local and remote ip address:port */
591             fprintf(stderr, "[l:");
592             if (apr_socket_addr_get(&sa, APR_LOCAL, skt) == APR_SUCCESS) {
593                 char buf[32];
594                 apr_sockaddr_ip_getbuf(buf, 32, sa);
595                 fprintf(stderr, "%s:%d", buf, sa->port);
596             }
597             fprintf(stderr, " r:");
598             if (apr_socket_addr_get(&sa, APR_REMOTE, skt) == APR_SUCCESS) {
599                 char buf[32];
600                 apr_sockaddr_ip_getbuf(buf, 32, sa);
601                 fprintf(stderr, "%s:%d", buf, sa->port);
602             }
603             fprintf(stderr, "] ");
604         }
605
606         if (filename)
607             fprintf(stderr, "%s: ", filename);
608
609         va_start(argp, fmt);
610         vfprintf(stderr, fmt, argp);
611         va_end(argp);
612     }
613 }
614