]>
Commit | Line | Data |
---|---|---|
d9b890b8 AG |
1 | --- modules/http/http_protocol.c (revision 226972) |
2 | +++ modules/http/http_protocol.c (working copy) | |
3 | @@ -2856,18 +2856,35 @@ | |
4 | #define MIN_LENGTH(len1, len2) ((len1 > len2) ? len2 : len1) | |
5 | request_rec *r = f->r; | |
6 | conn_rec *c = r->connection; | |
7 | - byterange_ctx *ctx = f->ctx; | |
8 | + byterange_ctx *ctx; | |
9 | apr_bucket *e; | |
10 | apr_bucket_brigade *bsend; | |
11 | apr_off_t range_start; | |
12 | apr_off_t range_end; | |
13 | char *current; | |
14 | - apr_off_t bb_length; | |
15 | apr_off_t clength = 0; | |
16 | apr_status_t rv; | |
17 | int found = 0; | |
18 | ||
19 | - if (!ctx) { | |
20 | + /* Iterate through the brigade until reaching EOS or a bucket with | |
21 | + * unknown length. */ | |
22 | + for (e = APR_BRIGADE_FIRST(bb); | |
23 | + (e != APR_BRIGADE_SENTINEL(bb) && !APR_BUCKET_IS_EOS(e) | |
24 | + && e->length != (apr_size_t)-1); | |
25 | + e = APR_BUCKET_NEXT(e)) { | |
26 | + clength += e->length; | |
27 | + } | |
28 | + | |
29 | + /* Don't attempt to do byte range work if this brigade doesn't | |
30 | + * contain an EOS, or if any of the buckets has an unknown length; | |
31 | + * this avoids the cases where it is expensive to perform | |
32 | + * byteranging (i.e. may require arbitrary amounts of memory). */ | |
33 | + if (!APR_BUCKET_IS_EOS(e) || clength <= 0) { | |
34 | + ap_remove_output_filter(f); | |
35 | + return ap_pass_brigade(f->next, bb); | |
36 | + } | |
37 | + | |
38 | + { | |
39 | int num_ranges = ap_set_byterange(r); | |
40 | ||
41 | /* We have nothing to do, get out of the way. */ | |
42 | @@ -2876,7 +2893,7 @@ | |
43 | return ap_pass_brigade(f->next, bb); | |
44 | } | |
45 | ||
46 | - ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx)); | |
47 | + ctx = apr_pcalloc(r->pool, sizeof(*ctx)); | |
48 | ctx->num_ranges = num_ranges; | |
49 | /* create a brigade in case we never call ap_save_brigade() */ | |
50 | ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc); | |
51 | @@ -2903,29 +2920,6 @@ | |
52 | } | |
53 | } | |
54 | ||
55 | - /* We can't actually deal with byte-ranges until we have the whole brigade | |
56 | - * because the byte-ranges can be in any order, and according to the RFC, | |
57 | - * we SHOULD return the data in the same order it was requested. | |
58 | - * | |
59 | - * XXX: We really need to dump all bytes prior to the start of the earliest | |
60 | - * range, and only slurp up to the end of the latest range. By this we | |
61 | - * mean that we should peek-ahead at the lowest first byte of any range, | |
62 | - * and the highest last byte of any range. | |
63 | - */ | |
64 | - if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) { | |
65 | - ap_save_brigade(f, &ctx->bb, &bb, r->pool); | |
66 | - return APR_SUCCESS; | |
67 | - } | |
68 | - | |
69 | - /* Prepend any earlier saved brigades. */ | |
70 | - APR_BRIGADE_PREPEND(bb, ctx->bb); | |
71 | - | |
72 | - /* It is possible that we won't have a content length yet, so we have to | |
73 | - * compute the length before we can actually do the byterange work. | |
74 | - */ | |
75 | - apr_brigade_length(bb, 1, &bb_length); | |
76 | - clength = (apr_off_t)bb_length; | |
77 | - | |
78 | /* this brigade holds what we will be sending */ | |
79 | bsend = apr_brigade_create(r->pool, c->bucket_alloc); | |
80 | ||
81 |