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
22serf_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
37apr_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
74apr_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
100serf_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
108void 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
118void 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
128char *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
139void *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
149char *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
158char *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
188static 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
225void 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
309void 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. */
320static 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
352apr_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
383apr_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
409apr_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
435void serf_linebuf_init(serf_linebuf_t *linebuf)
436{
437    linebuf->state = SERF_LINEBUF_EMPTY;
438    linebuf->used = 0;
439}
440
441
442apr_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. */
568static 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
579void 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
595void 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
606void 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
641