Mercurial > hg > nginx
comparison src/http/modules/ngx_http_range_filter.c @ 160:e7e094d34162
nginx-0.0.1-2003-10-27-11:53:49 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 27 Oct 2003 08:53:49 +0000 |
parents | 46eb23d9471d |
children | 84036764e215 |
comparison
equal
deleted
inserted
replaced
159:981e4af2a425 | 160:e7e094d34162 |
---|---|
1 | 1 |
2 #include <ngx_config.h> | 2 #include <ngx_config.h> |
3 #include <ngx_core.h> | 3 #include <ngx_core.h> |
4 #include <ngx_http.h> | 4 #include <ngx_http.h> |
5 | |
6 | |
7 /* | |
8 * the single part format: | |
9 * | |
10 * "HTTP/1.0 206 Partial Content" CRLF | |
11 * ... header ... | |
12 * "Content-Type: image/jpeg" CRLF | |
13 * "Content-Length: SIZE" CRLF | |
14 * "Content-Range: bytes START-END/SIZE" CRLF | |
15 * CRLF | |
16 * ... data ... | |
17 * | |
18 * | |
19 * the mutlipart format: | |
20 * | |
21 * "HTTP/1.0 206 Partial Content" CRLF | |
22 * ... header ... | |
23 * "Content-Type: multipart/byteranges; boundary=0123456789" CRLF | |
24 * CRLF | |
25 * CRLF | |
26 * "--0123456789" CRLF | |
27 * "Content-Type: image/jpeg" CRLF | |
28 * "Content-Range: bytes START0-END0/SIZE" CRLF | |
29 * CRLF | |
30 * ... data ... | |
31 * CRLF | |
32 * "--0123456789" CRLF | |
33 * "Content-Type: image/jpeg" CRLF | |
34 * "Content-Range: bytes START1-END1/SIZE" CRLF | |
35 * CRLF | |
36 * ... data ... | |
37 * CRLF | |
38 * "--0123456789--" CRLF | |
39 */ | |
5 | 40 |
6 | 41 |
7 typedef struct { | 42 typedef struct { |
8 ngx_str_t boundary_header; | 43 ngx_str_t boundary_header; |
9 } ngx_http_range_filter_ctx_t; | 44 } ngx_http_range_filter_ctx_t; |
44 char *p; | 79 char *p; |
45 off_t start, end; | 80 off_t start, end; |
46 ngx_http_range_t *range; | 81 ngx_http_range_t *range; |
47 ngx_http_range_filter_ctx_t *ctx; | 82 ngx_http_range_filter_ctx_t *ctx; |
48 | 83 |
49 if (r->main | 84 if (r->http_version < NGX_HTTP_VERSION_10 |
50 || r->http_version < NGX_HTTP_VERSION_10 | |
51 || r->headers_out.status != NGX_HTTP_OK | 85 || r->headers_out.status != NGX_HTTP_OK |
52 || r->headers_out.content_length_n == -1 | 86 || r->headers_out.content_length_n == -1 |
87 | |
53 /* STUB: we currently support ranges for file hunks only */ | 88 /* STUB: we currently support ranges for file hunks only */ |
89 || !r->sendfile | |
54 || r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) | 90 || r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) |
55 { | 91 { |
56 return ngx_http_next_header_filter(r); | 92 return ngx_http_next_header_filter(r); |
57 } | 93 } |
58 | 94 |
73 } | 109 } |
74 | 110 |
75 ngx_init_array(r->headers_out.ranges, r->pool, 5, sizeof(ngx_http_range_t), | 111 ngx_init_array(r->headers_out.ranges, r->pool, 5, sizeof(ngx_http_range_t), |
76 NGX_ERROR); | 112 NGX_ERROR); |
77 | 113 |
78 #if (NGX_SUPPRESS_WARN) | 114 rc = 0; |
79 range = NULL; | 115 range = NULL; |
80 #endif | |
81 | |
82 rc = 0; | |
83 p = r->headers_in.range->value.data + 6; | 116 p = r->headers_in.range->value.data + 6; |
84 | 117 |
85 for ( ;; ) { | 118 for ( ;; ) { |
86 start = end = 0; | 119 start = end = 0; |
87 | 120 |
154 | 187 |
155 break; | 188 break; |
156 } | 189 } |
157 | 190 |
158 if (rc) { | 191 if (rc) { |
192 | |
193 /* rc == NGX_HTTP_RANGE_NOT_SATISFIABLE */ | |
194 | |
159 r->headers_out.status = rc; | 195 r->headers_out.status = rc; |
160 r->headers_out.ranges.nelts = 0; | 196 r->headers_out.ranges.nelts = 0; |
161 | 197 |
162 ngx_test_null(r->headers_out.content_range, | 198 ngx_test_null(r->headers_out.content_range, |
163 ngx_push_table(r->headers_out.headers), | 199 ngx_push_table(r->headers_out.headers), |
186 NGX_ERROR); | 222 NGX_ERROR); |
187 | 223 |
188 ngx_test_null(r->headers_out.content_range->value.data, | 224 ngx_test_null(r->headers_out.content_range->value.data, |
189 ngx_palloc(r->pool, 6 + 20 + 1 + 20 + 1 + 20 + 1), | 225 ngx_palloc(r->pool, 6 + 20 + 1 + 20 + 1 + 20 + 1), |
190 NGX_ERROR); | 226 NGX_ERROR); |
227 | |
228 /* "Content-Range: bytes SSSS-EEEE/TTTT" header */ | |
191 | 229 |
192 r->headers_out.content_range->value.len = | 230 r->headers_out.content_range->value.len = |
193 ngx_snprintf(r->headers_out.content_range->value.data, | 231 ngx_snprintf(r->headers_out.content_range->value.data, |
194 6 + 20 + 1 + 20 + 1 + 20 + 1, | 232 6 + 20 + 1 + 20 + 1 + 20 + 1, |
195 "bytes " OFF_FMT "-" OFF_FMT "/" OFF_FMT, | 233 "bytes " OFF_FMT "-" OFF_FMT "/" OFF_FMT, |
219 | 257 |
220 ngx_test_null(ctx->boundary_header.data, ngx_palloc(r->pool, len), | 258 ngx_test_null(ctx->boundary_header.data, ngx_palloc(r->pool, len), |
221 NGX_ERROR); | 259 NGX_ERROR); |
222 | 260 |
223 boundary = ngx_next_temp_number(0); | 261 boundary = ngx_next_temp_number(0); |
262 | |
263 /* | |
264 * The boundary header of the range: | |
265 * CRLF | |
266 * "--0123456789" CRLF | |
267 * "Content-Type: image/jpeg" CRLF | |
268 * "Content-Range: bytes " | |
269 */ | |
224 | 270 |
225 if (r->headers_out.charset.len) { | 271 if (r->headers_out.charset.len) { |
226 ctx->boundary_header.len = | 272 ctx->boundary_header.len = |
227 ngx_snprintf(ctx->boundary_header.data, len, | 273 ngx_snprintf(ctx->boundary_header.data, len, |
228 CRLF "--%010u" CRLF | 274 CRLF "--%010u" CRLF |
246 | 292 |
247 ngx_test_null(r->headers_out.content_type->value.data, | 293 ngx_test_null(r->headers_out.content_type->value.data, |
248 ngx_palloc(r->pool, 31 + 10 + 1), | 294 ngx_palloc(r->pool, 31 + 10 + 1), |
249 NGX_ERROR); | 295 NGX_ERROR); |
250 | 296 |
297 /* "Content-Type: multipart/byteranges; boundary=0123456789" */ | |
298 | |
251 r->headers_out.content_type->value.len = | 299 r->headers_out.content_type->value.len = |
252 ngx_snprintf(r->headers_out.content_type->value.data, | 300 ngx_snprintf(r->headers_out.content_type->value.data, |
253 31 + 10 + 1, | 301 31 + 10 + 1, |
254 "multipart/byteranges; boundary=%010u", | 302 "multipart/byteranges; boundary=%010u", |
255 boundary); | 303 boundary); |
256 | 304 |
257 /* the last "CRLF--BOUNDARY--CRLF" */ | 305 /* the size of the last boundary CRLF "--0123456789--" CRLF */ |
258 len = 4 + 10 + 4; | 306 len = 4 + 10 + 4; |
259 | 307 |
260 range = r->headers_out.ranges.elts; | 308 range = r->headers_out.ranges.elts; |
261 for (i = 0; i < r->headers_out.ranges.nelts; i++) { | 309 for (i = 0; i < r->headers_out.ranges.nelts; i++) { |
262 ngx_test_null(range[i].content_range.data, | 310 ngx_test_null(range[i].content_range.data, |
263 ngx_palloc(r->pool, 20 + 1 + 20 + 1 + 20 + 5), | 311 ngx_palloc(r->pool, 20 + 1 + 20 + 1 + 20 + 5), |
264 NGX_ERROR); | 312 NGX_ERROR); |
265 | 313 |
266 range[i].content_range.len = | 314 /* the size of the range: "SSSS-EEEE/TTTT" CRLF CRLF */ |
315 | |
316 range[i].content_range.len = | |
267 ngx_snprintf(range[i].content_range.data, | 317 ngx_snprintf(range[i].content_range.data, |
268 20 + 1 + 20 + 1 + 20 + 5, | 318 20 + 1 + 20 + 1 + 20 + 5, |
269 OFF_FMT "-" OFF_FMT "/" OFF_FMT CRLF CRLF, | 319 OFF_FMT "-" OFF_FMT "/" OFF_FMT CRLF CRLF, |
270 range[i].start, range[i].end - 1, | 320 range[i].start, range[i].end - 1, |
271 r->headers_out.content_length_n); | 321 r->headers_out.content_length_n); |
272 | 322 |
273 len += ctx->boundary_header.len + range[i].content_range.len | 323 len += ctx->boundary_header.len + range[i].content_range.len |
274 + (size_t) (range[i].end - range[i].start); | 324 + (size_t) (range[i].end - range[i].start); |
275 } | 325 } |
276 | 326 |
277 r->headers_out.content_length_n = len; | 327 r->headers_out.content_length_n = len; |
278 r->headers_out.content_length = NULL; | 328 r->headers_out.content_length = NULL; |
279 } | 329 } |
302 | 352 |
303 if (in | 353 if (in |
304 && in->hunk->type & NGX_HUNK_FILE | 354 && in->hunk->type & NGX_HUNK_FILE |
305 && in->hunk->type & NGX_HUNK_LAST) | 355 && in->hunk->type & NGX_HUNK_LAST) |
306 { | 356 { |
357 range = r->headers_out.ranges.elts; | |
358 | |
307 if (r->headers_out.ranges.nelts == 1) { | 359 if (r->headers_out.ranges.nelts == 1) { |
308 range = r->headers_out.ranges.elts; | |
309 in->hunk->file_pos = range->start; | 360 in->hunk->file_pos = range->start; |
310 in->hunk->file_last = range->end; | 361 in->hunk->file_last = range->end; |
311 | 362 |
312 return ngx_http_next_body_filter(r, in); | 363 return ngx_http_next_body_filter(r, in); |
313 } | 364 } |
314 | 365 |
315 ctx = ngx_http_get_module_ctx(r, ngx_http_range_filter_module); | 366 ctx = ngx_http_get_module_ctx(r, ngx_http_range_filter_module); |
316 ll = &out; | 367 ll = &out; |
317 | 368 |
318 range = r->headers_out.ranges.elts; | |
319 for (i = 0; i < r->headers_out.ranges.nelts; i++) { | 369 for (i = 0; i < r->headers_out.ranges.nelts; i++) { |
370 | |
371 /* | |
372 * The boundary header of the range: | |
373 * CRLF | |
374 * "--0123456789" CRLF | |
375 * "Content-Type: image/jpeg" CRLF | |
376 * "Content-Range: bytes " | |
377 */ | |
320 | 378 |
321 ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); | 379 ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); |
322 h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY; | 380 h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY; |
323 h->pos = ctx->boundary_header.data; | 381 h->pos = ctx->boundary_header.data; |
324 h->last = ctx->boundary_header.data + ctx->boundary_header.len; | 382 h->last = ctx->boundary_header.data + ctx->boundary_header.len; |
325 | 383 |
326 ngx_test_null(hcl, ngx_alloc_chain_link(r->pool), NGX_ERROR); | 384 ngx_test_null(hcl, ngx_alloc_chain_link(r->pool), NGX_ERROR); |
327 hcl->hunk = h; | 385 hcl->hunk = h; |
328 | 386 |
387 /* "SSSS-EEEE/TTTT" CRLF CRLF */ | |
388 | |
329 ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); | 389 ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); |
330 h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP; | 390 h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP; |
331 h->pos = range[i].content_range.data; | 391 h->pos = range[i].content_range.data; |
332 h->last = range[i].content_range.data + range[i].content_range.len; | 392 h->last = range[i].content_range.data + range[i].content_range.len; |
333 | 393 |
334 ngx_test_null(rcl, ngx_alloc_chain_link(r->pool), NGX_ERROR); | 394 ngx_test_null(rcl, ngx_alloc_chain_link(r->pool), NGX_ERROR); |
335 rcl->hunk = h; | 395 rcl->hunk = h; |
396 | |
397 /* the range data */ | |
336 | 398 |
337 ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); | 399 ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); |
338 h->type = NGX_HUNK_FILE; | 400 h->type = NGX_HUNK_FILE; |
339 h->file_pos = range[i].start; | 401 h->file_pos = range[i].start; |
340 h->file_last = range[i].end; | 402 h->file_last = range[i].end; |
345 *ll = hcl; | 407 *ll = hcl; |
346 hcl->next = rcl; | 408 hcl->next = rcl; |
347 rcl->next = dcl; | 409 rcl->next = dcl; |
348 ll = &dcl->next; | 410 ll = &dcl->next; |
349 } | 411 } |
412 | |
413 /* the last boundary CRLF "--0123456789--" CRLF */ | |
350 | 414 |
351 ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); | 415 ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); |
352 h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP|NGX_HUNK_LAST; | 416 h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP|NGX_HUNK_LAST; |
353 ngx_test_null(h->pos, ngx_palloc(r->pool, 4 + 10 + 4), NGX_ERROR); | 417 ngx_test_null(h->pos, ngx_palloc(r->pool, 4 + 10 + 4), NGX_ERROR); |
354 h->last = ngx_cpymem(h->pos, ctx->boundary_header.data, 4 + 10); | 418 h->last = ngx_cpymem(h->pos, ctx->boundary_header.data, 4 + 10); |