Commit f72cbbdf authored by Geoff Simmons's avatar Geoff Simmons

Add the "unbr" VFP for decompression.

parent a655bc0e
......@@ -38,6 +38,7 @@ AM_CONDITIONAL(HAVE_RST2MAN, [test "x$RST2MAN" != "xno"])
m4_ifndef([VARNISH_PREREQ], AC_MSG_ERROR([Need varnish.m4 -- see README.rst]))
PKG_CHECK_MODULES([BROTLIENC], [libbrotlienc])
PKG_CHECK_MODULES([BROTLIDEC], [libbrotlidec])
VARNISH_PREREQ([trunk])
VARNISH_VMODS([brotli])
......
AUTOMAKE_OPTIONS = subdir-objects
AM_CFLAGS = $(VARNISHAPI_CFLAGS) -Wall -Werror -Wextra -std=c99 \
@BROTLIENC_CFLAGS@
@BROTLIENC_CFLAGS@ @BROTLIDEC_CFLAGS@
AM_LDFLAGS = $(VARNISHAPI_LIBS) $(VMOD_LDFLAGS) -ldl
vmod_LTLIBRARIES = libvmod_brotli.la
......@@ -17,7 +17,7 @@ dist_man_MANS = vfp_brotli.3
vfp_brotli.lo: $(nodist_libvmod_brotli_la_SOURCES)
libvmod_brotli_la_LIBADD = @BROTLIENC_LIBS@
libvmod_brotli_la_LIBADD = @BROTLIENC_LIBS@ @BROTLIDEC_LIBS@
vcc_if.h vmod_brotli.rst vmod_brotli.man.rst: vcc_if.c
......
# looks like -*- vcl -*-
varnishtest "brotli decompression"
# Test vectors from github.com/google/brotli/tests/testdata
server s1 {
rxreq
txresp -hdr "Content-Encoding: br" \
-body { The quick brown fox jumps over the lazy dog}
rxreq
txresp -hdr "Content-Encoding: br" -body { Xyzzy}
rxreq
txresp -hdr "Content-Encoding: br" -hdr "Content-Length: 12"
sendhex "1b 13 00 00 a4 b0 b2 ea 81 47 02 8a"
rxreq
txresp -hdr "Content-Encoding: br" -hdr "Content-Length: 10"
sendhex "1b 3f 00 00 24 b0 e2 99 80 12"
rxreq
txresp -hdr "Content-Encoding: br" -hdr "Content-Length: 58"
sendhex "5b ff af 02 c0 22 79 5c fb 5a 8c 42 3b f4 25 55"
sendhex "19 5a 92 99 b1 35 c8 19 9e 9e 0a 7b 4b 90 b9 3c"
sendhex "98 c8 09 40 f3 e6 d9 4d e4 6d 65 1b 27 87 13 5f"
sendhex "a6 e9 30 96 7b 3c 15 d8 53 1c"
rxreq
txresp -hdr "Content-Encoding: br" -hdr "Content-Length: 425"
sendhex "1b 4a 03 00 8c 94 6e de b4 d7 96 b1 78 86 f2 2d"
sendhex "e1 1a bc 0b 1c ba a9 c7 f7 cc 6e b2 42 34 51 44"
sendhex "8b 4e 13 08 a0 cd 6e e8 2c a5 53 a1 9c 5d 2c 1d"
sendhex "23 1a d2 56 be db eb 26 ba 03 65 7c 96 6a a2 76"
sendhex "ec ef 87 47 33 d6 27 0e 63 95 e2 1d 8d 2c c5 d1"
sendhex "28 9f 60 94 6f 02 8b dd aa 64 94 2c 1e 3b 65 7c"
sendhex "07 45 5a b2 e2 fc 49 81 2c 9f 40 ae ef 68 81 ac"
sendhex "16 7a 0f f5 3b 6d 1c b9 1e 2d 5f d5 c8 af 5e 85"
sendhex "aa 05 be 53 75 c2 b0 22 8a 15 c6 a3 b1 e6 42 14"
sendhex "f4 84 54 53 19 5f be c3 f2 1d d1 b7 e5 dd b6 d9"
sendhex "23 c6 f6 9f 9e f6 4d 65 30 fb c0 71 45 04 ad 03"
sendhex "b5 be c9 cb fd e2 50 5a 46 74 04 0d ff 20 04 77"
sendhex "b2 6d 27 bf 47 a9 9d 1b 96 2c 62 90 23 8b e0 f8"
sendhex "1d cf af 1d 3d ee 8a c8 75 23 66 dd de d6 6d e3"
sendhex "2a 82 8a 78 8a db e6 20 4c b7 5c 63 ba 30 e3 3f"
sendhex "b6 ee 8c 22 a2 2a b0 22 0a 99 ff 3d 62 51 ee 08"
sendhex "f6 3d 4a e4 cc ef 22 87 11 e2 83 28 e4 f5 8f 35"
sendhex "19 63 5b e1 5a 92 73 dd a1 50 9d 38 5c eb b5 03"
sendhex "6a 64 90 94 c8 8d fb 2f 8a 86 22 cc 1d 87 e0 48"
sendhex "0a 96 77 90 39 c6 23 23 48 fb 11 47 56 ca 20 e3"
sendhex "42 81 f7 77 32 c1 a5 5c 40 21 65 17 40 29 17 17"
sendhex "6c 56 32 98 38 06 dc 99 4d 33 29 bb 02 df 4c 26"
sendhex "93 6c 17 82 86 20 d7 03 79 7d 9a 00 d7 87 00 e7"
sendhex "0b 66 e3 4c 66 71 67 08 32 f9 08 3e 81 33 cd 17"
sendhex "72 31 f0 b8 94 52 4b 90 31 8e 68 c1 ef 90 c9 e5"
sendhex "f2 61 09 72 25 ad ec c5 62 c0 0b 12 05 f7 91 75"
sendhex "0d ee 61 2e 2e 19 09 c2 03"
rxreq
txresp -hdr "Content-Encoding: br" -hdr "Content-Length: 69"
sendhex "1b 76 00 00 14 4a ac 9b 7a bd e1 97 9d 7f 8e c2"
sendhex "82 36 0e 9c e0 90 03 f7 8b 9e 38 e6 b6 00 ab c3"
sendhex "ca a0 c2 da 66 36 dc cd 80 8d 2e 21 d7 6e e3 ea"
sendhex "4c b8 f0 d2 b8 c7 c2 70 4d 3a f0 69 7e a1 b8 45"
sendhex "73 ab c4 57 1e"
} -start
varnish v1 -vcl+backend {
import ${vmod_brotli};
sub vcl_backend_response {
set beresp.filters = "unbr";
set beresp.uncacheable = true;
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Content-Encoding == <undef>
expect resp.bodylen == 43
expect resp.body == "The quick brown fox jumps over the lazy dog"
txreq
rxresp
expect resp.status == 200
expect resp.http.Content-Encoding == <undef>
expect resp.bodylen == 5
expect resp.body == "Xyzzy"
txreq
rxresp
expect resp.status == 200
expect resp.http.Content-Encoding == <undef>
expect resp.bodylen == 20
expect resp.body == "XXXXXXXXXXYYYYYYYYYY"
txreq
rxresp
expect resp.status == 200
expect resp.http.Content-Encoding == <undef>
expect resp.bodylen == 64
expect resp.body == "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
txreq
rxresp
expect resp.status == 200
expect resp.http.Content-Encoding == <undef>
expect resp.bodylen == 176128
# 4096 repetitions
expect resp.body ~ "^The quick brown fox jumps over the lazy dog"
expect resp.body ~ "The quick brown fox jumps over the lazy dog$"
txreq
rxresp
expect resp.status == 200
expect resp.http.Content-Encoding == <undef>
expect resp.bodylen == 843
expect resp.body == "znxcvnmz,xvnm.,zxcnv.,xcn.z,vn.zvn.zxcvn.,zxcn.vn.v,znm.,vnzx.,vnzxc.vn.z,vnz.,nv.z,nvmzxc,nvzxcvcnm.,vczxvnzxcnvmxc.zmcnvzm.,nvmc,nzxmc,vn.mnnmzxc,vnxcnmv,znvzxcnmv,.xcnvm,zxcnzxv.zx,qweryweurqioweupropqwutioweupqrioweutiopweuriopweuriopqwurioputiopqwuriowuqerioupqweropuweropqwurweuqriopuropqwuriopuqwriopuqweopruioqweurqweuriouqweopruioupqiytioqtyiowtyqptypryoqweutioioqtweqruowqeytiowquiourowetyoqwupiotweuqiorweuqroipituqwiorqwtioweuriouytuioerytuioweryuitoweytuiweyuityeruirtyuqriqweuropqweiruioqweurioqwuerioqwyuituierwotueryuiotweyrtuiwertyioweryrueioqptyioruyiopqwtjkasdfhlafhlasdhfjklashjkfhasjklfhklasjdfhklasdhfjkalsdhfklasdhjkflahsjdkfhklasfhjkasdfhasfjkasdhfklsdhalghhaf;hdklasfhjklashjklfasdhfasdjklfhsdjklafsd;hkldadfjjklasdhfjasddfjklfhakjklasdjfkl;asdjfasfljasdfhjklasdfhjkaghjkashf;djfklasdjfkljasdklfjklasdjfkljasdfkljaklfj"
txreq
rxresp
expect resp.status == 200
expect resp.http.Content-Encoding == <undef>
expect resp.bodylen == 119
expect resp.body == "ukko nooa, ukko nooa oli kunnon mies, kun han meni saunaan, pisti laukun naulaan, ukko nooa, ukko nooa oli kunnon mies."
} -run
......@@ -24,6 +24,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Implementation inspired by Varnish cache_gzip.c
*/
/* for strdup() */
......@@ -34,6 +36,7 @@
#include <stdlib.h>
#include <string.h>
#include <brotli/encode.h>
#include <brotli/decode.h>
#include "cache/cache.h"
#include "cache/cache_filter.h"
......@@ -43,131 +46,178 @@
/* XXX make this configurable; cf. varnishd default gzip_buffer */
#define BUFFER_SZ (32 * 1024 * 1024)
struct vbr_enc {
unsigned magic;
#define VBR_ENC_MAGIC 0x467c387b
BrotliEncoderState *state;
uint8_t *buf;
struct vbr_stream {
const uint8_t *next_in;
uint8_t *next_out;
size_t bufsz;
size_t buflen;
size_t avail_in;
size_t avail_out;
size_t total_out;
};
static struct vbr_enc *
newEnc(void)
enum vbr_which {ENC, DEC};
struct vbr {
unsigned magic;
#define VBR_MAGIC 0x467c387b
struct vbr_stream stream;
union {
BrotliEncoderState *enc;
BrotliDecoderState *dec;
} state;
uint8_t *buf;
size_t bufsz;
size_t buflen;
enum vbr_which which;
};
static struct vbr *
newVBR(enum vbr_which which)
{
struct vbr_enc *vbr_enc;
struct vbr *vbr;
/* XXX inc encs counter */
ALLOC_OBJ(vbr_enc, VBR_ENC_MAGIC);
if (vbr_enc == NULL)
return (NULL);
vbr_enc->state = BrotliEncoderCreateInstance(NULL, NULL, NULL);
if (vbr_enc->state == NULL)
/* XXX inc counters */
ALLOC_OBJ(vbr, VBR_MAGIC);
if (vbr == NULL)
return (NULL);
if (which == ENC) {
vbr->state.enc = BrotliEncoderCreateInstance(NULL, NULL, NULL);
if (vbr->state.enc == NULL)
return (NULL);
}
else {
vbr->state.dec = BrotliDecoderCreateInstance(NULL, NULL, NULL);
if (vbr->state.dec == NULL)
return (NULL);
}
/* XXX configure the handle */
return (vbr_enc);
vbr->which = which;
return (vbr);
}
static void
destroy(struct vbr_enc **vp)
destroy(struct vbr **vp)
{
struct vbr_enc *vbr_enc;
struct vbr *vbr;
TAKE_OBJ_NOTNULL(vbr_enc, vp, VBR_ENC_MAGIC);
TAKE_OBJ_NOTNULL(vbr, vp, VBR_MAGIC);
/* XXX log results: bytes in, bytes out */
/* XXX IMO no finish op necessary here */
BrotliEncoderDestroyInstance(vbr_enc->state);
if (vbr_enc->buf != NULL)
free(vbr_enc->buf);
FREE_OBJ(vbr_enc);
if (vbr->which == ENC)
BrotliEncoderDestroyInstance(vbr->state.enc);
else
BrotliDecoderDestroyInstance(vbr->state.dec);
if (vbr->buf != NULL)
free(vbr->buf);
FREE_OBJ(vbr);
}
static int
getBuf(struct vbr_enc *vbr_enc)
getBuf(struct vbr *vbr)
{
CHECK_OBJ_NOTNULL(vbr_enc, VBR_ENC_MAGIC);
AZ(vbr_enc->bufsz);
AZ(vbr_enc->buflen);
AZ(vbr_enc->buf);
CHECK_OBJ_NOTNULL(vbr, VBR_MAGIC);
AZ(vbr->bufsz);
AZ(vbr->buflen);
AZ(vbr->buf);
/* XXX make this configurable */
vbr_enc->bufsz = BUFFER_SZ;
vbr_enc->buf = malloc(vbr_enc->bufsz);
if (vbr_enc->buf == NULL) {
vbr_enc->bufsz = 0;
vbr->bufsz = BUFFER_SZ;
vbr->buf = malloc(vbr->bufsz);
if (vbr->buf == NULL) {
vbr->bufsz = 0;
return (-1);
}
return (0);
}
static const char *
decodeErrMsg(struct vbr *vbr)
{
CHECK_OBJ_NOTNULL(vbr, VBR_MAGIC);
assert(vbr->which == DEC);
return (BrotliDecoderErrorString(
BrotliDecoderGetErrorCode(vbr->state.dec)));
}
static void
setInputBuf(struct vbr_enc *vbr_enc, const void *ptr, ssize_t len)
setInputBuf(struct vbr *vbr, const void *ptr, ssize_t len)
{
CHECK_OBJ_NOTNULL(vbr_enc, VBR_ENC_MAGIC);
CHECK_OBJ_NOTNULL(vbr, VBR_MAGIC);
AZ(vbr_enc->avail_in);
vbr_enc->next_in = TRUST_ME(ptr);
vbr_enc->avail_in = len;
AZ(vbr->stream.avail_in);
vbr->stream.next_in = ptr;
vbr->stream.avail_in = len;
}
static int
isInputBufEmpty(const struct vbr_enc *vbr_enc)
isInputBufEmpty(const struct vbr *vbr)
{
CHECK_OBJ_NOTNULL(vbr_enc, VBR_ENC_MAGIC);
return (vbr_enc->avail_in == 0);
CHECK_OBJ_NOTNULL(vbr, VBR_MAGIC);
return (vbr->stream.avail_in == 0);
}
static void
setOutputBuf(struct vbr_enc *vbr_enc, const void *ptr, ssize_t len)
setOutputBuf(struct vbr *vbr, const void *ptr, ssize_t len)
{
CHECK_OBJ_NOTNULL(vbr_enc, VBR_ENC_MAGIC);
CHECK_OBJ_NOTNULL(vbr, VBR_MAGIC);
vbr_enc->next_out = TRUST_ME(ptr);
vbr_enc->avail_out = len;
vbr->stream.next_out = TRUST_ME(ptr);
vbr->stream.avail_out = len;
}
#if 0
static int
isOutputBufFull(const struct vbr_enc *vbr_enc)
{
CHECK_OBJ_NOTNULL(vbr_enc, VBR_ENC_MAGIC);
return (vbr_enc->avail_out == 0);
}
#endif
static BROTLI_BOOL
encode(struct vbr_enc *vbr_enc, ssize_t *dl, int finished)
encode(struct vbr *vbr, ssize_t *dl, int finished)
{
BROTLI_BOOL ret;
const uint8_t *before;
enum BrotliEncoderOperation op = BROTLI_OPERATION_PROCESS;
CHECK_OBJ_NOTNULL(vbr_enc, VBR_ENC_MAGIC);
before = vbr_enc->next_out;
CHECK_OBJ_NOTNULL(vbr, VBR_MAGIC);
assert(vbr->which == ENC);
before = vbr->stream.next_out;
if (finished)
op = BROTLI_OPERATION_FINISH;
ret = BrotliEncoderCompressStream(vbr_enc->state, op,
&vbr_enc->avail_in,
&vbr_enc->next_in,
&vbr_enc->avail_out,
&vbr_enc->next_out,
&vbr_enc->total_out);
*dl = (const uint8_t *)vbr_enc->next_out - before;
ret = BrotliEncoderCompressStream(vbr->state.enc, op,
&vbr->stream.avail_in,
&vbr->stream.next_in,
&vbr->stream.avail_out,
&vbr->stream.next_out,
&vbr->stream.total_out);
*dl = (const uint8_t *)vbr->stream.next_out - before;
return (ret);
}
/* VFP interface */
static BrotliDecoderResult
decode(struct vbr *vbr, ssize_t *dl)
{
BrotliDecoderResult ret;
const uint8_t *before;
CHECK_OBJ_NOTNULL(vbr, VBR_MAGIC);
assert(vbr->which == DEC);
before = vbr->stream.next_out;
ret = BrotliDecoderDecompressStream(vbr->state.dec,
&vbr->stream.avail_in,
&vbr->stream.next_in,
&vbr->stream.avail_out,
&vbr->stream.next_out,
&vbr->stream.total_out);
*dl = (const uint8_t *)vbr->stream.next_out - before;
return (ret);
}
/* VFP interfaces */
static const struct vfp vfp_br, vfp_unbr;
/* init and fini methods for both br and unbr */
static enum vfp_status v_matchproto_(vfp_init_f)
vfp_brenc_init(struct vfp_ctx *ctx, struct vfp_entry *ent)
vfp_br_init(struct vfp_ctx *ctx, struct vfp_entry *ent)
{
struct vbr_enc *vbr_enc;
struct vbr *vbr;
CHECK_OBJ_NOTNULL(ctx, VFP_CTX_MAGIC);
CHECK_OBJ_NOTNULL(ent, VFP_ENTRY_MAGIC);
......@@ -178,28 +228,58 @@ vfp_brenc_init(struct vfp_ctx *ctx, struct vfp_entry *ent)
What do we want to do about partial responses?
*/
if (http_GetHdr(ctx->resp, H_Content_Encoding, NULL))
return (VFP_NULL);
if ((vbr_enc = newEnc()) == NULL)
if (ent->vfp == &vfp_br) {
if (http_GetHdr(ctx->resp, H_Content_Encoding, NULL))
return (VFP_NULL);
vbr = newVBR(ENC);
}
else {
if (!http_HdrIs(ctx->resp, H_Content_Encoding, "br"))
return (VFP_NULL);
vbr = newVBR(DEC);
}
if (vbr == NULL)
return (VFP_ERROR);
ent->priv1 = vbr_enc;
if (getBuf(vbr_enc))
ent->priv1 = vbr;
if (getBuf(vbr))
return (VFP_ERROR);
setInputBuf(vbr_enc, vbr_enc->buf, 0);
AZ(vbr_enc->buflen);
setInputBuf(vbr, vbr->buf, 0);
AZ(vbr->buflen);
http_Unset(ctx->resp, H_Content_Encoding);
http_Unset(ctx->resp, H_Content_Length);
RFC2616_Weaken_Etag(ctx->resp);
http_SetHeader(ctx->resp, "Content-Encoding: br");
RFC2616_Vary_AE(ctx->resp);
if (ent->vfp == &vfp_br) {
http_SetHeader(ctx->resp, "Content-Encoding: br");
RFC2616_Vary_AE(ctx->resp);
}
return (VFP_OK);
}
static void v_matchproto_(vfp_fini_f)
vfp_br_fini(struct vfp_ctx *ctx, struct vfp_entry *ent)
{
struct vbr *vbr;
CHECK_OBJ_NOTNULL(ctx, VFP_CTX_MAGIC);
CHECK_OBJ_NOTNULL(ent, VFP_ENTRY_MAGIC);
if (ent->priv1 != NULL) {
CAST_OBJ(vbr, ent->priv1, VBR_MAGIC);
ent->priv1 = NULL;
destroy(&vbr);
}
}
/* pull for br (compression) */
static enum vfp_status v_matchproto_(vfp_pull_f)
vfp_brenc_pull(struct vfp_ctx *ctx, struct vfp_entry *ent, void *ptr,
ssize_t *lenp)
vfp_br_pull(struct vfp_ctx *ctx, struct vfp_entry *ent, void *ptr,
ssize_t *lenp)
{
struct vbr_enc *vbr_enc;
struct vbr *vbr;
ssize_t len, dl;
enum vfp_status vp = VFP_ERROR;
int finished = 0;
......@@ -207,26 +287,27 @@ vfp_brenc_pull(struct vfp_ctx *ctx, struct vfp_entry *ent, void *ptr,
CHECK_OBJ_NOTNULL(ctx, VFP_CTX_MAGIC);
CHECK_OBJ_NOTNULL(ent, VFP_ENTRY_MAGIC);
CAST_OBJ_NOTNULL(vbr_enc, ent->priv1, VBR_ENC_MAGIC);
CAST_OBJ_NOTNULL(vbr, ent->priv1, VBR_MAGIC);
assert(vbr->which == ENC);
AN(ptr);
AN(lenp);
len = *lenp;
*lenp = 0;
setOutputBuf(vbr_enc, ptr, len);
setOutputBuf(vbr, ptr, len);
do {
if (isInputBufEmpty(vbr_enc)) {
len = vbr_enc->bufsz;
vp = VFP_Suck(ctx, vbr_enc->buf, &len);
if (isInputBufEmpty(vbr)) {
len = vbr->bufsz;
vp = VFP_Suck(ctx, vbr->buf, &len);
if (vp == VFP_ERROR)
break;
if (vp == VFP_END)
finished = 1;
setInputBuf(vbr_enc, vbr_enc->buf, len);
setInputBuf(vbr, vbr->buf, len);
}
if (!isInputBufEmpty(vbr_enc) || finished) {
done = encode(vbr_enc, &dl, finished);
if (!isInputBufEmpty(vbr) || finished) {
done = encode(vbr, &dl, finished);
if (done != BROTLI_TRUE)
return (VFP_Error(ctx, "brotli encode failed"));
if (dl > 0) {
......@@ -234,7 +315,7 @@ vfp_brenc_pull(struct vfp_ctx *ctx, struct vfp_entry *ent, void *ptr,
return (VFP_OK);
}
}
AN(isInputBufEmpty(vbr_enc));
AN(isInputBufEmpty(vbr));
} while (!finished);
if (done != BROTLI_TRUE)
......@@ -242,26 +323,72 @@ vfp_brenc_pull(struct vfp_ctx *ctx, struct vfp_entry *ent, void *ptr,
return (VFP_END);
}
static void v_matchproto_(vfp_fini_f)
vfp_brenc_fini(struct vfp_ctx *ctx, struct vfp_entry *ent)
/* pull for unbr (decompression) */
static enum vfp_status v_matchproto_(vfp_pull_f)
vfp_unbr_pull(struct vfp_ctx *ctx, struct vfp_entry *ent, void *ptr,
ssize_t *lenp)
{
struct vbr_enc *vbr_enc;
struct vbr *vbr;
ssize_t len, dl;
enum vfp_status vp = VFP_ERROR;
BrotliDecoderResult result = BROTLI_DECODER_RESULT_ERROR;
CHECK_OBJ_NOTNULL(ctx, VFP_CTX_MAGIC);
CHECK_OBJ_NOTNULL(ent, VFP_ENTRY_MAGIC);
CAST_OBJ_NOTNULL(vbr, ent->priv1, VBR_MAGIC);
assert(vbr->which == DEC);
AN(ptr);
AN(lenp);
if (ent->priv1 != NULL) {
CAST_OBJ(vbr_enc, ent->priv1, VBR_ENC_MAGIC);
ent->priv1 = NULL;
destroy(&vbr_enc);
}
len = *lenp;
*lenp = 0;
setOutputBuf(vbr, ptr, len);
do {
if (isInputBufEmpty(vbr)) {
len = vbr->bufsz;
vp = VFP_Suck(ctx, vbr->buf, &len);
if (vp == VFP_ERROR)
break;
setInputBuf(vbr, vbr->buf, len);
}
if (!isInputBufEmpty(vbr) || vp == VFP_END) {
result = decode(vbr, &dl);
if (result == BROTLI_DECODER_RESULT_SUCCESS &&
!isInputBufEmpty(vbr))
return(VFP_Error(ctx,
"Junk after brotli data"));
if (result == BROTLI_DECODER_RESULT_ERROR)
return (VFP_Error(ctx,
"Invalid brotli data: %s",
decodeErrMsg(vbr)));
if (dl > 0) {
*lenp = dl;
return (VFP_OK);
}
}
AN(isInputBufEmpty(vbr));
} while (result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT);
if (result != BROTLI_DECODER_RESULT_SUCCESS)
return (VFP_Error(ctx, "Invalid brotli data at end: %s",
decodeErrMsg(vbr)));
return (VFP_END);
}
static const struct vfp vfp_brenc = {
static const struct vfp vfp_br = {
.name = "br",
.init = vfp_brenc_init,
.pull = vfp_brenc_pull,
.fini = vfp_brenc_fini,
.init = vfp_br_init,
.pull = vfp_br_pull,
.fini = vfp_br_fini,
};
static const struct vfp vfp_unbr = {
.name = "unbr",
.init = vfp_br_init,
.pull = vfp_unbr_pull,
.fini = vfp_br_fini,
};
/* Event function */
......@@ -275,10 +402,12 @@ vmod_event(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
switch(e) {
case VCL_EVENT_LOAD:
VRT_AddVFP(ctx, &vfp_brenc);
VRT_AddVFP(ctx, &vfp_br);
VRT_AddVFP(ctx, &vfp_unbr);
return (0);
case VCL_EVENT_DISCARD:
VRT_RemoveVFP(ctx, &vfp_brenc);
VRT_RemoveVFP(ctx, &vfp_br);
VRT_RemoveVFP(ctx, &vfp_unbr);
return (0);
case VCL_EVENT_WARM:
case VCL_EVENT_COLD:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment