From 1ebf5a5fcda0c9154e22ed02404fd46525a7fd9f Mon Sep 17 00:00:00 2001 From: bossiel Date: Wed, 10 Aug 2011 22:59:15 +0000 Subject: Move deprecated v1.0 from trunk to branches --- tinySIGCOMP/src/tcomp_statehandler.c | 415 +++++++++++++++++++++++++++++++++++ 1 file changed, 415 insertions(+) create mode 100644 tinySIGCOMP/src/tcomp_statehandler.c (limited to 'tinySIGCOMP/src/tcomp_statehandler.c') diff --git a/tinySIGCOMP/src/tcomp_statehandler.c b/tinySIGCOMP/src/tcomp_statehandler.c new file mode 100644 index 0000000..0cc6373 --- /dev/null +++ b/tinySIGCOMP/src/tcomp_statehandler.c @@ -0,0 +1,415 @@ +/* +* Copyright (C) 2009-2010 Mamadou Diop. +* +* Contact: Mamadou Diop +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO 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. +* +* DOUBANGO 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 DOUBANGO. +* +*/ + +/**@file tcomp_statehandler.c + * @brief SigComp state handler. + * Entity responsible for accessing and storing state information once permission is granted by the application. + * + * @author Mamadou Diop + * + * @date Created: Sat Nov 8 16:54:58 2009 mdiop + */ +#include "tcomp_statehandler.h" +#include "tcomp_rfc5049_sip.h" +#include "tcomp_nack_codes.h" +#include "tcomp_dicts.h" +#include "tcomp_udvm.h" + +#include "tsk_debug.h" + +static int pred_find_compartment_by_id(const tsk_list_item_t *item, const void *id) +{ + if(item && item->data){ + tcomp_compartment_t *compartment = item->data; + uint64_t res = (compartment->identifier - *((uint64_t*)id)); + return res > 0 ? (int)1 : (res < 0 ? (int)-1 : (int)0); + } + return -1; +} + +/**Creates new SigComp state handler. +*/ +tcomp_statehandler_t* tcomp_statehandler_create() +{ + return tsk_object_new(tcomp_statehandler_def_t); +} + +tcomp_compartment_t *tcomp_statehandler_getCompartment(const tcomp_statehandler_t *statehandler, uint64_t id) +{ + tcomp_compartment_t *result = tsk_null; + tcomp_compartment_t* newcomp = tsk_null; + const tsk_list_item_t *item_const; + + if(!statehandler){ + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + tsk_safeobj_lock(statehandler); + + item_const = tsk_list_find_item_by_pred(statehandler->compartments, pred_find_compartment_by_id, &id); + if(!item_const || !(result = item_const->data)){ + newcomp = tcomp_compartment_create(id, tcomp_params_getParameters(statehandler->sigcomp_parameters)); + result = newcomp; + tsk_list_push_back_data(statehandler->compartments, ((void**) &newcomp)); + } + + tsk_safeobj_unlock(statehandler); + + return result; +} + +void tcomp_statehandler_deleteCompartment(tcomp_statehandler_t *statehandler, uint64_t id) +{ + tcomp_compartment_t *compartment; + const tsk_list_item_t *item_const; + + if(!statehandler){ + TSK_DEBUG_ERROR("Invalid parameter"); + return; + } + + tsk_safeobj_lock(statehandler); + + item_const = tsk_list_find_item_by_pred(statehandler->compartments, pred_find_compartment_by_id, &id); + if(item_const && (compartment = item_const->data)){ + TSK_DEBUG_INFO("SigComp - Delete compartment %lld", id); + tsk_list_remove_item_by_data(statehandler->compartments, compartment); + } + + tsk_safeobj_unlock(statehandler); +} + + +tsk_bool_t tcomp_statehandler_compartmentExist(tcomp_statehandler_t *statehandler, uint64_t id) +{ + tsk_bool_t exist; + + if(!statehandler){ + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_false; + } + + tsk_safeobj_lock(statehandler); + exist = (tsk_list_find_item_by_pred(statehandler->compartments, pred_find_compartment_by_id, &id) ? 1 : 0); + tsk_safeobj_unlock(statehandler); + + return exist; +} + + +uint16_t tcomp_statehandler_findState(tcomp_statehandler_t *statehandler, const tcomp_buffer_handle_t *partial_identifier, tcomp_state_t** lpState) +{ + uint16_t count = 0; + tsk_list_item_t *item; + + if(!statehandler){ + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + tsk_safeobj_lock(statehandler); + + // + // Compartments + // + tsk_list_foreach(item, statehandler->compartments){ + tcomp_compartment_t *compartment = item->data; + count = tcomp_compartment_findState(compartment, partial_identifier, lpState); + } + + if(count){ + goto bail; + } + + // + // Dictionaries + // + tsk_list_foreach(item, statehandler->dictionaries){ + tcomp_dictionary_t *dictionary = item->data; + if(tcomp_buffer_startsWith(dictionary->identifier, partial_identifier)){ + *lpState = dictionary; + count++; + } + } +bail: + tsk_safeobj_unlock(statehandler); + + return count; +} + +void tcomp_statehandler_handleResult(tcomp_statehandler_t *statehandler, tcomp_result_t **lpResult) +{ + tcomp_compartment_t *lpCompartment; + uint16_t compartment_total_size; + uint8_t i; + + if(!statehandler){ + TSK_DEBUG_ERROR("Invalid parameter"); + return; + } + + /*== Do not lock --> all functions are thread-safe. */ + //tsk_safeobj_lock(statehandler); + + /* + * The compressor does not wish (or no longer wishes) to save state information? + */ + if((*lpResult)->ret_feedback && (*lpResult)->req_feedback->S){ + if(tcomp_statehandler_compartmentExist(statehandler, (*lpResult)->compartmentId)){ + tcomp_statehandler_deleteCompartment(statehandler, (*lpResult)->compartmentId); + } + return; + } + + /* + * Find corresponding compartment (only if !S) + */ + if(lpCompartment = tcomp_statehandler_getCompartment(statehandler, (*lpResult)->compartmentId)){ + compartment_total_size = lpCompartment->total_memory_size; + } + else{ + goto bail; + } + +//compartment_create_states: + /* + * Request state creation now we have the corresponding compartement. + */ + if(tcomp_result_getTempStatesToCreateSize(*lpResult)){ + /* Check compartment allocated size*/ + if(!compartment_total_size){ + goto compartment_free_states; + } + + // FIXME: lock + for (i = 0; i < tcomp_result_getTempStatesToCreateSize(*lpResult); i++) + { + tcomp_state_t **lpState = ((*lpResult)->statesToCreate + i); + if(!lpState || !*lpState) continue; + + /* + * If the state creation request needs more state memory than the + * total state_memory_size for the compartment, the state handler + * deletes all but the first (state_memory_size - 64) bytes from the state_value. + */ + if(TCOMP_GET_STATE_SIZE(*lpState) > compartment_total_size){ + tsk_size_t oldSize, newSize; + tcomp_compartment_clearStates(lpCompartment); + oldSize = tcomp_buffer_getSize((*lpState)->value); + newSize = (compartment_total_size - 64); + tcomp_buffer_removeBuff((*lpState)->value, newSize, (oldSize-newSize)); + (*lpState)->length = newSize; + + tcomp_compartment_addState(lpCompartment, lpState); + } + + /* + * If the state creation request exceeds the state memory allocated + * to the compartment, sufficient items of state created by the same + * compartment are freed until enough memory is available to + * accommodate the new state. + */ + else{ + while(lpCompartment->total_memory_left < TCOMP_GET_STATE_SIZE(*lpState)){ + tcomp_compartment_freeStateByPriority(lpCompartment); + } + tcomp_compartment_addState(lpCompartment, lpState); + } + } + } + +compartment_free_states: + /* + * Request state free now we have the correponding comprtement + */ + if(tcomp_result_getTempStatesToFreeSize((const tcomp_result_t*)*lpResult)){ + tcomp_compartment_freeStates(lpCompartment, (*lpResult)->statesToFree, tcomp_result_getTempStatesToFreeSize((const tcomp_result_t*)*lpResult)); + } + +//compartment_remote_params: + /* + * Set remote -compressor- parameters. + */ + tcomp_compartment_setRemoteParams(lpCompartment, (*lpResult)->remote_parameters); + +//feedbacks: + /* + * Set both Returned and Requested feedbacks. + */ + + if(tcomp_buffer_getSize((*lpResult)->req_feedback->item)){ + tcomp_compartment_setReqFeedback(lpCompartment, (*lpResult)->req_feedback->item); + } + if(tcomp_buffer_getSize((*lpResult)->ret_feedback)){ + tcomp_compartment_setRetFeedback(lpCompartment, (*lpResult)->ret_feedback); + } + +bail: ; + //--tsk_safeobj_unlock(lpCompartment); + //--tsk_safeobj_unlock(statehandler); +} + +tsk_bool_t tcomp_statehandler_handleNack(tcomp_statehandler_t *statehandler, const tcomp_nackinfo_t * nackinfo) +{ + tcomp_buffer_handle_t *sha_id; + tsk_list_item_t *item; + if(!statehandler){ + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_false; + } + + tcomp_buffer_referenceBuff(&sha_id, ((tcomp_nackinfo_t*)nackinfo)->sha1, TSK_SHA1_DIGEST_SIZE); + + tsk_list_foreach(item, statehandler->compartments) + { + tcomp_compartment_t* lpCompartement = item->data; + if(tcomp_compartment_hasNack(lpCompartement, &sha_id)) + { + // this compartment is responsible for this nack + switch(nackinfo->reasonCode) + { + case NACK_STATE_NOT_FOUND: + { + // Next commented because in this version remote state ids are never saved. + // Only the ghost has information on last partial state id to use --> reset the ghost + /*SigCompState* lpState = NULL; + lpCompartement->findState(&nack_info->details, &lpState); + if(lpState) + { + lpCompartement->freeState(lpState); + }*/ + tcomp_compartment_freeGhostState(lpCompartement); + } + break; + + default: + { + tcomp_compartment_clearStates(lpCompartement); + } + break; + } + } + } + return tsk_true; +} + +int tcomp_statehandler_addSipSdpDictionary(tcomp_statehandler_t *statehandler) +{ + if(!statehandler){ + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + tsk_safeobj_lock(statehandler); + + if(!statehandler->hasSipSdpDictionary){ + tcomp_dictionary_t* sip_dict = tcomp_dicts_create_sip_dict(); + tsk_list_push_back_data(statehandler->dictionaries, ((void**) &sip_dict)); + statehandler->hasSipSdpDictionary = 1; + } + + tsk_safeobj_unlock(statehandler); + return 0; +} + +int tcomp_statehandler_addPresenceDictionary(tcomp_statehandler_t *statehandler) +{ + if(!statehandler){ + TSK_DEBUG_ERROR("NULL SigComp state handler."); + return -1; + } + + tsk_safeobj_lock(statehandler); + + if(!statehandler->hasPresenceDictionary){ + tcomp_dictionary_t* pres_dict = tcomp_dicts_create_presence_dict(); + tsk_list_push_back_data(statehandler->dictionaries, ((void**) &pres_dict)); + statehandler->hasPresenceDictionary = 1; + } + + tsk_safeobj_unlock(statehandler); + return 0; +} + + + + + + + +//======================================================== +// State hanlder object definition +// + +static tsk_object_t* tcomp_statehandler_ctor(tsk_object_t * self, va_list * app) +{ + tcomp_statehandler_t *statehandler = self; + if(statehandler){ + /* Initialize safeobject */ + tsk_safeobj_init(statehandler); + + /* RFC 3320 - 3.3. SigComp Parameters */ + statehandler->sigcomp_parameters = tcomp_params_create(); + tcomp_params_setDmsValue(statehandler->sigcomp_parameters, SIP_RFC5049_DECOMPRESSION_MEMORY_SIZE); + tcomp_params_setSmsValue(statehandler->sigcomp_parameters, SIP_RFC5049_STATE_MEMORY_SIZE); + tcomp_params_setCpbValue(statehandler->sigcomp_parameters, SIP_RFC5049_CYCLES_PER_BIT); + + statehandler->dictionaries = tsk_list_create(); + statehandler->compartments = tsk_list_create(); + + statehandler->sigcomp_parameters->SigComp_version = SIP_RFC5049_SIGCOMP_VERSION; + } + else{ + TSK_DEBUG_ERROR("Null SigComp state handler."); + } + + return self; +} + +static void* tcomp_statehandler_dtor(tsk_object_t *self) +{ + tcomp_statehandler_t *statehandler = self; + if(statehandler){ + /* Deinitialize safeobject */ + tsk_safeobj_deinit(statehandler); + + TSK_OBJECT_SAFE_FREE(statehandler->sigcomp_parameters); + + TSK_OBJECT_SAFE_FREE(statehandler->dictionaries); + TSK_OBJECT_SAFE_FREE(statehandler->compartments); + } + else{ + TSK_DEBUG_ERROR("Null SigComp state handler."); + } + + return self; +} + +static const tsk_object_def_t tsk_statehandler_def_s = +{ + sizeof(tcomp_statehandler_t), + tcomp_statehandler_ctor, + tcomp_statehandler_dtor, + tsk_null +}; +const tsk_object_def_t *tcomp_statehandler_def_t = &tsk_statehandler_def_s; -- cgit v1.1