#include "precomp.h" DEBUG_FILEZONE(ZONE_T120_GCCNC); /* * registry.cpp * * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY * * Abstract: * This is the registry class implementation file. All registry operations * at both the Top Provider and subordinate nodes. It is responsible for * queing registry request, maintaining the registry, sending confirms to * the application SAP, etc. Registry objects at sub-ordinate nodes are * responsible for queuing up the registry request to be sent on to the * Top Provider. On of these classes should be created per node. This * class handles request from all existing application SAPs. * * FOR A MORE DETAILED EXPLANATION OF THIS CLASS SEE THE INTERFACE FILE * * Private Instance Variables: * m_pMCSUserObject * Pointer to the User Attachment object used to deliver all registry * request and responses to remote nodes. * m_RegEntryList * This is the list that holds all the registry entries associated * with this conference. * m_fTopProvider * This flag specifies if this is the top provider node (TRUE means * this is the top provider node). * m_nCurrentTokenID * This is a counter that is used to generate the token IDs by the * registry object at the top provider. * m_nConfID * Conference ID assocaited with this conference. * m_pEmptyRegItem * This is a pointer to an empty registry item that is used to generate * empty items for PDUs that don't contain a registry item. * m_AppSapEidList2 * This list contains pointers to the command target objects associated * with each of the enrolled APEs * m_nRegHandle * This is a counter that is used to generate the handles allocated * by the registry object at the top provider. * m_pAppRosterMgrList * This list hold all the current application roster managers and * is used to verify that a requesting APE is actually enrolled with * the conference. * * Caveats: * None. * * Author: * blp */ #include "registry.h" #include "appsap.h" #define FIRST_DYNAMIC_TOKEN_ID 16384 #define MAXIMUM_ALLOWABLE_ALLOCATED_HANDLES (16 * 1024) // for T.126 /* * CRegistry() * * Public Function Description * This is the registry constructor. It is responsible for initializing * instance variables. * */ CRegistry::CRegistry(PMCSUser user_object, BOOL top_provider, GCCConfID conference_id, CAppRosterMgrList *app_roster_manager_list, PGCCError pRetCode) : CRefCount(MAKE_STAMP_ID('A','R','e','g')), m_AppSapEidList2(DESIRED_MAX_APP_SAP_ITEMS), m_pMCSUserObject(user_object), m_fTopProvider(top_provider), m_nCurrentTokenID(FIRST_DYNAMIC_TOKEN_ID), m_nConfID(conference_id), m_nRegHandle(0), m_pAppRosterMgrList(app_roster_manager_list) { GCCRegistryItem registry_item; *pRetCode = GCC_NO_ERROR; /* ** If this is the Top Provider we now build a vacant registry item to ** be used when an entry in the registry is being accessed that does not ** exists. */ if (m_fTopProvider) { registry_item.item_type = GCC_REGISTRY_NONE; DBG_SAVE_FILE_LINE m_pEmptyRegItem = new CRegItem(®istry_item, pRetCode); if (m_pEmptyRegItem == NULL || GCC_NO_ERROR != *pRetCode) { *pRetCode = GCC_ALLOCATION_FAILURE; } } else { m_pEmptyRegItem = NULL; } } /* * ~CRegistry() * * Public Function Description * This is the registry destructor. It is responsible for freeing any * outstanding memory associated with the application registry. */ CRegistry::~CRegistry(void) { REG_ENTRY *pRegEntry; m_RegEntryList.Reset(); // Free up any registry entries while (NULL != (pRegEntry = m_RegEntryList.Iterate())) { if (NULL != pRegEntry->registry_key) { pRegEntry->registry_key->Release(); } if (NULL != pRegEntry->entry_item) { pRegEntry->entry_item->Release(); } delete pRegEntry; } if (NULL != m_pEmptyRegItem) { m_pEmptyRegItem->Release(); } } /* * void EnrollAPE () * * Public Function Description * This routine is used to inform the application registry of a newly * enrolling APE and its corresponding command target interface. */ void CRegistry::EnrollAPE(EntityID eid, CAppSap *pAppSap) { m_AppSapEidList2.Append(eid, pAppSap); } /* * void UnEnrollApplicationSAP () * * Public Function Description * This routine is used to inform the application registry of an * APE that is unerolling from the conference. * * Caveats * This routine removes ownership from all the entries currently owned by * the passed in application entity. It will also remove any outstanding * request for the SAP that unenrolled. */ void CRegistry::UnEnrollAPE ( EntityID entity_id ) { REG_ENTRY *lpRegEntry; UserID my_user_id = m_pMCSUserObject->GetMyNodeID(); m_RegEntryList.Reset(); while (NULL != (lpRegEntry = m_RegEntryList.Iterate())) { /* ** First we remove this APE from the list of nodes that are ** monitoring this entry. */ lpRegEntry->monitoring_list.Remove(entity_id); /* ** Next, if this is the top provider, we clean up the the ** ownership properties of this entry and issue any PDUs and/or ** messages that are necessary. */ if (m_fTopProvider) { if ((lpRegEntry->owner_id == my_user_id) && (lpRegEntry->entity_id == entity_id)) { /* ** Ownership is removed from any registry entries this ** entity owned. */ lpRegEntry->owner_id = 0; lpRegEntry->entity_id = 0; // Send Monitor Indication if necessary if (lpRegEntry->monitoring_state == ON) { /* ** Deliver the monitor indication to the Top ** Provider's Node Controller if necessary. */ SendMonitorEntryIndicationMessage (lpRegEntry); m_pMCSUserObject->RegistryMonitorEntryIndication( lpRegEntry->registry_key, lpRegEntry->entry_item, lpRegEntry->owner_id, lpRegEntry->entity_id, lpRegEntry->modification_rights); } } } } // Remove this enity from the command target list if it exists. m_AppSapEidList2.Remove(entity_id); } /* * GCCError RegisterChannel () * * Public Function Description * This routine is responsible for registering a specified channel. * It has two different paths of execution based on whether this is * a Top Provider registry or a subordinate node registry object. */ GCCError CRegistry::RegisterChannel ( PGCCRegistryKey registry_key, ChannelID channel_id, EntityID entity_id) { GCCError rc = GCC_NO_ERROR; REG_ENTRY *registry_entry = NULL; // a must CRegKeyContainer *registry_key_data = NULL; // a must CRegItem *registry_item_data = NULL; // a must GCCRegistryItem registry_item; CAppSap *requester_sap; if (NULL == (requester_sap = m_AppSapEidList2.Find(entity_id))) return (GCC_APP_NOT_ENROLLED); /* ** Next set up the Registry Key and Registry Item. Return immediately if ** a resource failure occurs. */ DBG_SAVE_FILE_LINE registry_key_data = new CRegKeyContainer(registry_key, &rc); if (NULL == registry_key_data || GCC_NO_ERROR != rc) { ERROR_OUT(("CRegistry::RegisterChannel: can't create regitry key")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } if (m_fTopProvider == FALSE) { m_pMCSUserObject->RegistryRegisterChannelRequest(registry_key_data, channel_id, entity_id); // The registry key data object is no longer needed here registry_key_data->Release(); rc = GCC_NO_ERROR; goto MyExit; } // no PDU is sent when request occurs at the top provider /* ** First check to see if the registry entry exists and if it ** does check the ownership to make sure this node has ** permission to change the entry. */ registry_entry = GetRegistryEntry(registry_key_data); if (registry_entry != NULL) { // Entry already exists, send back negative result requester_sap->RegistryConfirm( m_nConfID, GCC_REGISTER_CHANNEL_CONFIRM, registry_entry->registry_key, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, FALSE, GCC_RESULT_ENTRY_ALREADY_EXISTS); // The registry key data object is no longer needed registry_key_data->Release(); rc = GCC_NO_ERROR; goto MyExit; } // Set up the registry item here registry_item.item_type = GCC_REGISTRY_CHANNEL_ID; registry_item.channel_id = channel_id; DBG_SAVE_FILE_LINE registry_item_data = new CRegItem(®istry_item, &rc); if (registry_item_data == NULL || GCC_NO_ERROR != rc) { ERROR_OUT(("CRegistry::RegisterChannel: can't create regitry item")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } // Since entry does not exists create it here DBG_SAVE_FILE_LINE registry_entry = new REG_ENTRY; if (registry_entry == NULL) { ERROR_OUT(("CRegistry::RegisterChannel: can't create regitry entry")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } // Fill in the new entry registry_entry->registry_key = registry_key_data; registry_entry->entry_item = registry_item_data; registry_entry->monitoring_state = OFF; registry_entry->owner_id = m_pMCSUserObject->GetMyNodeID(); registry_entry->entity_id = entity_id; /* ** Initialize to public incase entry is switched to ** a parameter. Note that as long as the entry is ** not a PARAMETER modification rights will not be ** used. */ registry_entry->modification_rights = GCC_PUBLIC_RIGHTS; // Add registry entry to registry list m_RegEntryList.Append(registry_entry); // Send success for the result requester_sap->RegistryConfirm ( m_nConfID, GCC_REGISTER_CHANNEL_CONFIRM, registry_entry->registry_key, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, FALSE, GCC_RESULT_SUCCESSFUL); rc = GCC_NO_ERROR; MyExit: if (GCC_NO_ERROR != rc) { if (NULL != registry_key_data) { registry_key_data->Release(); } if (NULL != registry_item_data) { registry_item_data->Release(); } if(registry_entry) { delete registry_entry; } } return (rc); } /* * GCCError AssignToken () * * Public Function Description * This routine is responsible for generating and registering a new token. * It has two different paths of execution based on whether this is * a Top Provider registry or a subordinate node registry object. */ GCCError CRegistry::AssignToken ( PGCCRegistryKey registry_key, EntityID entity_id ) { GCCError rc = GCC_NO_ERROR; REG_ENTRY *registry_entry = NULL; // a must CRegKeyContainer *registry_key_data = NULL; // a must CRegItem *registry_item_data = NULL; // a must GCCRegistryItem registry_item; CAppSap *requester_sap; if (NULL == (requester_sap = m_AppSapEidList2.Find(entity_id))) return (GCC_APP_NOT_ENROLLED); DBG_SAVE_FILE_LINE registry_key_data = new CRegKeyContainer(registry_key, &rc); if ((registry_key_data == NULL) || (rc != GCC_NO_ERROR)) { ERROR_OUT(("CRegistry::AssignToken: can't create regitry key")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } if (m_fTopProvider == FALSE) { m_pMCSUserObject->RegistryAssignTokenRequest(registry_key_data, entity_id); // The registry key data object is no longer needed here registry_key_data->Release(); rc = GCC_NO_ERROR; goto MyExit; } // no PDU is sent when request occurs at the top provider /* ** First check to see if the registry entry exists and if it ** does check the ownership to make sure this node has ** permission to change the entry. */ registry_entry = GetRegistryEntry(registry_key_data); if (registry_entry != NULL) { // Entry already exists, send back negative result requester_sap->RegistryConfirm( m_nConfID, GCC_ASSIGN_TOKEN_CONFIRM, registry_entry->registry_key, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, FALSE, GCC_RESULT_ENTRY_ALREADY_EXISTS); // The registry key data object is no longer needed registry_key_data->Release(); rc = GCC_NO_ERROR; goto MyExit; } // Set up the registry item here registry_item.item_type = GCC_REGISTRY_TOKEN_ID; registry_item.token_id = GetUnusedToken(); DBG_SAVE_FILE_LINE registry_item_data = new CRegItem(®istry_item, &rc); if ((registry_item_data == NULL) || (rc != GCC_NO_ERROR)) { ERROR_OUT(("CRegistry::AssignToken: can't create regitry item")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } DBG_SAVE_FILE_LINE registry_entry = new REG_ENTRY; if (registry_entry == NULL) { ERROR_OUT(("CRegistry::AssignToken: can't create regitry entry")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } // Fill in the new entry registry_entry->registry_key = registry_key_data; registry_entry->entry_item = registry_item_data; registry_entry->monitoring_state = OFF; registry_entry->owner_id = m_pMCSUserObject->GetMyNodeID(); registry_entry->entity_id = entity_id; /* ** Initialize to public incase entry is switched to ** a parameter. Note that as long as the entry is ** not a PARAMETER modification rights will not be ** used. */ registry_entry->modification_rights = GCC_PUBLIC_RIGHTS; // Add registry entry to registry list m_RegEntryList.Append(registry_entry); // Send success for the result requester_sap->RegistryConfirm ( m_nConfID, GCC_ASSIGN_TOKEN_CONFIRM, registry_entry->registry_key, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, FALSE, GCC_RESULT_SUCCESSFUL); rc = GCC_NO_ERROR; MyExit: if (GCC_NO_ERROR != rc) { if (NULL != registry_key_data) { registry_key_data->Release(); } if (NULL != registry_item_data) { registry_item_data->Release(); } delete registry_entry; } return (rc); } /* * GCCError SetParameter () * * Public Function Description * This routine is responsible for generating and registering a new token. * It has two different paths of execution based on whether this is * a Top Provider registry or a subordinate node registry object. */ GCCError CRegistry::SetParameter ( PGCCRegistryKey registry_key, LPOSTR parameter_value, GCCModificationRights modification_rights, EntityID entity_id ) { GCCError rc = GCC_NO_ERROR; REG_ENTRY *registry_entry = NULL; // a must CRegKeyContainer *registry_key_data = NULL; // a must CRegItem *registry_item_data = NULL; // a must GCCResult result; GCCRegistryItem registry_item; BOOL application_is_enrolled = FALSE; CAppSap *requester_sap; if (NULL == (requester_sap = m_AppSapEidList2.Find(entity_id))) return (GCC_APP_NOT_ENROLLED); DBG_SAVE_FILE_LINE registry_key_data = new CRegKeyContainer(registry_key, &rc); if ((registry_key_data == NULL) || (rc != GCC_NO_ERROR)) { ERROR_OUT(("CRegistry::SetParameter: can't create regitry key")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } if (m_fTopProvider == FALSE) { m_pMCSUserObject->RegistrySetParameterRequest(registry_key_data, parameter_value, modification_rights, entity_id); // The registry key data object is no longer needed here registry_key_data->Release(); rc = GCC_NO_ERROR; goto MyExit; } // no PDU is sent when request occurs at the top provider // Set up the registry item here if (parameter_value != NULL) { registry_item.item_type = GCC_REGISTRY_PARAMETER; registry_item.parameter = *parameter_value; } else { registry_item.item_type = GCC_REGISTRY_NONE; } DBG_SAVE_FILE_LINE registry_item_data = new CRegItem(®istry_item, &rc); if ((registry_item_data == NULL) || (rc != GCC_NO_ERROR)) { ERROR_OUT(("CRegistry::SetParameter: can't create regitry item")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } /* ** First check to see if the registry entry exists and if it ** does check the ownership and modification rights to make ** sure this node has permission to change the entry. */ registry_entry = GetRegistryEntry(registry_key_data); if (registry_entry != NULL) { /* ** Here we make sure that this request is comming from an ** APE that previously enrolled. */ CAppRosterMgr *lpAppRosterMgr; m_pAppRosterMgrList->Reset(); while (NULL != (lpAppRosterMgr = m_pAppRosterMgrList->Iterate())) { if (lpAppRosterMgr->IsAPEEnrolled(registry_key_data->GetSessionKey(), m_pMCSUserObject->GetMyNodeID(), entity_id)) { application_is_enrolled = TRUE; break; } } /* ** Check ownership rights here: First check is to make ** sure that this is the owner if Owner rights is ** specified. Next check is to make sure that */ if (((registry_entry->modification_rights == GCC_OWNER_RIGHTS) && (registry_entry->owner_id == m_pMCSUserObject->GetMyNodeID()) && (registry_entry->entity_id == entity_id)) || ((registry_entry->modification_rights == GCC_SESSION_RIGHTS) && (application_is_enrolled)) || (registry_entry->modification_rights == GCC_PUBLIC_RIGHTS) || (registry_entry->owner_id == 0)) { /* ** Monitoring state should not be affected by ** this request. */ *registry_entry->entry_item = *registry_item_data; /* ** Only the owner is allowed to change the modification ** rights of a registry entry (unless the entry is ** unowned). Also if there is no owner, we set up the ** new owner here. */ if (((registry_entry->owner_id == m_pMCSUserObject->GetMyNodeID()) && (registry_entry->entity_id == entity_id)) || (registry_entry->owner_id == 0)) { registry_entry->owner_id = m_pMCSUserObject->GetMyNodeID(); registry_entry->entity_id = entity_id; /* ** If no modification rights are specified we must ** set the modification rights to be public. */ if (modification_rights != GCC_NO_MODIFICATION_RIGHTS_SPECIFIED) { registry_entry->modification_rights = modification_rights; } } // Send Monitor Indication if necessary if (registry_entry->monitoring_state == ON) { /* ** Deliver the monitor indication to the Top ** Provider's Node Controller if necessary. */ SendMonitorEntryIndicationMessage(registry_entry); /* ** Broadcast a monitor entry indication to all ** nodes in the conference. */ m_pMCSUserObject->RegistryMonitorEntryIndication( registry_entry->registry_key, registry_entry->entry_item, registry_entry->owner_id, registry_entry->entity_id, registry_entry->modification_rights); } // Send success for the result result = GCC_RESULT_SUCCESSFUL; } else { result = GCC_RESULT_INDEX_ALREADY_OWNED; } requester_sap->RegistryConfirm( m_nConfID, GCC_SET_PARAMETER_CONFIRM, registry_entry->registry_key, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, FALSE, result); // The registry key data object is no longer needed registry_key_data->Release(); // The registry item data object is no longer needed registry_item_data->Release(); rc = GCC_NO_ERROR; goto MyExit; } // registry entry does not exist, create one. DBG_SAVE_FILE_LINE registry_entry = new REG_ENTRY; if (registry_entry == NULL) { ERROR_OUT(("CRegistry::SetParameter: can't create regitry entry")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } // Fill in the new entry registry_entry->registry_key = registry_key_data; registry_entry->entry_item = registry_item_data; registry_entry->monitoring_state = OFF; registry_entry->owner_id = m_pMCSUserObject->GetMyNodeID(); registry_entry->entity_id = entity_id; /* ** If no modification rights are specified we must ** initialize the modification rights to be public. ** Note that modification rights are only specified ** for the SetParameter call. */ registry_entry->modification_rights = (modification_rights == GCC_NO_MODIFICATION_RIGHTS_SPECIFIED) ? GCC_PUBLIC_RIGHTS : modification_rights; // Add registry entry to registry list m_RegEntryList.Append(registry_entry); // Send success for the result requester_sap->RegistryConfirm( m_nConfID, GCC_SET_PARAMETER_CONFIRM, registry_entry->registry_key, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, FALSE, GCC_RESULT_SUCCESSFUL); rc = GCC_NO_ERROR; MyExit: if (GCC_NO_ERROR != rc) { if (NULL != registry_key_data) { registry_key_data->Release(); } if (NULL != registry_item_data) { registry_item_data->Release(); } delete registry_entry; } return (rc); } /* * GCCError RetrieveEntry () * * Public Function Description * This routine is used by a local APE to obtain an item that was * registered with GCC. If this registry object does NOT * live at the top provider node this class is responsible for * forwarding the request on up to the top provider. */ GCCError CRegistry::RetrieveEntry ( PGCCRegistryKey registry_key, EntityID entity_id ) { GCCError rc; REG_ENTRY *registry_entry; CRegKeyContainer *registry_key_data = NULL; // a must CAppSap *requester_sap; if (NULL == (requester_sap = m_AppSapEidList2.Find(entity_id))) { return GCC_APP_NOT_ENROLLED; } DBG_SAVE_FILE_LINE registry_key_data = new CRegKeyContainer(registry_key, &rc); if ((registry_key_data == NULL) || (rc != GCC_NO_ERROR)) { ERROR_OUT(("CRegistry::RetrieveEntry: can't create regitry key")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } if (m_fTopProvider == FALSE) { m_pMCSUserObject->RegistryRetrieveEntryRequest(registry_key_data, entity_id); rc = GCC_NO_ERROR; goto MyExit; } // no PDU is sent when request occurs at the top provider registry_entry = GetRegistryEntry(registry_key_data); if (registry_entry != NULL) { // Send back a positive result with the entry item requester_sap->RegistryConfirm( m_nConfID, GCC_RETRIEVE_ENTRY_CONFIRM, registry_entry->registry_key, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, FALSE, GCC_RESULT_SUCCESSFUL); } else { // Send back a negative result requester_sap->RegistryConfirm( m_nConfID, GCC_RETRIEVE_ENTRY_CONFIRM, registry_key_data, m_pEmptyRegItem, GCC_NO_MODIFICATION_RIGHTS_SPECIFIED, 0, // No owner id 0, // No entity id FALSE, GCC_RESULT_ENTRY_DOES_NOT_EXIST); } rc = GCC_NO_ERROR; MyExit: if (NULL != registry_key_data) { registry_key_data->Release(); } return (rc); } /* * GCCError DeleteEntry () * * Public Function Description * This routine is used by a local APE to delete an item that was * registered with GCC. If this registry object does NOT * live at the top provider node this class is responsible for * forwarding the request on up to the top provider. */ GCCError CRegistry::DeleteEntry ( PGCCRegistryKey registry_key, EntityID entity_id ) { GCCError rc; REG_ENTRY *registry_entry; CRegKeyContainer *registry_key_data = NULL; // a must CAppSap *requester_sap; if (NULL == (requester_sap = m_AppSapEidList2.Find(entity_id))) { return GCC_APP_NOT_ENROLLED; } DBG_SAVE_FILE_LINE registry_key_data = new CRegKeyContainer(registry_key, &rc); if ((registry_key_data == NULL) || (rc != GCC_NO_ERROR)) { ERROR_OUT(("CRegistry::DeleteEntry: can't create regitry key")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } if (m_fTopProvider == FALSE) { m_pMCSUserObject->RegistryDeleteEntryRequest(registry_key_data, entity_id); rc = GCC_NO_ERROR; goto MyExit; } // no PDU is sent when request occurs at the top provider /* ** First check to see if the registry entry exists and if it does ** check the ownership to make sure this node has permission to ** change the entry. */ registry_entry = GetRegistryEntry(registry_key_data); if (registry_entry != NULL) { if (((registry_entry->owner_id == m_pMCSUserObject->GetMyNodeID()) && (registry_entry->entity_id == entity_id)) || (registry_entry->owner_id == 0)) { /* ** First convert this to a non-entry incase it needs to ** be included in a monitor indication. We first delete ** the old entry item and replace it with an Emtpy item. */ registry_entry->entry_item->Release(); registry_entry->entry_item = m_pEmptyRegItem; registry_entry->owner_id = 0; registry_entry->entity_id = 0; registry_entry->modification_rights = GCC_NO_MODIFICATION_RIGHTS_SPECIFIED; // Send Monitor Indication if necessary if (registry_entry->monitoring_state == ON) { /* ** Deliver the monitor indication to the Top ** Provider's Node Controller if necessary. */ SendMonitorEntryIndicationMessage(registry_entry); /* ** Broadcast a monitor entry indication to all ** nodes in the conference. */ m_pMCSUserObject->RegistryMonitorEntryIndication( registry_entry->registry_key, registry_entry->entry_item, registry_entry->owner_id, registry_entry->entity_id, registry_entry->modification_rights); } m_RegEntryList.Remove(registry_entry); if (NULL != registry_entry->registry_key) { registry_entry->registry_key->Release(); } delete registry_entry; // Send success for the result requester_sap->RegistryConfirm( m_nConfID, GCC_DELETE_ENTRY_CONFIRM, registry_key_data, NULL, GCC_NO_MODIFICATION_RIGHTS_SPECIFIED, 0, 0, FALSE, GCC_RESULT_SUCCESSFUL); } else { // No ownership rights send back negative result requester_sap->RegistryConfirm ( m_nConfID, GCC_DELETE_ENTRY_CONFIRM, registry_entry->registry_key, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, FALSE, GCC_RESULT_INDEX_ALREADY_OWNED); } } else { // Send failure for the result. Entry does not exist requester_sap->RegistryConfirm ( m_nConfID, GCC_DELETE_ENTRY_CONFIRM, registry_key_data, NULL, GCC_NO_MODIFICATION_RIGHTS_SPECIFIED, 0, 0, FALSE, GCC_RESULT_ENTRY_DOES_NOT_EXIST); } rc = GCC_NO_ERROR; MyExit: // The registry key data object is no longer needed here if (NULL != registry_key_data) { registry_key_data->Release(); } return (rc); } /* * GCCError MonitorRequest () * * Public Function Description * This routine is used by a local APE to monitor an item that was * registered with GCC. If this registry object does NOT * live at the top provider node this class is responsible for * forwarding the request on up to the top provider. */ GCCError CRegistry::MonitorRequest ( PGCCRegistryKey registry_key, BOOL enable_delivery, EntityID entity_id ) { GCCError rc = GCC_NO_ERROR; REG_ENTRY *registry_entry; CRegKeyContainer *registry_key_data; GCCResult result = GCC_RESULT_SUCCESSFUL; CAppSap *requester_sap; BOOL fToConfirm = FALSE; if (NULL == (requester_sap = m_AppSapEidList2.Find(entity_id))) { return GCC_APP_NOT_ENROLLED; } /* ** First set up the Registry Key. Return immediately if a resource ** failure occurs. */ DBG_SAVE_FILE_LINE registry_key_data = new CRegKeyContainer(registry_key, &rc); if ((registry_key_data != NULL) && (rc == GCC_NO_ERROR)) { /* ** If the request is recieved at a node that is not the top ** provider we must send the request on to the top provider. */ if (m_fTopProvider == FALSE) { if (enable_delivery) { /* ** Here we first go ahead and add the requesting APE to the ** list of applications wishing to monitor this particular ** entry. Note that if this entry does not exists at the top ** provider, this entry will be removed during the confirm. */ rc = AddAPEToMonitoringList(registry_key_data, entity_id, requester_sap); if (rc == GCC_NO_ERROR) { /* ** Wait for the response before sending the confirm ** if we get this far. */ m_pMCSUserObject->RegistryMonitorRequest(registry_key_data, entity_id); } else { result = GCC_RESULT_RESOURCES_UNAVAILABLE; fToConfirm = TRUE; } } else { RemoveAPEFromMonitoringList(registry_key_data, entity_id); result = GCC_RESULT_SUCCESSFUL; fToConfirm = TRUE; } } else // No PDU is sent when request occurs at the top provider { if (enable_delivery) { /* ** First check to see if the registry entry exists. If it does ** not we go ahead and create an empty entry so that we can ** add the monitoring APE to that entries list of monitoring ** APEs. */ registry_entry = GetRegistryEntry(registry_key_data); if (registry_entry != NULL) { /* ** Here we go ahead and add the requesting APE to the ** list of applications wishing to monitor this entry. */ rc = AddAPEToMonitoringList(registry_key_data, entity_id, requester_sap); if (rc == GCC_NO_ERROR) { // Set the monitoring state to ON registry_entry->monitoring_state = ON; } else { result = GCC_RESULT_RESOURCES_UNAVAILABLE; } } else { result = GCC_RESULT_ENTRY_DOES_NOT_EXIST; } } else { RemoveAPEFromMonitoringList(registry_key_data, entity_id); } fToConfirm = TRUE; } } else { ERROR_OUT(("CRegistry::MonitorRequest: can't create registry key")); rc = GCC_ALLOCATION_FAILURE; } if (fToConfirm) { ASSERT(NULL != registry_key_data); requester_sap->RegistryConfirm( m_nConfID, GCC_MONITOR_CONFIRM, registry_key_data, NULL, GCC_NO_MODIFICATION_RIGHTS_SPECIFIED, 0, 0, enable_delivery, result); } // The registry key data object is no longer needed if (NULL != registry_key_data) { registry_key_data->Release(); } return (rc); } /* * GCCError AllocateHandleRequest () * * Public Function Description * This routine is used by a local APE to allocate a specified number of * handles from the application registry. If this registry object does NOT * live at the top provider node this class is responsible for * forwarding the request on up to the top provider. */ GCCError CRegistry::AllocateHandleRequest( UINT number_of_handles, EntityID entity_id ) { UINT temp_registry_handle; CAppSap *requester_sap; if (NULL == (requester_sap = m_AppSapEidList2.Find(entity_id))) { return GCC_APP_NOT_ENROLLED; } if (m_fTopProvider == FALSE) { m_pMCSUserObject->RegistryAllocateHandleRequest(number_of_handles, entity_id); } else // No PDU is sent when request occurs at the top provider { UINT nFirstHandle = 0; GCCResult nResult; if ((number_of_handles > 0) && (number_of_handles <= MAXIMUM_ALLOWABLE_ALLOCATED_HANDLES)) { temp_registry_handle = m_nRegHandle + number_of_handles; if (temp_registry_handle > m_nRegHandle) { nFirstHandle = m_nRegHandle; nResult = GCC_RESULT_SUCCESSFUL; m_nRegHandle = temp_registry_handle; } else { ASSERT(0 == nFirstHandle); nResult = GCC_RESULT_NO_HANDLES_AVAILABLE; } } else { ASSERT(0 == nFirstHandle); nResult = GCC_RESULT_INVALID_NUMBER_OF_HANDLES; } requester_sap->RegistryAllocateHandleConfirm ( m_nConfID, number_of_handles, nFirstHandle, nResult); } return (GCC_NO_ERROR); } /* * GCCError ProcessRegisterChannelPDU () * * Public Function Description * This routine is used by the top provider node to process incomming * register channel PDUs. It is responsible for returning any * necessary responses that must be sent back to the requesting node. */ GCCError CRegistry::ProcessRegisterChannelPDU ( CRegKeyContainer *registry_key_data, ChannelID channel_id, UserID requester_node_id, EntityID requester_entity_id ) { GCCError rc = GCC_NO_ERROR; REG_ENTRY *registry_entry; CRegItem *registry_item_data; GCCRegistryItem registry_item; BOOL application_is_enrolled = FALSE; CAppRosterMgr *lpAppRosterMgr; /* ** We first make sure that this request is comming from an APE that ** previously enrolled. Here we are not worried about a specific ** session, only that the APE is enrolled. */ m_pAppRosterMgrList->Reset(); while (NULL != (lpAppRosterMgr = m_pAppRosterMgrList->Iterate())) { if (lpAppRosterMgr->IsAPEEnrolled (requester_node_id, requester_entity_id)) { application_is_enrolled = TRUE; break; } } if (application_is_enrolled) { /* ** Next check to see if the registry entry exists and if it does ** check the ownership to make sure this node has permission to ** change the entry. */ registry_entry = GetRegistryEntry ( registry_key_data ); if (registry_entry != NULL) { // Entry already exists, send back negative result m_pMCSUserObject->RegistryResponse( REGISTER_CHANNEL, requester_node_id, requester_entity_id, registry_key_data, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, GCC_RESULT_ENTRY_ALREADY_EXISTS); } else { registry_item.item_type = GCC_REGISTRY_CHANNEL_ID; registry_item.channel_id = channel_id; DBG_SAVE_FILE_LINE registry_item_data = new CRegItem(®istry_item, &rc); if ((registry_item_data != NULL) && (rc == GCC_NO_ERROR)) { DBG_SAVE_FILE_LINE registry_entry = new REG_ENTRY; if (registry_entry != NULL) { // Fill in the new entry DBG_SAVE_FILE_LINE registry_entry->registry_key = new CRegKeyContainer(registry_key_data, &rc); if ((registry_entry->registry_key != NULL) && (rc == GCC_NO_ERROR)) { registry_entry->entry_item = registry_item_data; registry_entry->monitoring_state = OFF; registry_entry->owner_id = requester_node_id; registry_entry->entity_id = requester_entity_id; /* ** Initialize to public incase entry is switched to ** a parameter. Note that as long as the entry is ** not a PARAMETER modification rights will not be ** used. */ registry_entry->modification_rights = GCC_PUBLIC_RIGHTS; m_RegEntryList.Append(registry_entry); // Send success for the result m_pMCSUserObject->RegistryResponse( REGISTER_CHANNEL, requester_node_id, requester_entity_id, registry_entry->registry_key, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, GCC_RESULT_SUCCESSFUL); } else if (registry_entry->registry_key == NULL) { delete registry_entry; registry_item_data->Release(); rc = GCC_ALLOCATION_FAILURE; } else { registry_entry->registry_key->Release(); delete registry_entry; registry_item_data->Release(); } } else { rc = GCC_ALLOCATION_FAILURE; } } else if (registry_item_data == NULL) { rc = GCC_ALLOCATION_FAILURE; } else { registry_item_data->Release(); } } } else { // Send back negative result stating invalid requester m_pMCSUserObject->RegistryResponse( REGISTER_CHANNEL, requester_node_id, requester_entity_id, registry_key_data, NULL, GCC_NO_MODIFICATION_RIGHTS_SPECIFIED, 0, 0, GCC_RESULT_INVALID_REQUESTER); } return (rc); } /* * GCCError ProcessAssignTokenPDU () * * Public Function Description * This routine is used by the top provider node to process incomming * register token PDUs. It is responsible for returning any * necessary responses that must be sent back to the requesting node. */ GCCError CRegistry::ProcessAssignTokenPDU ( CRegKeyContainer *registry_key_data, UserID requester_node_id, EntityID requester_entity_id ) { GCCError rc = GCC_NO_ERROR; REG_ENTRY *registry_entry; CRegItem *registry_item_data; GCCRegistryItem registry_item; BOOL application_is_enrolled = FALSE; CAppRosterMgr *lpAppRosterMgr; /* ** We first make sure that this request is comming from an APE that ** previously enrolled. Here we are not worried about a specific ** session, only that the APE is enrolled. */ m_pAppRosterMgrList->Reset(); while (NULL != (lpAppRosterMgr = m_pAppRosterMgrList->Iterate())) { if (lpAppRosterMgr->IsAPEEnrolled (requester_node_id, requester_entity_id)) { application_is_enrolled = TRUE; break; } } if (application_is_enrolled) { /* ** First check to see if the registry entry exists and if it does ** check the ownership to make sure this node has permission to ** change the entry. */ registry_entry = GetRegistryEntry ( registry_key_data ); if (registry_entry != NULL) { // Entry already exists, send back negative result m_pMCSUserObject->RegistryResponse(ASSIGN_TOKEN, requester_node_id, requester_entity_id, registry_key_data, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, GCC_RESULT_ENTRY_ALREADY_EXISTS); } else { DBG_SAVE_FILE_LINE registry_entry = new REG_ENTRY; if (registry_entry != NULL) { registry_item.item_type = GCC_REGISTRY_TOKEN_ID; registry_item.token_id = GetUnusedToken(); DBG_SAVE_FILE_LINE registry_item_data = new CRegItem(®istry_item, &rc); if ((registry_item_data != NULL) && (rc == GCC_NO_ERROR)) { // Fill in the new entry DBG_SAVE_FILE_LINE registry_entry->registry_key = new CRegKeyContainer(registry_key_data, &rc); if ((registry_entry->registry_key != NULL) && (rc == GCC_NO_ERROR)) { registry_entry->entry_item = registry_item_data; registry_entry->monitoring_state = OFF; registry_entry->owner_id = requester_node_id; registry_entry->entity_id = requester_entity_id; /* ** Initialize to public incase entry is switched to ** a parameter. Note that as long as the entry is ** not a PARAMETER modification rights will not be ** used. */ registry_entry->modification_rights = GCC_PUBLIC_RIGHTS; // Add registry entry to registry list m_RegEntryList.Append(registry_entry); // Send success for the result m_pMCSUserObject->RegistryResponse( ASSIGN_TOKEN, requester_node_id, requester_entity_id, registry_key_data, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, GCC_RESULT_SUCCESSFUL); } else if (registry_entry->registry_key == NULL) { registry_item_data->Release(); delete registry_entry; rc = GCC_ALLOCATION_FAILURE; } else { registry_entry->registry_key->Release(); registry_item_data->Release(); delete registry_entry; } } else { if (registry_item_data == NULL) { rc = GCC_ALLOCATION_FAILURE; } else { registry_item_data->Release(); } delete registry_entry; } } else { rc = GCC_ALLOCATION_FAILURE; } } } else { m_pMCSUserObject->RegistryResponse( ASSIGN_TOKEN, requester_node_id, requester_entity_id, registry_key_data, NULL, GCC_NO_MODIFICATION_RIGHTS_SPECIFIED, 0, 0, GCC_RESULT_INVALID_REQUESTER); } return (rc); } /* * GCCError ProcessSetParameterPDU () * * Public Function Description * This routine is used by the top provider node to process incomming * register parameter PDUs. It is responsible for returning any * necessary responses that must be sent back to the requesting node. */ GCCError CRegistry::ProcessSetParameterPDU ( CRegKeyContainer *registry_key_data, LPOSTR parameter_value, GCCModificationRights modification_rights, UserID requester_node_id, EntityID requester_entity_id ) { GCCError rc = GCC_NO_ERROR; REG_ENTRY *registry_entry; CRegItem *registry_item_data; GCCResult result; GCCRegistryItem registry_item; BOOL application_is_enrolled = FALSE; CAppRosterMgr *lpAppRosterMgr; /* ** We first make sure that this request is comming from an APE that ** previously enrolled. Here we are not worried about a specific ** session, only that the APE is enrolled. */ m_pAppRosterMgrList->Reset(); while (NULL != (lpAppRosterMgr = m_pAppRosterMgrList->Iterate())) { if (lpAppRosterMgr->IsAPEEnrolled (requester_node_id, requester_entity_id)) { application_is_enrolled = TRUE; break; } } if (application_is_enrolled) { // Set up the registry item if (parameter_value != NULL) { registry_item.item_type = GCC_REGISTRY_PARAMETER; registry_item.parameter = *parameter_value; } else registry_item.item_type = GCC_REGISTRY_NONE; /* ** Check to see if the registry entry exists and if it does ** check the ownership to make sure this node has permission to ** change the entry. */ registry_entry = GetRegistryEntry ( registry_key_data ); if (registry_entry != NULL) { /* ** Here we make sure that this request is comming from an ** APE that previously enrolled in the appropriate session. */ m_pAppRosterMgrList->Reset(); while (NULL != (lpAppRosterMgr = m_pAppRosterMgrList->Iterate())) { if (lpAppRosterMgr->IsAPEEnrolled (registry_key_data->GetSessionKey (), requester_node_id, requester_entity_id)) { application_is_enrolled = TRUE; break; } } /* ** Check ownership rights here: First check is to make ** sure that this is the owner if Owner rights is ** specified. Next check is to make sure that */ if (((registry_entry->modification_rights == GCC_OWNER_RIGHTS) && (registry_entry->owner_id == requester_node_id) && (registry_entry->entity_id == requester_entity_id)) || ((registry_entry->modification_rights == GCC_SESSION_RIGHTS) && (application_is_enrolled)) || (registry_entry->modification_rights == GCC_PUBLIC_RIGHTS) || (registry_entry->owner_id == 0)) { DBG_SAVE_FILE_LINE registry_item_data = new CRegItem(®istry_item, &rc); if ((registry_item_data != NULL) && (rc == GCC_NO_ERROR)) { // Monitoring state should not be affected by this request *registry_entry->entry_item = *registry_item_data; /* ** Only the owner is allowed to change the modification ** rights of a registry entry (unless the entry is ** unowned). Also if there is no owner, we set up the ** new owner here. */ if (((registry_entry->owner_id == requester_node_id) && (registry_entry->entity_id == requester_entity_id)) || (registry_entry->owner_id == 0)) { /* ** This will take care of setting up the new owner if ** one exists. */ registry_entry->owner_id = requester_node_id; registry_entry->entity_id = requester_entity_id; /* ** If no modification rights are specified we must ** set the modification rights to be public. */ if (modification_rights != GCC_NO_MODIFICATION_RIGHTS_SPECIFIED) { registry_entry->modification_rights = modification_rights; } } // Send Monitor Indication if necessary if (registry_entry->monitoring_state == ON) { /* ** Deliver the monitor indication to the Top ** Provider's Node Controller if necessary. */ SendMonitorEntryIndicationMessage(registry_entry); /* ** Broadcast a monitor entry indication to all ** nodes in the conference. */ m_pMCSUserObject->RegistryMonitorEntryIndication( registry_entry->registry_key, registry_entry->entry_item, registry_entry->owner_id, registry_entry->entity_id, registry_entry->modification_rights); } registry_item_data->Release(); // Send success for the result result = GCC_RESULT_SUCCESSFUL; } else if (registry_item_data == NULL) { rc = GCC_ALLOCATION_FAILURE; result = GCC_RESULT_RESOURCES_UNAVAILABLE; } else { registry_item_data->Release(); result = GCC_RESULT_RESOURCES_UNAVAILABLE; } } else result = GCC_RESULT_INDEX_ALREADY_OWNED; // No ownership rights send back negative result m_pMCSUserObject->RegistryResponse(SET_PARAMETER, requester_node_id, requester_entity_id, registry_key_data, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, result); } else { DBG_SAVE_FILE_LINE registry_entry = new REG_ENTRY; if (registry_entry != NULL) { DBG_SAVE_FILE_LINE registry_item_data = new CRegItem(®istry_item, &rc); if ((registry_item_data != NULL) && (rc == GCC_NO_ERROR)) { // Fill in the new entry DBG_SAVE_FILE_LINE registry_entry->registry_key = new CRegKeyContainer(registry_key_data, &rc); if ((registry_entry->registry_key != NULL) && (rc == GCC_NO_ERROR)) { registry_entry->entry_item = registry_item_data; registry_entry->monitoring_state = OFF; registry_entry->owner_id = requester_node_id; registry_entry->entity_id = requester_entity_id; /* ** If no modification rights are specified we must ** initialize the modification rights to be public. ** Note that modification rights are only specified ** for the SetParameter call. */ if (modification_rights == GCC_NO_MODIFICATION_RIGHTS_SPECIFIED) { registry_entry->modification_rights = GCC_PUBLIC_RIGHTS; } else { registry_entry->modification_rights = modification_rights; } // Add registry entry to registry list m_RegEntryList.Append(registry_entry); // Send success for the result m_pMCSUserObject->RegistryResponse( SET_PARAMETER, requester_node_id, requester_entity_id, registry_key_data, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, GCC_RESULT_SUCCESSFUL); } else if (registry_entry->registry_key == NULL) { registry_item_data->Release(); delete registry_entry; rc = GCC_ALLOCATION_FAILURE; } else { registry_entry->registry_key->Release(); registry_item_data->Release(); delete registry_entry; } } else if (registry_item_data == NULL) { delete registry_entry; rc = GCC_ALLOCATION_FAILURE; } } else { rc = GCC_ALLOCATION_FAILURE; } } } else { m_pMCSUserObject->RegistryResponse( SET_PARAMETER, requester_node_id, requester_entity_id, registry_key_data, NULL, GCC_NO_MODIFICATION_RIGHTS_SPECIFIED, 0, 0, GCC_RESULT_INVALID_REQUESTER); } return (rc); } /* * void ProcessRetrieveEntryPDU () * * Public Function Description * This routine is used by the top provider node to process an incomming * request to retrieve a registry entry. It is responsible for returning * any necessary responses that must be sent back to the requesting node. */ void CRegistry::ProcessRetrieveEntryPDU ( CRegKeyContainer *registry_key_data, UserID requester_node_id, EntityID requester_entity_id) { REG_ENTRY *registry_entry; registry_entry = GetRegistryEntry ( registry_key_data ); if (registry_entry != NULL) { // Send back a positive result with the entry item m_pMCSUserObject->RegistryResponse(RETRIEVE_ENTRY, requester_node_id, requester_entity_id, registry_key_data, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, GCC_RESULT_SUCCESSFUL); } else { // Send back a negative result m_pMCSUserObject->RegistryResponse(RETRIEVE_ENTRY, requester_node_id, requester_entity_id, registry_key_data, m_pEmptyRegItem, GCC_NO_MODIFICATION_RIGHTS_SPECIFIED, 0, 0, GCC_RESULT_ENTRY_DOES_NOT_EXIST); } } /* * void ProcessDeleteEntryPDU () * * Public Function Description * This routine is used by the top provider node to process an incomming * request to delete a registry entry. It is responsible for returning * any necessary responses that must be sent back to the requesting node. */ void CRegistry::ProcessDeleteEntryPDU ( CRegKeyContainer *registry_key_data, UserID requester_node_id, EntityID requester_entity_id) { REG_ENTRY *registry_entry; BOOL application_is_enrolled = FALSE; CAppRosterMgr *lpAppRosterMgr; /* ** We first make sure that this request is comming from an APE that ** previously enrolled. Here we are not worried about a specific ** session, only that the APE is enrolled. */ m_pAppRosterMgrList->Reset(); while (NULL != (lpAppRosterMgr = m_pAppRosterMgrList->Iterate())) { if (lpAppRosterMgr->IsAPEEnrolled (requester_node_id, requester_entity_id)) { application_is_enrolled = TRUE; break; } } if (application_is_enrolled) { /* ** First check to see if the registry entry exists and if it does ** check the ownership to make sure this node has permission to ** change the entry. */ registry_entry = GetRegistryEntry ( registry_key_data ); if (registry_entry != NULL) { if (((registry_entry->owner_id == requester_node_id) && (registry_entry->entity_id == requester_entity_id)) || (registry_entry->owner_id == NULL)) { m_pMCSUserObject->RegistryResponse( DELETE_ENTRY, requester_node_id, requester_entity_id, registry_key_data, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, GCC_RESULT_SUCCESSFUL); /* ** First convert this to a non-entry incase it needs to ** be included in a monitor indication. We first delete ** the old entry item and replace it with an Emtpy item. */ if (NULL != registry_entry->entry_item) { registry_entry->entry_item->Release(); } registry_entry->entry_item = m_pEmptyRegItem; registry_entry->owner_id = 0; registry_entry->entity_id = 0; registry_entry->modification_rights = GCC_NO_MODIFICATION_RIGHTS_SPECIFIED; // Send Monitor Indication if necessary if (registry_entry->monitoring_state == ON) { /* ** Deliver the monitor indication to the Top ** Provider's Node Controller if necessary. */ SendMonitorEntryIndicationMessage(registry_entry); /* ** Broadcast a monitor entry indication to all ** nodes in the conference. */ m_pMCSUserObject->RegistryMonitorEntryIndication( registry_entry->registry_key, registry_entry->entry_item, registry_entry->owner_id, registry_entry->entity_id, registry_entry->modification_rights); } // Remove the entry from the list m_RegEntryList.Remove(registry_entry); if (NULL != registry_entry->registry_key) { registry_entry->registry_key->Release(); } delete registry_entry; } else { // No ownership rights send back negative result m_pMCSUserObject->RegistryResponse( DELETE_ENTRY, requester_node_id, requester_entity_id, registry_key_data, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, GCC_RESULT_INDEX_ALREADY_OWNED); } } else { // Send failure for the result. Entry does not exist m_pMCSUserObject->RegistryResponse( DELETE_ENTRY, requester_node_id, requester_entity_id, registry_key_data, m_pEmptyRegItem, GCC_NO_MODIFICATION_RIGHTS_SPECIFIED, 0, 0, GCC_RESULT_ENTRY_DOES_NOT_EXIST); } } else { m_pMCSUserObject->RegistryResponse( DELETE_ENTRY, requester_node_id, requester_entity_id, registry_key_data, NULL, GCC_NO_MODIFICATION_RIGHTS_SPECIFIED, 0, 0, GCC_RESULT_INVALID_REQUESTER); } } /* * void ProcessMonitorEntryPDU () * * Public Function Description * This routine is used by the top provider node to process an incomming * request to monitor a registry entry. It is responsible for returning * any necessary responses that must be sent back to the requesting node. */ void CRegistry::ProcessMonitorEntryPDU ( CRegKeyContainer *registry_key_data, UserID requester_node_id, EntityID requester_entity_id ) { REG_ENTRY *registry_entry; /* ** First check to see if the registry entry exists and if it does ** check the ownership to make sure this node has permission to ** change the entry. */ registry_entry = GetRegistryEntry ( registry_key_data ); if (registry_entry != NULL) { // Set the monitoring state to on for the life of this entry. registry_entry->monitoring_state = ON; // No ownership rights send back negative result m_pMCSUserObject->RegistryResponse(MONITOR_ENTRY, requester_node_id, requester_entity_id, registry_key_data, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id, GCC_RESULT_SUCCESSFUL); } else { // Send failure for the result. Entry does not exist m_pMCSUserObject->RegistryResponse(MONITOR_ENTRY, requester_node_id, requester_entity_id, registry_key_data, m_pEmptyRegItem, GCC_NO_MODIFICATION_RIGHTS_SPECIFIED, 0, 0, GCC_RESULT_ENTRY_DOES_NOT_EXIST); } } /* * void ProcessRegistryResponsePDU () * * Public Function Description * This routine is used by nodes other than the top provider node to * process registry responses from the top provider. It is responsible for * generating any local messages associated with this response. */ void CRegistry::ProcessRegistryResponsePDU ( RegistryResponsePrimitiveType primitive_type, CRegKeyContainer *registry_key_data, CRegItem *registry_item_data, GCCModificationRights modification_rights, EntityID requester_entity_id, UserID owner_node_id, EntityID owner_entity_id, GCCResult result) { GCCError error_value = GCC_NO_ERROR; GCCMessageType message_type; CAppSap *pAppSap; // Pop the next outstanding request off the queue if (NULL != (pAppSap = m_AppSapEidList2.Find(requester_entity_id))) { switch (primitive_type) { case REGISTER_CHANNEL: message_type = GCC_REGISTER_CHANNEL_CONFIRM; break; case ASSIGN_TOKEN: message_type = GCC_ASSIGN_TOKEN_CONFIRM; break; case SET_PARAMETER: message_type = GCC_SET_PARAMETER_CONFIRM; break; case RETRIEVE_ENTRY: message_type = GCC_RETRIEVE_ENTRY_CONFIRM; break; case DELETE_ENTRY: message_type = GCC_DELETE_ENTRY_CONFIRM; break; case MONITOR_ENTRY: message_type = GCC_MONITOR_CONFIRM; /* ** Here we must check the result. If the result failed ** we pull the monitoring SAP from the monitor list. */ if (result != GCC_RESULT_SUCCESSFUL) { RemoveAPEFromMonitoringList ( registry_key_data, requester_entity_id); } break; default: error_value = GCC_INVALID_PARAMETER; ERROR_OUT(("CRegistry::ProcessRegistryResponsePDU: Bad request type, primitive_type=%d", (UINT) primitive_type)); break; } if (error_value == GCC_NO_ERROR) { /* ** Note the the monitor enable variable is always set to TRUE ** when a monitor response is received from the Top Provider. ** Otherwise, this is not even used. */ pAppSap->RegistryConfirm(m_nConfID, message_type, registry_key_data, registry_item_data, modification_rights, owner_node_id, owner_entity_id, TRUE, result); } } else { WARNING_OUT(("CRegistry::ProcessRegistryResponsePDU: no such app sap")); } } /* * void ProcessMonitorIndicationPDU () * * Public Function Description * This routine is used by nodes other than the top provider node to * process registry monitor indications from the top provider. It is * responsible for generating any local messages associated with this * response. */ void CRegistry::ProcessMonitorIndicationPDU ( CRegKeyContainer *registry_key_data, CRegItem *registry_item_data, GCCModificationRights modification_rights, UserID owner_node_id, EntityID owner_entity_id) { REG_ENTRY *lpRegEntry; EntityID eid; CAppSap *pAppSap; m_RegEntryList.Reset(); while (NULL != (lpRegEntry = m_RegEntryList.Iterate())) { if (*registry_key_data == *lpRegEntry->registry_key) { lpRegEntry->monitoring_list.Reset(); while (GCC_INVALID_EID != (eid = lpRegEntry->monitoring_list.Iterate())) { if (NULL != (pAppSap = m_AppSapEidList2.Find(eid))) { pAppSap->RegistryMonitorIndication(m_nConfID, registry_key_data, registry_item_data, modification_rights, owner_node_id, owner_entity_id); } } } } } /* * void ProcessAllocateHandleRequestPDU () * * Public Function Description * This routine is used by the top provider node to process an incomming * request to allocate a number of handles. It is responsible for * returning any necessary responses that must be sent back to the * requesting node. */ void CRegistry::ProcessAllocateHandleRequestPDU ( UINT number_of_handles, EntityID requester_entity_id, UserID requester_node_id) { UINT temp_registry_handle; if (m_fTopProvider) { if ((number_of_handles > 0) && (number_of_handles <= MAXIMUM_ALLOWABLE_ALLOCATED_HANDLES)) { temp_registry_handle = m_nRegHandle + number_of_handles; if (temp_registry_handle > m_nRegHandle) { m_pMCSUserObject->RegistryAllocateHandleResponse( number_of_handles, m_nRegHandle, requester_entity_id, requester_node_id, GCC_RESULT_SUCCESSFUL); m_nRegHandle = temp_registry_handle; } else { m_pMCSUserObject->RegistryAllocateHandleResponse( number_of_handles, 0, requester_entity_id, requester_node_id, GCC_RESULT_NO_HANDLES_AVAILABLE); } } else { m_pMCSUserObject->RegistryAllocateHandleResponse( number_of_handles, 0, requester_entity_id, requester_node_id, GCC_RESULT_INVALID_NUMBER_OF_HANDLES); } } } /* * void ProcessAllocateHandleResponsePDU () * * Public Function Description * This routine is used by a node other than the top provider node to * process an allocate handle response. It is responsible for generating * any local messages associated with this response. */ void CRegistry::ProcessAllocateHandleResponsePDU ( UINT number_of_handles, UINT first_handle, EntityID eidRequester, GCCResult result) { CAppSap *pAppSap; if (NULL != (pAppSap = m_AppSapEidList2.Find(eidRequester))) { pAppSap->RegistryAllocateHandleConfirm(m_nConfID, number_of_handles, first_handle, result); } } /* * void RemoveNodeOwnership () * * Public Function Description * This routine removes ownership of all the registry entries associated * with the specified node ID. These entries become unowned. This request * should only be made from the top provider node. This is a local * operation. */ void CRegistry::RemoveNodeOwnership ( UserID node_id ) { if (m_fTopProvider) { REG_ENTRY *lpRegEntry; m_RegEntryList.Reset(); while (NULL != (lpRegEntry = m_RegEntryList.Iterate())) { if (lpRegEntry->owner_id == node_id) { lpRegEntry->owner_id = 0; lpRegEntry->entity_id = 0; // Send Monitor Indication if necessary if (lpRegEntry->monitoring_state == ON) { /* ** Deliver the monitor indication to the Top ** Provider's Node Controller if necessary. */ SendMonitorEntryIndicationMessage (lpRegEntry); m_pMCSUserObject->RegistryMonitorEntryIndication( lpRegEntry->registry_key, lpRegEntry->entry_item, lpRegEntry->owner_id, lpRegEntry->entity_id, lpRegEntry->modification_rights); } } } } } /* * void RemoveEntityOwnership () * * Public Function Description * This routine removes ownership of all the registry entries associated * with the specified APE. These entries become unowned. This request * should only be made from the top provider node. This is a local * operation. */ void CRegistry::RemoveEntityOwnership ( UserID node_id, EntityID entity_id ) { if (m_fTopProvider) { REG_ENTRY *lpRegEntry; m_RegEntryList.Reset(); while (NULL != (lpRegEntry = m_RegEntryList.Iterate())) { if ((lpRegEntry->owner_id == node_id) && (lpRegEntry->entity_id == entity_id)) { lpRegEntry->owner_id = 0; lpRegEntry->entity_id = 0; // Send Monitor Indication if necessary if (lpRegEntry->monitoring_state == ON) { /* ** Deliver the monitor indication to the Top ** Provider's Node Controller if necessary. */ SendMonitorEntryIndicationMessage(lpRegEntry); m_pMCSUserObject->RegistryMonitorEntryIndication( lpRegEntry->registry_key, lpRegEntry->entry_item, lpRegEntry->owner_id, lpRegEntry->entity_id, lpRegEntry->modification_rights); } } } } } /* * void RemoveSessionKeyReference () * * Public Function Description * This routine removes all registry entries associated with the * specified session. This is a local operation. */ void CRegistry::RemoveSessionKeyReference(CSessKeyContainer *session_key) { BOOL keys_match; CRegKeyContainer *registry_key_data; if (m_fTopProvider) { /* ** This outer loop is to handle resetting the rogue wave iterator. ** You can not delete a list entry while in the iterator with out ** resetting it. */ while (1) { REG_ENTRY *lpRegEntry; keys_match = FALSE; m_RegEntryList.Reset(); while (NULL != (lpRegEntry= m_RegEntryList.Iterate())) { registry_key_data = lpRegEntry->registry_key; if (registry_key_data->IsThisYourSessionKey (session_key)) keys_match = TRUE; if (keys_match) { /* ** First convert this to a non-entry incase it needs to ** be included in a monitor indication. We first delete ** the old entry item and replace it with an Emtpy item. */ if (NULL != lpRegEntry->entry_item) { lpRegEntry->entry_item->Release(); } lpRegEntry->entry_item = m_pEmptyRegItem; lpRegEntry->owner_id = 0; lpRegEntry->entity_id = 0; lpRegEntry->modification_rights = GCC_NO_MODIFICATION_RIGHTS_SPECIFIED; // Send Monitor Indication if necessary if (lpRegEntry->monitoring_state == ON) { /* ** Deliver the monitor indication to the Top ** Provider's Node Controller if necessary. */ SendMonitorEntryIndicationMessage(lpRegEntry); /* ** Broadcast a monitor entry indication to all ** nodes in the conference. */ m_pMCSUserObject->RegistryMonitorEntryIndication( lpRegEntry->registry_key, lpRegEntry->entry_item, lpRegEntry->owner_id, lpRegEntry->entity_id, lpRegEntry->modification_rights); } if (NULL != lpRegEntry->registry_key) { lpRegEntry->registry_key->Release(); } m_RegEntryList.Remove(lpRegEntry); delete lpRegEntry; break; } } if (keys_match == FALSE) break; } } } /* * REG_ENTRY *GetRegistryEntry () * * Private Function Description * This routine is responsible for searching the registry list for * the registry entry specified by the passed in registry key. NULL * is returned if the entry can not be found. * * Formal Parameters: * registry_key_data - (i) Registry key associated with entry to get. * * Return Value * Pointer to the registry item assoicated with the specified registry * key. NULL if it does not exists. * * Side Effects * None. * * Caveats * None. */ REG_ENTRY *CRegistry::GetRegistryEntry(CRegKeyContainer *registry_key_data) { REG_ENTRY *registry_entry = NULL; REG_ENTRY *lpRegEntry; m_RegEntryList.Reset(); while (NULL != (lpRegEntry = m_RegEntryList.Iterate())) { if (*lpRegEntry->registry_key == *registry_key_data) { registry_entry = lpRegEntry; break; } } return (registry_entry); } /* * TokenID GetUnusedToken () * * Private Function Description * This routine is responsible for generating an unused token. The routine * will return a token ID of zero if all are used up (this is very * unlikely). * * Formal Parameters: * None. * * Return Value * The generated token ID. Zero if no token IDs are available. * * Side Effects * None. * * Caveats * None. */ TokenID CRegistry::GetUnusedToken () { TokenID token_id = 0; CRegItem *registry_item_data; REG_ENTRY *lpRegEntry; while (token_id == 0) { token_id = m_nCurrentTokenID; m_nCurrentTokenID++; if (m_nCurrentTokenID == (TokenID)0xffff) { m_nCurrentTokenID = (TokenID)16384; } m_RegEntryList.Reset(); while (NULL != (lpRegEntry = m_RegEntryList.Iterate())) { registry_item_data = lpRegEntry->entry_item; if (registry_item_data->IsThisYourTokenID(token_id)) { token_id = 0; break; } } } return (token_id); } /* * GCCError AddAPEToMonitoringList () * * Private Function Description * This routine is used to add a new APE to the monitoring list. * * Formal Parameters: * registry_key_data - (i) Registry key associated with entry being * monitored. * entity_id - (i) Entity ID associated with the APE that is * doing the monitoring. * requester_sap - (i) Pointer to the command target associated * with APE making the request. * * Return Value * GCC_NO_ERROR - No error occured. * GCC_ALLOCATION_FAILURE - A resource error occured. * * Side Effects * None. * * Caveats * None. */ GCCError CRegistry::AddAPEToMonitoringList( CRegKeyContainer *registry_key_data, EntityID entity_id, CAppSap *requester_sap) { GCCError rc = GCC_NO_ERROR; REG_ENTRY *registry_entry; BOOL entry_does_exists; GCCRegistryItem registry_item; registry_entry = GetRegistryEntry (registry_key_data); /* ** If the registry does not exists we go ahead and create an empty ** entry here. */ if (registry_entry == NULL) { DBG_SAVE_FILE_LINE registry_entry = new REG_ENTRY; if (registry_entry != NULL) { // First allocate an empty registry item registry_item.item_type = GCC_REGISTRY_NONE; DBG_SAVE_FILE_LINE registry_entry->entry_item = new CRegItem(®istry_item, &rc); if ((registry_entry->entry_item != NULL) && (rc == GCC_NO_ERROR)) { // Next allocate the registry key DBG_SAVE_FILE_LINE registry_entry->registry_key = new CRegKeyContainer(registry_key_data, &rc); if ((registry_entry->registry_key != NULL) && (rc == GCC_NO_ERROR)) { /* ** If everything is OK up to here we go ahead and add the ** registry entry to the local entry list. */ m_RegEntryList.Append(registry_entry); } else if (registry_entry->registry_key == NULL) { rc = GCC_ALLOCATION_FAILURE; registry_entry->entry_item->Release(); } else { registry_entry->registry_key->Release(); registry_entry->entry_item->Release(); } } else if (registry_entry->entry_item == NULL) { rc = GCC_ALLOCATION_FAILURE; } else { registry_entry->entry_item->Release(); } if (rc != GCC_NO_ERROR) { delete registry_entry; } } else { rc = GCC_ALLOCATION_FAILURE; } } if (rc == GCC_NO_ERROR) { m_AppSapEidList2.Append(entity_id, requester_sap); /* ** Make sure that this entry does not already exists in the ** monitoring list. */ EntityID eid; registry_entry->monitoring_list.Reset(); entry_does_exists = FALSE; while (GCC_INVALID_EID != (eid = registry_entry->monitoring_list.Iterate())) { if (eid == entity_id) { entry_does_exists = TRUE; break; } } if (entry_does_exists == FALSE) { registry_entry->monitoring_list.Append(entity_id); } } return rc; } /* * void RemoveAPEFromMonitoringList () * * Private Function Description * This routine is used to remove an APE from the monitoring list. * * Formal Parameters: * registry_key_data - (i) Registry key associated with entry being * monitored. * entity_id - (i) Entity ID associated with the APE that is * being removed from the monitoring list. * * Return Value * None. * * Side Effects * None. * * Caveats * None. */ void CRegistry::RemoveAPEFromMonitoringList( CRegKeyContainer *registry_key_data, EntityID entity_id) { REG_ENTRY *registry_entry; registry_entry = GetRegistryEntry (registry_key_data); if (registry_entry != NULL) { /* ** Make sure that this entry does not already exists in the ** monitoring list. */ registry_entry->monitoring_list.Remove(entity_id); } } /* * void SendMonitorEntryIndicationMessage () * * Private Function Description * This routine is used to generate a monitor indication to all the * APEs that are currently monitoring the specified registry entry. * * Formal Parameters: * registry_entry - (i) Pointer to the registry entry being monitored. * * Return Value * None. * * Side Effects * None. * * Caveats * None. */ void CRegistry::SendMonitorEntryIndicationMessage(REG_ENTRY *registry_entry) { EntityID eid; CAppSap *pAppSap; registry_entry->monitoring_list.Reset(); while (GCC_INVALID_EID != (eid = registry_entry->monitoring_list.Iterate())) { if (NULL != (pAppSap = m_AppSapEidList2.Find(eid))) { pAppSap->RegistryMonitorIndication( m_nConfID, registry_entry->registry_key, registry_entry->entry_item, registry_entry->modification_rights, registry_entry->owner_id, registry_entry->entity_id); } } }