xref: /trueos/contrib/serf/buckets/buckets.c (revision 9394ef331eb7d0ba7f22583970cc84b62ad9f19a)
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 
serf_bucket_create(const serf_bucket_type_t * type,serf_bucket_alloc_t * allocator,void * data)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 
serf_default_read_iovec(serf_bucket_t * bucket,apr_size_t requested,int vecs_size,struct iovec * vecs,int * vecs_used)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 
serf_default_read_for_sendfile(serf_bucket_t * bucket,apr_size_t requested,apr_hdtr_t * hdtr,apr_file_t ** file,apr_off_t * offset,apr_size_t * len)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 
serf_default_read_bucket(serf_bucket_t * bucket,const serf_bucket_type_t * type)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 
serf_default_destroy(serf_bucket_t * bucket)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 
serf_default_destroy_and_data(serf_bucket_t * bucket)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 
serf_bstrmemdup(serf_bucket_alloc_t * allocator,const char * str,apr_size_t size)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 
serf_bmemdup(serf_bucket_alloc_t * allocator,const void * mem,apr_size_t size)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 
serf_bstrdup(serf_bucket_alloc_t * allocator,const char * str)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 
serf_bstrcatv(serf_bucket_alloc_t * allocator,struct iovec * vec,int vecs,apr_size_t * bytes_written)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 
find_crlf(const char ** data,apr_size_t * len,int * found)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 
serf_util_readline(const char ** data,apr_size_t * len,int acceptable,int * found)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 
serf_databuf_init(serf_databuf_t * databuf)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. */
common_databuf_prep(serf_databuf_t * databuf,apr_size_t * len)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 
serf_databuf_read(serf_databuf_t * databuf,apr_size_t requested,const char ** data,apr_size_t * len)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 
serf_databuf_readline(serf_databuf_t * databuf,int acceptable,int * found,const char ** data,apr_size_t * len)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 
serf_databuf_peek(serf_databuf_t * databuf,const char ** data,apr_size_t * len)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 
serf_linebuf_init(serf_linebuf_t * linebuf)435 void serf_linebuf_init(serf_linebuf_t *linebuf)
436 {
437     linebuf->state = SERF_LINEBUF_EMPTY;
438     linebuf->used = 0;
439 }
440 
441 
serf_linebuf_fetch(serf_linebuf_t * linebuf,serf_bucket_t * bucket,int acceptable)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. */
log_time()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 
serf__log(int verbose_flag,const char * filename,const char * fmt,...)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 
serf__log_nopref(int verbose_flag,const char * fmt,...)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 
serf__log_skt(int verbose_flag,const char * filename,apr_socket_t * skt,const char * fmt,...)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 
641