doubango/tinyNET/src/mbms/tnet_mbms.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 tnet_mbms.c
  * @brief 3GPP MBMS
  */
 
 #include "tnet_mbms.h"
 
 #include "../tnet_endianness.h"
 
 #include "tsk_string.h"
 #include "tsk_memory.h"
 #include "tsk_debug.h"
 
 #include <string.h>
 
 tnet_mbms_ctx_t* tnet_mbms_ctx_create()
 {
 	return tsk_object_new(tnet_mbms_ctx_def_t);
 }
 
 
 tsk_bool_t tnet_mbms_check_network_tmgi(tnet_mbms_ctx_t* ctx)
 {
 	if(ctx == tsk_null)
 		return tsk_false;
 
 	if (ctx->mbms_service_id == tsk_null || 
 		ctx->mcc == tsk_null || 
 		ctx->mnc == tsk_null ||
 	    ctx->mbms_service_id_length != TNET_MBMS_SERVICE_ID_SIZE || 
 		ctx->mcc_length != TNET_MBMS_MCC_SIZE || 
 		ctx->mnc_length < 2 ||
 		ctx->mnc_length > 3)
 	{
 		return tsk_false;
 	}
 
 	//TODO: Need to check MBMS Service ID and MCC/MNC values in MBSFNAreaConfiguration and SystemInformationBlockType1 messages (LTE)
 	return tsk_true;
 }
 
 tsk_bool_t tnet_mbms_parse_tmgi(tnet_mbms_ctx_t* ctx, uint8_t* tmgi, tsk_size_t tmgi_size)
 {
 	tsk_bool_t ret = tsk_false;
 	uint8_t* p;
 
 	if(ctx == tsk_null)
 		return tsk_false;
 
 	if(tmgi_size != TNET_MBMS_TMGI_SIZE)
 		return tsk_false;
 
 	if(tmgi == tsk_null)
 		return tsk_false;
 
 	#if HAVE_CRT //Debug memory
 	ctx->tmgi = (uint8_t*)calloc(TNET_MBMS_TMGI_SIZE, sizeof(uint8_t));
 		
 	#else
 		
 	ctx->tmgi = (uint8_t*)tsk_calloc(TNET_MBMS_TMGI_SIZE, sizeof(uint8_t));
 	#endif //HAVE_CRT
 	if(ctx->tmgi == tsk_null)
 		goto bail;
 	memcpy(ctx->tmgi, tmgi, tmgi_size);
 	ctx->tmgi_size = TNET_MBMS_TMGI_SIZE;
 	p = ctx->tmgi;
 	#if HAVE_CRT //Debug memory
 	ctx->mbms_service_id = (uint8_t*)calloc(TNET_MBMS_SERVICE_ID_SIZE, sizeof(uint8_t));
 		
 	#else
 	ctx->mbms_service_id = (uint8_t*)tsk_calloc(TNET_MBMS_SERVICE_ID_SIZE, sizeof(uint8_t));
 		
 	#endif //HAVE_CRT
 	if(ctx->mbms_service_id == tsk_null)
 	{
 		TSK_FREE(ctx->tmgi);
 		ctx->tmgi_size = 0;
 		goto bail;
 	}
 	memcpy(ctx->mbms_service_id, p, TNET_MBMS_SERVICE_ID_SIZE);
 	ctx->mbms_service_id_length = TNET_MBMS_SERVICE_ID_SIZE;
 	p += TNET_MBMS_SERVICE_ID_SIZE;
 	#if HAVE_CRT //Debug memory
 	ctx->mcc = (uint8_t*)calloc(TNET_MBMS_MCC_SIZE, sizeof(uint8_t));
 		
 	#else
 	ctx->mcc = (uint8_t*)tsk_calloc(TNET_MBMS_MCC_SIZE, sizeof(uint8_t));
 		
 	#endif //HAVE_CRT
 	if(ctx->mcc == tsk_null)
 	{
 		TSK_FREE(ctx->tmgi);
 		ctx->tmgi_size = 0;
 		TSK_FREE(ctx->mbms_service_id);
 		ctx->mbms_service_id_length = 0;
 		goto bail;
 	}
 	ctx->mcc[0] = p[0] & 0x0F;
 	ctx->mcc[1] = (p[0] & 0xF0) >> 4;
 	ctx->mcc[2] = p[1] & 0x0F; 
 	ctx->mcc_length = TNET_MBMS_MCC_SIZE;
 	
 	if(((p[1] & 0xF0) >> 4) == 0x0F)
 	{
 		ctx->mnc_length = 2;
 		#if HAVE_CRT //Debug memory
 		ctx->mnc = (uint8_t*)calloc(ctx->mnc_length, sizeof(uint8_t));
 		
 		#else
 		ctx->mnc = (uint8_t*)tsk_calloc(ctx->mnc_length, sizeof(uint8_t));
 		
 		#endif //HAVE_CRT
 		if(ctx->mnc == tsk_null)
 		{
 			TSK_FREE(ctx->tmgi);
 			ctx->tmgi_size = 0;
 			TSK_FREE(ctx->mbms_service_id);
 			ctx->mbms_service_id_length = 0;
 			TSK_FREE(ctx->mcc);
 			ctx->mcc_length = 0;
 			ctx->mnc_length = 0;
 			goto bail;
 		}
 		ctx->mnc[0] = p[2] & 0x0F;
 		ctx->mnc[1] = (p[2] & 0xF0) >> 4;
 	}
 	else
 	{
 		ctx->mnc_length = 3;
 		#if HAVE_CRT //Debug memory
 		ctx->mnc = (uint8_t*)calloc(ctx->mnc_length, sizeof(uint8_t));
 		
 	#else
 		ctx->mnc = (uint8_t*)tsk_calloc(ctx->mnc_length, sizeof(uint8_t));
 		
 	#endif //HAVE_CRT
 		if(ctx->mnc == tsk_null)
 			goto bail;
 		ctx->mnc[0] = p[2] & 0x0F;
 		ctx->mnc[1] = (p[2] & 0xF0) >> 4;
 		ctx->mnc[2] = (p[1] & 0xF0) >> 4;
 	}
 
 	ret = tsk_true;
 
 bail:
 	return ret;
 }
 
 
 //=================================================================================================
 //	[[MBMS CONTEXT]] object definition
 //
 static tsk_object_t* tnet_mbms_ctx_ctor(tsk_object_t * self, va_list * app)
 {
 	tnet_mbms_ctx_t *ctx = self;
 	if (ctx){
 
 		ctx->tmgi = tsk_null;
 		ctx->tmgi_size = 0;
 		ctx->mbms_service_id = tsk_null;
 		ctx->mbms_service_id_length = 0;
 		ctx->mcc = tsk_null;
 		ctx->mcc_length = 0;
 		ctx->mnc = tsk_null;
 		ctx->mnc_length = 0;
 
 		tsk_safeobj_init(ctx);
 	}
 	return self;
 }
 
 static tsk_object_t* tnet_mbms_ctx_dtor(tsk_object_t * self)
 {
 	tnet_mbms_ctx_t *ctx = self;
 	if (ctx){
 		tsk_safeobj_deinit(ctx);
 
 		TSK_FREE(ctx->tmgi);
 		TSK_FREE(ctx->mbms_service_id);
 		TSK_FREE(ctx->mcc);
 		TSK_FREE(ctx->mnc);
 
 	}
 	return self;
 }
 
 static const tsk_object_def_t tnet_mbms_ctx_def_s =
 {
 	sizeof(tnet_mbms_ctx_t),
 	tnet_mbms_ctx_ctor,
 	tnet_mbms_ctx_dtor,
 	tsk_null,
 };
 const tsk_object_def_t *tnet_mbms_ctx_def_t = &tnet_mbms_ctx_def_s;