#include "precomp.h" DEBUG_FILEZONE(ZONE_T120_APP_ROSTER); /* * arostmgr.cpp * * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY * * Abstract: * This is the implementation file for the Application Roster * Manager Class. * * SEE THE INTERFACE FILE FOR A MORE DETAILED DESCRIPION OF THIS CLASS. * * Private Instance Variables * m_nConfID * The conference ID associated with this roster manager. Used * when delivering roster update messages. * m_fTopProvider * Flag indicating if this is a top provider node for this conference. * m_pMcsUserObject * This is the user attachment object associated with this conference. * m_AppSapEidList2 * This list maintains all of the command target pointers for each * of the enrolled APEs. This list is used to deliver roster * update messages. * m_pConf * Pointer to object that will receive all owner callback messages * delivered from the application roster manager. * m_GlobalRosterList * This list maintains pointers to all the global application rosters. * m_LocalRosterList * This list maintains pointers to all the local application rosters. * This list will not be used if this is a Top Provider node. * m_RosterDeleteList * This list is used to hold any application rosters that have * been marked to be deleted (usually when they become empty). We * don't delete immediately to allow messages and PDUs to be processed * before deletion. * m_pSessionKey * This is the session key used to hold the protocol key associated * with this application roster manager. * * Caveats: * None * * Author: * blp */ #include "arostmgr.h" #include "arostmsg.h" #include "appsap.h" #include "csap.h" #include "conf.h" /* * CAppRosterMgr () * * Public Function Description * when pGccSessKey is not NULL * This is the application roster manager constructor. It is responsible * for initializing all the instance variables used by this class. * This constructor is used when the initial roster data that is * availble comes from local API data. * * when pSessKey is not NULL * This is the application roster manager constructor. It is responsible * for initializing all the instance variables used by this class. * This constructor is used when the initial roster data that is * availble comes from remote PDU data. * This constructor handles a number of different possiblities: * For Non Top Providers: * 1) A refresh received from the top provider. * 2) An update from a node below this one. * * For the Top Provider: * 1) An Update from a lower node */ CAppRosterMgr::CAppRosterMgr( PGCCSessionKey pGccSessKey, PSessionKey pPduSessKey, GCCConfID nConfID, PMCSUser pMcsUserObject, CConf *pConf, PGCCError pRetCode) : CRefCount(MAKE_STAMP_ID('A','R','M','r')), m_nConfID(nConfID), // m_fTopProvider(FALSE), m_pMcsUserObject(pMcsUserObject), m_AppSapEidList2(DESIRED_MAX_APP_SAP_ITEMS), m_pConf(pConf) { GCCError rc = GCC_NO_ERROR; DebugEntry(CAppRosterMgr::CAppRosterMgr); // Determine if this is a top provider node m_fTopProvider = (m_pMcsUserObject->GetTopNodeID() == m_pMcsUserObject->GetMyNodeID()); /* ** Set up this roster managers session key which will be used to ** determine whether or not to process a roster request or update. */ if (NULL != pGccSessKey) { ASSERT(NULL == pPduSessKey); DBG_SAVE_FILE_LINE m_pSessionKey = new CSessKeyContainer(pGccSessKey, &rc); } else if (NULL != pPduSessKey) { DBG_SAVE_FILE_LINE m_pSessionKey = new CSessKeyContainer(pPduSessKey, &rc); } else { ERROR_OUT(("CAppRosterMgr::CAppRosterMgr: invalid session key")); rc = GCC_BAD_SESSION_KEY; goto MyExit; } if (NULL == m_pSessionKey || GCC_NO_ERROR != rc) { ERROR_OUT(("CAppRosterMgr::CAppRosterMgr: can't create session key")); rc = GCC_ALLOCATION_FAILURE; // we do the cleanup in the destructor goto MyExit; } ASSERT(GCC_NO_ERROR == rc); MyExit: DebugExitINT(CAppRosterMgr:;CAppRosterMgr, rc); *pRetCode = rc; } /* * ~CAppRosterMgr() * * Public Function Description * This is the application roster manager destructor. It is used to * free up all memory associated with this class. */ CAppRosterMgr::~CAppRosterMgr(void) { m_GlobalRosterList.DeleteList(); m_LocalRosterList.DeleteList(); m_RosterDeleteList.DeleteList(); if (NULL != m_pSessionKey) { m_pSessionKey->Release(); } } /* * GCCError EnrollRequest () * * Public Function Description * This routine is called whenever an APE wishes to enroll with the * conference in a specific session. This routine can be used to * either add a new record or replace a currently existing record. */ GCCError CAppRosterMgr:: EnrollRequest(GCCEnrollRequest *pReq, GCCEntityID eid, GCCNodeID nid, CAppSap *pAppSap) { GCCError rc = GCC_NO_ERROR; CAppRoster *pAppRoster = NULL; BOOL perform_add_record; BOOL maintain_pdu_data; DebugEntry(CAppRosterMgr::EnrollRequest); /* ** First we must make sure that the default version of this session ** key matches this application roster manager's */ if (! IsThisSessionKeyValid(pReq->pSessionKey)) { rc = GCC_BAD_SESSION_KEY; goto MyExit; } // Now save the App SAP so we can send roster report indications if (! m_AppSapEidList2.Find(eid)) { m_AppSapEidList2.Append(eid, pAppSap); perform_add_record = TRUE; } else { perform_add_record = FALSE; } /* ** Next we must make sure that the global application roster (and ** local for non top providers) that matches this session key exist. ** If they don't exists then create them here. */ pAppRoster = GetApplicationRoster(pReq->pSessionKey, &m_GlobalRosterList); if (pAppRoster == NULL) { maintain_pdu_data = m_fTopProvider; /* ** Here we create the global default application rosters. If ** this is the Top Provider we DO maintain PDU data within the ** roster. */ DBG_SAVE_FILE_LINE pAppRoster = new CAppRoster(pReq->pSessionKey, NULL, // pSessKey this, // pOwnerObject m_fTopProvider,// fTopProvider FALSE, // fLocalRoster maintain_pdu_data, // fMaintainPduBuffer &rc); if ((pAppRoster != NULL) && (rc == GCC_NO_ERROR)) { m_GlobalRosterList.Append(pAppRoster); } else { rc = GCC_ALLOCATION_FAILURE; goto MyExit; } } if (! m_fTopProvider) { pAppRoster = GetApplicationRoster(pReq->pSessionKey, &m_LocalRosterList); if (pAppRoster == NULL) { // Here we create the local default application rosters. DBG_SAVE_FILE_LINE pAppRoster = new CAppRoster(pReq->pSessionKey, NULL, // pSessKey this, // pOwnerObject m_fTopProvider,// fTopProvider TRUE, // fLocalRoster TRUE, // fMaintainPduBuffer &rc); if ((pAppRoster != NULL) && (rc == GCC_NO_ERROR)) { m_LocalRosterList.Append(pAppRoster); } else { rc = GCC_ALLOCATION_FAILURE; goto MyExit; } } } // // LONCHANC: Something wrong here. roster_ptr could be either // the one in the global list or the one in the local list. // Should we add records to both roster_ptr??? // // LONCHANC: It seems to me that only the local list has records in non-top provider. // On the other hand, only the global list has the record in top provider. // cf. UnEnrollRequest(). // if (perform_add_record) { // Add the new record to the roster rc = pAppRoster->AddRecord(pReq, nid, eid); if (GCC_NO_ERROR != rc) { ERROR_OUT(("AppRosterManager::EnrollRequest: can't add record")); } } else { rc = pAppRoster->ReplaceRecord(pReq, nid, eid); if (GCC_NO_ERROR != rc) { ERROR_OUT(("AppRosterManager::EnrollRequest: can't repalce record")); } } // zero out the roster pointer because it should no be freed // in case of adding or replacing a record. // because the roster pointer has been added to the list, // it will be freed later. pAppRoster = NULL; MyExit: if (GCC_NO_ERROR != rc) { if (pAppRoster != NULL) { pAppRoster->Release(); } } DebugExitINT(CAppRosterMgr::EnrollRequest, rc); return rc; } /* * GCCError UnEnrollRequest () * * Public Function Description * This routine is called whenever an APE wishes to unenroll from the * conference (or a specific session). */ GCCError CAppRosterMgr::UnEnrollRequest ( PGCCSessionKey session_key, EntityID entity_id) { GCCError rc = GCC_NO_ERROR; CAppRoster *application_roster = NULL; CAppRosterList *roster_list; DebugEntry(CAppRosterMgr::UnEnrollRequest); // Is this a valid session key for the application roster manager if (IsThisSessionKeyValid (session_key) == FALSE) rc = GCC_INVALID_PARAMETER; else if (m_AppSapEidList2.Remove(entity_id)) { // Now find the affected roster roster_list = m_fTopProvider ? &m_GlobalRosterList : &m_LocalRosterList; application_roster = GetApplicationRoster ( session_key, roster_list); // Now unenroll from the specified roster if (application_roster != NULL) { rc = application_roster->RemoveRecord( m_pMcsUserObject->GetMyNodeID(), entity_id); } else rc = GCC_BAD_SESSION_KEY; } else rc = GCC_APP_NOT_ENROLLED; DebugExitINT(CAppRosterMgr::UnEnrollRequest, rc); return rc; } /* * GCCError ProcessRosterUpdateIndicationPDU () * * Public Function Description * This routine processes an incomming roster update PDU. It is * responsible for passing the PDU on to the right application roster. */ GCCError CAppRosterMgr::ProcessRosterUpdateIndicationPDU( PSetOfApplicationInformation set_of_application_info, UserID sender_id) { GCCError rc = GCC_NO_ERROR; CAppRosterList *roster_list; CAppRoster *application_roster; BOOL maintain_pdu_buffer; BOOL is_local_roster; DebugEntry(CAppRosterMgr::ProcessRosterUpdateIndicationPDU); /* ** First make sure that the session key contained in the current ** set of application information is valid for this application roster ** manager. */ if (IsThisSessionKeyPDUValid(&set_of_application_info->value.session_key)) { /* ** Now search for the appropriate application roster. If it is not ** found we must create it here. */ // // LONCHANC: // (1) If top provider, add default application roster to the global roster list. // (2) If non-top provider, we do not create both the local and global version of the // application roster for this particular session key. // instead, We create only the appropriate one here // and wait until we receive either a refresh from the // top provider or an update from a node below this one // in the connection hierarchy (or an application // enroll) before creating the other. // (3) If this PDU was sent from below this node it // must be an update of the local roster so save // the roster in the local roster list. // roster_list = (m_fTopProvider || (sender_id == m_pMcsUserObject->GetTopNodeID())) ? &m_GlobalRosterList : &m_LocalRosterList; application_roster = GetApplicationRosterFromPDU ( &set_of_application_info->value.session_key, roster_list); if (application_roster != NULL) { rc = application_roster-> ProcessRosterUpdateIndicationPDU( set_of_application_info, sender_id); } else { // First determine the characteristics of this roster if (m_fTopProvider) { maintain_pdu_buffer = TRUE; is_local_roster = FALSE; } else if (sender_id == m_pMcsUserObject->GetTopNodeID()) { maintain_pdu_buffer = FALSE; is_local_roster = FALSE; } else { maintain_pdu_buffer = TRUE; is_local_roster = TRUE; } // Create the application roster from the passed in PDU. DBG_SAVE_FILE_LINE application_roster = new CAppRoster(NULL, // pGccSessKey &set_of_application_info->value.session_key, // pSessKey this, // pOwnerObject m_fTopProvider,// fTopProvider is_local_roster,// fLocalRoster maintain_pdu_buffer,// fMaintainPduBuffer &rc); if ((application_roster != NULL) && (rc == GCC_NO_ERROR)) { // Process the PDU with the created application roster. rc = application_roster-> ProcessRosterUpdateIndicationPDU( set_of_application_info, sender_id); if (rc == GCC_NO_ERROR) { roster_list->Append(application_roster); } } else { if (application_roster != NULL) { application_roster->Release(); } else { rc = GCC_ALLOCATION_FAILURE; } } } } else { ERROR_OUT(("AppRosterManager::ProcessRosterUpdateIndicationPDU:" "ASSERTION: Application Information is not valid")); rc = GCC_INVALID_PARAMETER; } DebugExitINT(CAppRosterMgr::ProcessRosterUpdateIndicationPDU, rc); return rc; } /* * PSetOfApplicationInformation FlushRosterUpdateIndication () * * Public Function Description * This routine is used to access any PDU data that might currently be * queued inside the application rosters managed by this application * roster manager. It also is responsible for flushing any queued * roster update messages if necessary. */ PSetOfApplicationInformation CAppRosterMgr::FlushRosterUpdateIndication( PSetOfApplicationInformation * set_of_information, PGCCError rc) { PSetOfApplicationInformation pOld = NULL, pCurr; CAppRosterList *roster_list; CAppRoster *lpAppRoster; DebugEntry(CAppRosterMgr::FlushRosterUpdateIndication); /* ** First we deal with flushing the PDU data. We iterate through the ** appropriate list (Global if the Top Provider and Local if not the ** Top Provider) and get any PDU data associated with each of these. ** Note that some of these may not contain any PDU data. */ *rc = GCC_NO_ERROR; *set_of_information = NULL; roster_list = m_fTopProvider ? &m_GlobalRosterList : &m_LocalRosterList; roster_list->Reset(); while (NULL != (lpAppRoster = roster_list->Iterate())) { lpAppRoster->FlushRosterUpdateIndicationPDU(&pCurr); if (pCurr != NULL) { if (*set_of_information == NULL) *set_of_information = pCurr; else { if(pOld) { pOld->next = pCurr; } } (pOld = pCurr)->next = NULL; } } /* ** Next we deal with delivering the application roster update messages. ** We first check to see if any of the global rosters have changed. If ** none have changed, we will not deliver a roster update indication. */ m_GlobalRosterList.Reset(); while (NULL != (lpAppRoster = m_GlobalRosterList.Iterate())) { if (lpAppRoster->HasRosterChanged()) { TRACE_OUT(("AppRosterManager::FlushRosterUpdateIndication:Roster HAS Changed")); *rc = SendRosterReportMessage (); break; } } /* ** Cleanup and reset any application rosters after the above flush is ** completed. This takes care of removing any rosters that have become ** empty. It also resets the rosters which takes care of resetting all ** the internal instance variables to their appropriate initial state. */ CleanupApplicationRosterLists (); DebugExitPTR(CAppRosterMgr::FlushRosterUpdateIndication, pOld); // // LONCHANC: Yes, we need to return the last item in the list such that // we can continue to grow the list. // In fact, the next call to FlushRosterUpdateIndication() will have // &pOld as the input argument. // It is quite tricky. // // Please note that pOld is initialized to NULL. // return (pOld); } /* * PSetOfApplicationInformation GetFullRosterRefreshPDU () * * Public Function Description * This routine is used to obtain a complete roster refresh of all the * rosters maintained by this roster manger. */ PSetOfApplicationInformation CAppRosterMgr::GetFullRosterRefreshPDU ( PSetOfApplicationInformation * set_of_information, PGCCError rc) { PSetOfApplicationInformation new_set_of_information = NULL; DebugEntry(CAppRosterMgr::GetFullRosterRefreshPDU); if (m_fTopProvider) { CAppRoster *lpAppRoster; *rc = GCC_NO_ERROR; *set_of_information = NULL; /* ** First we must tell all the application rosters to build the ** a full refresh PDU internally. */ m_GlobalRosterList.Reset(); while (NULL != (lpAppRoster = m_GlobalRosterList.Iterate())) { *rc = lpAppRoster->BuildFullRefreshPDU(); if (GCC_NO_ERROR != *rc) { return NULL; } } /* ** Now we flush all the refreshes. Note that this also takes care ** of delivering any queued application roster update messages. */ new_set_of_information = FlushRosterUpdateIndication (set_of_information, rc); } else *rc = GCC_INVALID_PARAMETER; DebugExitPTR(CAppRosterMgr::GetFullRosterRefreshPDU, new_set_of_information); return (new_set_of_information); } /* * Boolean IsThisYourSessionKey () * * Public Function Description * This routine is used to determine if the specified "API" session key is * associated with this application roster manager. */ /* * Boolean IsThisYourSessionKeyPDU () * * Public Function Description * This routine is used to determine if the specified "PDU" session key is * associated with this application roster manager. */ /* * GCCError RemoveEntityReference () * * Public Function Description * This routine is used to remove the specified APE entity from the * session it is enrolled with. Note that this routine is only used * to remove local entity references. */ GCCError CAppRosterMgr::RemoveEntityReference(EntityID entity_id) { GCCError rc = GCC_NO_ERROR; CAppRosterList *roster_list; DebugEntry(CAppRosterMgr::RemoveEntityReference); /* ** First remove this entity from the command target list if it is valid. ** We then iterate through all the rosters until we determine which ** roster holds the record associated with this entity. */ if (m_AppSapEidList2.Remove(entity_id)) { CAppRoster *lpAppRoster; /* ** Now get the affected roster. Note that if this is not the ** top provider we wait for the full refresh to update the ** global roster. */ roster_list = m_fTopProvider ? &m_GlobalRosterList : &m_LocalRosterList; /* ** Try to delete this record from every roster in the list. ** Break when the correct roster is found. */ roster_list->Reset(); while (NULL != (lpAppRoster = roster_list->Iterate())) { rc = lpAppRoster->RemoveRecord(m_pMcsUserObject->GetMyNodeID(), entity_id); if (rc == GCC_NO_ERROR) break; } } else rc = GCC_APP_NOT_ENROLLED; DebugExitINT(CAppRosterMgr::RemoveEntityReference, rc); return rc; } /* * GCCError RemoveUserReference () * * Public Function Description * This routine is used to remove all references associated with the * node defined by the detached user. */ GCCError CAppRosterMgr::RemoveUserReference( UserID detached_user) { GCCError rc = GCC_NO_ERROR; GCCError error_value; CAppRosterList *roster_list; CAppRoster *lpAppRoster; DebugEntry(CAppRosterMgr::RemoveUserReference); /* ** Now get the affected roster. Note that if this is not the ** top provider we wait for the full refresh to update the ** global roster. */ roster_list = m_fTopProvider ? &m_GlobalRosterList : &m_LocalRosterList; // Try to delete this user from every roster in the list roster_list->Reset(); while (NULL != (lpAppRoster = roster_list->Iterate())) { error_value = lpAppRoster->RemoveUserReference (detached_user); if ((error_value != GCC_NO_ERROR) && (error_value != GCC_INVALID_PARAMETER)) { rc = error_value; WARNING_OUT(("AppRosterManager::RemoveUserReference:" "FATAL error occured while removing user reference.")); break; } } DebugExitINT(CAppRosterMgr::RemoveUserReference, rc); return rc; } /* * Boolean IsEntityEnrolled () * * Public Function Description * This routine informs the caller if the specified entity is enrolled * with any sessions managed by this application roster manager. */ BOOL CAppRosterMgr::IsEntityEnrolled(EntityID application_entity) { BOOL rc = TRUE; CAppRosterList *application_roster_list; CAppRoster *lpAppRoster; DebugEntry(CAppRosterMgr::IsEntityEnrolled); application_roster_list = m_fTopProvider ? &m_GlobalRosterList : &m_LocalRosterList; application_roster_list->Reset(); while (NULL != (lpAppRoster = application_roster_list->Iterate())) { if (lpAppRoster->DoesRecordExist(m_pMcsUserObject->GetMyNodeID(), application_entity)) { rc = TRUE; break; } } DebugExitBOOL(AppRosterManager:IsEntityEnrolled, rc); return rc; } /* * GCCError ApplicationRosterInquire () * * Public Function Description * This routine fills in an application roster message with either * a single roster (if a session other than the default is specified) * or the complete list of "Global" rosters contained by this roster * manager (if the specified session key is NULL or the session ID is * zero. */ GCCError CAppRosterMgr::ApplicationRosterInquire ( PGCCSessionKey session_key, CAppRosterMsg *roster_message) { GCCError rc = GCC_NO_ERROR; CAppRoster *application_roster = NULL; CSessKeyContainer *pSessKeyData; DebugEntry(CAppRosterMgr::ApplicationRosterInquire); if (session_key != NULL) { if (session_key->session_id != 0) { /* ** Here we try to find the specific application roster that was ** requested. */ DBG_SAVE_FILE_LINE pSessKeyData = new CSessKeyContainer(session_key, &rc); if ((pSessKeyData != NULL) && (rc == GCC_NO_ERROR)) { CAppRoster *lpAppRoster; m_GlobalRosterList.Reset(); while (NULL != (lpAppRoster = m_GlobalRosterList.Iterate())) { CSessKeyContainer *pTempSessKeyData = lpAppRoster->GetSessionKey(); if (*pTempSessKeyData == *pSessKeyData) { application_roster = lpAppRoster; break; } } } if (pSessKeyData != NULL) { pSessKeyData->Release(); if (application_roster == NULL) { rc = GCC_NO_SUCH_APPLICATION; } } else { rc = GCC_ALLOCATION_FAILURE; } } } if (rc == GCC_NO_ERROR) { if (application_roster != NULL) { roster_message->AddRosterToMessage(application_roster); } else { CAppRoster *lpAppRoster; m_GlobalRosterList.Reset(); while (NULL != (lpAppRoster = m_GlobalRosterList.Iterate())) { roster_message->AddRosterToMessage(lpAppRoster); } } } DebugExitINT(AppRosterManager:ApplicationRosterInquire, rc); return rc; } /* * BOOL IsAPEEnrolled () * * Public Function Description * This function determines if the specified APE is enrolled with * any session in the list. It does not worry about a specific * session. */ BOOL CAppRosterMgr::IsAPEEnrolled( UserID node_id, EntityID entity_id) { BOOL rc = FALSE; CAppRoster *lpAppRoster; DebugEntry(CAppRosterMgr::IsAPEEnrolled); /* ** First get a single session key. Note that it makes no difference ** where the key comes from because we are only goin to be comparing ** the base object key. */ m_GlobalRosterList.Reset(); while (NULL != (lpAppRoster = m_GlobalRosterList.Iterate())) { if (lpAppRoster->DoesRecordExist (node_id, entity_id)) { rc = TRUE; break; } } DebugExitBOOL(AppRosterManager:IsAPEEnrolled, rc); return rc; } /* * BOOL IsAPEEnrolled () * * Public Function Description * This function determines if the specified APE is enrolled with * a specific session in the list. */ BOOL CAppRosterMgr::IsAPEEnrolled( CSessKeyContainer *session_key_data, UserID node_id, EntityID entity_id) { BOOL rc = FALSE; CAppRoster *lpAppRoster; DebugEntry(CAppRosterMgr::IsAPEEnrolled); /* ** First get a single session key. Note that it makes no difference ** where the key comes from because we are only goin to be comparing ** the base object key. */ m_GlobalRosterList.Reset(); while (NULL != (lpAppRoster = m_GlobalRosterList.Iterate())) { // We are looking for a session key match if (*(lpAppRoster->GetSessionKey()) == *session_key_data) { // If a match was found check to see if record exist rc = lpAppRoster->DoesRecordExist (node_id, entity_id); } } DebugExitBOOL(AppRosterManager:IsAPEEnrolled, rc); return rc; } /* * GCCError IsEmpty () * * Public Function Description * This routine determines if this application roster managfer contains * any application rosters. */ BOOL CAppRosterMgr::IsEmpty(void) { return (m_GlobalRosterList.IsEmpty() && m_LocalRosterList.IsEmpty()) ? TRUE : FALSE; } /* * GCCError SendRosterReportMessage () * * Private Function Description * This routine is responsible for sending the application roster * update indications to the application SAPs. * * Formal Parameters: * None. * * Return Value * GCC_NO_ERROR - No error occured. * GCC_ALLOCATION_FAILURE - A resource error occured. * * Side Effects * None. * * Caveats: * We send indications for all rosters. Even roster that don't currently * contain records. */ GCCError CAppRosterMgr:: SendRosterReportMessage(void) { GCCError rc = GCC_NO_ERROR; CAppRosterMsg *roster_message; DebugEntry(CAppRosterMgr::SendRosterReportMessage); if (! m_GlobalRosterList.IsEmpty()) { // First allocate the roster message DBG_SAVE_FILE_LINE roster_message = new CAppRosterMsg(); if (roster_message != NULL) { CAppRoster *lpAppRoster; m_GlobalRosterList.Reset(); while (NULL != (lpAppRoster = m_GlobalRosterList.Iterate())) { roster_message->AddRosterToMessage(lpAppRoster); } /* ** Here we iterate through the complete list of application ** saps to send the roster report indication. Note that ** we used the sent list to avoid sending the same roster ** update to a single SAP more than once. Note that since ** this sent list is defined as a local instance variable, ** it automatically is cleaned up after each roster update. ** ** Note also that we iterate on a temporary list here in case ** an application unenrolls (usually due to a resource error) ** during this callback. We must protect the rogue wave ** iterator. */ CAppSap *pAppSap; CAppSapList SentList; CAppSapEidList2 ToSendList(m_AppSapEidList2); ToSendList.Reset(); while (NULL != (pAppSap = ToSendList.Iterate())) { if (! SentList.Find(pAppSap)) { /* ** Hold on to this sap so that we don't send to it ** again for this update. */ SentList.Append(pAppSap); // Here we actually deliver the roster update. pAppSap->AppRosterReportIndication(m_nConfID, roster_message); } } /* ** Here we send the roster report indication to the ** controler sap. */ g_pControlSap->AppRosterReportIndication(m_nConfID, roster_message); /* ** Here we free up the roster message. Note that if this ** message got locked in the roster report indication calls ** this free will not delete the roster memory. */ roster_message->Release(); } else rc = GCC_ALLOCATION_FAILURE; } DebugExitINT(AppRosterManager::SendRosterReportMessage, rc); return rc; } /* * CAppRoster *GetApplicationRoster () * * Private Function Description * This routine is responsible for returning the application pointer * associated with the specified session key. * * Formal Parameters: * session_key - Session key associated with roster to return. * roster_list - Roster list to search. * * Return Value * Either NULL if roster does not exists in list or a pointer to * the appropriate application roster. * * Side Effects * None. * * Caveats: * None. */ CAppRoster * CAppRosterMgr::GetApplicationRoster ( PGCCSessionKey session_key, CAppRosterList *roster_list) { GCCError rc; CAppRoster *application_roster = NULL; CAppRoster *lpAppRoster; CSessKeyContainer *pTempSessKeyData; DebugEntry(CAppRosterMgr::GetApplicationRoster); // First create a temporary session key for comparison purposes DBG_SAVE_FILE_LINE pTempSessKeyData = new CSessKeyContainer(session_key, &rc); if (pTempSessKeyData != NULL && GCC_NO_ERROR == rc) { // Now find the affected roster // // LONCHANC: The following line is totally wrong!!! // we passed in roster_list, but now we overwrite it right here??? // Commented out the following line. // roster_list = m_fTopProvider ? &m_GlobalRosterList : &m_LocalRosterList; // roster_list->Reset(); while (NULL != (lpAppRoster = roster_list->Iterate())) { if(*lpAppRoster->GetSessionKey() == *pTempSessKeyData) { application_roster = lpAppRoster; break; } } } if (pTempSessKeyData != NULL) pTempSessKeyData->Release(); DebugExitPTR(AppRosterManager::GetApplicationRoster, application_roster); return (application_roster); } /* * CAppRoster * GetApplicationRosterFromPDU () * * Private Function Description * This routine is responsible for returning the application pointer * associated with the specified session key PDU. * * Formal Parameters: * session_key - Session key PDU associated with roster to return. * roster_list - Roster list to search. * * Return Value * Either NULL if roster does not exists in list or a pointer to * the appropriate application roster. * * Side Effects * None. * * Caveats: * None. */ CAppRoster * CAppRosterMgr::GetApplicationRosterFromPDU ( PSessionKey session_key, CAppRosterList *roster_list) { CSessKeyContainer *session_key_data; CAppRoster *pAppRoster; DebugEntry(CAppRosterMgr::GetApplicationRosterFromPDU); roster_list->Reset(); while (NULL != (pAppRoster = roster_list->Iterate())) { session_key_data = pAppRoster->GetSessionKey(); if (session_key_data->IsThisYourSessionKeyPDU (session_key)) { break; } } DebugExitPTR(CAppRosterMgr::GetApplicationRosterFromPDU, pAppRoster); return pAppRoster; } /* * BOOL IsThisSessionKeyValid () * * Private Function Description * This routine is responsible for determining if the specified * session key's application protocol key matches this application * roster manager's. This routine works on API data. * * Formal Parameters: * session_key - Session key to check. * * Return Value * TRUE - If we have a match. * FALSE - If we do NOT have a match. * * Side Effects * None. * * Caveats: * None. */ /* * BOOL IsThisSessionKeyPDUValid () * * Private Function Description * This routine is responsible for determining if the specified * session key's application protocol key matches this application * roster manager's. This routine works on PDU data. * * Formal Parameters: * session_key - Session key to check. * * Return Value * TRUE - If we have a match. * FALSE - If we do NOT have a match. * * Side Effects * None. * * Caveats: * None. */ /* * void CleanupApplicationRosterLists () * * Private Function Description * This routine is responsible for cleaning up any empty application * rosters. It also resets all the application rosters back to their * neutral state so that any new updates will be handled correctly. * * Formal Parameters: * None. * * Return Value * None. * * Side Effects * An owner callback will occur when the roster becomes empty. * * Caveats: * This routine does not actually delete the empty rosters until it * is placed in the delete list. Instead it places the rosters into the * list of deleted rosters which causes them to be deleted the next time * this routine is called (or when the object is destructed). */ void CAppRosterMgr::CleanupApplicationRosterLists(void) { CAppRoster *lpAppRoster; DebugEntry(CAppRosterMgr::CleanupApplicationRosterLists); /* ** First we iterate through the list of deleted rosters and delete ** each entry in it. */ m_RosterDeleteList.DeleteList(); /* ** Next we iterate through all the rosters and remove any that ** contain no application records. Here instead of deleting the ** roster we move the roster into the delete list. We cannot do ** the delete here because it is possible that PDU data owned by the ** roster being deleted may be used after the Flush is called (or ** after this routine is called). Therefore, we save it in the delete ** list and delete it next time we enter this routine. */ // Start with the Global Application Roster List m_GlobalRosterList.Reset(); while (NULL != (lpAppRoster = m_GlobalRosterList.Iterate())) { if (lpAppRoster->GetNumberOfApplicationRecords() == 0) { // // Here we clean up any "dangling" entries in the application // registry by removing all the entries that contain the // session key associated with the roster that is being deleted. // Note that this is only done when a Global roster list is //removed. // CRegistry *pAppReg = m_pConf->GetRegistry(); pAppReg->RemoveSessionKeyReference(lpAppRoster->GetSessionKey()); m_GlobalRosterList.Remove(lpAppRoster); m_RosterDeleteList.Append(lpAppRoster); TRACE_OUT(("AppRosterMgr: Cleanup: Deleting Global Roster")); /* ** Since you can not delete a list entry while iterating on it ** we must reset the iterator every time an entry is removed. */ m_GlobalRosterList.Reset(); } else { /* ** Here we reset the application roster to its neutral state. ** This affects the nodes added and nodes removed flags. */ lpAppRoster->ResetApplicationRoster(); } } // Next deal with the Local Application Roster List if (! m_fTopProvider) { m_LocalRosterList.Reset(); while (NULL != (lpAppRoster = m_LocalRosterList.Iterate())) { if (lpAppRoster->GetNumberOfApplicationRecords() == 0) { m_LocalRosterList.Remove(lpAppRoster); m_RosterDeleteList.Append(lpAppRoster); TRACE_OUT(("AppRosterMgr: Cleanup: Deleting Local Roster")); /* ** Since you can not delete a list entry while iterating on it ** we must reset the iterator every time an entry is removed. */ m_LocalRosterList.Reset(); } else { /* ** Here we reset the application roster to its neutral state. ** This affects the nodes added and nodes removed flags. */ lpAppRoster->ResetApplicationRoster(); } } } DebugExitVOID(CAppRosterMgr::CleanupApplicationRosterLists); } /* * void DeleteRosterRecord () * * Public Function Description * This function overides the base class function and is used to * receive all owner callback information from the application * rosters owned by this object. */ void CAppRosterMgr:: DeleteRosterRecord ( GCCNodeID nidRecordToDelete, GCCEntityID eidRecordToDelete ) { // // Here we remove ownership from any registry entries associated // with the record that was deleted. Note that since the entity // id must be unique for all the APEs at a node (as stated by // T.124) there is no need to include the session key to determine // which registry entries to clean up. // CRegistry *pAppReg = m_pConf->GetRegistry(); pAppReg->RemoveEntityOwnership(nidRecordToDelete, eidRecordToDelete); } void CAppRosterMgrList::DeleteList(void) { CAppRosterMgr *pAppRosterMgr; while (NULL != (pAppRosterMgr = Get())) { pAppRosterMgr->Release(); } }