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);