Commit a4645ba6 authored by Ghislain MARY's avatar Ghislain MARY

Handle body handler decompression.

parent 93045845
......@@ -53,6 +53,7 @@ BELLESIP_EXPORT belle_sip_memory_body_handler_t *belle_sip_memory_body_handler_n
BELLESIP_EXPORT void *belle_sip_memory_body_handler_get_buffer(const belle_sip_memory_body_handler_t *obj);
BELLESIP_EXPORT void belle_sip_memory_body_handler_set_buffer(belle_sip_memory_body_handler_t *obj, void *buffer);
BELLESIP_EXPORT void belle_sip_memory_body_handler_apply_encoding(belle_sip_memory_body_handler_t *obj, const char *encoding);
BELLESIP_EXPORT int belle_sip_memory_body_handler_unapply_encoding(belle_sip_memory_body_handler_t *obj, const char *encoding);
/*
* body handler that get/puts data from application.
......
......@@ -251,6 +251,66 @@ void belle_sip_memory_body_handler_apply_encoding(belle_sip_memory_body_handler_
}
}
int belle_sip_memory_body_handler_unapply_encoding(belle_sip_memory_body_handler_t *obj, const char *encoding) {
if (obj->buffer == NULL) return -1;
#ifdef HAVE_ZLIB
if (strcmp(encoding, "deflate") == 0) {
z_stream strm;
size_t initial_size = belle_sip_body_handler_get_size(BELLE_SIP_BODY_HANDLER(obj));
size_t final_size;
unsigned int avail_out = BELLE_SIP_MEMORY_BODY_HANDLER_ZLIB_CHUNK_SIZE;
unsigned int outbuf_size = avail_out;
unsigned char *outbuf = belle_sip_malloc(outbuf_size);
unsigned char *outbuf_ptr = outbuf;
int ret;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&strm);
if (ret != Z_OK) return -1;
strm.avail_in = initial_size;
strm.next_in = obj->buffer;
do {
if (avail_out < BELLE_SIP_MEMORY_BODY_HANDLER_ZLIB_CHUNK_SIZE) {
unsigned int cursize = outbuf_ptr - outbuf;
outbuf_size += BELLE_SIP_MEMORY_BODY_HANDLER_ZLIB_CHUNK_SIZE;
outbuf = belle_sip_realloc(outbuf, outbuf_size);
outbuf_ptr = outbuf + cursize;
}
strm.avail_out = avail_out;
strm.next_out = outbuf_ptr;
ret = inflate(&strm, Z_NO_FLUSH);
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&strm);
belle_sip_free(outbuf);
return -1;
}
outbuf_ptr += avail_out - strm.avail_out;
avail_out = outbuf_size - (outbuf_ptr - outbuf);
} while (ret != Z_STREAM_END);
inflateEnd(&strm);
final_size = outbuf_ptr - outbuf;
belle_sip_message("Body has been uncompressed: %u->%u:\n%s", (unsigned int)initial_size, (unsigned int)final_size, outbuf);
belle_sip_free(obj->buffer);
obj->buffer = outbuf;
belle_sip_body_handler_set_size(BELLE_SIP_BODY_HANDLER(obj), final_size);
return 0;
} else
#endif
{
belle_sip_warning("%s: unknown encoding '%s'", __FUNCTION__, encoding);
return -1;
}
}
belle_sip_memory_body_handler_t *belle_sip_memory_body_handler_new(belle_sip_body_handler_progress_callback_t cb, void *user_data){
belle_sip_memory_body_handler_t *obj=belle_sip_object_new(belle_sip_memory_body_handler_t);
belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,cb,user_data);
......
......@@ -290,11 +290,35 @@ static void belle_sip_channel_learn_public_ip_port(belle_sip_channel_t *obj, bel
obj->learnt_ip_port=TRUE;
}
static void uncompress_body_if_required(belle_sip_message_t *msg) {
belle_sip_body_handler_t *bh = belle_sip_message_get_body_handler(msg);
belle_sip_memory_body_handler_t *mbh = NULL;
belle_sip_header_t *ceh = NULL;
size_t body_len = 0;
if (bh != NULL) {
body_len = belle_sip_message_get_body_size(msg);
ceh = belle_sip_message_get_header(msg, "Content-Encoding");
}
if ((body_len > 0) && (ceh != NULL)) {
const char *content_encoding = belle_sip_header_get_unparsed_value(ceh);
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(bh, belle_sip_memory_body_handler_t)) {
mbh = BELLE_SIP_MEMORY_BODY_HANDLER(bh);
if (belle_sip_memory_body_handler_unapply_encoding(mbh, content_encoding) == 0) {
belle_sip_message_remove_header_from_ptr(msg, ceh);
}
} else {
belle_sip_warning("message [%p] has Content-Encoding [%s] that cannot be unapplied", msg, content_encoding);
}
}
}
static void belle_sip_channel_message_ready(belle_sip_channel_t *obj){
belle_sip_message_t *msg=obj->input_stream.msg;
belle_sip_body_handler_t *bh=belle_sip_message_get_body_handler(msg);
if (bh) belle_sip_body_handler_end_transfer(bh);
if (belle_sip_message_is_response(msg)) belle_sip_channel_learn_public_ip_port(obj,BELLE_SIP_RESPONSE(msg));
uncompress_body_if_required(msg);
obj->incoming_messages=belle_sip_list_append(obj->incoming_messages,msg);
obj->stop_logging_buffer=0;
belle_sip_channel_input_stream_reset(&obj->input_stream);
......
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