增加对BR压缩编码的支持及对应的单元测试用例

This commit is contained in:
luqiuwen
2018-12-09 18:02:43 +06:00
parent de92efb380
commit 1d89768160
9 changed files with 453 additions and 163 deletions

View File

@@ -8,6 +8,7 @@ target_link_libraries(http common)
target_link_libraries(http http-parser-static) target_link_libraries(http http-parser-static)
target_link_libraries(http libevent-static) target_link_libraries(http libevent-static)
target_link_libraries(http z) target_link_libraries(http z)
target_link_libraries(http brotlienc-static brotlidec-static)
### UNITTEST CASE ### UNITTEST CASE
add_executable(test-http-half test/test_http_half.cpp) add_executable(test-http-half test/test_http_half.cpp)

View File

@@ -21,7 +21,7 @@ struct http_plugin
/* GC events */ /* GC events */
struct event * gc_event_hs_private[TFE_THREAD_MAX]; struct event * gc_event_hs_private[TFE_THREAD_MAX];
/* ACCESS LOGGER */ /* ACCESS LOGGER */
void * access_logger; void * logger;
}; };
extern struct http_plugin * g_http_plugin; extern struct http_plugin * g_http_plugin;

View File

@@ -30,6 +30,7 @@ struct http_header_private
#define HTTP_ACCEPT_ENCODING_BZIP2 BV(4) #define HTTP_ACCEPT_ENCODING_BZIP2 BV(4)
#define HTTP_ACCEPT_ENCODING_X_GZIP BV(5) #define HTTP_ACCEPT_ENCODING_X_GZIP BV(5)
#define HTTP_ACCEPT_ENCODING_X_BZIP2 BV(6) #define HTTP_ACCEPT_ENCODING_X_BZIP2 BV(6)
#define HTTP_ACCEPT_ENCODING_BR BV(7)
TAILQ_HEAD(http_header_private_list, http_header_private); TAILQ_HEAD(http_header_private_list, http_header_private);
struct http_half_private struct http_half_private

View File

