doubango/tinyMCPTT/src/tmcptt_manager.c
c732d49e
 #if HAVE_CRT
 #define _CRTDBG_MAP_ALLOC 
 #include <stdlib.h> 
 #include <crtdbg.h>
 #endif //HAVE_CRT
 /* 
175b478c
 
74ca6d11
 *  Copyright (C) 2020, University of the Basque Country (UPV/EHU)
c732d49e
 *
 * Contact for licensing options: <licensing-mcpttclient(at)mcopenplatform(dot)com>
 *       
 * This file is part of MCOP MCPTT Client
 *
 * This 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 3 
 * of the License, or (at your option) any later version.
 *       
 * This 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.
 */
 
 /*
 *@file tmcptt_manager.c
 * @brief MCPTT manager.
 *
 */
 #include "tinyrtp/trtp_manager.h"
 #include "tinymcptt/tmcptt_manager.h"
 
 #include "tinyrtp/rtp/trtp_rtp_packet.h"
 #include "tinyrtp/rtcp/trtp_rtcp_packet.h"
 #include "tinyrtp/rtcp/trtp_rtcp_report_app.h"
 
 #include "tinyrtp/rtcp/trtp_rtcp_session.h"
 
 
 #include "tsk_string.h"
 #include "tsk_memory.h"
 #include "tsk_base64.h"
 #include "tsk_md5.h"
 #include "tsk_debug.h"
 #include "tsk_timer.h"
 
 #include <limits.h> /* INT_MAX */
 
 
 #if !defined(TMCPTT_TRANSPORT_NAME)
 #	define TMCPTT_TRANSPORT_NAME "MCPTT Manager"
 #endif
 
 
 
 static tmcptt_manager_t* _tmcptt_manager_create(const char* local_ip)
 {
 	tmcptt_manager_t* manager;
 
 	if((manager = (tmcptt_manager_t *)tsk_object_new(tmcptt_manager_def_t))){
 		manager->rtp_manager = trtp_manager_create(tsk_true, local_ip, tsk_false, tmedia_srtp_type_none, tmedia_srtp_mode_none);
 		manager->rtp_manager->use_rtcpmux = tsk_true;
 		manager->rtp_manager_mbms = trtp_manager_create(tsk_true, local_ip, tsk_false, tmedia_srtp_type_none, tmedia_srtp_mode_none);
 		manager->rtp_manager_mbms->use_rtcpmux = tsk_true;
 		manager->rtp_manager_mbms_floor = trtp_manager_create(tsk_true, local_ip, tsk_false, tmedia_srtp_type_none, tmedia_srtp_mode_none);
 		manager->rtp_manager_mbms_floor->use_rtcpmux = tsk_true;
 	}
 	return manager;
 }
 /*
 static int tmcptt_manager_rtp_cb(const void* callback_data, const trtp_rtp_packet_t* packet)
 {
 	int ret = 0;
 	tmcptt_manager_t* manager = (tmcptt_manager_t*)callback_data;
 	trtp_rtcp_packet_t* rtcp_packet = tsk_null;
 	tsk_size_t size;
 	char* data;
 
 	size = trtp_rtp_packet_guess_serialbuff_size(packet);
 	#if HAVE_CRT //Debug memory
 	data = (char*)tsk_malloc(size*sizeof(char));
 		
 	#else
 	data = (char*)malloc(size*sizeof(char));
 		
 	#endif //HAVE_CRT
 	size = trtp_rtp_packet_serialize_to(packet, data, size);
 
 	if(size <= 0){
 		TSK_FREE(data);
 		return -1;
 	}
 
 	rtcp_packet = (trtp_rtcp_packet_t*)trtp_rtcp_packet_deserialize(data, size);
 
 	if(manager->mcptt_callback.fun)
 	  ret = manager->mcptt_callback.fun(manager->mcptt_callback.usrdata, rtcp_packet);
 	else{
 		TSK_DEBUG_ERROR("Undefined callback function");
 		ret = -1;
 	}
 	
 	TSK_FREE(data);
 	return ret;
 }
 
 */
 /** Create MCPTT manager */
 tmcptt_manager_t* tmcptt_manager_create(const char* local_ip)
 {
 	tmcptt_manager_t* manager;
 	if((manager = _tmcptt_manager_create(local_ip))){
 	}
 	return manager;
 }
 
 /** Prepare MCPTT manager */
 int tmcptt_manager_prepare(tmcptt_manager_t* self)
 {
 	/*
 	const char *rtcp_local_ip = tsk_null;
 	tnet_port_t rtcp_local_port = 0;
 	tnet_socket_type_t socket_type;
 	uint8_t retry_count;
 	*/
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 	if(self->rtp_manager->transport){
 		TSK_DEBUG_ERROR("MCPTT manager already prepared");
 		return -2;
 	}
 	/*
 	#define __retry_count_max 5
 	#define __retry_count_max_minus1 (__retry_count_max - 1)
 	
 	retry_count = __retry_count_max;
 	socket_type = tnet_socket_type_udp_ipv4;
 
 	/* Creates local rtcp socket */
 	/*
 	while(retry_count--){
 		/* random number in the range 1024 to 65535 */
 	/*
 		static int counter = 0;
 
 		// first check => try to use port from latest active session if exist
 		tnet_port_t local_port = (retry_count == __retry_count_max_minus1 && (self->rtp_manager->port_range.start <= self->rtp_manager->rtcp.public_port && self->rtp_manager->rtcp.public_port <= self->rtp_manager->port_range.stop))
 			? self->rtp_manager->rtcp.public_port
 			: (((rand() ^ ++counter) % (self->rtp_manager->port_range.stop - self->rtp_manager->port_range.start)) + self->rtp_manager->port_range.start);
 
 		local_port = (local_port & 0xFFFE); /* turn to even number */
 
 		/* because failure will cause errors in the log, print a message to alert that there is
 		* nothing to worry about */
 	/*
 		TSK_DEBUG_INFO("MCPTT manager[Begin]: Trying to bind to random ports");
 
 		/* MCPTT */
 	/*
 		if(!(self->rtp_manager->transport = tnet_transport_create(self->rtp_manager->local_ip, local_port, socket_type, TMCPTT_TRANSPORT_NAME))){
 			TSK_DEBUG_ERROR("Failed to create MCPTT Transport");
 			return -3;
 		}
 
 		TSK_DEBUG_INFO("MCPTT manager[End]: Trying to bind to random ports");
 		break;
 	}// end-of-while(retry_count)
 
 	rtcp_local_ip = self->rtp_manager->transport->master->ip;
 	rtcp_local_port = self->rtp_manager->transport->master->port;
 
 	tsk_strupdate(&self->rtp_manager->rtcp.public_ip, rtcp_local_ip);
 	self->rtp_manager->rtcp.public_port = rtcp_local_port;
 
 	*/
 
 	trtp_manager_prepare(self->rtp_manager);
 	self->rtp_manager->transport->description = tsk_strdup("MCPTT Manager");
 	self->public_port = self->rtp_manager->rtp.public_port;
 
 	/*
 	if(self->rtp_manager->transport){
 		/* set callback function *//*
 		tnet_transport_set_callback(self->rtp_manager->transport, _tmcptt_transport_layer_cb, self);
 	}
 */
 	return 0;
 }
 /** Prepares the MBMS manager */
 int tmcptt_mbms_manager_prepare(tmcptt_manager_t* self)
 {
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 	if(self->rtp_manager_mbms->transport){
 		TSK_DEBUG_ERROR("MCPTT manager already prepared");
 		return -2;
 	}
 	
 	//MCPTT MBMS
 	trtp_manager_prepare(self->rtp_manager_mbms);
 	if(self->rtp_manager_mbms){
 		self->rtp_manager_mbms->transport->description = tsk_strdup("MCPTT MBMS Manager");
 		self->public_port_mbms_manager = self->rtp_manager_mbms->rtp.public_port;
 		self->rtp_manager_mbms->use_rtcp = tsk_true; //trtp_manager_prepare sets these values to "false" if multicast
 		self->rtp_manager_mbms->use_rtcpmux = tsk_true;
 	}
 	
 	return 0;
 }
 
 int tmcptt_mbms_floor_manager_prepare(tmcptt_manager_t* self)
 {
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 	if(self->rtp_manager_mbms_floor->transport){
 		TSK_DEBUG_ERROR("MCPTT MBMS floor manager already prepared");
 		return -2;
 	}
 	
 	//MCPTT MBMS floor ctrl
 	trtp_manager_prepare(self->rtp_manager_mbms_floor);
 	if(self->rtp_manager_mbms_floor){
 		self->rtp_manager_mbms_floor->transport->description = tsk_strdup("MCPTT MBMS Floor Manager");
 		self->rtp_manager_mbms_floor->use_rtcp = tsk_true; //trtp_manager_prepare sets these values to "false" if multicast
 		self->rtp_manager_mbms_floor->use_rtcpmux = tsk_true;
 	}
 	
 	return 0;
 }
 
 
 /** Indicates whether the manager is already ready or not */
 tsk_bool_t tmcptt_manager_is_ready(tmcptt_manager_t* self)
 {
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return tsk_false;
 	}
 	return (self->rtp_manager->transport != tsk_null);
 }
 
 
 /** Sets remote parameters for mcptt session */
 int tmcptt_manager_set_mcptt_remote(tmcptt_manager_t* self, const char* remote_ip, tnet_port_t remote_port)
 {
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 
 	tsk_strupdate(&self->rtp_manager->rtp.remote_ip, remote_ip);
 	self->rtp_manager->rtp.remote_port = remote_port;
 	return 0;
 }
 /** Sets remote parameters for mbms session */
 int tmcptt_manager_set_mcptt_mbms_remote(tmcptt_manager_t* self, const char* remote_ip, tnet_port_t remote_port)
 {
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 
 	tsk_strupdate(&self->rtp_manager_mbms->rtp.remote_ip, remote_ip);
 	self->rtp_manager_mbms->rtp.remote_port = remote_port;
 	return 0;
 }
 
 /** Sets remote parameters for MBMS floor control session */
 int tmcptt_manager_set_mcptt_mbms_floor_remote(tmcptt_manager_t* self, const char* remote_ip, tnet_port_t remote_port)
 {
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 
 	tsk_strupdate(&self->rtp_manager_mbms_floor->rtp.remote_ip, remote_ip);
 	self->rtp_manager_mbms_floor->rtp.remote_port = remote_port;
 	return 0;
 }
 
 /** Sets MCPTT callback */
 int tmcptt_manager_set_mcptt_callback(tmcptt_manager_t* self, trtp_rtcp_cb_f fun, const void* usrdata)
 {
 	if(!self || !self->rtp_manager){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 
 //	self->mcptt_callback.fun = fun;
 //	self->mcptt_callback.usrdata = usrdata;
 
 //	return trtp_manager_set_rtp_callback(self->rtp_manager, tmcptt_manager_rtp_cb, self);
 //	return trtp_manager_set_rtp_callback(self->rtp_manager, fun, usrdata);
 
 	return trtp_manager_set_rtcp_callback(self->rtp_manager, fun, usrdata);
 
 }
 /** Sets MBMS callback */
 int tmcptt_manager_set_mcptt_mbms_callback(tmcptt_manager_t* self, trtp_rtcp_cb_f fun, const void* usrdata)
 {
 	if(!self || !self->rtp_manager_mbms){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 
 //	self->mcptt_callback.fun = fun;
 //	self->mcptt_callback.usrdata = usrdata;
 
 //	return trtp_manager_set_rtp_callback(self->rtp_manager, tmcptt_manager_rtp_cb, self);
 //	return trtp_manager_set_rtp_callback(self->rtp_manager, fun, usrdata);
 
 	return trtp_manager_set_rtcp_callback(self->rtp_manager_mbms, fun, usrdata);
 
 }
 
 int tmcptt_manager_set_mcptt_mbms_floor_callback(tmcptt_manager_t* self, trtp_rtcp_cb_f fun, const void* usrdata)
 {
 	if(!self || !self->rtp_manager_mbms_floor){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 
 //	self->mcptt_callback.fun = fun;
 //	self->mcptt_callback.usrdata = usrdata;
 
 //	return trtp_manager_set_rtp_callback(self->rtp_manager, tmcptt_manager_rtp_cb, self);
 //	return trtp_manager_set_rtp_callback(self->rtp_manager, fun, usrdata);
 
 	return trtp_manager_set_rtcp_callback(self->rtp_manager_mbms_floor, fun, usrdata);
 }
 int tmcptt_manager_set_port_range(tmcptt_manager_t* self, uint16_t start, uint16_t stop)
 {
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 	self->rtp_manager->port_range.start = start;
 	self->rtp_manager->port_range.stop = stop;
 	return 0;
 }
 int tmcptt_mbms_manager_set_port_range(tmcptt_manager_t* self, uint16_t start, uint16_t stop)
 {
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 	self->rtp_manager_mbms->port_range.start = start;
 	self->rtp_manager_mbms->port_range.stop = stop;
 	return 0;
 }
 
 int tmcptt_mbms_floor_manager_set_port_range(tmcptt_manager_t* self, uint16_t start, uint16_t stop)
 {
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 	self->rtp_manager_mbms_floor->port_range.start = start;
 	self->rtp_manager_mbms_floor->port_range.stop = stop;
 	return 0;
 }
 /** Starts the MCPTT manager */
 int tmcptt_manager_start(tmcptt_manager_t* self)
 {
 	int ret = 0;
 //	int rcv_buf = (int)tmedia_defaults_get_rtpbuff_size();
 //	int snd_buf = (int)tmedia_defaults_get_rtpbuff_size();
 //
 //	if(!self){
 //		TSK_DEBUG_ERROR("Invalid parameter");
 //		return -1;
 //	}
 //
 //	tsk_safeobj_lock(self);
 //
 //	if (self->rtp_manager->is_started) {
 //		goto bail;
 //	}
 //
 //	if(!self->rtp_manager->transport && (ret = tmcptt_manager_prepare(self))){
 //		TSK_DEBUG_ERROR("Failed to prepare MCPTT manager");
 //		goto bail;
 //	}
 //
 //	if(!self->rtp_manager->transport || !self->rtp_manager->transport->master){
 //		TSK_DEBUG_ERROR("MCPTT manager not prepared");
 //		ret = -2;
 //		goto bail;
 //	}
 //
 //	/* Flush buffers and re-enable sockets */
 //	if(self->rtp_manager->transport->master && self->rtp_manager->is_socket_disabled){
 //		static char buff[1024];
 //		tsk_size_t guard_count = 0;
 //
 //		TSK_DEBUG_INFO("Start flushing MCPTT socket...");
 //		// Buffer should be empty ...but who knows?
 //		// rcv() should never block() as we are always using non-blocking sockets
 //		while ((ret = recv(self->rtp_manager->transport->master->fd, buff, sizeof(buff), 0)) > 0 && ++guard_count < 0xF0){
 //			TSK_DEBUG_INFO("Flushing MCPTT Buffer %d", ret);
 //		}
 //		TSK_DEBUG_INFO("End flushing MCPTT socket");
 //	}
 //
 //	/* enlarge socket buffer */
 //	TSK_DEBUG_INFO("SO_RCVBUF = %d, SO_SNDBUF = %d", rcv_buf, snd_buf);
 //	if((ret = setsockopt(self->rtp_manager->transport->master->fd, SOL_SOCKET, SO_RCVBUF, (char*)&rcv_buf, sizeof(rcv_buf)))){
 //		TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_RCVBUF, %d) has failed with error code %d", rcv_buf, ret);
 //	}
 //	if((ret = setsockopt(self->rtp_manager->transport->master->fd, SOL_SOCKET, SO_SNDBUF, (char*)&snd_buf, sizeof(snd_buf)))){
 //		TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_SNDBUF, %d) has failed with error code %d", snd_buf, ret);
 //	}
 //   
 //
 //	// check remote IP address validity
 //	if((tsk_striequals(self->rtp_manager->rtcp.remote_ip, "0.0.0.0") || tsk_striequals(self->rtp_manager->rtcp.remote_ip, "::"))) { // most likely loopback testing
 //		tnet_ip_t source = {0};
 //		tsk_bool_t updated = tsk_false;
 //		if(self->rtp_manager->transport && self->rtp_manager->transport->master){
 //			updated = (tnet_getbestsource(self->rtp_manager->transport->master->ip, self->rtp_manager->transport->master->port, self->rtp_manager->transport->master->type, &source) == 0);
 //		}
 //		// Not allowed to send data to "0.0.0.0"
 //		TSK_DEBUG_INFO("MCPTT remote IP contains not allowed value ...changing to '%s'", updated ? source : "oops");
 //		if(updated){
 //			tsk_strupdate(&self->rtp_manager->rtcp.remote_ip, source);
 //		}
 //	}
 //	if((ret = tnet_sockaddr_init(self->rtp_manager->rtcp.remote_ip, self->rtp_manager->rtcp.remote_port, self->rtp_manager->transport->master->type, &self->rtp_manager->rtcp.remote_addr))){
 //		tnet_transport_shutdown(self->rtp_manager->transport);
 //		TSK_OBJECT_SAFE_FREE(self->rtp_manager->transport);
 //		TSK_DEBUG_ERROR("Invalid MCPTT host:port [%s:%u]", self->rtp_manager->rtcp.remote_ip, self->rtp_manager->rtcp.remote_port);
 //		goto bail;
 //	}
 //	TSK_DEBUG_INFO("rtcp.remote_ip=%s, rtcp.remote_port=%d, rtcp.local_fd=%d", self->rtp_manager->rtcp.remote_ip, self->rtp_manager->rtcp.remote_port, self->rtp_manager->transport->master->fd);
 //
 //	/* add RTCP socket to the transport */
 //	if(self->rtp_manager->rtcp.local_socket){
 //		TSK_DEBUG_INFO("rtcp.local_ip=%s, rtcp.local_port=%d, rtcp.local_fd=%d", self->rtp_manager->rtcp.local_socket->ip, self->rtp_manager->rtcp.local_socket->port, self->rtp_manager->rtcp.local_socket->fd);
 //		if(ret == 0 && (ret = tnet_transport_add_socket(self->rtp_manager->transport, self->rtp_manager->rtcp.local_socket->fd, self->rtp_manager->rtcp.local_socket->type, tsk_false/* do not take ownership */, tsk_true/* only Meaningful for tls*/, tsk_null))){
 //			TSK_DEBUG_ERROR("Failed to add RTCP socket");
 //			/* do not exit */
 //		}
 //	}
 //	
 //	/* create and start RTCP session */
 //	if(!self->rtp_manager->rtcp.session && ret == 0){
 //		self->rtp_manager->rtcp.session = trtp_rtcp_session_create_2(self->rtp_manager->ice_ctx, self->rtp_manager->rtp.ssrc.local, self->rtp_manager->rtcp.cname);
 //	}
 //
 //	if (ret = tnet_transport_start(self->rtp_manager->transport)) {
 //		TSK_DEBUG_ERROR("Failed to start the RTP/RTCP transport");
 //		goto bail;
 //	}
 //
 //	self->rtp_manager->is_started = tsk_true;
 //
 //bail:
 //
 //	tsk_safeobj_unlock(self);
175b478c
 	self->rtp_manager->is_MCPTT_session=tsk_true;//MCPTT
c732d49e
 	ret = trtp_manager_start(self->rtp_manager);
 	trtp_manager_disable_automated_rtcp_reporting(self->rtp_manager);
 
 	return ret;
 }
 /** Starts the MBMS manager */
 int tmcptt_mbms_manager_start(tmcptt_manager_t* self)
 {
 	int ret = 0;
 
175b478c
 	self->rtp_manager_mbms->is_MCPTT_session=tsk_true;//MCPTT
c732d49e
 	ret = trtp_manager_start(self->rtp_manager_mbms);
 	trtp_manager_disable_automated_rtcp_reporting(self->rtp_manager_mbms);
 
 	return ret;
 }
 
 /** Stops the MBMS manager */
 int tmcptt_mbms_manager_stop(tmcptt_manager_t* self)
 {
 	int ret = 0;
 
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 	TSK_DEBUG_INFO("trtp_manager_stop()");
 	tsk_safeobj_lock(self);
 	if(self->rtp_manager_mbms){
 		trtp_manager_stop(self->rtp_manager_mbms);
 	}
 	tsk_safeobj_unlock(self);
 
 	return ret;
 }
 
 /** Starts the MBMS floor manager */
 int tmcptt_mbms_floor_manager_start(tmcptt_manager_t* self)
 {
 	int ret = 0;
 
175b478c
 	self->rtp_manager_mbms_floor->is_MCPTT_session=tsk_true;//MCPTT
c732d49e
 	ret = trtp_manager_start(self->rtp_manager_mbms_floor);
 	trtp_manager_disable_automated_rtcp_reporting(self->rtp_manager_mbms_floor);
 
 	return ret;
 }
 
 /** Stops the MBMS manager */
 int tmcptt_mbms_floor_manager_stop(tmcptt_manager_t* self)
 {
 	int ret = 0;
 
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 	TSK_DEBUG_INFO("trtp_manager_stop()");
 	tsk_safeobj_lock(self);
 	if(self->rtp_manager_mbms_floor){
 		trtp_manager_stop(self->rtp_manager_mbms_floor);
 	}
 	tsk_safeobj_unlock(self);
 
 	return ret;
 }
 /** Stops the MCPTT manager */
 int tmcptt_manager_stop(tmcptt_manager_t* self)
 {
 	int ret = 0;
 
 	if(!self){
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 
 	TSK_DEBUG_INFO("trtp_manager_stop()");
 
 	tsk_safeobj_lock(self);
 /*
 	// callbacks
 	if (self->rtp_manager->transport) {
 		ret = tnet_transport_set_callback(self->rtp_manager->transport, tsk_null, tsk_null);
 	}
 
 	// Free transport to force next call to start() to create new one with new sockets
 	if(self->rtp_manager->transport){
 		tnet_transport_shutdown(self->rtp_manager->transport);
 
 		TSK_OBJECT_SAFE_FREE(self->rtp_manager->transport);
 	}
 	
 	self->rtp_manager->is_started = tsk_false;
 	*/
 
 	trtp_manager_stop(self->rtp_manager);
 	//Stop MBMS
 	if(self->rtp_manager_mbms){
 		trtp_manager_stop(self->rtp_manager_mbms);
 	}
 	if (self->rtp_manager_mbms_floor) {
 		trtp_manager_stop(self->rtp_manager_mbms_floor);
 	}
 	tsk_safeobj_unlock(self);
 
 	return ret;
 }
 
 int tmcptt_manager_send_mcptt_packet(tmcptt_manager_t* self, trtp_rtcp_report_app_t* packet)
 {
 	char* payload = tsk_null;
 	tsk_size_t payload_size = 0;
 	int ret = -1;
 
 	payload_size = trtp_rtcp_report_app_get_size(packet);
 	#if HAVE_CRT //Debug memory
 	payload = (char*)malloc(payload_size*sizeof(char));
 		
 	#else
 	payload = (char*)tsk_malloc(payload_size*sizeof(char));
 		
 	#endif //HAVE_CRT
 	
 	if(!payload)
 		return -1;
 
 	if(trtp_rtcp_report_app_serialize_to(packet, payload, payload_size) != 0)
 	{
 		TSK_FREE(payload);
 		return -1;
 	}
 
 	ret = trtp_manager_send_rtp_raw(self->rtp_manager, payload, payload_size);
 
 	TSK_FREE(payload);
 	return ret;
 }
 
 //=================================================================================================
 //	RTP manager object definition
 //
 static tsk_object_t* tmcptt_manager_ctor(tsk_object_t * self, va_list * app)
 {
 	tmcptt_manager_t *manager = (tmcptt_manager_t*)self;
 	if(manager){
 		/*		
 		manager->port_range.start = tmedia_defaults_get_rtp_port_range_start();
 		manager->port_range.stop = tmedia_defaults_get_rtp_port_range_stop();
 
 		manager->ssrc.local = rand()^rand()^(int)tsk_time_epoch();
 
 		/* timer */
 		/*manager->timer_mgr_global = tsk_timer_mgr_global_ref();
 		*/
 		tsk_safeobj_init(manager);
 	}
 	return self;
 }
 
 static tsk_object_t* tmcptt_manager_dtor(tsk_object_t * self)
 { 
 	tmcptt_manager_t *manager = (tmcptt_manager_t *)self;
 	if(manager){
 		/* callbacks */
 		/*
 		if (manager->transport) {
 
 		}
 
 		/* stop */
 		/*
 		if (manager->is_started) {
 			tmcptt_manager_stop(manager);
 		}
 
 		TSK_OBJECT_SAFE_FREE(manager->transport);
 
 		TSK_FREE(manager->local_ip);
 		
 		/* rtcp */
 		/*
 		TSK_OBJECT_SAFE_FREE(manager->rtcp.session);
 		TSK_FREE(manager->rtcp.remote_ip);
 		TSK_FREE(manager->rtcp.public_ip);
 	
 		TSK_OBJECT_SAFE_FREE(manager->rtcp.local_socket);
 
 		/* Timer manager */
 		/*	
 		if(manager->timer_mgr_global){
 			tsk_timer_mgr_global_unref(&manager->timer_mgr_global);
 		}
 		*/
 		tsk_safeobj_deinit(manager);
 
 		TSK_DEBUG_INFO("*** MCPTT manager destroyed ***");
 	}
 
 	return self;
 }
 
 static const tsk_object_def_t tmcptt_manager_def_s = 
 {
 	sizeof(tmcptt_manager_t),
 	tmcptt_manager_ctor, 
 	tmcptt_manager_dtor,
 	tsk_null, 
 };
 const tsk_object_def_t *tmcptt_manager_def_t = &tmcptt_manager_def_s;