Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libvfp-brotli
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
uplex-varnish
libvfp-brotli
Commits
f72cbbdf
Commit
f72cbbdf
authored
Feb 12, 2019
by
Geoff Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add the "unbr" VFP for decompression.
parent
a655bc0e
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
363 additions
and
104 deletions
+363
-104
configure.ac
configure.ac
+1
-0
Makefile.am
src/Makefile.am
+2
-2
decode.vtc
src/tests/decode.vtc
+129
-0
vfp_brotli.c
src/vfp_brotli.c
+231
-102
No files found.
configure.ac
View file @
f72cbbdf
...
...
@@ -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])
...
...
src/Makefile.am
View file @
f72cbbdf
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
...
...
src/tests/decode.vtc
0 → 100644
View file @
f72cbbdf
# 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
src/vfp_brotli.c
View file @
f72cbbdf
...
...
@@ -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_br
enc
_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_br
enc
_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_br
enc
=
{
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
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment