]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/serf/buckets/buckets.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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 #include "serf_private.h"
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 char *serf_bstrcatv(serf_bucket_alloc_t *allocator, struct iovec *vec,
159                     int vecs, apr_size_t *bytes_written)
160 {
161     int i;
162     apr_size_t new_len = 0;
163     char *c, *newstr;
164
165     for (i = 0; i < vecs; i++) {
166         new_len += vec[i].iov_len;
167     }
168
169     /* It's up to the caller to free this memory later. */
170     newstr = serf_bucket_mem_alloc(allocator, new_len);
171
172     c = newstr;
173     for (i = 0; i < vecs; i++) {
174         memcpy(c, vec[i].iov_base, vec[i].iov_len);
175         c += vec[i].iov_len;
176     }
177
178     if (bytes_written) {
179         *bytes_written = c - newstr;
180     }
181
182     return newstr;
183 }
184
185 /* ==================================================================== */
186
187
188 static void find_crlf(const char **data, apr_size_t *len, int *found)
189 {
190     const char *start = *data;
191     const char *end = start + *len;
192
193     while (start < end) {
194         const char *cr = memchr(start, '\r', *len);
195
196         if (cr == NULL) {
197             break;
198         }
199         ++cr;
200
201         if (cr < end && cr[0] == '\n') {
202             *len -= cr + 1 - start;
203             *data = cr + 1;
204             *found = SERF_NEWLINE_CRLF;
205             return;
206         }
207         if (cr == end) {
208             *len = 0;
209             *data = end;
210             *found = SERF_NEWLINE_CRLF_SPLIT;
211             return;
212         }
213
214         /* It was a bare CR without an LF. Just move past it. */
215         *len -= cr - start;
216         start = cr;
217     }
218
219     *data = start + *len;
220     *len -= *data - start;
221     *found = SERF_NEWLINE_NONE;
222 }
223
224
225 void serf_util_readline(
226     const char **data,
227     apr_size_t *len,
228     int acceptable,
229     int *found)
230 {
231     const char *start;
232     const char *cr;
233     const char *lf;
234     int want_cr;
235     int want_crlf;
236     int want_lf;
237
238     /* If _only_ CRLF is acceptable, then the scanning needs a loop to
239      * skip false hits on CR characters. Use a separate function.
240      */
241     if (acceptable == SERF_NEWLINE_CRLF) {
242         find_crlf(data, len, found);
243         return;
244     }
245
246     start = *data;
247     cr = lf = NULL;
248     want_cr = acceptable & SERF_NEWLINE_CR;
249     want_crlf = acceptable & SERF_NEWLINE_CRLF;
250     want_lf = acceptable & SERF_NEWLINE_LF;
251
252     if (want_cr || want_crlf) {
253         cr = memchr(start, '\r', *len);
254     }
255     if (want_lf) {
256         lf = memchr(start, '\n', *len);
257     }
258
259     if (cr != NULL) {
260         if (lf != NULL) {
261             if (cr + 1 == lf)
262                 *found = want_crlf ? SERF_NEWLINE_CRLF : SERF_NEWLINE_CR;
263             else if (want_cr && cr < lf)
264                 *found = SERF_NEWLINE_CR;
265             else
266                 *found = SERF_NEWLINE_LF;
267         }
268         else if (cr == start + *len - 1) {
269             /* the CR occurred in the last byte of the buffer. this could be
270              * a CRLF split across the data boundary.
271              * ### FIX THIS LOGIC? does caller need to detect?
272              */
273             *found = want_crlf ? SERF_NEWLINE_CRLF_SPLIT : SERF_NEWLINE_CR;
274         }
275         else if (want_cr)
276             *found = SERF_NEWLINE_CR;
277         else /* want_crlf */
278             *found = SERF_NEWLINE_NONE;
279     }
280     else if (lf != NULL)
281         *found = SERF_NEWLINE_LF;
282     else
283         *found = SERF_NEWLINE_NONE;
284
285     switch (*found) {
286       case SERF_NEWLINE_LF:
287         *data = lf + 1;
288         break;
289       case SERF_NEWLINE_CR:
290       case SERF_NEWLINE_CRLF:
291       case SERF_NEWLINE_CRLF_SPLIT:
292         *data = cr + 1 + (*found == SERF_NEWLINE_CRLF);
293         break;
294       case SERF_NEWLINE_NONE:
295         *data += *len;
296         break;
297       default:
298         /* Not reachable */
299         return;
300     }
301
302     *len -= *data - start;
303 }
304
305
306 /* ==================================================================== */
307
308
309 void serf_databuf_init(serf_databuf_t *databuf)
310 {
311     /* nothing is sitting in the buffer */
312     databuf->remaining = 0;
313
314     /* avoid thinking we have hit EOF */
315     databuf->status = APR_SUCCESS;
316 }
317
318 /* Ensure the buffer is prepared for reading. Will return APR_SUCCESS,
319  * APR_EOF, or some failure code. *len is only set for EOF. */
320 static apr_status_t common_databuf_prep(serf_databuf_t *databuf,
321                                         apr_size_t *len)
322 {
323     apr_size_t readlen;
324     apr_status_t status;
325
326     /* if there is data in the buffer, then we're happy. */
327     if (databuf->remaining > 0)
328         return APR_SUCCESS;
329
330     /* if we already hit EOF, then keep returning that. */
331     if (APR_STATUS_IS_EOF(databuf->status)) {
332         /* *data = NULL;   ?? */
333         *len = 0;
334         return APR_EOF;
335     }
336
337     /* refill the buffer */
338     status = (*databuf->read)(databuf->read_baton, sizeof(databuf->buf),
339                               databuf->buf, &readlen);
340     if (SERF_BUCKET_READ_ERROR(status)) {
341         return status;
342     }
343
344     databuf->current = databuf->buf;
345     databuf->remaining = readlen;
346     databuf->status = status;
347
348     return APR_SUCCESS;
349 }
350
351
352 apr_status_t serf_databuf_read(
353     serf_databuf_t *databuf,
354     apr_size_t requested,
355     const char **data,
356     apr_size_t *len)
357 {
358     apr_status_t status = common_databuf_prep(databuf, len);
359     if (status)
360         return status;
361
362     /* peg the requested amount to what we have remaining */
363     if (requested == SERF_READ_ALL_AVAIL || requested > databuf->remaining)
364         requested = databuf->remaining;
365
366     /* return the values */
367     *data = databuf->current;
368     *len = requested;
369
370     /* adjust our internal state to note we've consumed some data */
371     databuf->current += requested;
372     databuf->remaining -= requested;
373
374     /* If we read everything, then we need to return whatever the data
375      * read returned to us. This is going to be APR_EOF or APR_EGAIN.
376      * If we have NOT read everything, then return APR_SUCCESS to indicate
377      * that we're ready to return some more if asked.
378      */
379     return databuf->remaining ? APR_SUCCESS : databuf->status;
380 }
381
382
383 apr_status_t serf_databuf_readline(
384     serf_databuf_t *databuf,
385     int acceptable,
386     int *found,
387     const char **data,
388     apr_size_t *len)
389 {
390     apr_status_t status = common_databuf_prep(databuf, len);
391     if (status)
392         return status;
393
394     /* the returned line will start at the current position. */
395     *data = databuf->current;
396
397     /* read a line from the buffer, and adjust the various pointers. */
398     serf_util_readline(&databuf->current, &databuf->remaining, acceptable,
399                        found);
400
401     /* the length matches the amount consumed by the readline */
402     *len = databuf->current - *data;
403
404     /* see serf_databuf_read's return condition */
405     return databuf->remaining ? APR_SUCCESS : databuf->status;
406 }
407
408
409 apr_status_t serf_databuf_peek(
410     serf_databuf_t *databuf,
411     const char **data,
412     apr_size_t *len)
413 {
414     apr_status_t status = common_databuf_prep(databuf, len);
415     if (status)
416         return status;
417
418     /* return everything we have */
419     *data = databuf->current;
420     *len = databuf->remaining;
421
422     /* If the last read returned EOF, then the peek should return the same.
423      * The other possibility in databuf->status is APR_EAGAIN, which we
424      * should never return. Thus, just return APR_SUCCESS for non-EOF cases.
425      */
426     if (APR_STATUS_IS_EOF(databuf->status))
427         return APR_EOF;
428     return APR_SUCCESS;
429 }
430
431
432 /* ==================================================================== */
433
434
435 void serf_linebuf_init(serf_linebuf_t *linebuf)
436 {
437     linebuf->state = SERF_LINEBUF_EMPTY;
438     linebuf->used = 0;
439 }
440
441
442 apr_status_t serf_linebuf_fetch(
443     serf_linebuf_t *linebuf,
444     serf_bucket_t *bucket,
445     int acceptable)
446 {
447     /* If we had a complete line, then assume the caller has used it, so
448      * we can now reset the state.
449      */
450     if (linebuf->state == SERF_LINEBUF_READY) {
451         linebuf->state = SERF_LINEBUF_EMPTY;
452
453         /* Reset the line_used, too, so we don't have to test the state
454          * before using this value.
455          */
456         linebuf->used = 0;
457     }
458
459     while (1) {
460         apr_status_t status;
461         const char *data;
462         apr_size_t len;
463
464         if (linebuf->state == SERF_LINEBUF_CRLF_SPLIT) {
465             /* On the previous read, we received just a CR. The LF might
466              * be present, but the bucket couldn't see it. We need to
467              * examine a single character to determine how to handle the
468              * split CRLF.
469              */
470
471             status = serf_bucket_peek(bucket, &data, &len);
472             if (SERF_BUCKET_READ_ERROR(status))
473                 return status;
474
475             if (len > 0) {
476                 if (*data == '\n') {
477                     /* We saw the second part of CRLF. We don't need to
478                      * save that character, so do an actual read to suck
479                      * up that character.
480                      */
481                     /* ### check status */
482                     (void) serf_bucket_read(bucket, 1, &data, &len);
483                 }
484                 /* else:
485                  *   We saw the first character of the next line. Thus,
486                  *   the current line is terminated by the CR. Just
487                  *   ignore whatever we peeked at. The next reader will
488                  *   see it and handle it as appropriate.
489                  */
490
491                 /* Whatever was read, the line is now ready for use. */
492                 linebuf->state = SERF_LINEBUF_READY;
493             } else {
494                 /* no data available, try again later. */
495                 return APR_EAGAIN;
496             }
497         }
498         else {
499             int found;
500
501             status = serf_bucket_readline(bucket, acceptable, &found,
502                                           &data, &len);
503             if (SERF_BUCKET_READ_ERROR(status)) {
504                 return status;
505             }
506             /* Some bucket types (socket) might need an extra read to find
507                out EOF state, so they'll return no data in that read. This
508                means we're done reading, return what we got. */
509             if (APR_STATUS_IS_EOF(status) && len == 0) {
510                 return status;
511             }
512             if (linebuf->used + len > sizeof(linebuf->line)) {
513                 /* ### need a "line too long" error */
514                 return APR_EGENERAL;
515             }
516
517             /* Note: our logic doesn't change for SERF_LINEBUF_PARTIAL. That
518              * only affects how we fill the buffer. It is a communication to
519              * our caller on whether the line is ready or not.
520              */
521
522             /* If we didn't see a newline, then we should mark the line
523              * buffer as partially complete.
524              */
525             if (found == SERF_NEWLINE_NONE) {
526                 linebuf->state = SERF_LINEBUF_PARTIAL;
527             }
528             else if (found == SERF_NEWLINE_CRLF_SPLIT) {
529                 linebuf->state = SERF_LINEBUF_CRLF_SPLIT;
530
531                 /* Toss the partial CR. We won't ever need it. */
532                 --len;
533             }
534             else {
535                 /* We got a newline (of some form). We don't need it
536                  * in the line buffer, so back up the length. Then
537                  * mark the line as ready.
538                  */
539                 len -= 1 + (found == SERF_NEWLINE_CRLF);
540
541                 linebuf->state = SERF_LINEBUF_READY;
542             }
543
544             /* ### it would be nice to avoid this copy if at all possible,
545                ### and just return the a data/len pair to the caller. we're
546                ### keeping it simple for now. */
547             memcpy(&linebuf->line[linebuf->used], data, len);
548             linebuf->used += len;
549         }
550
551         /* If we saw anything besides "success. please read again", then
552          * we should return that status. If the line was completed, then
553          * we should also return.
554          */
555         if (status || linebuf->state == SERF_LINEBUF_READY)
556             return status;
557
558         /* We got APR_SUCCESS and the line buffer is not complete. Let's
559          * loop to read some more data.
560          */
561     }
562     /* NOTREACHED */
563 }
564
565 /* Logging functions.
566    Use with one of the [COMP]_VERBOSE defines so that the compiler knows to
567    optimize this code out when no logging is needed. */
568 static void log_time()
569 {
570     apr_time_exp_t tm;
571
572     apr_time_exp_lt(&tm, apr_time_now());
573     fprintf(stderr, "[%d-%02d-%02dT%02d:%02d:%02d.%06d%+03d] ",
574             1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday,
575             tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
576             tm.tm_gmtoff/3600);
577 }
578
579 void serf__log(int verbose_flag, const char *filename, const char *fmt, ...)
580 {
581     va_list argp;
582
583     if (verbose_flag) {
584         log_time();
585
586         if (filename)
587             fprintf(stderr, "%s: ", filename);
588
589         va_start(argp, fmt);
590         vfprintf(stderr, fmt, argp);
591         va_end(argp);
592     }
593 }
594
595 void serf__log_nopref(int verbose_flag, const char *fmt, ...)
596 {
597     va_list argp;
598
599     if (verbose_flag) {
600         va_start(argp, fmt);
601         vfprintf(stderr, fmt, argp);
602         va_end(argp);
603     }
604 }
605
606 void serf__log_skt(int verbose_flag, const char *filename, apr_socket_t *skt,
607                    const char *fmt, ...)
608 {
609     va_list argp;
610
611     if (verbose_flag) {
612         apr_sockaddr_t *sa;
613         log_time();
614
615         if (skt) {
616             /* Log local and remote ip address:port */
617             fprintf(stderr, "[l:");
618             if (apr_socket_addr_get(&sa, APR_LOCAL, skt) == APR_SUCCESS) {
619                 char buf[32];
620                 apr_sockaddr_ip_getbuf(buf, 32, sa);
621                 fprintf(stderr, "%s:%d", buf, sa->port);
622             }
623             fprintf(stderr, " r:");
624             if (apr_socket_addr_get(&sa, APR_REMOTE, skt) == APR_SUCCESS) {
625                 char buf[32];
626                 apr_sockaddr_ip_getbuf(buf, 32, sa);
627                 fprintf(stderr, "%s:%d", buf, sa->port);
628             }
629             fprintf(stderr, "] ");
630         }
631
632         if (filename)
633             fprintf(stderr, "%s: ", filename);
634
635         va_start(argp, fmt);
636         vfprintf(stderr, fmt, argp);
637         va_end(argp);
638     }
639 }
640