//-------------------------------------------------------------------------------------------------- static void CleanupClientData ( le_msg_SessionRef_t sessionRef, void *contextPtr ) { LE_DEBUG("Client %p is closed !!!", sessionRef); // Iterate over the server data reference map and remove anything that matches // the client session. _LOCK le_ref_IterRef_t iterRef = le_ref_GetIterator(_HandlerRefMap); le_result_t result = le_ref_NextNode(iterRef); _ServerData_t const* serverDataPtr; while ( result == LE_OK ) { serverDataPtr = le_ref_GetValue(iterRef); if ( sessionRef != serverDataPtr->clientSessionRef ) { LE_DEBUG("Found session ref %p; does not match", serverDataPtr->clientSessionRef); } else { LE_DEBUG("Found session ref %p; match found, so needs cleanup", serverDataPtr->clientSessionRef); // Remove the handler, if the Remove handler functions exists. if ( serverDataPtr->removeHandlerFunc != NULL ) { serverDataPtr->removeHandlerFunc( serverDataPtr->handlerRef ); } // Release the server data block le_mem_Release((void*)serverDataPtr); // Delete the associated safeRef le_ref_DeleteRef( _HandlerRefMap, (void*)le_ref_GetSafeRef(iterRef) ); // Since the reference map was modified, the iterator is no longer valid and // so has to be re-initalized. This means that some values may get revisited, // but eventually this will iterate over the whole reference map. // todo: Is there an easier way? iterRef = le_ref_GetIterator(_HandlerRefMap); } // Get the next value in the reference mpa result = le_ref_NextNode(iterRef); } _UNLOCK }
//-------------------------------------------------------------------------------------------------- void le_avdata_ReleaseSession ( le_avdata_RequestSessionObjRef_t sessionRequestRef ) { le_ref_IterRef_t iterRef; // Look up the reference. If it is NULL, then the reference is not valid. // Otherwise, delete the reference and request avcServer to release session. void* sessionPtr = le_ref_Lookup(AvSessionRequestRefMap, sessionRequestRef); if (sessionPtr == NULL) { LE_ERROR("Invalid session request reference %p", sessionPtr); return; } else { LE_PRINT_VALUE("%p", sessionPtr); le_ref_DeleteRef(AvSessionRequestRefMap, sessionRequestRef); } // Stop the session when all clients release their session reference. iterRef = le_ref_GetIterator(AvSessionRequestRefMap); if (le_ref_NextNode(iterRef) == LE_NOT_FOUND) { // Close the session if there is no new open request for 2 seconds. le_timer_Restart(SessionReleaseTimerRef); } }
//-------------------------------------------------------------------------------------------------- static le_mcc_Call_t* GetCallObject ( const char* destinationPtr, int16_t id, bool getInProgess ) { le_mcc_Call_t* callPtr = NULL; le_ref_IterRef_t iterRef = le_ref_GetIterator(MccCallRefMap); while (le_ref_NextNode(iterRef) == LE_OK) { callPtr = (le_mcc_Call_t*) le_ref_GetValue(iterRef); // Check callId if ( (id != (-1)) && (callPtr->callId == id) && ( (getInProgess && callPtr->inProgress) || !getInProgess ) ) { return callPtr; } // check phone number if ( (strncmp(destinationPtr, callPtr->telNumber, sizeof(callPtr->telNumber)) == 0) && ( (getInProgess && callPtr->inProgress) || !getInProgess ) ) { return callPtr; } } return NULL; }
//-------------------------------------------------------------------------------------------------- static void ClientCloseSessionHandler ( le_msg_SessionRef_t sessionRef, void* contextPtr ) { if ( sessionRef == NULL ) { LE_ERROR("sessionRef is NULL"); return; } LE_INFO("Client %p closed, remove allocated resources", sessionRef); le_ref_IterRef_t iterRef = le_ref_GetIterator(InstanceRefMap); InstanceRefData_t const* instRefDataPtr; // Search for the instance references used by the closed client, and clean up any data. while ( le_ref_NextNode(iterRef) == LE_OK ) { instRefDataPtr = le_ref_GetValue(iterRef); if ( instRefDataPtr->clientSessionRef == sessionRef ) { // Delete instance data, and also delete asset data, if last instance is deleted assetData_DeleteInstanceAndAsset(instRefDataPtr->instRef); // Delete safe reference and associated data le_mem_Release((void*)instRefDataPtr); le_ref_DeleteRef( InstanceRefMap, (void*)le_ref_GetSafeRef(iterRef) ); } } // Send registration update after the asset is removed. assetData_RegistrationUpdate(ASSET_DATA_SESSION_STATUS_CHECK); // Search for the session request reference(s) used by the closed client, and clean up any data. iterRef = le_ref_GetIterator(AvSessionRequestRefMap); while (le_ref_NextNode(iterRef) == LE_OK) { if (le_ref_GetValue(iterRef) == sessionRef) { le_avdata_ReleaseSession((void*)le_ref_GetSafeRef(iterRef)); } } }
//-------------------------------------------------------------------------------------------------- static void DestroyAllOwnedSessions ( le_msg_SessionRef_t sessionRef, void* contextPtr ) { le_ref_IterRef_t it = le_ref_GetIterator(SessionRefMap); le_result_t iterRes = le_ref_NextNode(it); while (iterRes == LE_OK) { mqtt_Session* s = le_ref_GetValue(it); LE_ASSERT(s != NULL); mqtt_SessionRef_t sRef = (mqtt_SessionRef_t)(le_ref_GetSafeRef(it)); LE_ASSERT(sRef != NULL); // Advance the interator before deletion to prevent invalidation iterRes = le_ref_NextNode(it); if (s->clientSession == sessionRef) { DestroySessionInternal(s); le_ref_DeleteRef(SessionRefMap, sRef); } } }
// ------------------------------------------------------------------------------------------------- void ni_ForEachIter ( itr_ForEachHandler functionPtr, ///< The function to call with our matches. void* contextPtr ///< Pass along any extra information the callback function ///< may require. ) // ------------------------------------------------------------------------------------------------- { LE_ASSERT(functionPtr != NULL); le_ref_IterRef_t refIterator = le_ref_GetIterator(IteratorRefMap); while (le_ref_NextNode(refIterator) == LE_OK) { ni_ConstIteratorRef_t iteratorRef = le_ref_GetValue(refIterator); if (iteratorRef != NULL) { functionPtr(iteratorRef, contextPtr); } } }
//-------------------------------------------------------------------------------------------------- static void CloseSessionEventHandler ( le_msg_SessionRef_t sessionRef, void* contextPtr ) { le_mcc_Call_t* callPtr = NULL; SessionRefNode_t* sessionRefNodePtr; le_dls_Link_t* linkPtr; le_ref_IterRef_t iterRef = le_ref_GetIterator(MccCallRefMap); while (le_ref_NextNode(iterRef) == LE_OK) { callPtr = (le_mcc_Call_t*) le_ref_GetValue(iterRef); // Remove corresponding node from the sessionRefList linkPtr = le_dls_Peek(&(callPtr->sessionRefList)); while (linkPtr != NULL) { sessionRefNodePtr = CONTAINER_OF(linkPtr, SessionRefNode_t, link); linkPtr = le_dls_PeekNext(&(callPtr->sessionRefList), linkPtr); // Remove corresponding node from the sessionRefList if ( sessionRefNodePtr->sessionRef == sessionRef ) { le_dls_Remove(&(callPtr->sessionRefList), &(sessionRefNodePtr->link)); le_mem_Release(sessionRefNodePtr); callPtr->refCount--; le_mem_Release(callPtr); } } } }
//-------------------------------------------------------------------------------------------------- le_avdata_RequestSessionObjRef_t le_avdata_RequestSession ( void ) { le_result_t result = LE_OK; // If this is a duplicate request send the existing reference. le_ref_IterRef_t iterRef = le_ref_GetIterator(AvSessionRequestRefMap); while (le_ref_NextNode(iterRef) == LE_OK) { if (le_ref_GetValue(iterRef) == le_avdata_GetClientSessionRef()) { LE_DEBUG("Duplicate session request from client."); return (le_avdata_RequestSessionObjRef_t) le_ref_GetSafeRef(iterRef); } } le_timer_Stop(SessionReleaseTimerRef); // Ask the avc server to pass the request to control app or to initiate a session. result = avcServer_RequestSession(); // If the fresh request fails, return NULL. if (result != LE_OK) { return NULL; } // Need to return a unique reference that will be used by release. Use the client session ref // as the data, since we need to delete the ref when the client closes. le_avdata_RequestSessionObjRef_t requestRef = le_ref_CreateRef(AvSessionRequestRefMap, le_avdata_GetClientSessionRef()); return requestRef; }