@@ -3,204 +3,391 @@
#include <http_half.h> #include <http_half.h>
#include <http_convert.h> #include <http_convert.h>
#include <event2/buffer.h> #include <event2/buffer.h>
#include <brotli/decode.h>
#include <brotli/encode.h>
struct hf_content_uncompress struct hf_content_uncompress
{ {
/* MODE AND CALLBACKS */ /* MODE AND CALLBACKS */
unsigned int content_encode; unsigned int content_encode;
hf_private_cb * data_cb; hf_private_cb * data_cb;
void * data_cb_user; void * data_cb_user;
/* ZLIB STREAM */ /* ZLIB STREAM */
z_stream * z_stream_ptr; z_stream * z_stream_ptr;
unsigned char * chunk; /* BR DECODER STATE */
size_t sz_chunk; BrotliDecoderState * brdec_state;
unsigned char * chunk;
size_t sz_chunk;
}; };
struct hf_content_compress struct hf_content_compress
{ {
z_stream * z_stream_ptr; unsigned int content_encode;
unsigned int content_encode; z_stream * z_stream_ptr;
BrotliEncoderState * brenc_state;
}; };
void hf_content_uncompress_destroy(struct hf_content_uncompress * cv_object) void hf_content_uncompress_destroy(struct hf_content_uncompress * cv_object)
{ {
(void) inflateEnd(cv_object->z_stream_ptr); if (cv_object->z_stream_ptr != NULL)
free(cv_object->z_stream_ptr); {
free(cv_object->chunk); inflateEnd(cv_object->z_stream_ptr);
cv_object->z_stream_ptr = NULL; free(cv_object->z_stream_ptr);
free(cv_object); cv_object->z_stream_ptr = NULL;
}
if (cv_object->brdec_state)
{
BrotliDecoderDestroyInstance(cv_object->brdec_state);
cv_object->brdec_state = NULL;
}
free(cv_object->chunk);
free(cv_object);
} }
struct hf_content_uncompress * hf_content_uncompress_create(unsigned int content_encode, struct hf_content_uncompress * hf_content_uncompress_create(unsigned int content_encode,
hf_private_cb * data_cb, void * data_cb_user) hf_private_cb * data_cb, void * data_cb_user)
{ {
struct hf_content_uncompress * cv_object = ALLOC(struct hf_content_uncompress, 1); struct hf_content_uncompress * cv_object = ALLOC(struct hf_content_uncompress, 1);
assert(data_cb != NULL); assert(data_cb != NULL);
cv_object->content_encode = content_encode; cv_object->content_encode = content_encode;
cv_object->data_cb = data_cb; cv_object->data_cb = data_cb;
cv_object->data_cb_user = data_cb_user; cv_object->data_cb_user = data_cb_user;
/* ZSTREAM */ /* CHUNK, 4K */
cv_object->z_stream_ptr = ALLOC(z_stream, 1);
cv_object->z_stream_ptr->zalloc = NULL;
cv_object->z_stream_ptr->zfree = NULL;
cv_object->z_stream_ptr->opaque = NULL;
cv_object->z_stream_ptr->avail_in = 0;
cv_object->z_stream_ptr->next_in = Z_NULL;
/* CHUNK, 4K */
#define CHUNK_SIZE (1024 * 1024 * 4) #define CHUNK_SIZE (1024 * 1024 * 4)
cv_object->chunk = (unsigned char *) malloc(CHUNK_SIZE); cv_object->chunk = (unsigned char *) malloc(CHUNK_SIZE);
cv_object->sz_chunk = CHUNK_SIZE; cv_object->sz_chunk = CHUNK_SIZE;
int ret = 0; /* ZSTREAM */
if (content_encode == HTTP_ACCEPT_ENCODING_GZIP) if (content_encode == HTTP_ACCEPT_ENCODING_GZIP || content_encode == HTTP_ACCEPT_ENCODING_DEFLATE)
{ {
ret = inflateInit2(cv_object->z_stream_ptr, MAX_WBITS + 16); cv_object->z_stream_ptr = ALLOC(z_stream, 1);
} cv_object->z_stream_ptr->zalloc = NULL;
else if (content_encode == HTTP_ACCEPT_ENCODING_DEFLATE) cv_object->z_stream_ptr->zfree = NULL;
{ cv_object->z_stream_ptr->opaque = NULL;
ret = inflateInit2(cv_object->z_stream_ptr, -MAX_WBITS); cv_object->z_stream_ptr->avail_in = 0;
} cv_object->z_stream_ptr->next_in = Z_NULL;
if (ret != Z_OK) goto __errout; int ret = 0;
return cv_object; if (content_encode == HTTP_ACCEPT_ENCODING_GZIP)
{
ret = inflateInit2(cv_object->z_stream_ptr, MAX_WBITS + 16);
}
if (content_encode == HTTP_ACCEPT_ENCODING_DEFLATE)
{
ret = inflateInit2(cv_object->z_stream_ptr, -MAX_WBITS);
}
if (ret != Z_OK)
{
goto __errout;
}
}
if (content_encode == HTTP_ACCEPT_ENCODING_BR)
{
cv_object->brdec_state = BrotliDecoderCreateInstance(NULL, NULL, NULL);
if (unlikely(cv_object->brdec_state == NULL)) goto __errout;
}
return cv_object;
__errout: __errout:
free(cv_object->z_stream_ptr); if (cv_object->z_stream_ptr != NULL)
free(cv_object->chunk); {
free(cv_object); free(cv_object->z_stream_ptr);
return NULL; cv_object->z_stream_ptr = NULL;
}
if (cv_object->brdec_state != NULL)
{
BrotliDecoderDestroyInstance(cv_object->brdec_state);
cv_object->brdec_state = NULL;
}
free(cv_object->chunk);
free(cv_object);
return NULL;
}
static int __hf_content_uncompress_write_zlib(struct hf_content_uncompress * cv_object,
struct http_half_private * hf_private, tfe_http_event http_ev, const unsigned char * data, size_t datalen)
{
z_stream * z_stream_ptr = cv_object->z_stream_ptr;
z_stream_ptr->avail_in = (unsigned int) datalen;
z_stream_ptr->next_in = (unsigned char *) data;
if (z_stream_ptr->avail_in == 0)
{
(void) inflateEnd(z_stream_ptr);
return Z_ERRNO;
}
int ret = 0;
do
{
z_stream_ptr->avail_out = (unsigned int) cv_object->sz_chunk;
z_stream_ptr->next_out = cv_object->chunk;
ret = inflate(z_stream_ptr, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT ||
ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
{
goto __error;
}
unsigned int have = (unsigned int) cv_object->sz_chunk - z_stream_ptr->avail_out;
if (have > 0 && cv_object->data_cb != NULL)
{
cv_object->data_cb(hf_private, http_ev, cv_object->chunk, (size_t) have, cv_object->data_cb_user);
}
}
while (z_stream_ptr->avail_out == 0);
return ret;
__error:
(void) inflateEnd(z_stream_ptr);
return ret;
}
static int __hf_content_uncompress_write_br(struct hf_content_uncompress * cv_object,
struct http_half_private * hf_private, tfe_http_event http_ev, const unsigned char * data, size_t datalen)
{
size_t available_in = datalen;
const unsigned char * next_in = data;
size_t available_out;
unsigned char * next_out;
int ret;
for (;;)
{
available_out = cv_object->sz_chunk;
next_out = cv_object->chunk;
ret = BrotliDecoderDecompressStream(cv_object->brdec_state, &available_in, &next_in,
&available_out, &next_out, 0);
size_t have = (unsigned int) cv_object->sz_chunk - available_out;
if (have > 0 && cv_object->data_cb != NULL)
{
cv_object->data_cb(hf_private, http_ev, cv_object->chunk, have, cv_object->data_cb_user);
}
if (ret == BROTLI_DECODER_RESULT_SUCCESS || ret == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT)
{
return 1;
}
if (ret == BROTLI_DECODER_RESULT_ERROR)
{
BrotliDecoderErrorCode errcode = BrotliDecoderGetErrorCode(cv_object->brdec_state);
TFE_LOG_ERROR(g_http_plugin->logger, "BrotliDecoderDecompressStream() failed: errno = %d, %s",
errcode, BrotliDecoderErrorString(errcode)); return -1;
}
assert(ret == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT);
}
} }
int hf_content_uncompress_write(struct hf_content_uncompress * cv_object, int hf_content_uncompress_write(struct hf_content_uncompress * cv_object,
struct http_half_private * hf_private, tfe_http_event http_ev, const unsigned char * data, size_t datalen) struct http_half_private * hf_private, tfe_http_event http_ev, const unsigned char * data, size_t datalen)
{ {
z_stream * z_stream_ptr = cv_object->z_stream_ptr; if (cv_object->content_encode == HTTP_ACCEPT_ENCODING_GZIP ||
z_stream_ptr->avail_in = (unsigned int) datalen; cv_object->content_encode == HTTP_ACCEPT_ENCODING_DEFLATE)
z_stream_ptr->next_in = (unsigned char *) data; {
return __hf_content_uncompress_write_zlib(cv_object, hf_private, http_ev, data, datalen);
}
if (z_stream_ptr->avail_in == 0) if (cv_object->content_encode == HTTP_ACCEPT_ENCODING_BR)
{ {
(void) inflateEnd(z_stream_ptr); return __hf_content_uncompress_write_br(cv_object, hf_private, http_ev, data, datalen);
return Z_ERRNO; }
}
int ret = 0; assert(0);
do return -1;
{
z_stream_ptr->avail_out = (unsigned int) cv_object->sz_chunk;
z_stream_ptr->next_out = cv_object->chunk;
ret = inflate(z_stream_ptr, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
{
goto __error;
}
unsigned int have = (unsigned int) cv_object->sz_chunk - z_stream_ptr->avail_out;
if (have > 0 && cv_object->data_cb != NULL)
{
cv_object->data_cb(hf_private, http_ev, cv_object->chunk, (size_t) have, cv_object->data_cb_user);
}
} while (z_stream_ptr->avail_out == 0);
return ret;
__error:
(void) inflateEnd(z_stream_ptr);
return ret;
} }
struct hf_content_compress * hf_content_compress_create(unsigned int content_encode) struct hf_content_compress * hf_content_compress_create(unsigned int content_encode)
{ {
struct hf_content_compress * cv_object = ALLOC(struct hf_content_compress, 1); struct hf_content_compress * cv_object = ALLOC(struct hf_content_compress, 1);
cv_object->content_encode = content_encode; cv_object->content_encode = content_encode;
/* ZSTREAM */ if (cv_object->content_encode == HTTP_ACCEPT_ENCODING_GZIP ||
cv_object->z_stream_ptr = ALLOC(z_stream, 1); cv_object->content_encode == HTTP_ACCEPT_ENCODING_DEFLATE)
cv_object->z_stream_ptr->zalloc = NULL; {
cv_object->z_stream_ptr->zfree = NULL; cv_object->z_stream_ptr = ALLOC(z_stream, 1);
cv_object->z_stream_ptr->opaque = NULL; cv_object->z_stream_ptr->zalloc = NULL;
cv_object->z_stream_ptr->avail_in = 0; cv_object->z_stream_ptr->zfree = NULL;
cv_object->z_stream_ptr->next_in = Z_NULL; cv_object->z_stream_ptr->opaque = NULL;
cv_object->z_stream_ptr->avail_in = 0;
cv_object->z_stream_ptr->next_in = Z_NULL;
int __windows_bits = 0; int __windows_bits = 0;
if (content_encode == HTTP_ACCEPT_ENCODING_GZIP) if (content_encode == HTTP_ACCEPT_ENCODING_GZIP)
{ {
__windows_bits = MAX_WBITS + 16; __windows_bits = MAX_WBITS + 16;
} }
if (content_encode == HTTP_ACCEPT_ENCODING_DEFLATE) if (content_encode == HTTP_ACCEPT_ENCODING_DEFLATE)
{ {
__windows_bits = -MAX_WBITS; __windows_bits = -MAX_WBITS;
} }
int ret = deflateInit2(cv_object->z_stream_ptr, Z_DEFAULT_COMPRESSION, int ret = deflateInit2(cv_object->z_stream_ptr, Z_DEFAULT_COMPRESSION,
Z_DEFLATED, __windows_bits, 8, Z_DEFAULT_STRATEGY); Z_DEFLATED, __windows_bits, 8, Z_DEFAULT_STRATEGY);
if (ret != Z_OK) goto __errout; if (ret != Z_OK) goto __errout;
return cv_object; }
if (cv_object->content_encode == HTTP_ACCEPT_ENCODING_BR)
{
cv_object->brenc_state = BrotliEncoderCreateInstance(NULL, NULL, NULL);
if (unlikely(cv_object->brenc_state == NULL)) goto __errout;
}
return cv_object;
__errout: __errout:
free(cv_object->z_stream_ptr); if (cv_object->z_stream_ptr)
free(cv_object); {
return NULL; free(&cv_object->z_stream_ptr);
cv_object->z_stream_ptr = NULL;
}
if (cv_object->brenc_state)
{
BrotliEncoderDestroyInstance(cv_object->brenc_state);
cv_object->brenc_state = NULL;
}
free(cv_object);
return NULL;
}
#define SZ_IOVEC 2
#define SZ_RESERVE_SPACE 512
static int __hf_content_compress_write_zlib(struct hf_content_compress * cv_object,
const unsigned char * in_data, size_t sz_in_data, struct evbuffer * out_ev_buf, int end)
{
struct evbuffer_iovec v[SZ_IOVEC];
/* Reserve the space, because the length of the compressed data will be short
* than uncompressed data in usually, we set the reserve space as much as sz_in_data */
size_t __sz_reserve_space = sz_in_data > SZ_RESERVE_SPACE ? sz_in_data : SZ_RESERVE_SPACE;
int iov_count = evbuffer_reserve_space(out_ev_buf, __sz_reserve_space, v, SZ_IOVEC);
if (iov_count < 1 || iov_count > SZ_IOVEC) return -1;
z_stream * z = cv_object->z_stream_ptr;
z->next_in = (unsigned char *) in_data;
z->avail_in = (unsigned int) sz_in_data;
unsigned int iov_offset = 0;
z->next_out = (unsigned char *) v[iov_offset].iov_base;
z->avail_out = (unsigned int) v[iov_offset].iov_len;
int flush = end ? Z_FINISH : Z_NO_FLUSH;
int ret = 0;
do
{
ret = deflate(z, flush);
assert(ret != Z_STREAM_ERROR);
assert(iov_offset < SZ_IOVEC);
if (z->avail_out == 0 || z->avail_in == 0)
{
unsigned int len = (unsigned int) v[iov_offset].iov_len - z->avail_out;
v[iov_offset].iov_len = (size_t) len;
iov_offset++;
z->next_out = (unsigned char *) v[iov_offset].iov_base;
z->avail_out = (unsigned int) v[iov_offset].iov_len;
}
}
while (z->avail_in > 0);
assert(end == 0 || ret == Z_STREAM_END);
(void) ret;
return evbuffer_commit_space(out_ev_buf, v, iov_count);
}
static int __hf_content_compress_write_br(struct hf_content_compress * cv_object,
const unsigned char * in_data, size_t sz_in_data, struct evbuffer * out_ev_buf, int end)
{
struct evbuffer_iovec v[SZ_IOVEC];
/* Reserve the space, because the length of the compressed data will be short
* than uncompressed data in usually, we set the reserve space as much as sz_in_data */
size_t __sz_reserve_space = sz_in_data > SZ_RESERVE_SPACE ? sz_in_data : SZ_RESERVE_SPACE;
int iov_count = evbuffer_reserve_space(out_ev_buf, __sz_reserve_space, v, SZ_IOVEC);
if (iov_count < 1 || iov_count > SZ_IOVEC) return -1;
const unsigned char * next_in = in_data;
size_t avail_in = sz_in_data;
unsigned int iov_offset = 0;
unsigned char * next_out = (unsigned char *)v[iov_offset].iov_base;
size_t avail_out = v[iov_offset].iov_len;
enum BrotliEncoderOperation op = end ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS;
int ret = 0;
do
{
ret = BrotliEncoderCompressStream(cv_object->brenc_state, op,
&avail_in, &next_in, &avail_out, &next_out, NULL);
if(unlikely(ret == BROTLI_FALSE))
{
TFE_LOG_ERROR(g_http_plugin->logger, "BrotliEncoderCompressStream() error.");
return ret;
}
assert(iov_offset < SZ_IOVEC);
if (avail_out == 0 || avail_in == 0)
{
size_t len = v[iov_offset].iov_len - avail_out;
v[iov_offset].iov_len = len;
iov_offset++;
next_out = (unsigned char *) v[iov_offset].iov_base;
avail_out = (unsigned int) v[iov_offset].iov_len;
}
}
while (avail_in > 0);
(void) ret;
return evbuffer_commit_space(out_ev_buf, v, iov_count);
} }
int hf_content_compress_write(struct hf_content_compress * cv_object, int hf_content_compress_write(struct hf_content_compress * cv_object,
const unsigned char * in_data, size_t sz_in_data, struct evbuffer * out_ev_buf, int end) const unsigned char * in_data, size_t sz_in_data, struct evbuffer * out_ev_buf, int end)
{ {
#define SZ_IOVEC 2 if (cv_object->content_encode == HTTP_ACCEPT_ENCODING_GZIP ||
struct evbuffer_iovec v[SZ_IOVEC]; cv_object->content_encode == HTTP_ACCEPT_ENCODING_DEFLATE)
{
return __hf_content_compress_write_zlib(cv_object, in_data, sz_in_data, out_ev_buf, end);
}
/* Reserve the space, because the length of the compressed data will be short if (cv_object->content_encode == HTTP_ACCEPT_ENCODING_BR)
* than uncompressed data in usually, we set the reserve space as much as sz_in_data */ {
size_t __sz_reserve_space = sz_in_data > 512 ? sz_in_data : 512; return __hf_content_compress_write_br(cv_object, in_data, sz_in_data, out_ev_buf, end);
int iov_count = evbuffer_reserve_space(out_ev_buf, __sz_reserve_space, v, SZ_IOVEC); }
if (iov_count < 1 || iov_count > SZ_IOVEC) return -1;
z_stream * z = cv_object->z_stream_ptr; assert(0);
z->next_in = (unsigned char *) in_data; return -1;
z->avail_in = (unsigned int) sz_in_data;
unsigned int iov_offset = 0;
z->next_out = (unsigned char *) v[iov_offset].iov_base;
z->avail_out = (unsigned int) v[iov_offset].iov_len;
int flush = end ? Z_FINISH : Z_NO_FLUSH;
int ret = 0;
do
{
ret = deflate(z, flush);
assert(ret != Z_STREAM_ERROR);
assert(iov_offset < SZ_IOVEC);
if (z->avail_out == 0 || z->avail_in == 0)
{
unsigned int len = (unsigned int) v[iov_offset].iov_len - z->avail_out;
v[iov_offset].iov_len = (size_t) len;
iov_offset++;
z->next_out = (unsigned char *) v[iov_offset].iov_base;
z->avail_out = (unsigned int) v[iov_offset].iov_len;
}
} while (z->avail_in > 0);
assert(end == 0 || ret == Z_STREAM_END);
(void)ret;
return evbuffer_commit_space(out_ev_buf, v, iov_count);
} }
void hf_content_compress_destroy(hf_content_compress * cv_object) void hf_content_compress_destroy(hf_content_compress * cv_object)
{ {
(void) deflateEnd(cv_object->z_stream_ptr); (void) deflateEnd(cv_object->z_stream_ptr);
free(cv_object->z_stream_ptr); free(cv_object->z_stream_ptr);
cv_object->z_stream_ptr = NULL; cv_object->z_stream_ptr = NULL;
free(cv_object); free(cv_object);
} }

View File

@@ -89,8 +89,8 @@ int http_plugin_init(struct tfe_proxy * proxy)
plugin_ctx->gc_event_hs_private[thread_id] = gc_event; plugin_ctx->gc_event_hs_private[thread_id] = gc_event;
} }
plugin_ctx->access_logger = MESA_create_runtime_log_handle("log/http.log", RLOG_LV_INFO); plugin_ctx->logger = MESA_create_runtime_log_handle("log/http.log", RLOG_LV_INFO);
assert(plugin_ctx->access_logger != NULL); assert(plugin_ctx->logger != NULL);
return 0; return 0;
} }
@@ -438,7 +438,7 @@ enum tfe_stream_action http_connection_entry(const struct tfe_stream * stream, e
/* Some kind of error happened, write log and detach the stream */ /* Some kind of error happened, write log and detach the stream */
if (ret == -1) if (ret == -1)
{ {
TFE_LOG_ERROR(g_http_plugin->access_logger, "%s: Failed at parsing stream as HTTP, %u, %s, %s", TFE_LOG_ERROR(g_http_plugin->logger, "%s: Failed at parsing stream as HTTP, %u, %s, %s",
stream->str_stream_info, hf_private_in->parse_errno, http_errno_name(hf_private_in->parse_errno), stream->str_stream_info, hf_private_in->parse_errno, http_errno_name(hf_private_in->parse_errno),
http_errno_description(hf_private_in->parse_errno)); http_errno_description(hf_private_in->parse_errno));

View File

@@ -97,6 +97,11 @@ uint16_t __hf_content_encoding_parse(const char * str_content_encoding)
return HTTP_ACCEPT_ENCODING_X_BZIP2; return HTTP_ACCEPT_ENCODING_X_BZIP2;
} }
if(strcasestr(str_content_encoding, "br") != NULL)
{
return HTTP_ACCEPT_ENCODING_BR;
}
return HTTP_ACCEPT_ENCODING_NONE; return HTTP_ACCEPT_ENCODING_NONE;
} }
@@ -109,6 +114,7 @@ const char * __hf_content_encoding_to_str(unsigned int encode)
case HTTP_ACCEPT_ENCODING_DEFLATE: return "deflate"; case HTTP_ACCEPT_ENCODING_DEFLATE: return "deflate";
case HTTP_ACCEPT_ENCODING_BZIP2: return "bzip2"; case HTTP_ACCEPT_ENCODING_BZIP2: return "bzip2";
case HTTP_ACCEPT_ENCODING_X_BZIP2: return "x-bzip2"; case HTTP_ACCEPT_ENCODING_X_BZIP2: return "x-bzip2";
case HTTP_ACCEPT_ENCODING_BR: return "br";
default: return ""; default: return "";
} }
} }
@@ -431,7 +437,7 @@ static int __parser_callback_on_body(struct http_parser * parser, const char * a
const char * __str_stream = hf_private->session->hc_private->stream->str_stream_info; const char * __str_stream = hf_private->session->hc_private->stream->str_stream_info;
const char * __str_url = hf_private->session->hs_public.req->req_spec.url; const char * __str_url = hf_private->session->hs_public.req->req_spec.url;
TFE_LOG_ERROR(g_http_plugin->access_logger, "%s %s %s, ret = %d. ", __str_stream, __str_url, __what, ret); TFE_LOG_ERROR(g_http_plugin->logger, "%s %s %s, ret = %d. ", __str_stream, __str_url, __what, ret);
hf_private->is_passthrough = true; return -1; hf_private->is_passthrough = true; return -1;
} }
} }
@@ -1200,7 +1206,7 @@ void __write_access_log(struct http_session_private * hs_private)
request->major, request->minor, __str_resp_code, __str_cont_type, __str_cont_encoding, request->major, request->minor, __str_resp_code, __str_cont_type, __str_cont_encoding,
__str_upgrade, __str_req_passthrough, __str_resp_passthrough, __str_user_req, __str_user_resp, __str_suspend); __str_upgrade, __str_req_passthrough, __str_resp_passthrough, __str_user_req, __str_user_resp, __str_suspend);
TFE_LOG_INFO(g_http_plugin->access_logger, "%s", __access_log); TFE_LOG_INFO(g_http_plugin->logger, "%s", __access_log);
free(__access_log); free(__access_log);
} }

