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

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Maxim Dounin
                      5:  * Copyright (C) Nginx, Inc.
                      6:  */
                      7: 
                      8: 
                      9: #include <ngx_config.h>
                     10: #include <ngx_core.h>
                     11: #include <ngx_http.h>
                     12: 
                     13: #include <zlib.h>
                     14: 
                     15: 
                     16: typedef struct {
                     17:     ngx_flag_t           enable;
                     18:     ngx_bufs_t           bufs;
                     19: } ngx_http_gunzip_conf_t;
                     20: 
                     21: 
                     22: typedef struct {
                     23:     ngx_chain_t         *in;
                     24:     ngx_chain_t         *free;
                     25:     ngx_chain_t         *busy;
                     26:     ngx_chain_t         *out;
                     27:     ngx_chain_t        **last_out;
                     28: 
                     29:     ngx_buf_t           *in_buf;
                     30:     ngx_buf_t           *out_buf;
                     31:     ngx_int_t            bufs;
                     32: 
                     33:     unsigned             started:1;
                     34:     unsigned             flush:4;
                     35:     unsigned             redo:1;
                     36:     unsigned             done:1;
                     37:     unsigned             nomem:1;
                     38: 
                     39:     z_stream             zstream;
                     40:     ngx_http_request_t  *request;
                     41: } ngx_http_gunzip_ctx_t;
                     42: 
                     43: 
                     44: static ngx_int_t ngx_http_gunzip_filter_inflate_start(ngx_http_request_t *r,
                     45:     ngx_http_gunzip_ctx_t *ctx);
                     46: static ngx_int_t ngx_http_gunzip_filter_add_data(ngx_http_request_t *r,
                     47:     ngx_http_gunzip_ctx_t *ctx);
                     48: static ngx_int_t ngx_http_gunzip_filter_get_buf(ngx_http_request_t *r,
                     49:     ngx_http_gunzip_ctx_t *ctx);
                     50: static ngx_int_t ngx_http_gunzip_filter_inflate(ngx_http_request_t *r,
                     51:     ngx_http_gunzip_ctx_t *ctx);
                     52: static ngx_int_t ngx_http_gunzip_filter_inflate_end(ngx_http_request_t *r,
                     53:     ngx_http_gunzip_ctx_t *ctx);
                     54: 
                     55: static void *ngx_http_gunzip_filter_alloc(void *opaque, u_int items,
                     56:     u_int size);
                     57: static void ngx_http_gunzip_filter_free(void *opaque, void *address);
                     58: 
                     59: static ngx_int_t ngx_http_gunzip_filter_init(ngx_conf_t *cf);
                     60: static void *ngx_http_gunzip_create_conf(ngx_conf_t *cf);
                     61: static char *ngx_http_gunzip_merge_conf(ngx_conf_t *cf,
                     62:     void *parent, void *child);
                     63: 
                     64: 
                     65: static ngx_command_t  ngx_http_gunzip_filter_commands[] = {
                     66: 
                     67:     { ngx_string("gunzip"),
                     68:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
                     69:       ngx_conf_set_flag_slot,
                     70:       NGX_HTTP_LOC_CONF_OFFSET,
                     71:       offsetof(ngx_http_gunzip_conf_t, enable),
                     72:       NULL },
                     73: 
                     74:     { ngx_string("gunzip_buffers"),
                     75:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
                     76:       ngx_conf_set_bufs_slot,
                     77:       NGX_HTTP_LOC_CONF_OFFSET,
                     78:       offsetof(ngx_http_gunzip_conf_t, bufs),
                     79:       NULL },
                     80: 
                     81:       ngx_null_command
                     82: };
                     83: 
                     84: 
                     85: static ngx_http_module_t  ngx_http_gunzip_filter_module_ctx = {
                     86:     NULL,                                  /* preconfiguration */
                     87:     ngx_http_gunzip_filter_init,           /* postconfiguration */
                     88: 
                     89:     NULL,                                  /* create main configuration */
                     90:     NULL,                                  /* init main configuration */
                     91: 
                     92:     NULL,                                  /* create server configuration */
                     93:     NULL,                                  /* merge server configuration */
                     94: 
                     95:     ngx_http_gunzip_create_conf,           /* create location configuration */
                     96:     ngx_http_gunzip_merge_conf             /* merge location configuration */
                     97: };
                     98: 
                     99: 
                    100: ngx_module_t  ngx_http_gunzip_filter_module = {
                    101:     NGX_MODULE_V1,
                    102:     &ngx_http_gunzip_filter_module_ctx,    /* module context */
                    103:     ngx_http_gunzip_filter_commands,       /* module directives */
                    104:     NGX_HTTP_MODULE,                       /* module type */
                    105:     NULL,                                  /* init master */
                    106:     NULL,                                  /* init module */
                    107:     NULL,                                  /* init process */
                    108:     NULL,                                  /* init thread */
                    109:     NULL,                                  /* exit thread */
                    110:     NULL,                                  /* exit process */
                    111:     NULL,                                  /* exit master */
                    112:     NGX_MODULE_V1_PADDING
                    113: };
                    114: 
                    115: 
                    116: static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
                    117: static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
                    118: 
                    119: 
                    120: static ngx_int_t
                    121: ngx_http_gunzip_header_filter(ngx_http_request_t *r)
                    122: {
                    123:     ngx_http_gunzip_ctx_t   *ctx;
                    124:     ngx_http_gunzip_conf_t  *conf;
                    125: 
                    126:     conf = ngx_http_get_module_loc_conf(r, ngx_http_gunzip_filter_module);
                    127: 
                    128:     /* TODO support multiple content-codings */
                    129:     /* TODO always gunzip - due to configuration or module request */
                    130:     /* TODO ignore content encoding? */
                    131: 
                    132:     if (!conf->enable
                    133:         || r->headers_out.content_encoding == NULL
                    134:         || r->headers_out.content_encoding->value.len != 4
                    135:         || ngx_strncasecmp(r->headers_out.content_encoding->value.data,
                    136:                            (u_char *) "gzip", 4) != 0)
                    137:     {
                    138:         return ngx_http_next_header_filter(r);
                    139:     }
                    140: 
                    141:     r->gzip_vary = 1;
                    142: 
                    143:     if (!r->gzip_tested) {
                    144:         if (ngx_http_gzip_ok(r) == NGX_OK) {
                    145:             return ngx_http_next_header_filter(r);
                    146:         }
                    147: 
                    148:     } else if (r->gzip_ok) {
                    149:         return ngx_http_next_header_filter(r);
                    150:     }
                    151: 
                    152:     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gunzip_ctx_t));
                    153:     if (ctx == NULL) {
                    154:         return NGX_ERROR;
                    155:     }
                    156: 
                    157:     ngx_http_set_ctx(r, ctx, ngx_http_gunzip_filter_module);
                    158: 
                    159:     ctx->request = r;
                    160: 
                    161:     r->filter_need_in_memory = 1;
                    162: 
                    163:     r->headers_out.content_encoding->hash = 0;
                    164:     r->headers_out.content_encoding = NULL;
                    165: 
                    166:     ngx_http_clear_content_length(r);
                    167:     ngx_http_clear_accept_ranges(r);
                    168:     ngx_http_clear_etag(r);
                    169: 
                    170:     return ngx_http_next_header_filter(r);
                    171: }
                    172: 
                    173: 
                    174: static ngx_int_t
                    175: ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
                    176: {
                    177:     int                     rc;
                    178:     ngx_chain_t            *cl;
                    179:     ngx_http_gunzip_ctx_t  *ctx;
                    180: 
                    181:     ctx = ngx_http_get_module_ctx(r, ngx_http_gunzip_filter_module);
                    182: 
                    183:     if (ctx == NULL || ctx->done) {
                    184:         return ngx_http_next_body_filter(r, in);
                    185:     }
                    186: 
                    187:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    188:                    "http gunzip filter");
                    189: 
                    190:     if (!ctx->started) {
                    191:         if (ngx_http_gunzip_filter_inflate_start(r, ctx) != NGX_OK) {
                    192:             goto failed;
                    193:         }
                    194:     }
                    195: 
                    196:     if (in) {
                    197:         if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
                    198:             goto failed;
                    199:         }
                    200:     }
                    201: 
                    202:     if (ctx->nomem) {
                    203: 
                    204:         /* flush busy buffers */
                    205: 
                    206:         if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) {
                    207:             goto failed;
                    208:         }
                    209: 
                    210:         cl = NULL;
                    211: 
                    212:         ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
                    213:                                 (ngx_buf_tag_t) &ngx_http_gunzip_filter_module);
                    214:         ctx->nomem = 0;
                    215:     }
                    216: 
                    217:     for ( ;; ) {
                    218: 
                    219:         /* cycle while we can write to a client */
                    220: 
                    221:         for ( ;; ) {
                    222: 
                    223:             /* cycle while there is data to feed zlib and ... */
                    224: 
                    225:             rc = ngx_http_gunzip_filter_add_data(r, ctx);
                    226: 
                    227:             if (rc == NGX_DECLINED) {
                    228:                 break;
                    229:             }
                    230: 
                    231:             if (rc == NGX_AGAIN) {
                    232:                 continue;
                    233:             }
                    234: 
                    235: 
                    236:             /* ... there are buffers to write zlib output */
                    237: 
                    238:             rc = ngx_http_gunzip_filter_get_buf(r, ctx);
                    239: 
                    240:             if (rc == NGX_DECLINED) {
                    241:                 break;
                    242:             }
                    243: 
                    244:             if (rc == NGX_ERROR) {
                    245:                 goto failed;
                    246:             }
                    247: 
                    248:             rc = ngx_http_gunzip_filter_inflate(r, ctx);
                    249: 
                    250:             if (rc == NGX_OK) {
                    251:                 break;
                    252:             }
                    253: 
                    254:             if (rc == NGX_ERROR) {
                    255:                 goto failed;
                    256:             }
                    257: 
                    258:             /* rc == NGX_AGAIN */
                    259:         }
                    260: 
                    261:         if (ctx->out == NULL) {
                    262:             return ctx->busy ? NGX_AGAIN : NGX_OK;
                    263:         }
                    264: 
                    265:         rc = ngx_http_next_body_filter(r, ctx->out);
                    266: 
                    267:         if (rc == NGX_ERROR) {
                    268:             goto failed;
                    269:         }
                    270: 
                    271:         ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &ctx->out,
                    272:                                 (ngx_buf_tag_t) &ngx_http_gunzip_filter_module);
                    273:         ctx->last_out = &ctx->out;
                    274: 
                    275:         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    276:                        "gunzip out: %p", ctx->out);
                    277: 
                    278:         ctx->nomem = 0;
                    279: 
                    280:         if (ctx->done) {
                    281:             return rc;
                    282:         }
                    283:     }
                    284: 
                    285:     /* unreachable */
                    286: 
                    287: failed:
                    288: 
                    289:     ctx->done = 1;
                    290: 
                    291:     return NGX_ERROR;
                    292: }
                    293: 
                    294: 
                    295: static ngx_int_t
                    296: ngx_http_gunzip_filter_inflate_start(ngx_http_request_t *r,
                    297:     ngx_http_gunzip_ctx_t *ctx)
                    298: {
                    299:     int  rc;
                    300: 
                    301:     ctx->zstream.next_in = Z_NULL;
                    302:     ctx->zstream.avail_in = 0;
                    303: 
                    304:     ctx->zstream.zalloc = ngx_http_gunzip_filter_alloc;
                    305:     ctx->zstream.zfree = ngx_http_gunzip_filter_free;
                    306:     ctx->zstream.opaque = ctx;
                    307: 
                    308:     /* windowBits +16 to decode gzip, zlib 1.2.0.4+ */
                    309:     rc = inflateInit2(&ctx->zstream, MAX_WBITS + 16);
                    310: 
                    311:     if (rc != Z_OK) {
                    312:         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                    313:                       "inflateInit2() failed: %d", rc);
                    314:         return NGX_ERROR;
                    315:     }
                    316: 
                    317:     ctx->started = 1;
                    318: 
                    319:     ctx->last_out = &ctx->out;
                    320:     ctx->flush = Z_NO_FLUSH;
                    321: 
                    322:     return NGX_OK;
                    323: }
                    324: 
                    325: 
                    326: static ngx_int_t
                    327: ngx_http_gunzip_filter_add_data(ngx_http_request_t *r,
                    328:     ngx_http_gunzip_ctx_t *ctx)
                    329: {
                    330:     if (ctx->zstream.avail_in || ctx->flush != Z_NO_FLUSH || ctx->redo) {
                    331:         return NGX_OK;
                    332:     }
                    333: 
                    334:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    335:                    "gunzip in: %p", ctx->in);
                    336: 
                    337:     if (ctx->in == NULL) {
                    338:         return NGX_DECLINED;
                    339:     }
                    340: 
                    341:     ctx->in_buf = ctx->in->buf;
                    342:     ctx->in = ctx->in->next;
                    343: 
                    344:     ctx->zstream.next_in = ctx->in_buf->pos;
                    345:     ctx->zstream.avail_in = ctx->in_buf->last - ctx->in_buf->pos;
                    346: 
                    347:     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    348:                    "gunzip in_buf:%p ni:%p ai:%ud",
                    349:                    ctx->in_buf,
                    350:                    ctx->zstream.next_in, ctx->zstream.avail_in);
                    351: 
                    352:     if (ctx->in_buf->last_buf || ctx->in_buf->last_in_chain) {
                    353:         ctx->flush = Z_FINISH;
                    354: 
                    355:     } else if (ctx->in_buf->flush) {
                    356:         ctx->flush = Z_SYNC_FLUSH;
                    357: 
                    358:     } else if (ctx->zstream.avail_in == 0) {
                    359:         /* ctx->flush == Z_NO_FLUSH */
                    360:         return NGX_AGAIN;
                    361:     }
                    362: 
                    363:     return NGX_OK;
                    364: }
                    365: 
                    366: 
                    367: static ngx_int_t
                    368: ngx_http_gunzip_filter_get_buf(ngx_http_request_t *r,
                    369:     ngx_http_gunzip_ctx_t *ctx)
                    370: {
                    371:     ngx_http_gunzip_conf_t  *conf;
                    372: 
                    373:     if (ctx->zstream.avail_out) {
                    374:         return NGX_OK;
                    375:     }
                    376: 
                    377:     conf = ngx_http_get_module_loc_conf(r, ngx_http_gunzip_filter_module);
                    378: 
                    379:     if (ctx->free) {
                    380:         ctx->out_buf = ctx->free->buf;
                    381:         ctx->free = ctx->free->next;
                    382: 
                    383:         ctx->out_buf->flush = 0;
                    384: 
                    385:     } else if (ctx->bufs < conf->bufs.num) {
                    386: 
                    387:         ctx->out_buf = ngx_create_temp_buf(r->pool, conf->bufs.size);
                    388:         if (ctx->out_buf == NULL) {
                    389:             return NGX_ERROR;
                    390:         }
                    391: 
                    392:         ctx->out_buf->tag = (ngx_buf_tag_t) &ngx_http_gunzip_filter_module;
                    393:         ctx->out_buf->recycled = 1;
                    394:         ctx->bufs++;
                    395: 
                    396:     } else {
                    397:         ctx->nomem = 1;
                    398:         return NGX_DECLINED;
                    399:     }
                    400: 
                    401:     ctx->zstream.next_out = ctx->out_buf->pos;
                    402:     ctx->zstream.avail_out = conf->bufs.size;
                    403: 
                    404:     return NGX_OK;
                    405: }
                    406: 
                    407: 
                    408: static ngx_int_t
                    409: ngx_http_gunzip_filter_inflate(ngx_http_request_t *r,
                    410:     ngx_http_gunzip_ctx_t *ctx)
                    411: {
                    412:     int           rc;
                    413:     ngx_buf_t    *b;
                    414:     ngx_chain_t  *cl;
                    415: 
                    416:     ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    417:                    "inflate in: ni:%p no:%p ai:%ud ao:%ud fl:%d redo:%d",
                    418:                    ctx->zstream.next_in, ctx->zstream.next_out,
                    419:                    ctx->zstream.avail_in, ctx->zstream.avail_out,
                    420:                    ctx->flush, ctx->redo);
                    421: 
                    422:     rc = inflate(&ctx->zstream, ctx->flush);
                    423: 
                    424:     if (rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR) {
                    425:         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                    426:                       "inflate() failed: %d, %d", ctx->flush, rc);
                    427:         return NGX_ERROR;
                    428:     }
                    429: 
                    430:     ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    431:                    "inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
                    432:                    ctx->zstream.next_in, ctx->zstream.next_out,
                    433:                    ctx->zstream.avail_in, ctx->zstream.avail_out,
                    434:                    rc);
                    435: 
                    436:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    437:                    "gunzip in_buf:%p pos:%p",
                    438:                    ctx->in_buf, ctx->in_buf->pos);
                    439: 
                    440:     if (ctx->zstream.next_in) {
                    441:         ctx->in_buf->pos = ctx->zstream.next_in;
                    442: 
                    443:         if (ctx->zstream.avail_in == 0) {
                    444:             ctx->zstream.next_in = NULL;
                    445:         }
                    446:     }
                    447: 
                    448:     ctx->out_buf->last = ctx->zstream.next_out;
                    449: 
                    450:     if (ctx->zstream.avail_out == 0) {
                    451: 
                    452:         /* zlib wants to output some more data */
                    453: 
                    454:         cl = ngx_alloc_chain_link(r->pool);
                    455:         if (cl == NULL) {
                    456:             return NGX_ERROR;
                    457:         }
                    458: 
                    459:         cl->buf = ctx->out_buf;
                    460:         cl->next = NULL;
                    461:         *ctx->last_out = cl;
                    462:         ctx->last_out = &cl->next;
                    463: 
                    464:         ctx->redo = 1;
                    465: 
                    466:         return NGX_AGAIN;
                    467:     }
                    468: 
                    469:     ctx->redo = 0;
                    470: 
                    471:     if (ctx->flush == Z_SYNC_FLUSH) {
                    472: 
                    473:         ctx->flush = Z_NO_FLUSH;
                    474: 
                    475:         cl = ngx_alloc_chain_link(r->pool);
                    476:         if (cl == NULL) {
                    477:             return NGX_ERROR;
                    478:         }
                    479: 
                    480:         b = ctx->out_buf;
                    481: 
                    482:         if (ngx_buf_size(b) == 0) {
                    483: 
                    484:             b = ngx_calloc_buf(ctx->request->pool);
                    485:             if (b == NULL) {
                    486:                 return NGX_ERROR;
                    487:             }
                    488: 
                    489:         } else {
                    490:             ctx->zstream.avail_out = 0;
                    491:         }
                    492: 
                    493:         b->flush = 1;
                    494: 
                    495:         cl->buf = b;
                    496:         cl->next = NULL;
                    497:         *ctx->last_out = cl;
                    498:         ctx->last_out = &cl->next;
                    499: 
                    500:         return NGX_OK;
                    501:     }
                    502: 
                    503:     if (rc == Z_STREAM_END && ctx->flush == Z_FINISH
                    504:         && ctx->zstream.avail_in == 0)
                    505:     {
                    506: 
                    507:         if (ngx_http_gunzip_filter_inflate_end(r, ctx) != NGX_OK) {
                    508:             return NGX_ERROR;
                    509:         }
                    510: 
                    511:         return NGX_OK;
                    512:     }
                    513: 
                    514:     if (rc == Z_STREAM_END && ctx->zstream.avail_in > 0) {
                    515: 
                    516:         rc = inflateReset(&ctx->zstream);
                    517: 
                    518:         if (rc != Z_OK) {
                    519:             ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                    520:                           "inflateReset() failed: %d", rc);
                    521:             return NGX_ERROR;
                    522:         }
                    523: 
                    524:         ctx->redo = 1;
                    525: 
                    526:         return NGX_AGAIN;
                    527:     }
                    528: 
                    529:     if (ctx->in == NULL) {
                    530: 
                    531:         b = ctx->out_buf;
                    532: 
                    533:         if (ngx_buf_size(b) == 0) {
                    534:             return NGX_OK;
                    535:         }
                    536: 
                    537:         cl = ngx_alloc_chain_link(r->pool);
                    538:         if (cl == NULL) {
                    539:             return NGX_ERROR;
                    540:         }
                    541: 
                    542:         ctx->zstream.avail_out = 0;
                    543: 
                    544:         cl->buf = b;
                    545:         cl->next = NULL;
                    546:         *ctx->last_out = cl;
                    547:         ctx->last_out = &cl->next;
                    548: 
                    549:         return NGX_OK;
                    550:     }
                    551: 
                    552:     return NGX_AGAIN;
                    553: }
                    554: 
                    555: 
                    556: static ngx_int_t
                    557: ngx_http_gunzip_filter_inflate_end(ngx_http_request_t *r,
                    558:     ngx_http_gunzip_ctx_t *ctx)
                    559: {
                    560:     int           rc;
                    561:     ngx_buf_t    *b;
                    562:     ngx_chain_t  *cl;
                    563: 
                    564:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    565:                    "gunzip inflate end");
                    566: 
                    567:     rc = inflateEnd(&ctx->zstream);
                    568: 
                    569:     if (rc != Z_OK) {
                    570:         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                    571:                       "inflateEnd() failed: %d", rc);
                    572:         return NGX_ERROR;
                    573:     }
                    574: 
                    575:     b = ctx->out_buf;
                    576: 
                    577:     if (ngx_buf_size(b) == 0) {
                    578: 
                    579:         b = ngx_calloc_buf(ctx->request->pool);
                    580:         if (b == NULL) {
                    581:             return NGX_ERROR;
                    582:         }
                    583:     }
                    584: 
                    585:     cl = ngx_alloc_chain_link(r->pool);
                    586:     if (cl == NULL) {
                    587:         return NGX_ERROR;
                    588:     }
                    589: 
                    590:     cl->buf = b;
                    591:     cl->next = NULL;
                    592:     *ctx->last_out = cl;
                    593:     ctx->last_out = &cl->next;
                    594: 
                    595:     b->last_buf = (r == r->main) ? 1 : 0;
                    596:     b->last_in_chain = 1;
                    597:     b->sync = 1;
                    598: 
                    599:     ctx->done = 1;
                    600: 
                    601:     return NGX_OK;
                    602: }
                    603: 
                    604: 
                    605: static void *
                    606: ngx_http_gunzip_filter_alloc(void *opaque, u_int items, u_int size)
                    607: {
                    608:     ngx_http_gunzip_ctx_t *ctx = opaque;
                    609: 
                    610:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
                    611:                    "gunzip alloc: n:%ud s:%ud",
                    612:                    items, size);
                    613: 
                    614:     return ngx_palloc(ctx->request->pool, items * size);
                    615: }
                    616: 
                    617: 
                    618: static void
                    619: ngx_http_gunzip_filter_free(void *opaque, void *address)
                    620: {
                    621: #if 0
                    622:     ngx_http_gunzip_ctx_t *ctx = opaque;
                    623: 
                    624:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
                    625:                    "gunzip free: %p", address);
                    626: #endif
                    627: }
                    628: 
                    629: 
                    630: static void *
                    631: ngx_http_gunzip_create_conf(ngx_conf_t *cf)
                    632: {
                    633:     ngx_http_gunzip_conf_t  *conf;
                    634: 
                    635:     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_gunzip_conf_t));
                    636:     if (conf == NULL) {
                    637:         return NULL;
                    638:     }
                    639: 
                    640:     /*
                    641:      * set by ngx_pcalloc():
                    642:      *
                    643:      *     conf->bufs.num = 0;
                    644:      */
                    645: 
                    646:     conf->enable = NGX_CONF_UNSET;
                    647: 
                    648:     return conf;
                    649: }
                    650: 
                    651: 
                    652: static char *
                    653: ngx_http_gunzip_merge_conf(ngx_conf_t *cf, void *parent, void *child)
                    654: {
                    655:     ngx_http_gunzip_conf_t *prev = parent;
                    656:     ngx_http_gunzip_conf_t *conf = child;
                    657: 
                    658:     ngx_conf_merge_value(conf->enable, prev->enable, 0);
                    659: 
                    660:     ngx_conf_merge_bufs_value(conf->bufs, prev->bufs,
                    661:                               (128 * 1024) / ngx_pagesize, ngx_pagesize);
                    662: 
                    663:     return NGX_CONF_OK;
                    664: }
                    665: 
                    666: 
                    667: static ngx_int_t
                    668: ngx_http_gunzip_filter_init(ngx_conf_t *cf)
                    669: {
                    670:     ngx_http_next_header_filter = ngx_http_top_header_filter;
                    671:     ngx_http_top_header_filter = ngx_http_gunzip_header_filter;
                    672: 
                    673:     ngx_http_next_body_filter = ngx_http_top_body_filter;
                    674:     ngx_http_top_body_filter = ngx_http_gunzip_body_filter;
                    675: 
                    676:     return NGX_OK;
                    677: }

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