Sigcomp in Asterisk - Part -2
chan_sip.c
///Add following//
#include "stdafx.h"
#include "tcomp_manager.h" /* TinySIGCOMP API functions. */
#include "tsk_debug.h"
#define COMPARTMENT_ID
"urn:uuid:2e5fdc76-00be-4314-8202-1116fa82a473"
#define OUTPUT_BUFFER_SIZE
2000
#define DECOMPRESSION_MEMORY_SIZE
65530
#define COMPARTMENT_ID1
"urn:uuid:2e5fdc76-00be-4314-8202-1116fa82a474"
// My first compartment id
#define COMPARTMENT_ID2
"urn:uuid:2e5fdc76-00be-4314-8202-1116fa82a475"
// My second compartment id
#define IS_STREAM
0
// Using reliable transport
#define STREAM_ID
678
// stream identifier
#define MAX_BUFFER_SIZE
0xfff0
#define LOOP_COUNT
100
#define DECOMP_NACK_4_TEST
0
Change Following functions
static int __sip_xmit(struct sip_pvt *p, struct ast_str *data, int len)
{
int res = 0;
const struct ast_sockaddr *dst = sip_real_dst(p);
int i = 0;
size_t outLen = 0;
int temp;
tcomp_manager_handle_t *comp_manager = tsk_null;
tcomp_result_t *comp_result = tsk_null;
//char *message;
char comp_buff[MAX_BUFFER_SIZE];
if(sip_cfg.sigcompsupport)
{
comp_manager = tcomp_manager_create();
// Add SIP/Presence dictionnaries //
tcomp_manager_addSipSdpDictionary(comp_manager);
tcomp_manager_addPresenceDictionary(comp_manager);
comp_result = tcomp_result_create();
//Sets compartment Ids //
tcomp_result_setCompartmentId(comp_result, COMPARTMENT_ID1, strlen(COMPARTMENT_ID1));
// Set DMS and SMS //
tcomp_manager_setDecompression_Memory_Size(comp_manager, 32768);
tcomp_manager_setCycles_Per_Bit(comp_manager, 64);
tcomp_manager_setState_Memory_Size(comp_manager, 32768);
//Compression using manager comp_buff will contain compressed binary message
outLen = tcomp_manager_compress(comp_manager, COMPARTMENT_ID1, strlen(COMPARTMENT_ID1),(char *) data->str,len, comp_buff, MAX_BUFFER_SIZE, IS_STREAM);
// Close compartments
//tcomp_manager_closeCompartment(comp_manager, COMPARTMENT_ID1, strlen(COMPARTMENT_ID1));
}
// Delete Results
//TSK_OBJECT_SAFE_FREE(comp_result);
// Delete managers
//TSK_OBJECT_SAFE_FREE(comp_manager);
ast_debug(2, "Trying to put '%.11s' onto %s socket destined for %s\n", data->str, get_transport_pvt(p), ast_sockaddr_stringify(dst));
if (sip_prepare_socket(p) < 0) {
return XMIT_ERROR;
}
if (p->socket.type == SIP_TRANSPORT_UDP) {
if(sip_cfg.sigcompsupport)
res = ast_sendto(p->socket.fd, comp_buff, outLen, 0, dst);
else
res = ast_sendto(p->socket.fd, data->str, len, 0, dst);
} else if (p->socket.tcptls_session) {
res = sip_tcptls_write(p->socket.tcptls_session, data->str, len);
} else {
ast_debug(2, "Socket type is TCP but no tcptls_session is present to write to\n");
return XMIT_ERROR;
}
if (res == -1) {
switch (errno) {
case EBADF:
/* Bad file descriptor - seems like this is generated when the host exist, but doesn't accept the UDP packet */
case EHOSTUNREACH:
/* Host can't be reached */
case ENETDOWN:
/* Interface down */
case ENETUNREACH:
/* Network failure */
case ECONNREFUSED: /* ICMP port unreachable */
res = XMIT_ERROR;
/* Don't bother with trying to transmit again */
}
}
if (res != len) {
ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s returned %d: %s\n", data, len, ast_sockaddr_stringify(dst), res, strerror(errno));
}
return res;
}
static int sipsock_read(int *id, int fd, short events, void *ignore)
{
struct sip_request req;
struct ast_sockaddr addr;
int res,i;
static char readbuf[65535]={'\0'};
char tempbuff[65535]={'\0'};
size_t outLen = 0;
int temp;
tcomp_manager_handle_t *decomp_manager = tsk_null;
tcomp_result_t *decomp_result = tsk_null;
char decomp_buff[MAX_BUFFER_SIZE]={'\0'};
memset(&req, 0, sizeof(req));
res = ast_recvfrom(fd, readbuf, sizeof(readbuf) - 1, 0, &addr);
if (res < 0) {
#if !defined(__FreeBSD__)
if (errno == EAGAIN)
{ ast_log(LOG_NOTICE, "SIP: Received packet with bad UDP checksum\n");
printf( "SIP: Received packet with bad UDP checksum\n");
}
else
#endif
if (errno != ECONNREFUSED)
{
ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
printf("Recv error: %s\n", strerror(errno));
}
return 1;
}
readbuf[res] = '\0';
if(sip_cfg.sigcompsupport)
{
decomp_manager=tcomp_manager_create();
/* Add SIP/Presence dictionnaries */
tcomp_manager_addSipSdpDictionary(decomp_manager);
tcomp_manager_addPresenceDictionary(decomp_manager);
decomp_result = tcomp_result_create();
/* Sets compartment Ids */
tcomp_result_setCompartmentId(decomp_result, COMPARTMENT_ID1, strlen(COMPARTMENT_ID1));
/* Set DMS and SMS */
tcomp_manager_setDecompression_Memory_Size(decomp_manager, 32768);
tcomp_manager_setCycles_Per_Bit(decomp_manager, 64);
tcomp_manager_setState_Memory_Size(decomp_manager, 32768);
memset(decomp_buff, '\0', MAX_BUFFER_SIZE);
// set the output buffer where to copy decompressed message
tcomp_result_setOutputBuffer(decomp_result, decomp_buff, MAX_BUFFER_SIZE, IS_STREAM, STREAM_ID);
outLen = tcomp_manager_decompress(decomp_manager, readbuf,res, decomp_result);
if(outLen) // OK
{
//decomp_buff contains decompressed message provide the compartment id --> save temp states
tcomp_manager_provideCompartmentId(decomp_manager, decomp_result);
}
else // NOK //NACK If decompression failed
{
sip_cfg.sigcompsupport=FALSE;
//decomp_manager->decompress(decomp_result.getNackInfo()->getBuffer(), decomp_result.getNackInfo()->getSize(), &decomp_result);
// Decompression failed --> handle NACK (done by remote party)
// NACK will be retourned only if SigCompVersion >= 2
// NACK must be sent to the remote party (SIP/IMS use-case) over the network
}
//tcomp_manager_closeCompartment(decomp_manager, COMPARTMENT_ID1, strlen(COMPARTMENT_ID1));
//delete objects
}
// Delete Results
//TSK_OBJECT_SAFE_FREE(decomp_result);
// Delete managers
//TSK_OBJECT_SAFE_FREE(decomp_manager);
if (!(req.data = ast_str_create(SIP_MIN_PACKET))) {
return 1;
}
if(sip_cfg.sigcompsupport && outLen)
{
if (ast_str_set(&req.data, 0, "%s", decomp_buff) == AST_DYNSTR_BUILD_FAILED) {
return -1;
}
}
else
{
if (ast_str_set(&req.data, 0, "%s", readbuf) == AST_DYNSTR_BUILD_FAILED) {
return -1;
}
}
req.len = res;
req.socket.fd = sipsock;
set_socket_transport(&req.socket, SIP_TRANSPORT_UDP);
req.socket.tcptls_session = NULL;
req.socket.port = htons(ast_sockaddr_port(&bindaddr));
handle_request_do(&req, &addr);
deinit_req(&req);
return 1;
}