View File

@@ -213,14 +213,13 @@ TEST_F(HttpConvertUncompress, GzipMonkeyFrag)
EXPECT_EQ(memcmp(__ctx->data, monkey, monkey_len), 0); EXPECT_EQ(memcmp(__ctx->data, monkey, monkey_len), 0);
} }
class HttpConvertCompress : public ::testing::Test class HttpConvertCompress : public ::testing::TestWithParam<unsigned int>
{ {
protected: protected:
static constexpr unsigned int __encode = HTTP_ACCEPT_ENCODING_GZIP;
void SetUp() override void SetUp() override
{ {
cv_compress_object = hf_content_compress_create(__encode); cv_compress_object = hf_content_compress_create(encode);
cv_uncompress_object = hf_content_uncompress_create(__encode, __gzip_uncompress_callback, &uncompress_buf); cv_uncompress_object = hf_content_uncompress_create(encode, __gzip_uncompress_callback, &uncompress_buf);
ASSERT_TRUE(cv_compress_object != NULL); ASSERT_TRUE(cv_compress_object != NULL);
} }
@@ -231,6 +230,7 @@ protected:
} }
protected: protected:
unsigned int encode = GetParam();
struct hf_content_compress * cv_compress_object{}; struct hf_content_compress * cv_compress_object{};
struct hf_content_uncompress * cv_uncompress_object{}; struct hf_content_uncompress * cv_uncompress_object{};
struct evbuffer * buf{evbuffer_new()}; struct evbuffer * buf{evbuffer_new()};
@@ -246,7 +246,7 @@ protected:
} }
}; };
TEST_F(HttpConvertCompress, MonkeyToGzip) TEST_P(HttpConvertCompress, MonkeyToGzip)
{ {
int ret = hf_content_compress_write(cv_compress_object, monkey, sizeof(monkey), buf, 1); int ret = hf_content_compress_write(cv_compress_object, monkey, sizeof(monkey), buf, 1);
ASSERT_EQ(ret, 0); ASSERT_EQ(ret, 0);
@@ -263,7 +263,7 @@ TEST_F(HttpConvertCompress, MonkeyToGzip)
EXPECT_EQ(memcmp(uncompress_buf.data(), monkey, sizeof(monkey)), 0); EXPECT_EQ(memcmp(uncompress_buf.data(), monkey, sizeof(monkey)), 0);
} }
TEST_F(HttpConvertCompress, MonkeyToGzipStream) TEST_P(HttpConvertCompress, MonkeyToGzipStream)
{ {
unsigned frag_length = sizeof(monkey) / 2; unsigned frag_length = sizeof(monkey) / 2;
@@ -287,7 +287,7 @@ TEST_F(HttpConvertCompress, MonkeyToGzipStream)
EXPECT_EQ(memcmp(uncompress_buf.data(), monkey, sizeof(monkey)), 0); EXPECT_EQ(memcmp(uncompress_buf.data(), monkey, sizeof(monkey)), 0);
} }
TEST_F(HttpConvertCompress, MonkeyToGzipStreamWithNullEnd) TEST_P(HttpConvertCompress, MonkeyToGzipStreamWithNullEnd)
{ {
unsigned frag_length = sizeof(monkey) / 2; unsigned frag_length = sizeof(monkey) / 2;
@@ -315,11 +315,80 @@ TEST_F(HttpConvertCompress, MonkeyToGzipStreamWithNullEnd)
EXPECT_EQ(memcmp(uncompress_buf.data(), monkey, sizeof(monkey)), 0); EXPECT_EQ(memcmp(uncompress_buf.data(), monkey, sizeof(monkey)), 0);
} }
INSTANTIATE_TEST_CASE_P(HttpConvertCompressGroup, HttpConvertCompress,
::testing::Values(HTTP_ACCEPT_ENCODING_GZIP, HTTP_ACCEPT_ENCODING_DEFLATE, HTTP_ACCEPT_ENCODING_BR));
void tfe_stream_write_access_log(const struct tfe_stream * stream, int level, const char * fmt, ...) void tfe_stream_write_access_log(const struct tfe_stream * stream, int level, const char * fmt, ...)
{ {
return; return;
} }
void tfe_stream_resume(const struct tfe_stream * stream)
{
return;
}
void tfe_stream_suspend(const struct tfe_stream * stream, enum tfe_conn_dir by)
{
return;
}
int tfe_stream_write(const struct tfe_stream * stream, enum tfe_conn_dir dir, const unsigned char * data, size_t size)
{
return 0;
}
int tfe_stream_write_frag(struct tfe_stream_write_ctx * w_ctx, const unsigned char * data, size_t size)
{
return 0;
}
int tfe_stream_action_set_opt(const struct tfe_stream * stream, enum tfe_stream_action_opt type,
void * value, size_t size)
{
return 0;
}
struct tfe_stream_write_ctx * tfe_stream_write_frag_start(const struct tfe_stream * stream, enum tfe_conn_dir dir)
{
return NULL;
}
struct event_base * tfe_proxy_get_work_thread_evbase(unsigned int thread_id)
{
return NULL;
}
struct event_base * tfe_proxy_get_gc_evbase(void)
{
return NULL;
}
void tfe_stream_write_frag_end(struct tfe_stream_write_ctx * w_ctx)
{
return;
}
void tfe_stream_detach(const struct tfe_stream * stream)
{
return;
}
int tfe_stream_preempt(const struct tfe_stream * stream)
{
return 0;
}
unsigned int tfe_proxy_get_work_thread_count()
{
return 0;
}
const char * tfe_version()
{
return NULL;
}
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);

