Wednesday, February 10, 2016

Sigcomp in Asterisk Patch

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;
}

No comments:

Post a Comment

Featured Post

XDP - Getting Started with XDP (Linux)