2018-09-26 21:31:17 +08:00
|
|
|
#include <zlib.h>
|
|
|
|
|
#include <http_common.h>
|
|
|
|
|
#include <http_half.h>
|
|
|
|
|
#include <http_convert.h>
|
|
|
|
|
|
|
|
|
|
struct hf_content_converter
|
|
|
|
|
{
|
|
|
|
|
/* MODE AND CALLBACKS */
|
|
|
|
|
enum hf_content_conv_work_mode mode;
|
|
|
|
|
unsigned int content_encode;
|
|
|
|
|
hf_private_cb * data_cb;
|
|
|
|
|
void * data_cb_user;
|
|
|
|
|
|
|
|
|
|
/* ZLIB STREAM */
|
|
|
|
|
z_stream * z_stream_ptr;
|
|
|
|
|
unsigned char * chunk;
|
|
|
|
|
size_t sz_chunk;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void hf_content_converter_destroy(struct hf_content_converter * cv_object)
|
|
|
|
|
{
|
|
|
|
|
if (cv_object->z_stream_ptr && cv_object->mode == HF_CONTENT_CONV_COMPRASS)
|
|
|
|
|
{
|
|
|
|
|
(void)deflateEnd(cv_object->z_stream_ptr);
|
|
|
|
|
free(cv_object->z_stream_ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cv_object->z_stream_ptr && cv_object->mode == HF_CONTENT_CONV_UNCOMPRASS)
|
|
|
|
|
{
|
|
|
|
|
(void)inflateEnd(cv_object->z_stream_ptr);
|
|
|
|
|
free(cv_object->z_stream_ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cv_object->z_stream_ptr = NULL;
|
|
|
|
|
free(cv_object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct hf_content_converter * hf_content_converter_create(enum hf_content_conv_work_mode mode,
|
|
|
|
|
unsigned int content_encode, hf_private_cb * data_cb, void * data_cb_user)
|
|
|
|
|
{
|
|
|
|
|
struct hf_content_converter * cv_object = ALLOC(struct hf_content_converter, 1);
|
|
|
|
|
assert(data_cb != NULL);
|
|
|
|
|
|
|
|
|
|
cv_object->mode = mode;
|
|
|
|
|
cv_object->content_encode = content_encode;
|
|
|
|
|
cv_object->data_cb = data_cb;
|
|
|
|
|
cv_object->data_cb_user = data_cb_user;
|
|
|
|
|
|
|
|
|
|
/* ZSTREAM */
|
|
|
|
|
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)
|
|
|
|
|
cv_object->chunk = (unsigned char *)malloc(CHUNK_SIZE);
|
|
|
|
|
cv_object->sz_chunk = CHUNK_SIZE;
|
|
|
|
|
|
|
|
|
|
int ret = 0;
|
|
|
|
|
if (content_encode == HTTP_ACCEPT_ENCODING_GZIP)
|
|
|
|
|
{
|
|
|
|
|
ret = inflateInit2(cv_object->z_stream_ptr, MAX_WBITS + 16);
|
|
|
|
|
}
|
|
|
|
|
else if (content_encode == HTTP_ACCEPT_ENCODING_DEFLATE)
|
|
|
|
|
{
|
2018-09-27 15:12:18 +08:00
|
|
|
ret = inflateInit2(cv_object->z_stream_ptr, -MAX_WBITS);
|
2018-09-26 21:31:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret != Z_OK) goto __errout;
|
|
|
|
|
return cv_object;
|
|
|
|
|
|
|
|
|
|
__errout:
|
|
|
|
|
free(cv_object->z_stream_ptr);
|
|
|
|
|
free(cv_object->chunk);
|
|
|
|
|
free(cv_object);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int hf_content_converter_write(struct hf_content_converter * 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);
|
|
|
|
|
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;
|
|
|
|
|
}
|