Annotation of embedaddon/nginx/src/http/modules/ngx_http_chunked_filter_module.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: #include <ngx_http.h>
                     11: 
                     12: 
                     13: typedef struct {
                     14:     ngx_chain_t         *free;
                     15:     ngx_chain_t         *busy;
                     16: } ngx_http_chunked_filter_ctx_t;
                     17: 
                     18: 
                     19: static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf);
                     20: 
                     21: 
                     22: static ngx_http_module_t  ngx_http_chunked_filter_module_ctx = {
                     23:     NULL,                                  /* preconfiguration */
                     24:     ngx_http_chunked_filter_init,          /* postconfiguration */
                     25: 
                     26:     NULL,                                  /* create main configuration */
                     27:     NULL,                                  /* init main configuration */
                     28: 
                     29:     NULL,                                  /* create server configuration */
                     30:     NULL,                                  /* merge server configuration */
                     31: 
                     32:     NULL,                                  /* create location configuration */
                     33:     NULL                                   /* merge location configuration */
                     34: };
                     35: 
                     36: 
                     37: ngx_module_t  ngx_http_chunked_filter_module = {
                     38:     NGX_MODULE_V1,
                     39:     &ngx_http_chunked_filter_module_ctx,   /* module context */
                     40:     NULL,                                  /* module directives */
                     41:     NGX_HTTP_MODULE,                       /* module type */
                     42:     NULL,                                  /* init master */
                     43:     NULL,                                  /* init module */
                     44:     NULL,                                  /* init process */
                     45:     NULL,                                  /* init thread */
                     46:     NULL,                                  /* exit thread */
                     47:     NULL,                                  /* exit process */
                     48:     NULL,                                  /* exit master */
                     49:     NGX_MODULE_V1_PADDING
                     50: };
                     51: 
                     52: 
                     53: static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
                     54: static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
                     55: 
                     56: 
                     57: static ngx_int_t
                     58: ngx_http_chunked_header_filter(ngx_http_request_t *r)
                     59: {
                     60:     ngx_http_core_loc_conf_t       *clcf;
                     61:     ngx_http_chunked_filter_ctx_t  *ctx;
                     62: 
                     63:     if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED
                     64:         || r->headers_out.status == NGX_HTTP_NO_CONTENT
                     65:         || r->headers_out.status < NGX_HTTP_OK
                     66:         || r != r->main
                     67:         || (r->method & NGX_HTTP_HEAD))
                     68:     {
                     69:         return ngx_http_next_header_filter(r);
                     70:     }
                     71: 
                     72:     if (r->headers_out.content_length_n == -1) {
                     73:         if (r->http_version < NGX_HTTP_VERSION_11) {
                     74:             r->keepalive = 0;
                     75: 
                     76:         } else {
                     77:             clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                     78: 
                     79:             if (clcf->chunked_transfer_encoding) {
                     80:                 r->chunked = 1;
                     81: 
                     82:                 ctx = ngx_pcalloc(r->pool,
                     83:                                   sizeof(ngx_http_chunked_filter_ctx_t));
                     84:                 if (ctx == NULL) {
                     85:                     return NGX_ERROR;
                     86:                 }
                     87: 
                     88:                 ngx_http_set_ctx(r, ctx, ngx_http_chunked_filter_module);
                     89: 
                     90:             } else {
                     91:                 r->keepalive = 0;
                     92:             }
                     93:         }
                     94:     }
                     95: 
                     96:     return ngx_http_next_header_filter(r);
                     97: }
                     98: 
                     99: 
                    100: static ngx_int_t
                    101: ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
                    102: {
                    103:     u_char                         *chunk;
                    104:     off_t                           size;
                    105:     ngx_int_t                       rc;
                    106:     ngx_buf_t                      *b;
                    107:     ngx_chain_t                    *out, *cl, *tl, **ll;
                    108:     ngx_http_chunked_filter_ctx_t  *ctx;
                    109: 
                    110:     if (in == NULL || !r->chunked || r->header_only) {
                    111:         return ngx_http_next_body_filter(r, in);
                    112:     }
                    113: 
                    114:     ctx = ngx_http_get_module_ctx(r, ngx_http_chunked_filter_module);
                    115: 
                    116:     out = NULL;
                    117:     ll = &out;
                    118: 
                    119:     size = 0;
                    120:     cl = in;
                    121: 
                    122:     for ( ;; ) {
                    123:         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    124:                        "http chunk: %d", ngx_buf_size(cl->buf));
                    125: 
                    126:         size += ngx_buf_size(cl->buf);
                    127: 
                    128:         if (cl->buf->flush
                    129:             || cl->buf->sync
                    130:             || ngx_buf_in_memory(cl->buf)
                    131:             || cl->buf->in_file)
                    132:         {
                    133:             tl = ngx_alloc_chain_link(r->pool);
                    134:             if (tl == NULL) {
                    135:                 return NGX_ERROR;
                    136:             }
                    137: 
                    138:             tl->buf = cl->buf;
                    139:             *ll = tl;
                    140:             ll = &tl->next;
                    141:         }
                    142: 
                    143:         if (cl->next == NULL) {
                    144:             break;
                    145:         }
                    146: 
                    147:         cl = cl->next;
                    148:     }
                    149: 
                    150:     if (size) {
                    151:         tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
                    152:         if (tl == NULL) {
                    153:             return NGX_ERROR;
                    154:         }
                    155: 
                    156:         b = tl->buf;
                    157:         chunk = b->start;
                    158: 
                    159:         if (chunk == NULL) {
                    160:             /* the "0000000000000000" is 64-bit hexadecimal string */
                    161: 
                    162:             chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1);
                    163:             if (chunk == NULL) {
                    164:                 return NGX_ERROR;
                    165:             }
                    166: 
                    167:             b->start = chunk;
                    168:             b->end = chunk + sizeof("0000000000000000" CRLF) - 1;
                    169:         }
                    170: 
                    171:         b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
                    172:         b->memory = 0;
                    173:         b->temporary = 1;
                    174:         b->pos = chunk;
                    175:         b->last = ngx_sprintf(chunk, "%xO" CRLF, size);
                    176: 
                    177:         tl->next = out;
                    178:         out = tl;
                    179:     }
                    180: 
                    181:     if (cl->buf->last_buf) {
                    182:         tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
                    183:         if (tl == NULL) {
                    184:             return NGX_ERROR;
                    185:         }
                    186: 
                    187:         b = tl->buf;
                    188: 
                    189:         b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
                    190:         b->temporary = 0;
                    191:         b->memory = 1;
                    192:         b->last_buf = 1;
                    193:         b->pos = (u_char *) CRLF "0" CRLF CRLF;
                    194:         b->last = b->pos + 7;
                    195: 
                    196:         cl->buf->last_buf = 0;
                    197: 
                    198:         *ll = tl;
                    199: 
                    200:         if (size == 0) {
                    201:             b->pos += 2;
                    202:         }
                    203: 
                    204:     } else if (size > 0) {
                    205:         tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
                    206:         if (tl == NULL) {
                    207:             return NGX_ERROR;
                    208:         }
                    209: 
                    210:         b = tl->buf;
                    211: 
                    212:         b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
                    213:         b->temporary = 0;
                    214:         b->memory = 1;
                    215:         b->pos = (u_char *) CRLF;
                    216:         b->last = b->pos + 2;
                    217: 
                    218:         *ll = tl;
                    219: 
                    220:     } else {
                    221:         *ll = NULL;
                    222:     }
                    223: 
                    224:     rc = ngx_http_next_body_filter(r, out);
                    225: 
                    226:     ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &out,
                    227:                             (ngx_buf_tag_t) &ngx_http_chunked_filter_module);
                    228: 
                    229:     return rc;
                    230: }
                    231: 
                    232: 
                    233: static ngx_int_t
                    234: ngx_http_chunked_filter_init(ngx_conf_t *cf)
                    235: {
                    236:     ngx_http_next_header_filter = ngx_http_top_header_filter;
                    237:     ngx_http_top_header_filter = ngx_http_chunked_header_filter;
                    238: 
                    239:     ngx_http_next_body_filter = ngx_http_top_body_filter;
                    240:     ngx_http_top_body_filter = ngx_http_chunked_body_filter;
                    241: 
                    242:     return NGX_OK;
                    243: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>