static ngx_int_t ngx_http_brotli_filter_compress(ngx_http_request_t *r, ngx_http_brotli_ctx_t *ctx) { BROTLI_BOOL rc; ngx_buf_t *b; ngx_chain_t *cl; rc = BrotliEncoderCompressStream(ctx->bro, ctx->flush, &ctx->available_in, (const uint8_t **)&ctx->next_in, &ctx->available_out, &ctx->next_out, NULL); if (rc != BROTLI_TRUE) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "compress() failed: %d, %d", ctx->flush, rc); return NGX_ERROR; } if (ctx->next_in) { ctx->in_buf->pos = ctx->next_in; if (ctx->available_in == 0) { ctx->next_in = NULL; } } ctx->out_buf->last = ctx->next_out; if (ctx->available_out == 0) { /* brotli wants to output some more compressed data */ cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = ctx->out_buf; cl->next = NULL; *ctx->last_out = cl; ctx->last_out = &cl->next; ctx->redo = 1; return NGX_AGAIN; } ctx->redo = 0; if (ctx->flush == BROTLI_OPERATION_FLUSH) { ctx->flush = BROTLI_OPERATION_PROCESS; cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } b = ctx->out_buf; if (ngx_buf_size(b) == 0) { b = ngx_calloc_buf(ctx->request->pool); if (b == NULL) { return NGX_ERROR; } } else { ctx->available_out = 0; } b->flush = 1; cl->buf = b; cl->next = NULL; *ctx->last_out = cl; ctx->last_out = &cl->next; r->connection->buffered &= ~NGX_HTTP_GZIP_BUFFERED; return NGX_OK; } if (BrotliEncoderIsFinished(ctx->bro)) { if (ngx_http_brotli_filter_end(r, ctx) != NGX_OK) { return NGX_ERROR; } return NGX_OK; } return NGX_AGAIN; }
static ngx_int_t ngx_http_brotli_filter_compress(ngx_http_request_t *r, ngx_http_brotli_ctx_t *ctx) { int rc; ngx_buf_t *b; ngx_chain_t *cl; ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "brotli in: ni:%p no:%p ai:%ud ao:%ud fl:%d redo:%d", ctx->bstream.next_in, ctx->bstream.next_out, ctx->bstream.avail_in, ctx->bstream.avail_out, ctx->flush, ctx->redo); rc = brotli_compress(&ctx->bstream, ctx->flush); if (rc != B_OK && rc != B_STREAM_END && rc != B_BUF_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "compress() failed: %d, %d", ctx->flush, rc); return NGX_ERROR; } ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "brotli out: ni:%p no:%p ai:%ud ao:%ud rc:%d", ctx->bstream.next_in, ctx->bstream.next_out, ctx->bstream.avail_in, ctx->bstream.avail_out, rc); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "brotli in_buf:%p pos:%p", ctx->in_buf, ctx->in_buf->pos); if (ctx->bstream.next_in) { ctx->in_buf->pos = ctx->bstream.next_in; if (ctx->bstream.avail_in == 0) { ctx->bstream.next_in = NULL; } } ctx->out_buf->last = ctx->bstream.next_out; if (ctx->bstream.avail_out == 0) { /* brotli wants to output some more compressed data */ cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = ctx->out_buf; cl->next = NULL; *ctx->last_out = cl; ctx->last_out = &cl->next; ctx->redo = 1; return NGX_AGAIN; } ctx->redo = 0; if (ctx->flush == B_SYNC_FLUSH) { ctx->flush = B_NO_FLUSH; cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } b = ctx->out_buf; if (ngx_buf_size(b) == 0) { b = ngx_calloc_buf(ctx->request->pool); if (b == NULL) { return NGX_ERROR; } } else { ctx->bstream.avail_out = 0; } b->flush = 1; cl->buf = b; cl->next = NULL; *ctx->last_out = cl; ctx->last_out = &cl->next; r->connection->buffered &= ~NGX_HTTP_GZIP_BUFFERED; return NGX_OK; } if (rc == B_STREAM_END) { if (ngx_http_brotli_filter_end(r, ctx) != NGX_OK) { return NGX_ERROR; } return NGX_OK; } return NGX_AGAIN; }