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