Annotation of embedaddon/nginx/src/http/modules/ngx_http_chunked_filter_module.c, revision 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>