26
vendor/CMakeLists.txt vendored
View File

@@ -282,3 +282,29 @@ add_library(libdablooms SHARED IMPORTED GLOBAL)
add_dependencies(libdablooms dablooms) add_dependencies(libdablooms dablooms)
set_property(TARGET libdablooms PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libdablooms.a) set_property(TARGET libdablooms PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libdablooms.a)
set_property(TARGET libdablooms PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include) set_property(TARGET libdablooms PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
#### Brotli
ExternalProject_Add(brotli PREFIX brotli
URL ${CMAKE_CURRENT_SOURCE_DIR}/brotli-1.0.7.tar.gz
URL_MD5 7b6edd4f2128f22794d0ca28c53898a5
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
ExternalProject_Get_Property(brotli INSTALL_DIR)
file(MAKE_DIRECTORY ${INSTALL_DIR}/include)
add_library(brotlicommon-static STATIC IMPORTED GLOBAL)
add_dependencies(brotlicommon-static brotli)
set_property(TARGET brotlicommon-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib64/libbrotlicommon-static.a)
set_property(TARGET brotlicommon-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
add_library(brotlidec-static STATIC IMPORTED GLOBAL)
add_dependencies(brotlidec-static brotli)
set_property(TARGET brotlidec-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib64/libbrotlidec-static.a)
set_property(TARGET brotlidec-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
target_link_libraries(brotlidec-static INTERFACE brotlicommon-static)
add_library(brotlienc-static STATIC IMPORTED GLOBAL)
add_dependencies(brotlienc-static brotli)
set_property(TARGET brotlienc-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib64/libbrotlienc-static.a)
set_property(TARGET brotlienc-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
target_link_libraries(brotlienc-static INTERFACE brotlicommon-static)

BIN
vendor/brotli-1.0.7.tar.gz vendored Normal file

Binary file not shown.