Commit 93045845 authored by Ghislain MARY's avatar Ghislain MARY

Handle body compression.

parent 2d03590c
......@@ -88,6 +88,7 @@ cmake_pop_check_state()
find_package(Threads)
find_package(Zlib)
find_package(Antlr3 REQUIRED)
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_INCLUDES ${ANTLR3C_INCLUDE_DIRS})
......@@ -129,6 +130,9 @@ if(ENABLE_TESTS)
set(ENABLE_TESTS OFF CACHE BOOL "Enable compilation of tests" FORCE)
endif()
endif()
if(ZLIB_FOUND)
set(HAVE_ZLIB 1)
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
......@@ -145,6 +149,9 @@ set(LIBS_PRIVATE "${LIBS_PRIVATE} -L${bctoolbox_library_path} -lbctoolbox")
if(CUNIT_FOUND)
set(REQUIRES_PRIVATE "${REQUIRES_PRIVATE} cunit")
endif()
if(ZLIB_FOUND)
set(REQUIRES_PRIVATE "${REQUIRES_PRIVATE} z")
endif()
if(HAVE_LIBDL)
set(LIBS_PRIVATE "${LIBS_PRIVATE} -ldl")
endif()
......@@ -168,6 +175,9 @@ endif()
if(CUNIT_FOUND)
include_directories(${CUNIT_INCLUDE_DIRS})
endif()
if(ZLIB_FOUND)
include_directories(${ZLIB_INCLUDE_DIRS})
endif()
if(MSVC)
include_directories(${MSVC_INCLUDE_DIR})
endif()
......
############################################################################
# FindZlib.txt
# Copyright (C) 2015 Belledonne Communications, Grenoble France
#
############################################################################
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
############################################################################
#
# - Find the zlib include file and library
#
# ZLIB_FOUND - system has zlib
# ZLIB_INCLUDE_DIRS - the zlib include directory
# ZLIB_LIBRARIES - The libraries needed to use zlib
set(_ZLIB_ROOT_PATHS
${CMAKE_INSTALL_PREFIX}
)
find_path(ZLIB_INCLUDE_DIRS
NAMES zlib.h
HINTS _ZLIB_ROOT_PATHS
PATH_SUFFIXES include
)
if(ZLIB_INCLUDE_DIRS)
set(HAVE_ZLIB_H 1)
endif()
if(ENABLE_STATIC)
if(IOS OR QNX)
set(_ZLIB_STATIC_NAMES z)
else()
set(_ZLIB_STATIC_NAMES zstatic zlibstatic zlibstaticd)
endif()
find_library(ZLIB_LIBRARIES
NAMES ${_ZLIB_STATIC_NAMES}
HINTS ${_ZLIB_ROOT_PATHS}
PATH_SUFFIXES bin lib
)
else()
find_library(ZLIB_LIBRARIES
NAMES z zlib zlibd
HINTS ${_ZLIB_ROOT_PATHS}
PATH_SUFFIXES bin lib
)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Zlib
DEFAULT_MSG
ZLIB_INCLUDE_DIRS ZLIB_LIBRARIES HAVE_ZLIB_H
)
mark_as_advanced(ZLIB_INCLUDE_DIRS ZLIB_LIBRARIES HAVE_ZLIB_H)
/***************************************************************************
* antlr3config.h.cmake
* config.h.cmake
* Copyright (C) 2014 Belledonne Communications, Grenoble France
*
****************************************************************************
......@@ -42,6 +42,7 @@
#cmakedefine HAVE_CU_GET_SUITE
#cmakedefine HAVE_TUNNEL
#cmakedefine HAVE_ZLIB
#cmakedefine BELLE_SDP_FORCE_RTP_MAP
#cmakedefine ENABLE_SERVER_SOCKETS
......@@ -52,6 +52,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);
/*
* body handler that get/puts data from application.
......
......@@ -40,6 +40,9 @@ endif()
if(HAVE_RESINIT)
list(APPEND LIBS resolv)
endif()
if(ZLIB_FOUND)
list(APPEND LIBS ${ZLIB_LIBRARIES})
endif()
if(WIN32)
list(APPEND LIBS ws2_32)
endif()
......
......@@ -17,6 +17,9 @@
*/
#include "belle_sip_internal.h"
#ifdef HAVE_ZLIB
#include "zlib.h"
#endif
/*
* Body handler base class implementation
......@@ -144,6 +147,7 @@ void belle_sip_body_handler_end_transfer(belle_sip_body_handler_t *obj){
struct belle_sip_memory_body_handler{
belle_sip_body_handler_t base;
uint8_t *buffer;
uint8_t encoding_applied;
};
static void belle_sip_memory_body_handler_destroy(belle_sip_memory_body_handler_t *obj){
......@@ -156,6 +160,7 @@ static void belle_sip_memory_body_handler_clone(belle_sip_memory_body_handler_t
memcpy(obj->buffer,orig->buffer,orig->base.expected_size);
obj->buffer[orig->base.expected_size]='\0';
}
obj->encoding_applied = orig->encoding_applied;
}
static void belle_sip_memory_body_handler_recv_chunk(belle_sip_body_handler_t *base, belle_sip_message_t *msg, size_t offset, const uint8_t *buf, size_t size){
......@@ -196,6 +201,56 @@ void belle_sip_memory_body_handler_set_buffer(belle_sip_memory_body_handler_t *o
obj->buffer = (uint8_t *)buffer;
}
#define BELLE_SIP_MEMORY_BODY_HANDLER_ZLIB_CHUNK_SIZE 16384
void belle_sip_memory_body_handler_apply_encoding(belle_sip_memory_body_handler_t *obj, const char *encoding) {
if ((obj->buffer == NULL) || (obj->encoding_applied == TRUE)) return;
#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;
ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK) return;
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;
deflate(&strm, Z_FINISH);
outbuf_ptr += avail_out - strm.avail_out;
avail_out = outbuf_size - (outbuf_ptr - outbuf);
} while (strm.avail_out == 0);
deflateEnd(&strm);
final_size = outbuf_ptr - outbuf;
belle_sip_message("Body has been compressed: %u->%u:\n%s", (unsigned int)initial_size, (unsigned int)final_size, obj->buffer);
belle_sip_free(obj->buffer);
obj->buffer = outbuf;
belle_sip_body_handler_set_size(BELLE_SIP_BODY_HANDLER(obj), final_size);
obj->encoding_applied = TRUE;
} else
#endif
{
belle_sip_warning("%s: unknown encoding '%s'", __FUNCTION__, encoding);
}
}
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);
......
......@@ -1091,6 +1091,28 @@ static void check_content_length(belle_sip_message_t *msg, size_t body_len){
}
}
static void compress_body_if_required(belle_sip_channel_t *channel) {
belle_sip_message_t *msg = channel->cur_out_message;
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);
belle_sip_memory_body_handler_apply_encoding(mbh, content_encoding);
} else {
belle_sip_warning("message [%p] has Content-Encoding [%s] that cannot be applied", msg, content_encoding);
}
}
}
static void _send_message(belle_sip_channel_t *obj){
char buffer[belle_sip_send_network_buffer_size];
size_t len=0;
......@@ -1201,6 +1223,7 @@ static void _send_message(belle_sip_channel_t *obj){
static void send_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
obj->cur_out_message=(belle_sip_message_t*)belle_sip_object_ref(msg);
obj->out_state=OUTPUT_STREAM_SENDING_HEADERS;
compress_body_if_required(obj);
_send_message(obj);
}
......
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