#include "precomp.h" DEBUG_FILEZONE(ZONE_T120_SAP); /* * csap.cpp * * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY * * Abstract: * This implementation file for the CControlSAP class contains Service * Access entry and exit points specific to the Node Controller. This * module inherits the common entry and exit points from the CBaseSap object. * On request and responses, parameter checking is performed to ensure that * they can be properly processed. Queuing and flushing of out bound * messages is taken care of in the base class. * * Protected Instance Variables: * See file SAP.CPP for definitions of instance variables. * * Private Instance Variables: * m_nJoinResponseTag: * This tag is used to match join request with join responses from the * node controller. * * m_JoinResponseTagList2: * This list keeps up with all the outstanding join response tags. * Tags are added to this list on a join indication and removed * from this list on a Join response. * * Private Member Functions: * IsNumericNameValid * This routine is used to validate a numeric string by checking to * make sure that none of the constraints imposed by the ASN.1 * specification are violated. * IsTextNameValid * This routine is used to validate a text string by checking to make * sure that none of the constraints imposed by the ASN.1 specification * are violated. * QueueJoinIndication * This routine is used to place join indications into the queue of * messages to be delivered to the node controller. * HandleResourceFailure * This routine is used to clean up after any resource allocation * failures which may have occurred by sending a status indication * reporting the error. * FreeCallbackMessage * This routine is used to free up any data which was allocated in * order to send a callback message to the node controller. * RetrieveUserDataList * This routine is used to fill in a user data list using a * CUserDataListContainer container. The memory needed to hold the user data * will be allocated by this routine. * * Caveats: * None. * * Author: * blp */ #include "ms_util.h" #include "csap.h" #include "conf.h" #include "gcontrol.h" // Defintions to support Join Response Tag hash list #define MAXIMUM_CONFERENCE_NAME_LENGTH 255 // This is how much time the apps have to cleanup with MCS and GCC // after GCCCleanup is called. They may be terminated if they do not // cleanup in this amount of time. #define PROCESS_TERMINATE_TIME 5000 /* * Static variables used within the C to C++ converter. * * Static_Controller * This is a pointer to the one-and-only controller created within the * GCC system. This object is created during * GCCStartup by the process * that is taking on the responsibilities of the node controller. */ GCCController *g_pGCCController = NULL; CControlSAP *g_pControlSap = NULL; char g_szGCCWndClassName[24]; // The MCS main thread handle extern HANDLE g_hMCSThread; /* * GCCError GCCStartup() * * Public * * Functional Description: * This API entry point is used to initialize the GCC DLL for action. It * creates an instance of the Controller, which controls all activity * during a GCC session. Note that there is only one instance of the * Controller, no matter how many applications are utilizing GCC * services. */ GCCError WINAPI T120_CreateControlSAP ( IT120ControlSAP **ppIControlSap, LPVOID pUserDefined, LPFN_T120_CONTROL_SAP_CB pfnControlSapCallback ) { GCCError rc; if (NULL != ppIControlSap && NULL != pfnControlSapCallback) { if (NULL == g_pGCCController && NULL == g_pControlSap) { // // Create the window class for all the SAPs, including both // control SAP and applet SAP. // WNDCLASS wc; ::wsprintfA(g_szGCCWndClassName, "GCC%0lx_%0lx", (UINT) ::GetCurrentProcessId(), (UINT) ::GetTickCount()); ASSERT(::lstrlenA(g_szGCCWndClassName) < sizeof(g_szGCCWndClassName)); ::ZeroMemory(&wc, sizeof(wc)); // wc.style = 0; wc.lpfnWndProc = SapNotifyWndProc; // wc.cbClsExtra = 0; // wc.cbWndExtra = 0; wc.hInstance = g_hDllInst; // wc.hIcon = NULL; // wc.hbrBackground = NULL; // wc.hCursor = NULL; // wc.lpszMenuName = NULL; wc.lpszClassName = g_szGCCWndClassName; if (::RegisterClass(&wc)) { /* * This process is to become the node controller. Create a * controller object to carry out these duties. */ DBG_SAVE_FILE_LINE g_pGCCController = new GCCController(&rc); if (NULL != g_pGCCController && GCC_NO_ERROR == rc) { /* ** Create the control SAP. Note that the Node Controller ** interface must be in place before this is called so ** that the control SAP can register itself. */ DBG_SAVE_FILE_LINE g_pControlSap = new CControlSAP(); if (NULL != g_pControlSap) { /* * Tell the application interface object what it * needs to know send callbacks to the node * controller. */ TRACE_OUT(("T120_CreateControlSAP: controller successfully created")); *ppIControlSap = g_pControlSap; g_pControlSap->RegisterNodeController(pfnControlSapCallback, pUserDefined); } else { ERROR_OUT(("T120_CreateControlSAP: can't create CControlSAP")); rc = GCC_ALLOCATION_FAILURE; } } else { ERROR_OUT(("T120_CreateControlSAP: deleting faulty controller")); if (NULL != g_pGCCController) { g_pGCCController->Release(); g_pGCCController = NULL; } rc = GCC_ALLOCATION_FAILURE; } } else { ERROR_OUT(("T120_CreateControlSAP: can't register window class, err=%u", (UINT) GetLastError())); rc = GCC_ALLOCATION_FAILURE; } } else { ERROR_OUT(("T120_CreateControlSAP: GCC has already been initialized, g_pControlSap=0x%x, g_pGCCCotnroller=0x%x", g_pControlSap, g_pGCCController)); rc = GCC_ALREADY_INITIALIZED; } } else { ERROR_OUT(("T120_CreateControlSAP: null pointers, ppIControlSap=0x%x, pfnControlSapCallback=0x%x", ppIControlSap, pfnControlSapCallback)); rc = GCC_INVALID_PARAMETER; } return rc; } /* * GCCError GCCCleanup() * * Public * * Functional Description: * This function deletes the controller (if one exists). It is VERY * important that only the routine that successfully called * GCCInitialize call this routine. Once this routine has been called, * all other GCC calls will fail. */ void CControlSAP::ReleaseInterface ( void ) { UnregisterNodeController(); /* * Destroy the controller, which will clean up all * resources in use at this time. Then reset the flag * indicating that GCC is initialized (since it no * longer is). */ TRACE_OUT(("GCCControlSap::ReleaseInterface: deleting controller")); g_pGCCController->Release(); // This is how much time the apps have to cleanup with MCS and GCC // after GCCCleanup is called. They may be terminated if they do not // cleanup in this amount of time. if (WAIT_TIMEOUT == ::WaitForSingleObject(g_hMCSThread, PROCESS_TERMINATE_TIME)) { WARNING_OUT(("GCCControlSap::ReleaseInterface: Timed out waiting for MCS thread to exit. Apps did not cleanup in time.")); } ::CloseHandle(g_hMCSThread); g_hMCSThread = NULL; // // LONCHANC: We should free control sap after exiting the GCC work thread // because the work thread may still use the control sap to flush messages. // Release(); ::UnregisterClass(g_szGCCWndClassName, g_hDllInst); } /* * CControlSAP() * * Public Function Description * This is the control sap constructor. It is responsible for * registering control sap with the application interface via * an owner callback. */ CControlSAP::CControlSAP ( void ) : CBaseSap(MAKE_STAMP_ID('C','S','a','p')), m_pfnNCCallback(NULL), m_pNCData(NULL), m_nJoinResponseTag(0), m_JoinResponseTagList2() { } /* * ~CControlSap() * * Public Function Description * This is the controller destructor. It is responsible for * flushing any pending upward bound messages and freeing all * the resources tied up with pending messages. Also it clears * the message queue and queue of command targets that are registered * with it. Actually all command targets at this point should * already have been unregistered but this is just a double check. */ CControlSAP::~CControlSAP ( void ) { // // No one should use this global pointer any more. // ASSERT(this == g_pControlSap); g_pControlSap = NULL; } void CControlSAP::PostCtrlSapMsg ( GCCCtrlSapMsgEx *pCtrlSapMsgEx ) { // // LONCHANC: GCC WorkThread may also get to here. // For instance, the following stack trace happen during exiting a conference. // CControlSAP::AddToMessageQueue() // CControlSAP::ConfDisconnectConfirm() // CConf::DisconnectProviderIndication() // CConf::Owner-Callback() // MCSUser::FlushOutgoingPDU() // CConf::FlushOutgoingPDU() // GCCController::EventLoop() // GCCControllerThread(void * 0x004f1bf0) // ASSERT(NULL != m_hwndNotify); ::PostMessage(m_hwndNotify, CSAPMSG_BASE + (UINT) pCtrlSapMsgEx->Msg.message_type, (WPARAM) pCtrlSapMsgEx, (LPARAM) this); } #if defined(GCCNC_DIRECT_INDICATION) || defined(GCCNC_DIRECT_CONFIRM) void CControlSAP::SendCtrlSapMsg ( GCCCtrlSapMsg *pCtrlSapMsg ) { extern DWORD g_dwNCThreadID; ASSERT(g_dwNCThreadID == ::GetCurrentThreadId()); if (NULL != m_pfnNCCallback) { pCtrlSapMsg->user_defined = m_pNCData; (*m_pfnNCCallback)(pCtrlSapMsg); } } #endif // GCCNC_DIRECT_INDICATION || GCCNC_DIRECT_CONFIRM /* * void RegisterNodeController() * * Public Functional Description: * This routine sets up the node controller callback structure which * holds all the information needed by GCC to perform a node controller * callback. It also sets up the task switching window required to * perform the context switch. */ /* * void UnregisterNodeController() * * Public Functional Description: */ /* * ConfCreateRequest() * * Public Function Description * This function is called by the interface when it gets a conference * create request from the node controller. This function just passes this * request to the controller via an owner callback. */ GCCError CControlSAP::ConfCreateRequest ( GCCConfCreateRequest *pReq, GCCConfID *pnConfID ) { GCCError rc; CONF_CREATE_REQUEST ccr; DebugEntry(CControlSAP::ConferenceCreateRequest); // initialize for cleanup ccr.convener_password = NULL; ccr.password = NULL; ccr.user_data_list = NULL; // copy security setting ccr.fSecure = pReq->fSecure; /* ** This section of the code performs all the necessary parameter ** checking. */ // Check for invalid conference name if (pReq->Core.conference_name != NULL) { /* ** Do not allow non-numeric or zero length strings to get ** past this point. */ if (pReq->Core.conference_name->numeric_string != NULL) { if (! IsNumericNameValid(pReq->Core.conference_name->numeric_string)) { ERROR_OUT(("CControlSAP::ConfCreateRequest: invalid numeric name=%s", pReq->Core.conference_name->numeric_string)); rc = GCC_INVALID_CONFERENCE_NAME; goto MyExit; } } else { ERROR_OUT(("CControlSAP::ConfCreateRequest: null numeric string")); rc = GCC_INVALID_CONFERENCE_NAME; goto MyExit; } if (pReq->Core.conference_name->text_string != NULL) { if (! IsTextNameValid(pReq->Core.conference_name->text_string)) { ERROR_OUT(("CControlSAP::ConfCreateRequest: invalid text name=%s", pReq->Core.conference_name->text_string)); rc = GCC_INVALID_CONFERENCE_NAME; goto MyExit; } } } else { ERROR_OUT(("CControlSAP::ConfCreateRequest: null conf name")); rc = GCC_INVALID_CONFERENCE_NAME; goto MyExit; } // Check for valid conference modifier if (pReq->Core.conference_modifier != NULL) { if (! IsNumericNameValid(pReq->Core.conference_modifier)) { ERROR_OUT(("CControlSAP::ConfCreateRequest: invalid conf modifier=%s", pReq->Core.conference_modifier)); rc = GCC_INVALID_CONFERENCE_MODIFIER; goto MyExit; } } // Check for valid convener password if (pReq->convener_password != NULL) { if (pReq->convener_password->numeric_string != NULL) { if (! IsNumericNameValid(pReq->convener_password->numeric_string)) { ERROR_OUT(("CControlSAP::ConfCreateRequest: invalid convener password=%s", pReq->convener_password->numeric_string)); rc = GCC_INVALID_PASSWORD; goto MyExit; } } else { ERROR_OUT(("CControlSAP::ConfCreateRequest: null convener password numeric string")); rc = GCC_INVALID_PASSWORD; goto MyExit; } // Construct the convener password container DBG_SAVE_FILE_LINE ccr.convener_password = new CPassword(pReq->convener_password, &rc); if (ccr.convener_password == NULL || GCC_NO_ERROR != rc) { ERROR_OUT(("CControlSAP::ConfCreateRequest: can't create convener password")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } } // Check for valid password if (pReq->password != NULL) { if (pReq->password->numeric_string != NULL) { if (! IsNumericNameValid(pReq->password->numeric_string)) { ERROR_OUT(("CControlSAP::ConfCreateRequest: invalid password=%s", pReq->password->numeric_string)); rc = GCC_INVALID_PASSWORD; goto MyExit; } } else { ERROR_OUT(("CControlSAP::ConfCreateRequest: null password numeric string")); rc = GCC_INVALID_PASSWORD; goto MyExit; } // Construct the password container DBG_SAVE_FILE_LINE ccr.password = new CPassword(pReq->password, &rc); if (ccr.password == NULL || GCC_NO_ERROR != rc) { ERROR_OUT(("CControlSAP::ConfCreateRequest: can't create password")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } } if (pReq->Core.connection_handle == NULL) { ERROR_OUT(("CControlSAP::ConfCreateRequest: bad connection handle")); rc = GCC_BAD_CONNECTION_HANDLE_POINTER; goto MyExit; } /* ** If no errors occurred start building the general purpose containers ** to be passed on. */ // copy the core component which has the same representation in both API and internal ccr.Core = pReq->Core; // Construct the user data list container if (pReq->number_of_user_data_members != 0) { DBG_SAVE_FILE_LINE ccr.user_data_list = new CUserDataListContainer(pReq->number_of_user_data_members, pReq->user_data_list, &rc); if (ccr.user_data_list == NULL || GCC_NO_ERROR != rc) { ERROR_OUT(("CControlSAP::ConfCreateRequest: can't create user data list container")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } } // Perform the owner callback ::EnterCriticalSection(&g_csGCCProvider); rc = g_pGCCController->ConfCreateRequest(&ccr, pnConfID); ::LeaveCriticalSection(&g_csGCCProvider); MyExit: // Free up all the containers // Free up the convener password container if (ccr.convener_password != NULL) { ccr.convener_password->Release(); } // Free up the password container if (ccr.password != NULL) { ccr.password->Release(); } // Free up any memory used in callback if (ccr.user_data_list != NULL) { ccr.user_data_list->Release(); } DebugExitINT(CControlSAP::ConferenceCreateRequest, rc); return rc; } /* * ConfCreateResponse () * * Public Function Description * This function is called by the interface when it gets a conference * create response from the node controller, to be sent to the provider * that issued the conference create request. This function just passes * this request to the controller via an owner callback. */ GCCError CControlSAP::ConfCreateResponse ( GCCNumericString conference_modifier, GCCConfID conference_id, BOOL use_password_in_the_clear, PDomainParameters domain_parameters, UINT number_of_network_addresses, PGCCNetworkAddress * local_network_address_list, UINT number_of_user_data_members, PGCCUserData * user_data_list, GCCResult result ) { GCCError rc = GCC_NO_ERROR; ConfCreateResponseInfo create_response_info; DebugEntry(CControlSAP::ConfCreateResponse); /* ** This section of the code performs all the necessary parameter ** checking. */ // Check for valid conference modifier if (conference_modifier != NULL) { if (IsNumericNameValid(conference_modifier) == FALSE) { ERROR_OUT(("CControlSAP::ConfCreateResponse: invalid conf modifier")); rc = GCC_INVALID_CONFERENCE_MODIFIER; } } /* ** If no errors occurred fill in the info structure and pass it on to the ** owner object. */ if (rc == GCC_NO_ERROR) { // Construct the user data list if (number_of_user_data_members != 0) { DBG_SAVE_FILE_LINE create_response_info.user_data_list = new CUserDataListContainer( number_of_user_data_members, user_data_list, &rc); if (create_response_info.user_data_list == NULL) { ERROR_OUT(("CControlSAP::ConfCreateResponse: can't create CUserDataListContainer")); rc = GCC_ALLOCATION_FAILURE; } } else { create_response_info.user_data_list = NULL; } if (rc == GCC_NO_ERROR) { // Fill in the conference create info structure and send it on create_response_info.conference_modifier = conference_modifier; create_response_info.conference_id = conference_id; create_response_info.use_password_in_the_clear = use_password_in_the_clear; create_response_info.domain_parameters = domain_parameters; create_response_info.number_of_network_addresses = number_of_network_addresses; create_response_info.network_address_list = local_network_address_list; create_response_info.result = result; // Perform the owner callback ::EnterCriticalSection(&g_csGCCProvider); rc = g_pGCCController->ConfCreateResponse(&create_response_info); ::LeaveCriticalSection(&g_csGCCProvider); } if (create_response_info.user_data_list != NULL) { create_response_info.user_data_list->Release(); } } DebugExitINT(CControlSAP::ConfCreateResponse, rc); return rc; } /* * ConfQueryRequest () * * Public Function Description * This function is called by the interface when it gets a conference * query request from the node controller. This function just passes * this request to the controller via an owner callback. */ GCCError CControlSAP::ConfQueryRequest ( GCCNodeType node_type, PGCCAsymmetryIndicator asymmetry_indicator, TransportAddress calling_address, TransportAddress called_address, BOOL fSecure, UINT number_of_user_data_members, PGCCUserData * user_data_list, PConnectionHandle connection_handle ) { GCCError rc = GCC_NO_ERROR; ConfQueryRequestInfo conf_query_request_info; DebugEntry(CControlSAP::ConfQueryRequest); // Check for an invalid called address. if (called_address == NULL) { ERROR_OUT(("CControlSAP::ConfQueryRequest: invalid transport")); rc = GCC_INVALID_TRANSPORT; } // Check for an invalid connection handle. if (connection_handle == NULL) { ERROR_OUT(("CControlSAP::ConfQueryRequest: null connection handle")); rc = GCC_BAD_CONNECTION_HANDLE_POINTER; } // Check for a valid node type. if ((node_type != GCC_TERMINAL) && (node_type != GCC_MULTIPORT_TERMINAL) && (node_type != GCC_MCU)) { ERROR_OUT(("CControlSAP::ConfQueryRequest: invalid node type=%u", (UINT) node_type)); rc = GCC_INVALID_NODE_TYPE; } // Check for an invalid asymmetry indicator. if (asymmetry_indicator != NULL) { if ((asymmetry_indicator->asymmetry_type != GCC_ASYMMETRY_CALLER) && (asymmetry_indicator->asymmetry_type != GCC_ASYMMETRY_CALLED) && (asymmetry_indicator->asymmetry_type != GCC_ASYMMETRY_UNKNOWN)) { ERROR_OUT(("CControlSAP::ConfQueryRequest: invalid asymmetry indicator=%u", (UINT) asymmetry_indicator->asymmetry_type)); rc = GCC_INVALID_ASYMMETRY_INDICATOR; } } // Create user data container if necessary. if ((number_of_user_data_members != 0) && (rc == GCC_NO_ERROR)) { DBG_SAVE_FILE_LINE conf_query_request_info.user_data_list = new CUserDataListContainer ( number_of_user_data_members, user_data_list, &rc); if (conf_query_request_info.user_data_list == NULL) { ERROR_OUT(("CControlSAP::ConfQueryRequest: can't create CUserDataListContainer")); rc = GCC_ALLOCATION_FAILURE; } } else { conf_query_request_info.user_data_list = NULL; } // Call back the controller to send the response. if (rc == GCC_NO_ERROR) { conf_query_request_info.node_type = node_type; conf_query_request_info.asymmetry_indicator = asymmetry_indicator; conf_query_request_info.calling_address = calling_address; conf_query_request_info.called_address = called_address; conf_query_request_info.connection_handle = connection_handle; conf_query_request_info.fSecure = fSecure; ::EnterCriticalSection(&g_csGCCProvider); rc = g_pGCCController->ConfQueryRequest(&conf_query_request_info); ::LeaveCriticalSection(&g_csGCCProvider); } if (conf_query_request_info.user_data_list != NULL) { conf_query_request_info.user_data_list->Release(); } DebugExitINT(CControlSAP::ConfQueryRequest, rc); return rc; } void CControlSAP::CancelConfQueryRequest ( ConnectionHandle hQueryReqConn ) { DebugEntry(CControlSAP::CancelConfQueryRequest); ::EnterCriticalSection(&g_csGCCProvider); g_pGCCController->CancelConfQueryRequest(hQueryReqConn); ::LeaveCriticalSection(&g_csGCCProvider); DebugExitVOID(CControlSAP::CancelConfQueryRequest); } /* * ConfQueryResponse () * * Public Function Description * This function is called by the DLL interface when it gets a conference * query response from the node controller. This function just passes * this response to the controller via an owner callback. */ GCCError CControlSAP::ConfQueryResponse ( GCCResponseTag query_response_tag, GCCNodeType node_type, PGCCAsymmetryIndicator asymmetry_indicator, UINT number_of_user_data_members, PGCCUserData * user_data_list, GCCResult result ) { GCCError rc = GCC_NO_ERROR; ConfQueryResponseInfo conf_query_response_info; DebugEntry(CControlSAP::ConfQueryResponse); // Check for a valid node type. if ((node_type != GCC_TERMINAL) && (node_type != GCC_MULTIPORT_TERMINAL) && (node_type != GCC_MCU)) { ERROR_OUT(("CControlSAP::ConfQueryResponse: invalid node type=%u", (UINT) node_type)); rc = GCC_INVALID_NODE_TYPE; } // Check for an invalid asymmetry indicator. if (asymmetry_indicator != NULL) { if ((asymmetry_indicator->asymmetry_type != GCC_ASYMMETRY_CALLER) && (asymmetry_indicator->asymmetry_type != GCC_ASYMMETRY_CALLED) && (asymmetry_indicator->asymmetry_type != GCC_ASYMMETRY_UNKNOWN)) { ERROR_OUT(("CControlSAP::ConfQueryResponse: invalid asymmetry indicator=%u", (UINT) asymmetry_indicator->asymmetry_type)); rc = GCC_INVALID_ASYMMETRY_INDICATOR; } } // Create user data container if necessary. if ((number_of_user_data_members != 0) && (rc == GCC_NO_ERROR)) { DBG_SAVE_FILE_LINE conf_query_response_info.user_data_list = new CUserDataListContainer( number_of_user_data_members, user_data_list, &rc); if (conf_query_response_info.user_data_list == NULL) { ERROR_OUT(("CControlSAP::ConfQueryResponse: can't create CUserDataListContainer")); rc = GCC_ALLOCATION_FAILURE; } } else { conf_query_response_info.user_data_list = NULL; } // Call back the controller to send the response. if (rc == GCC_NO_ERROR) { conf_query_response_info.query_response_tag = query_response_tag; conf_query_response_info.node_type = node_type; conf_query_response_info.asymmetry_indicator = asymmetry_indicator; conf_query_response_info.result = result; ::EnterCriticalSection(&g_csGCCProvider); rc = g_pGCCController->ConfQueryResponse(&conf_query_response_info); ::LeaveCriticalSection(&g_csGCCProvider); } // Free the data associated with the user data container. if (conf_query_response_info.user_data_list != NULL) { conf_query_response_info.user_data_list->Release(); } DebugExitINT(CControlSAP::ConfQueryResponse, rc); return rc; } /* * AnnouncePresenceRequest() * * Public Function Description * This function is called by the interface when it gets an announce * presence request from the node controller. This function passes this * request on to the appropriate conference object as obtained from * the list of command targets that control sap maintains. The ConferenceID * passed in is used to index the list of command targets to get the * correct conference. */ GCCError CControlSAP::AnnouncePresenceRequest ( GCCConfID conference_id, GCCNodeType node_type, GCCNodeProperties node_properties, LPWSTR pwszNodeName, UINT number_of_participants, LPWSTR * participant_name_list, LPWSTR pwszSiteInfo, UINT number_of_network_addresses, PGCCNetworkAddress * network_address_list, LPOSTR alternative_node_id, UINT number_of_user_data_members, PGCCUserData * user_data_list ) { GCCError rc = GCC_NO_ERROR; GCCNodeRecord node_record; DebugEntry(CControlSAP::AnnouncePresenceRequest); // Check for a valid node type if ((node_type != GCC_TERMINAL) && (node_type != GCC_MULTIPORT_TERMINAL) && (node_type != GCC_MCU)) { ERROR_OUT(("CControlSAP::AnnouncePresenceRequest: invalid node type=%u", node_type)); rc = GCC_INVALID_NODE_TYPE; } // Check for valid node properties. if ((node_properties != GCC_PERIPHERAL_DEVICE) && (node_properties != GCC_MANAGEMENT_DEVICE) && (node_properties != GCC_PERIPHERAL_AND_MANAGEMENT_DEVICE) && (node_properties != GCC_NEITHER_PERIPHERAL_NOR_MANAGEMENT)) { ERROR_OUT(("CControlSAP::AnnouncePresenceRequest: invalid node properties=%u", node_properties)); rc = GCC_INVALID_NODE_PROPERTIES; } // Check to make sure the conference exists. if (rc == GCC_NO_ERROR) { CConf *pConf; ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { // Fill in the node record and pass it on. node_record.node_type = node_type; node_record.node_properties = node_properties; node_record.node_name = pwszNodeName; node_record.number_of_participants = (USHORT)number_of_participants; node_record.participant_name_list = participant_name_list; node_record.site_information = pwszSiteInfo; node_record.number_of_network_addresses = number_of_network_addresses; node_record.network_address_list = network_address_list; node_record.alternative_node_id = alternative_node_id; node_record.number_of_user_data_members = (USHORT)number_of_user_data_members; node_record.user_data_list = user_data_list; // Pass the record on to the conference object. rc = pConf->ConfAnnouncePresenceRequest(&node_record); } else { TRACE_OUT(("CControlSAP::AnnouncePresenceRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); } DebugExitINT(CControlSAP::AnnouncePresenceRequest, rc); return rc; } /* * ConfDisconnectRequest() * * Public Function Description * This function is called by the interface when it gets a conference * disconnect request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ GCCError CControlSAP::ConfDisconnectRequest ( GCCConfID conference_id ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConfDisconnectRequest); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { // Pass the disconnect on to the conference object. rc = pConf->ConfDisconnectRequest(); } else { WARNING_OUT(("CControlSAP::ConfDisconnectRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfDisconnectRequest, rc); return rc; } /* * ConfTerminateRequest() * * Public Function Description * This function is called by the interface when it gets a conference * terminate request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConfTerminateRequest ( GCCConfID conference_id, GCCReason reason ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConfTerminateRequest); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { // Pass the disconnect on to the conference object rc = pConf->ConfTerminateRequest(reason); } else { WARNING_OUT(("CControlSAP::ConfTerminateRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfTerminateRequest, rc); return rc; } #endif // JASPER /* * ConfEjectUserRequest() * * Public Function Description * This function is called by the interface when it gets a conference * eject user request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ GCCError CControlSAP::ConfEjectUserRequest ( GCCConfID conference_id, UserID ejected_node_id, GCCReason reason ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConfEjectUserRequest); ::EnterCriticalSection(&g_csGCCProvider); if (ejected_node_id < MINIMUM_USER_ID_VALUE) { ERROR_OUT(("CControlSAP::ConfEjectUserRequest: invalid mcs user ID=%u", (UINT) ejected_node_id)); rc = GCC_INVALID_MCS_USER_ID; } else // Check to make sure the conference exists. if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { // Pass the command on to the conference object rc = pConf->ConfEjectUserRequest(ejected_node_id, reason); } else { WARNING_OUT(("CControlSAP::ConfEjectUserRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfEjectUserRequest, rc); return rc; } /* * ConfJoinRequest () * * Public Function Description * This function is called by the interface when it gets a conference * join request from the node controller, to be sent to the top provider * either directly or through a directly connected intermediate provider. * This function just passes this request to the controller via an owner * callback. */ GCCError CControlSAP::ConfJoinRequest ( PGCCConferenceName conference_name, GCCNumericString called_node_modifier, GCCNumericString calling_node_modifier, PGCCPassword convener_password, PGCCChallengeRequestResponse password_challenge, LPWSTR pwszCallerID, TransportAddress calling_address, TransportAddress called_address, BOOL fSecure, PDomainParameters domain_parameters, UINT number_of_network_addresses, PGCCNetworkAddress * local_network_address_list, UINT number_of_user_data_members, PGCCUserData * user_data_list, PConnectionHandle connection_handle, GCCConfID * pnConfID ) { GCCError rc = GCC_NO_ERROR; ConfJoinRequestInfo join_request_info; DebugEntry(CControlSAP::ConfJoinRequest); // Check for invalid conference name if (conference_name != NULL) { /* ** Check to make sure a valid conference name exists. */ if ((conference_name->numeric_string == NULL) && (conference_name->text_string == NULL)) { ERROR_OUT(("CControlSAP::ConfJoinRequest: invalid conference name (1)")); rc = GCC_INVALID_CONFERENCE_NAME; } /* ** If both numeric and text versions of the conference name exist, ** make sure they are both valid. */ else if ((conference_name->numeric_string != NULL) && (conference_name->text_string != NULL)) { if ((IsNumericNameValid(conference_name->numeric_string) == FALSE) || (IsTextNameValid(conference_name->text_string) == FALSE)) { ERROR_OUT(("CControlSAP::ConfJoinRequest: invalid conference name (2)")); rc = GCC_INVALID_CONFERENCE_NAME; } } /* ** If only a numeric version of the conference name is provided, check ** to make sure it is valid. */ else if (conference_name->numeric_string != NULL) { if (IsNumericNameValid(conference_name->numeric_string) == FALSE) { ERROR_OUT(("CControlSAP::ConfJoinRequest: invalid conference name (3)")); rc = GCC_INVALID_CONFERENCE_NAME; } } /* ** If only a text version of the conference name is provided, check to ** make sure it is valid. */ else { if (IsTextNameValid(conference_name->text_string) == FALSE) { ERROR_OUT(("CControlSAP::ConfJoinRequest: invalid conference name (4)")); rc = GCC_INVALID_CONFERENCE_NAME; } } } else { ERROR_OUT(("CControlSAP::ConfJoinRequest: invalid conference name (5)")); rc = GCC_INVALID_CONFERENCE_NAME; } // Check for valid called_node_modifier. if (called_node_modifier != NULL) { if (IsNumericNameValid(called_node_modifier) == FALSE) { ERROR_OUT(("CControlSAP::ConfJoinRequest: invalid called node modifier")); rc = GCC_INVALID_CONFERENCE_MODIFIER; } } // Check for valid calling_node_modifier if (calling_node_modifier != NULL) { if (IsNumericNameValid(calling_node_modifier) == FALSE) { ERROR_OUT(("CControlSAP::ConfJoinRequest: invalid calling node modifier")); rc = GCC_INVALID_CONFERENCE_MODIFIER; } } // Check for valid convener password if (convener_password != NULL) { if (convener_password->numeric_string != NULL) { if (IsNumericNameValid(convener_password->numeric_string) == FALSE) { ERROR_OUT(("CControlSAP::ConfJoinRequest: invalid convener password")); rc = GCC_INVALID_PASSWORD; } } else { ERROR_OUT(("CControlSAP::ConfJoinRequest: null convener password")); rc = GCC_INVALID_PASSWORD; } } if (connection_handle == NULL) { ERROR_OUT(("CControlSAP::ConfJoinRequest: null connection handle")); rc = GCC_BAD_CONNECTION_HANDLE_POINTER; } if (called_address == NULL) { ERROR_OUT(("CControlSAP::ConfJoinRequest: null transport address")); rc = GCC_INVALID_TRANSPORT_ADDRESS; } /* ** If no errors occurred start building the general purpose containers ** to be passed on. */ if (rc == GCC_NO_ERROR) { // Construct a convener password container if (convener_password != NULL) { DBG_SAVE_FILE_LINE join_request_info.convener_password = new CPassword(convener_password, &rc); if (join_request_info.convener_password == NULL) { ERROR_OUT(("CControlSAP::ConfJoinRequest: can't create CPassword (1)")); rc = GCC_ALLOCATION_FAILURE; } } else { join_request_info.convener_password = NULL; } // Construct a password challenge container if ((password_challenge != NULL) && (rc == GCC_NO_ERROR)) { DBG_SAVE_FILE_LINE join_request_info.password_challenge = new CPassword(password_challenge, &rc); if (join_request_info.password_challenge == NULL) { ERROR_OUT(("CControlSAP::ConfJoinRequest: can't create CPassword (2)")); rc = GCC_ALLOCATION_FAILURE; } } else { join_request_info.password_challenge = NULL; } // Construct the user data list if ((number_of_user_data_members != 0) && (rc == GCC_NO_ERROR)) { DBG_SAVE_FILE_LINE join_request_info.user_data_list = new CUserDataListContainer( number_of_user_data_members, user_data_list, &rc); if (join_request_info.user_data_list == NULL) { ERROR_OUT(("CControlSAP::ConfJoinRequest: can't create CUserDataListContainer")); rc = GCC_ALLOCATION_FAILURE; } } else { join_request_info.user_data_list = NULL; } /* ** If all the containers were successfully created go ahead and ** fill in the rest of the create request info structure and pass ** it on to the owner object. */ if (rc == GCC_NO_ERROR) { join_request_info.conference_name = conference_name; join_request_info.called_node_modifier = called_node_modifier; join_request_info.calling_node_modifier =calling_node_modifier; join_request_info.pwszCallerID = pwszCallerID; join_request_info.calling_address = calling_address; join_request_info.called_address = called_address; join_request_info.fSecure = fSecure; join_request_info.domain_parameters = domain_parameters; join_request_info.number_of_network_addresses = number_of_network_addresses; join_request_info.local_network_address_list = local_network_address_list; join_request_info.connection_handle = connection_handle; ::EnterCriticalSection(&g_csGCCProvider); rc = g_pGCCController->ConfJoinRequest(&join_request_info, pnConfID); ::LeaveCriticalSection(&g_csGCCProvider); } // Free up all the containers // Free up the convener password container if (join_request_info.convener_password != NULL) { join_request_info.convener_password->Release(); } // Free up the password container if (join_request_info.password_challenge != NULL) { join_request_info.password_challenge->Release(); } // Free up any memory used in callback if (join_request_info.user_data_list != NULL) { join_request_info.user_data_list->Release(); } } DebugExitINT(CControlSAP::ConfJoinRequest, rc); return rc; } /* * ConfJoinResponse () * * Public Function Description * This function is called by the interface when it gets a conference * join response from the node controller. This routine is responsible * for routing the response to either the conference that made the * request or the controller. Responses which are routed to a conference * are associated with requests that originate at a subnode that is a * node removed from the Top Provider. */ GCCError CControlSAP::ConfJoinResponse ( GCCResponseTag join_response_tag, PGCCChallengeRequestResponse password_challenge, UINT number_of_user_data_members, PGCCUserData * user_data_list, GCCResult result ) { GCCError rc = GCC_NO_ERROR; PJoinResponseStructure join_info; CPassword *password_challenge_container = NULL; CUserDataListContainer *user_data_container = NULL; DebugEntry(CControlSAP::ConfJoinResponse); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (join_info = m_JoinResponseTagList2.Find(join_response_tag))) { /* ** First create the data containers used in the join response. */ // Set up the password challenge container if (password_challenge != NULL) { DBG_SAVE_FILE_LINE password_challenge_container = new CPassword(password_challenge, &rc); if (password_challenge_container == NULL) { ERROR_OUT(("CControlSAP::ConfJoinResponse: can't create CPassword")); rc = GCC_ALLOCATION_FAILURE; } } // Set up the user data list container if ((number_of_user_data_members != 0) && (rc == GCC_NO_ERROR)) { DBG_SAVE_FILE_LINE user_data_container = new CUserDataListContainer(number_of_user_data_members, user_data_list, &rc); if (user_data_container == NULL) { ERROR_OUT(("CControlSAP::ConfJoinResponse: can't create CUserDataListContainer")); rc = GCC_ALLOCATION_FAILURE; } } if (rc == GCC_NO_ERROR) { if (join_info->command_target_call == FALSE) { ConfJoinResponseInfo join_response_info; /* ** Since the request originated from the Owner Object the ** response gets routed to the Owner Object. */ join_response_info.password_challenge = password_challenge_container; join_response_info.conference_id = join_info->conference_id; join_response_info.connection_handle = join_info->connection_handle; join_response_info.user_data_list = user_data_container; join_response_info.result = result; rc = g_pGCCController->ConfJoinIndResponse(&join_response_info); } else { CConf *pConf; /* ** If the conference is terminated before the conference join ** is responded to, a GCC_INVALID_CONFERENCE errror will occur. */ if (NULL != (pConf = g_pGCCController->GetConfObject(join_info->conference_id))) { rc = pConf->ConfJoinReqResponse( join_info->user_id, password_challenge_container, user_data_container, result); } else { WARNING_OUT(("CControlSAP::ConfJoinResponse: invalid conference ID=%u", (UINT) join_info->conference_id)); rc = GCC_INVALID_CONFERENCE; // If this error occurs go ahead and cleanup up m_JoinResponseTagList2.Remove(join_response_tag); delete join_info; } } } /* ** Remove the join information structure from the join response list ** if no error is returned. */ if (rc == GCC_NO_ERROR) { m_JoinResponseTagList2.Remove(join_response_tag); delete join_info; } // Free up all the containers // Free up the password challenge container if (password_challenge_container != NULL) { password_challenge_container->Release(); } // Free up any memory used in callback if (user_data_container != NULL) { user_data_container->Release(); } } else { rc = GCC_INVALID_JOIN_RESPONSE_TAG; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfJoinResponse, rc); return rc; } /* * ConfInviteRequest () * * Public Function Description * This function is called by the interface when it gets a conference * invite request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ GCCError CControlSAP::ConfInviteRequest ( GCCConfID conference_id, LPWSTR pwszCallerID, TransportAddress calling_address, TransportAddress called_address, BOOL fSecure, UINT number_of_user_data_members, PGCCUserData * user_data_list, PConnectionHandle connection_handle ) { GCCError rc = GCC_NO_ERROR; CUserDataListContainer *user_data_list_ptr = NULL; DebugEntry(CControlSAP::ConfInviteRequest); if (called_address == NULL) { ERROR_OUT(("CControlSAP::ConfInviteRequest: null called address")); rc = GCC_INVALID_TRANSPORT_ADDRESS; } if (connection_handle == NULL) { ERROR_OUT(("CControlSAP::ConfInviteRequest: null connection handle")); rc = GCC_BAD_CONNECTION_HANDLE_POINTER; } if (rc == GCC_NO_ERROR) { CConf *pConf; ::EnterCriticalSection(&g_csGCCProvider); // Check to make sure the conference exists. if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { // Construct the user data list container if (number_of_user_data_members != 0) { DBG_SAVE_FILE_LINE user_data_list_ptr = new CUserDataListContainer(number_of_user_data_members, user_data_list, &rc); if (user_data_list_ptr == NULL) { ERROR_OUT(("CControlSAP::ConfInviteRequest: can't create CUserDataListContainer")); rc = GCC_ALLOCATION_FAILURE; } } // Send the request on to the conference object. if (rc == GCC_NO_ERROR) { rc = pConf->ConfInviteRequest(pwszCallerID, calling_address, called_address, fSecure, user_data_list_ptr, connection_handle); } // Free up any memory used in callback if (user_data_list_ptr != NULL) { user_data_list_ptr->Release(); } } else { rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); } DebugExitINT(CControlSAP::ConfInviteRequest, rc); return rc; } void CControlSAP::CancelInviteRequest ( GCCConfID nConfID, ConnectionHandle hInviteReqConn ) { CConf *pConf; DebugEntry(CControlSAP::CancelInviteRequest); ::EnterCriticalSection(&g_csGCCProvider); // Check to make sure the conference exists. if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID))) { pConf->CancelInviteRequest(hInviteReqConn); } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitVOID(CControlSAP::CancelInviteRequest); } GCCError CControlSAP::GetParentNodeID ( GCCConfID nConfID, GCCNodeID *pnidParent ) { GCCError rc = T120_INVALID_PARAMETER; CConf *pConf; DebugEntry(CControlSAP::GetParentNodeID); if (NULL != pnidParent) { ::EnterCriticalSection(&g_csGCCProvider); // Check to make sure the conference exists. if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID))) { *pnidParent = pConf->GetParentNodeID(); rc = GCC_NO_ERROR; } ::LeaveCriticalSection(&g_csGCCProvider); } DebugExitINT(CControlSAP::GetParentNodeID, rc); return rc; } /* * ConfInviteResponse () * * Public Function Description * This function is called by the interface when it gets a conference * invite response from the node controller. This function passes the * response on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ GCCError CControlSAP::ConfInviteResponse ( GCCConfID conference_id, GCCNumericString conference_modifier, BOOL fSecure, PDomainParameters domain_parameters, UINT number_of_network_addresses, PGCCNetworkAddress * local_network_address_list, UINT number_of_user_data_members, PGCCUserData * user_data_list, GCCResult result ) { GCCError rc = GCC_NO_ERROR; ConfInviteResponseInfo invite_response_info; DebugEntry(CControlSAP::ConfInviteResponse); // Check for invalid conference name if (conference_modifier != NULL) { if (IsNumericNameValid(conference_modifier) == FALSE) { ERROR_OUT(("CControlSAP::ConfInviteResponse: invalid conference modifier")); rc = GCC_INVALID_CONFERENCE_MODIFIER; } } /* ** If no errors occurred fill in the info structure and pass it on to the ** owner object. */ if (rc == GCC_NO_ERROR) { // Construct the user data list if (number_of_user_data_members != 0) { DBG_SAVE_FILE_LINE invite_response_info.user_data_list = new CUserDataListContainer(number_of_user_data_members, user_data_list, &rc); if (invite_response_info.user_data_list == NULL) { ERROR_OUT(("CControlSAP::ConfInviteResponse: can't create CUserDataListContainer")); rc = GCC_ALLOCATION_FAILURE; } } else { invite_response_info.user_data_list = NULL; } if (rc == GCC_NO_ERROR) { invite_response_info.conference_id = conference_id; invite_response_info.conference_modifier = conference_modifier; invite_response_info.fSecure = fSecure; invite_response_info.domain_parameters = domain_parameters; invite_response_info.number_of_network_addresses = number_of_network_addresses; invite_response_info.local_network_address_list = local_network_address_list; invite_response_info.result = result; // Call back the controller to issue invite response. ::EnterCriticalSection(&g_csGCCProvider); rc = g_pGCCController->ConfInviteResponse(&invite_response_info); ::LeaveCriticalSection(&g_csGCCProvider); } // Free up the data associated with the user data container. if (invite_response_info.user_data_list != NULL) { invite_response_info.user_data_list->Release(); } } DebugExitINT(CControlSAP::ConfInviteResponse, rc); return rc; } /* * ConfLockRequest () * * Public Function Description: * This function is called by the interface when it gets a conference * lock request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConfLockRequest ( GCCConfID conference_id ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConfLockRequest); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConfLockRequest(); } else { WARNING_OUT(("CControlSAP::ConfInviteResponse: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfLockRequest, rc); return rc; } #endif // JASPER /* * ConfLockResponse () * * Public Function Description: * This function is called by the interface when it gets a conference * lock response from the node controller. This function passes the * response on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ GCCError CControlSAP::ConfLockResponse ( GCCConfID conference_id, UserID requesting_node, GCCResult result ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConfLockResponse); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConfLockResponse(requesting_node, result); } else { WARNING_OUT(("CControlSAP::ConfLockResponse: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfLockResponse, rc); return rc; } /* * ConfUnlockRequest () * * Public Function Description: * This function is called by the interface when it gets a conference * unlock request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConfUnlockRequest ( GCCConfID conference_id ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConfUnlockRequest); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConfUnlockRequest(); } else { WARNING_OUT(("CControlSAP::ConfUnlockRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfUnlockRequest, rc); return rc; } #endif // JASPER /* * ConfUnlockResponse () * * Public Function Description: * This function is called by the interface when it gets a conference * unlock response from the node controller. This function passes the * response on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConfUnlockResponse ( GCCConfID conference_id, UserID requesting_node, GCCResult result ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConfUnlockResponse); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConfUnlockResponse(requesting_node, result); } else { WARNING_OUT(("CControlSAP::ConfUnlockResponse: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfUnlockResponse, rc); return rc; } #endif // JASPER /* * ConductorAssignRequest () * * Public Function Description * This function is called by the interface when it gets a conductor * assign request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConductorAssignRequest ( GCCConfID conference_id ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConductorAssignRequest); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConductorAssignRequest(); } else { WARNING_OUT(("CControlSAP::ConductorAssignRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConductorAssignRequest, rc); return rc; } #endif // JASPER /* * ConductorReleaseRequest () * * Public Function Description * This function is called by the interface when it gets a conductor * release request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConductorReleaseRequest ( GCCConfID conference_id ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConductorReleaseRequest); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConductorReleaseRequest(); } else { WARNING_OUT(("CControlSAP::ConductorReleaseRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConductorReleaseRequest, rc); return rc; } #endif // JASPER /* * ConductorPleaseRequest () * * Public Function Description * This function is called by the interface when it gets a conductor * please request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConductorPleaseRequest ( GCCConfID conference_id ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConductorPleaseRequest); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConductorPleaseRequest(); } else { WARNING_OUT(("CControlSAP::ConductorPleaseRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConductorPleaseRequest, rc); return rc; } #endif // JASPER /* * ConductorGiveRequest () * * Public Function Description * This function is called by the interface when it gets a conductor * give request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConductorGiveRequest ( GCCConfID conference_id, UserID recipient_user_id ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConductorGiveRequest); // Make sure the ID of the conductorship recipient is valid. if (recipient_user_id < MINIMUM_USER_ID_VALUE) return (GCC_INVALID_MCS_USER_ID); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConductorGiveRequest (recipient_user_id); } else { WARNING_OUT(("CControlSAP::ConductorGiveRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConductorGiveRequest, rc); return rc; } #endif // JASPER /* * ConductorGiveResponse () * * Public Function Description * This function is called by the interface when it gets a conductor * give response from the node controller. This function passes the * response on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ GCCError CControlSAP::ConductorGiveResponse ( GCCConfID conference_id, GCCResult result ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConductorGiveResponse); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConductorGiveResponse (result); } else { WARNING_OUT(("CControlSAP::ConductorGiveResponse: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConductorGiveResponse, rc); return rc; } /* * ConductorPermitGrantRequest () * * Public Function Description * This function is called by the interface when it gets a conductor * permit grant request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConductorPermitGrantRequest ( GCCConfID conference_id, UINT number_granted, PUserID granted_node_list, UINT number_waiting, PUserID waiting_node_list ) { GCCError rc; CConf *pConf; UINT i; DebugEntry(CControlSAP::ConductorPermitGrantRequest); ::EnterCriticalSection(&g_csGCCProvider); // Check to make sure the conference exists. if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { /* ** Run through both lists to make sure that valid MCS User IDs ** are used. */ for (i = 0; i < number_granted; i++) { if (granted_node_list[i] < MINIMUM_USER_ID_VALUE) { ERROR_OUT(("CControlSAP::ConductorPermitGrantRequest: invalid granted user ID")); rc = GCC_INVALID_MCS_USER_ID; goto MyExit; } } for (i = 0; i < number_waiting; i++) { if (waiting_node_list[i] < MINIMUM_USER_ID_VALUE) { ERROR_OUT(("CControlSAP::ConductorPermitGrantRequest: invalid waiting user ID")); rc = GCC_INVALID_MCS_USER_ID; goto MyExit; } } rc = pConf->ConductorPermitGrantRequest(number_granted, granted_node_list, number_waiting, waiting_node_list); } else { rc = GCC_INVALID_CONFERENCE; } MyExit: ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConductorPermitGrantRequest, rc); return rc; } #endif // JASPER /* * ConductorPermitAskRequest() * * Public Function Description * This routine is called in order to ask for certain permissions to be * granted (or not granted) by the conductor. */ #ifdef JASPER GCCError CControlSAP::ConductorPermitAskRequest ( GCCConfID nConfID, BOOL fGrantPermission ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConductorPermitAskRequest); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID))) { rc = pConf->ConductorPermitAskRequest(fGrantPermission); } else { WARNING_OUT(("CControlSAP::ConductorPermitAskRequest: invalid conference ID=%u", (UINT) nConfID)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConductorPermitAskRequest, rc); return rc; } #endif // JASPER /* * ConfTimeRemainingRequest () * * Public Function Description * This function is called by the interface when it gets a conference time * remaining request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ GCCError CControlSAP::ConfTimeRemainingRequest ( GCCConfID conference_id, UINT time_remaining, UserID node_id ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConfTimeRemainingRequest); ::EnterCriticalSection(&g_csGCCProvider); // Check to make sure the node ID is valid and the conference exists. if ((node_id < MINIMUM_USER_ID_VALUE) && (node_id != 0)) { ERROR_OUT(("CControlSAP::ConfTimeRemainingRequest: invalid node ID")); rc = GCC_INVALID_MCS_USER_ID; } else if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConferenceTimeRemainingRequest(time_remaining, node_id); } else { WARNING_OUT(("CControlSAP::ConfTimeRemainingRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfTimeRemainingRequest, rc); return rc; } /* * ConfTimeInquireRequest () * * Public Function Description * This function is called by the interface when it gets a conference time * inquire request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConfTimeInquireRequest ( GCCConfID conference_id, BOOL time_is_conference_wide ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConfTimeInquireRequest); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConfTimeInquireRequest(time_is_conference_wide); } else { WARNING_OUT(("CControlSAP::ConfTimeInquireRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfTimeInquireRequest, rc); return rc; } #endif // JASPER /* * ConfExtendRequest () * * Public Function Description * This function is called by the interface when it gets a conference * extend request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConfExtendRequest ( GCCConfID conference_id, UINT extension_time, BOOL time_is_conference_wide ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConfExtendRequest); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConfExtendRequest(extension_time, time_is_conference_wide); } else { WARNING_OUT(("CControlSAP::ConfExtendRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfExtendRequest, rc); return rc; } #endif // JASPER /* * ConfAssistanceRequest () * * Public Function Description * This function is called by the interface when it gets a conference * assistance request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConfAssistanceRequest ( GCCConfID conference_id, UINT number_of_user_data_members, PGCCUserData * user_data_list ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::ConfAssistanceRequest); ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->ConfAssistanceRequest(number_of_user_data_members, user_data_list); } else { WARNING_OUT(("CControlSAP::ConfAssistanceRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfAssistanceRequest, rc); return rc; } #endif // JASPER /* * TextMessageRequest () * * Public Function Description * This function is called by the interface when it gets a text message * request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::TextMessageRequest ( GCCConfID conference_id, LPWSTR pwszTextMsg, UserID destination_node ) { GCCError rc; CConf *pConf; DebugEntry(CControlSAP::TextMessageRequest); ::EnterCriticalSection(&g_csGCCProvider); // Check to make sure the node ID is valid and the conference exists. if ((destination_node < MINIMUM_USER_ID_VALUE) && (destination_node != 0)) { ERROR_OUT(("CControlSAP::TextMessageRequest: invalid user ID")); rc = GCC_INVALID_MCS_USER_ID; } else if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { rc = pConf->TextMessageRequest(pwszTextMsg, destination_node); } else { WARNING_OUT(("CControlSAP::TextMessageRequest: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::TextMessageRequest, rc); return rc; } #endif // JASPER /* * ConfTransferRequest () * * Public Function Description * This function is called by the interface when it gets a conference * transfer request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConfTransferRequest ( GCCConfID conference_id, PGCCConferenceName destination_conference_name, GCCNumericString destination_conference_modifier, UINT number_of_destination_addresses, PGCCNetworkAddress *destination_address_list, UINT number_of_destination_nodes, PUserID destination_node_list, PGCCPassword password ) { GCCError rc = GCC_NO_ERROR; CPassword *password_data = NULL; CNetAddrListContainer *network_address_list = NULL; UINT i = 0; DebugEntry(CControlSAP::ConfTransferRequest); // Check for invalid conference name if (destination_conference_name != NULL) { /* ** Do not allow non-numeric or zero length strings to get ** past this point. */ if (destination_conference_name->numeric_string != NULL) { if (IsNumericNameValid ( destination_conference_name->numeric_string) == FALSE) { ERROR_OUT(("CControlSAP::ConfTransferRequest: invalid numeric conference name")); rc = GCC_INVALID_CONFERENCE_NAME; } } else if (destination_conference_name->text_string != NULL) { if (IsTextNameValid ( destination_conference_name->text_string) == FALSE) { ERROR_OUT(("CControlSAP::ConfTransferRequest: invalid text conference name")); rc = GCC_INVALID_CONFERENCE_NAME; } } else { ERROR_OUT(("CControlSAP::ConfTransferRequest: null numeric/text conference name")); rc = GCC_INVALID_CONFERENCE_NAME; } if ((rc == GCC_NO_ERROR) && (destination_conference_name->text_string != NULL)) { if (IsTextNameValid ( destination_conference_name->text_string) == FALSE) { ERROR_OUT(("CControlSAP::ConfTransferRequest: invalid text conference name")); rc = GCC_INVALID_CONFERENCE_NAME; } } } else { ERROR_OUT(("CControlSAP::ConfTransferRequest: null conference name")); rc = GCC_INVALID_CONFERENCE_NAME; } // Check for valid conference modifier if ((destination_conference_modifier != NULL) && (rc == GCC_NO_ERROR)) { if (IsNumericNameValid(destination_conference_modifier) == FALSE) { ERROR_OUT(("CControlSAP::ConfTransferRequest: invalid conference modifier")); rc = GCC_INVALID_CONFERENCE_MODIFIER; } } // Check for valid password if ((password != NULL) && (rc == GCC_NO_ERROR)) { if (password->numeric_string != NULL) { if (IsNumericNameValid(password->numeric_string) == FALSE) { ERROR_OUT(("CControlSAP::ConfTransferRequest: invalid password")); rc = GCC_INVALID_PASSWORD; } } else { ERROR_OUT(("CControlSAP::ConfTransferRequest: null password")); rc = GCC_INVALID_PASSWORD; } } // Check for invalid user IDs if (rc == GCC_NO_ERROR) { while (i != number_of_destination_nodes) { if (destination_node_list[i] < MINIMUM_USER_ID_VALUE) { rc = GCC_INVALID_MCS_USER_ID; break; } i++; } } if (rc == GCC_NO_ERROR) { CConf *pConf; ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { // Construct the password container if (password != NULL) { DBG_SAVE_FILE_LINE password_data = new CPassword(password, &rc); if (password_data == NULL) { ERROR_OUT(("CControlSAP::ConfTransferRequest: can't create CPassword")); rc = GCC_ALLOCATION_FAILURE; } } // Construct the network address(es) container if ((number_of_destination_addresses != 0) && (rc == GCC_NO_ERROR)) { DBG_SAVE_FILE_LINE network_address_list = new CNetAddrListContainer( number_of_destination_addresses, destination_address_list, &rc); if (network_address_list == NULL) { ERROR_OUT(("CControlSAP::CNetAddrListContainer: can't create CPassword")); rc = GCC_ALLOCATION_FAILURE; } } if (rc == GCC_NO_ERROR) { rc = pConf->ConfTransferRequest(destination_conference_name, destination_conference_modifier, network_address_list, number_of_destination_nodes, destination_node_list, password_data); } // Free the data associated with the containers. if (password_data != NULL) { password_data->Release(); } if (network_address_list != NULL) { network_address_list->Release(); } } else { rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); } DebugExitINT(CControlSAP::ConfTransferRequest, rc); return rc; } #endif // JASPER /* * ConfAddRequest () * * Public Function Description * This function is called by the interface when it gets a conference * add request from the node controller. This function passes the * request on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ #ifdef JASPER GCCError CControlSAP::ConfAddRequest ( GCCConfID conference_id, UINT number_of_network_addresses, PGCCNetworkAddress * network_address_list, UserID adding_node, UINT number_of_user_data_members, PGCCUserData * user_data_list ) { GCCError rc = GCC_NO_ERROR; CNetAddrListContainer *network_address_container = NULL; CUserDataListContainer *user_data_container = NULL; CConf *pConf; DebugEntry(CControlSAP::ConfAddRequest); if ((adding_node < MINIMUM_USER_ID_VALUE) && (adding_node != 0)) { ERROR_OUT(("CControlSAP::ConfAddRequest: invalid adding node ID")); return GCC_INVALID_MCS_USER_ID; } if (number_of_network_addresses == 0) { ERROR_OUT(("CControlSAP::ConfAddRequest: no network address")); return GCC_BAD_NETWORK_ADDRESS; } ::EnterCriticalSection(&g_csGCCProvider); if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { // Construct the network address(es) container if (number_of_network_addresses != 0) { DBG_SAVE_FILE_LINE network_address_container = new CNetAddrListContainer( number_of_network_addresses, network_address_list, &rc); if (network_address_container == NULL) { ERROR_OUT(("CControlSAP::ConfAddRequest: can't create CNetAddrListContainer")); rc = GCC_ALLOCATION_FAILURE; } } // Construct the user data list container if ((number_of_user_data_members != 0) && (rc == GCC_NO_ERROR)) { DBG_SAVE_FILE_LINE user_data_container = new CUserDataListContainer(number_of_user_data_members, user_data_list, &rc); if (user_data_container == NULL) { ERROR_OUT(("CControlSAP::ConfAddRequest: can't create CUserDataListContainer")); rc = GCC_ALLOCATION_FAILURE; } } else { user_data_container = NULL; } if (rc == GCC_NO_ERROR) { rc = pConf->ConfAddRequest(network_address_container, adding_node, user_data_container); } // Free the data associated with the containers. if (network_address_container != NULL) { network_address_container->Release(); } if (user_data_container != NULL) { user_data_container->Release(); } } else { rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfAddRequest, rc); return rc; } #endif // JASPER /* * ConfAddResponse () * * Public Function Description * This function is called by the interface when it gets a conference * add response from the node controller. This function passes the * response on to the appropriate conference object as obtained from * the list of command targets that the control sap maintains. */ GCCError CControlSAP::ConfAddResponse ( GCCResponseTag add_response_tag, GCCConfID conference_id, UserID requesting_node, UINT number_of_user_data_members, PGCCUserData * user_data_list, GCCResult result ) { GCCError rc = GCC_NO_ERROR; CUserDataListContainer *user_data_container = NULL; CConf *pConf; DebugEntry(CControlSAP::ConfAddResponse); if (requesting_node < MINIMUM_USER_ID_VALUE) { ERROR_OUT(("CControlSAP::ConfAddResponse: invalid user ID")); return GCC_INVALID_MCS_USER_ID; } ::EnterCriticalSection(&g_csGCCProvider); // Check to make sure the conference exists. if (NULL != (pConf = g_pGCCController->GetConfObject(conference_id))) { // Construct the user data list container if ((number_of_user_data_members != 0) && (rc == GCC_NO_ERROR)) { DBG_SAVE_FILE_LINE user_data_container = new CUserDataListContainer(number_of_user_data_members, user_data_list, &rc); if (user_data_container == NULL) { ERROR_OUT(("CControlSAP::ConfAddResponse: can't create CUserDataListContainer")); rc = GCC_ALLOCATION_FAILURE; } } else { user_data_container = NULL; } if (rc == GCC_NO_ERROR) { rc = pConf->ConfAddResponse(add_response_tag, requesting_node, user_data_container, result); } // Free the data associated with the user data container. if (user_data_container != NULL) { user_data_container->Release(); } } else { WARNING_OUT(("CControlSAP::ConfAddResponse: invalid conference ID=%u", (UINT) conference_id)); rc = GCC_INVALID_CONFERENCE; } ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ConfAddResponse, rc); return rc; } #ifdef NM_RESET_DEVICE /* * ResetDevice () * * Public Function Description * This routine is called in order to explicitly reset a particular * transport stack. The call is routed to the controller in order to take * the appropriate action. */ GCCError CControlSAP::ResetDevice ( LPSTR device_identifier ) { GCCError rc; MCSError mcs_error; DebugEntry(CControlSAP::ResetDevice); ::EnterCriticalSection(&g_csGCCProvider); // Call back the controller to reset the device. mcs_error = g_pMCSIntf->ResetDevice(device_identifier); rc = g_pMCSIntf->TranslateMCSIFErrorToGCCError(mcs_error); // // If the the node controller was in a query, this will tell the node controller // to remove the query. // ConfQueryConfirm(GCC_TERMINAL, NULL, NULL, NULL, GCC_RESULT_CONNECT_PROVIDER_FAILED, NULL); ::LeaveCriticalSection(&g_csGCCProvider); DebugExitINT(CControlSAP::ResetDevice, rc); return rc; } #endif // NM_RESET_DEVICE /* * ConfCreateIndication () * * Public Function Description * This function is called by the GCC Controller when it gets a connect * provider indication from MCS, carrying a conference create request PDU. * This function fills in all the parameters in the CreateIndicationInfo * structure. It then adds it to a queue of messages supposed to be sent to * the node controller in the next heartbeat. */ GCCError CControlSAP::ConfCreateIndication ( PGCCConferenceName conference_name, GCCConfID conference_id, CPassword *convener_password, CPassword *password, BOOL conference_is_locked, BOOL conference_is_listed, BOOL conference_is_conductible, GCCTerminationMethod termination_method, PPrivilegeListData conductor_privilege_list, PPrivilegeListData conducted_mode_privilege_list, PPrivilegeListData non_conducted_privilege_list, LPWSTR pwszConfDescriptor, LPWSTR pwszCallerID, TransportAddress calling_address, TransportAddress called_address, PDomainParameters domain_parameters, CUserDataListContainer *user_data_list, ConnectionHandle connection_handle ) { GCCError rc; DebugEntry(CControlSAP::ConfCreateIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_CREATE_INDICATION; /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // start with success rc = GCC_NO_ERROR; // Copy the conference name ::CSAP_CopyDataToGCCMessage_ConfName( conference_name, &(Msg.u.create_indication.conference_name)); // Copy the Convener Password ::CSAP_CopyDataToGCCMessage_Password( convener_password, &(Msg.u.create_indication.convener_password)); // Copy the Password ::CSAP_CopyDataToGCCMessage_Password( password, &(Msg.u.create_indication.password)); // Copy the Conductor Privilege List GCCConfPrivileges _ConductorPrivileges; ::CSAP_CopyDataToGCCMessage_PrivilegeList( conductor_privilege_list, &(Msg.u.create_indication.conductor_privilege_list), &_ConductorPrivileges); // Copy the Conducted-mode Conference Privilege List GCCConfPrivileges _ConductedModePrivileges; ::CSAP_CopyDataToGCCMessage_PrivilegeList( conducted_mode_privilege_list, &(Msg.u.create_indication.conducted_mode_privilege_list), &_ConductedModePrivileges); // Copy the Non-Conducted-mode Conference Privilege List GCCConfPrivileges _NonConductedPrivileges; ::CSAP_CopyDataToGCCMessage_PrivilegeList( non_conducted_privilege_list, &(Msg.u.create_indication.non_conducted_privilege_list), &_NonConductedPrivileges); // Copy the Conference Descriptor ::CSAP_CopyDataToGCCMessage_IDvsDesc( pwszConfDescriptor, &(Msg.u.create_indication.conference_descriptor)); // Copy the Caller Identifier ::CSAP_CopyDataToGCCMessage_IDvsDesc( pwszCallerID, &(Msg.u.create_indication.caller_identifier)); // Copy the Calling Address ::CSAP_CopyDataToGCCMessage_Call( calling_address, &(Msg.u.create_indication.calling_address)); // Copy the Called Address ::CSAP_CopyDataToGCCMessage_Call( called_address, &(Msg.u.create_indication.called_address)); // Copy the Domain Parameters DomainParameters _DomainParams; ::CSAP_CopyDataToGCCMessage_DomainParams( domain_parameters, &(Msg.u.create_indication.domain_parameters), &_DomainParams); // Copy the User Data LPBYTE pUserDataMemory = NULL; if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(Msg.u.create_indication.number_of_user_data_members), &(Msg.u.create_indication.user_data_list), &pUserDataMemory); } else { Msg.u.create_indication.number_of_user_data_members = 0; Msg.u.create_indication.user_data_list = NULL; } if (GCC_NO_ERROR == rc) { // Queue up the message for delivery to the Node Controller. Msg.nConfID = conference_id; Msg.u.create_indication.conference_id = conference_id; Msg.u.create_indication.conference_is_locked = conference_is_locked; Msg.u.create_indication.conference_is_listed = conference_is_listed; Msg.u.create_indication.conference_is_conductible = conference_is_conductible; Msg.u.create_indication.termination_method = termination_method; Msg.u.create_indication.connection_handle = connection_handle; SendCtrlSapMsg(&Msg); delete pUserDataMemory; } #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CREATE_INDICATION, TRUE))) { ::ZeroMemory(&(pMsgEx->Msg.u.create_indication), sizeof(pMsgEx->Msg.u.create_indication)); } else { ERROR_OUT(("CControlSAP::ConfCreateIndication: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // start with success rc = GCC_NO_ERROR; // Copy the conference name ::CSAP_CopyDataToGCCMessage_ConfName( pMsgEx->pToDelete, conference_name, &(pMsgEx->Msg.u.create_indication.conference_name), &rc); // Copy the Convener Password ::CSAP_CopyDataToGCCMessage_Password( TRUE, // convener password pMsgEx->pToDelete, convener_password, &(pMsgEx->Msg.u.create_indication.convener_password), &rc); // Copy the Password ::CSAP_CopyDataToGCCMessage_Password( FALSE, // non-convener password pMsgEx->pToDelete, password, &(pMsgEx->Msg.u.create_indication.password), &rc); // Copy the Conductor Privilege List ::CSAP_CopyDataToGCCMessage_PrivilegeList( conductor_privilege_list, &(pMsgEx->Msg.u.create_indication.conductor_privilege_list), &rc); pMsgEx->pToDelete->conductor_privilege_list = pMsgEx->Msg.u.create_indication.conductor_privilege_list; // Copy the Conducted-mode Conference Privilege List ::CSAP_CopyDataToGCCMessage_PrivilegeList( conducted_mode_privilege_list, &(pMsgEx->Msg.u.create_indication.conducted_mode_privilege_list), &rc); pMsgEx->pToDelete->conducted_mode_privilege_list = pMsgEx->Msg.u.create_indication.conducted_mode_privilege_list; // Copy the Non-Conducted-mode Conference Privilege List ::CSAP_CopyDataToGCCMessage_PrivilegeList( non_conducted_privilege_list, &(pMsgEx->Msg.u.create_indication.non_conducted_privilege_list), &rc); pMsgEx->pToDelete->non_conducted_privilege_list = pMsgEx->Msg.u.create_indication.non_conducted_privilege_list; // Copy the Conference Descriptor ::CSAP_CopyDataToGCCMessage_IDvsDesc( FALSE, // conference descriptor pMsgEx->pToDelete, pwszConfDescriptor, &(pMsgEx->Msg.u.create_indication.conference_descriptor), &rc); // Copy the Caller Identifier ::CSAP_CopyDataToGCCMessage_IDvsDesc( TRUE, // caller id pMsgEx->pToDelete, pwszCallerID, &(pMsgEx->Msg.u.create_indication.caller_identifier), &rc); // Copy the Calling Address ::CSAP_CopyDataToGCCMessage_Call( TRUE, // calling address pMsgEx->pToDelete, calling_address, &(pMsgEx->Msg.u.create_indication.calling_address), &rc); // Copy the Called Address ::CSAP_CopyDataToGCCMessage_Call( FALSE, // called address pMsgEx->pToDelete, called_address, &(pMsgEx->Msg.u.create_indication.called_address), &rc); // Copy the Domain Parameters ::CSAP_CopyDataToGCCMessage_DomainParams( pMsgEx->pToDelete, domain_parameters, &(pMsgEx->Msg.u.create_indication.domain_parameters), &rc); if (GCC_NO_ERROR != rc) { ERROR_OUT(("CControlSAP::ConfCreateIndication: can't copy data to gcc message")); goto MyExit; } // Copy the User Data if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(pMsgEx->Msg.u.create_indication.number_of_user_data_members), &(pMsgEx->Msg.u.create_indication.user_data_list), &(pMsgEx->pToDelete->user_data_list_memory)); if (GCC_NO_ERROR != rc) { goto MyExit; } } else { // pMsgEx->Msg.u.create_indication.number_of_user_data_members = 0; // pMsgEx->Msg.u.create_indication.user_data_list = NULL; } // Queue up the message for delivery to the Node Controller. pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.create_indication.conference_id = conference_id; pMsgEx->Msg.u.create_indication.conference_is_locked = conference_is_locked; pMsgEx->Msg.u.create_indication.conference_is_listed = conference_is_listed; pMsgEx->Msg.u.create_indication.conference_is_conductible = conference_is_conductible; pMsgEx->Msg.u.create_indication.termination_method = termination_method; pMsgEx->Msg.u.create_indication.connection_handle = connection_handle; PostIndCtrlSapMsg(pMsgEx); MyExit: if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfCreateIndication, rc); return rc; } /* * ConfQueryIndication () * * Public Function Description * This function is called by the GCC Controller when it need to send a * conference query indication to the node controller. It adds the message * to a queue of messages to be sent to the node controller in the next * heartbeat. */ GCCError CControlSAP::ConfQueryIndication ( GCCResponseTag query_response_tag, GCCNodeType node_type, PGCCAsymmetryIndicator asymmetry_indicator, TransportAddress calling_address, TransportAddress called_address, CUserDataListContainer *user_data_list, ConnectionHandle connection_handle ) { GCCError rc; DebugEntry(CControlSAP::ConfQueryIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_QUERY_INDICATION; /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // start with success rc = GCC_NO_ERROR; // Copy the Calling Address ::CSAP_CopyDataToGCCMessage_Call( calling_address, &(Msg.u.query_indication.calling_address)); // Copy the Calling Address ::CSAP_CopyDataToGCCMessage_Call( called_address, &(Msg.u.query_indication.called_address)); // Copy the asymmetry indicator if it exists GCCAsymmetryIndicator AsymIndicator; if (asymmetry_indicator != NULL) { Msg.u.query_indication.asymmetry_indicator = &AsymIndicator; AsymIndicator = *asymmetry_indicator; } else { Msg.u.query_indication.asymmetry_indicator = NULL; } // Lock and Copy the user data if it exists LPBYTE pUserDataMemory = NULL; if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(Msg.u.query_indication.number_of_user_data_members), &(Msg.u.query_indication.user_data_list), &pUserDataMemory); } else { Msg.u.query_indication.number_of_user_data_members = 0; Msg.u.query_indication.user_data_list = NULL; } if (GCC_NO_ERROR == rc) { // If everything is OK add the message to the message queue Msg.u.query_indication.query_response_tag = query_response_tag; Msg.u.query_indication.node_type = node_type; Msg.u.query_indication.connection_handle = connection_handle; SendCtrlSapMsg(&Msg); delete pUserDataMemory; } #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_QUERY_INDICATION, TRUE))) { ::ZeroMemory(&(pMsgEx->Msg.u.query_indication), sizeof(pMsgEx->Msg.u.query_indication)); } else { ERROR_OUT(("CControlSAP::ConfCreateIndication: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // start with success rc = GCC_NO_ERROR; // Copy the Calling Address ::CSAP_CopyDataToGCCMessage_Call( TRUE, // calling address pMsgEx->pToDelete, calling_address, &(pMsgEx->Msg.u.query_indication.calling_address), &rc); // Copy the Calling Address ::CSAP_CopyDataToGCCMessage_Call( FALSE, // called address pMsgEx->pToDelete, called_address, &(pMsgEx->Msg.u.query_indication.called_address), &rc); if (GCC_NO_ERROR != rc) { ERROR_OUT(("CControlSAP::ConfQueryIndication: can't copy data to gcc message")); goto MyExit; } // Copy the asymmetry indicator if it exists if (asymmetry_indicator != NULL) { DBG_SAVE_FILE_LINE pMsgEx->Msg.u.query_indication.asymmetry_indicator = new GCCAsymmetryIndicator; if (pMsgEx->Msg.u.query_indication.asymmetry_indicator != NULL) { *(pMsgEx->Msg.u.query_indication.asymmetry_indicator) = *asymmetry_indicator; } else { rc = GCC_ALLOCATION_FAILURE; goto MyExit; } } else { // pMsgEx->Msg.u.query_indication.asymmetry_indicator = NULL; } // Lock and Copy the user data if it exists if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(pMsgEx->Msg.u.query_indication.number_of_user_data_members), &(pMsgEx->Msg.u.query_indication.user_data_list), &(pMsgEx->pToDelete->user_data_list_memory)); if (GCC_NO_ERROR != rc) { goto MyExit; } } else { // pMsgEx->Msg.u.query_indication.number_of_user_data_members = 0; // pMsgEx->Msg.u.query_indication.user_data_list = NULL; } // If everything is OK add the message to the message queue pMsgEx->Msg.u.query_indication.query_response_tag = query_response_tag; pMsgEx->Msg.u.query_indication.node_type = node_type; pMsgEx->Msg.u.query_indication.connection_handle = connection_handle; PostIndCtrlSapMsg(pMsgEx); MyExit: if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfQueryIndication, rc); return rc; } /* * ConfQueryConfirm () * * Public Function Description * This function is called by the GCC Controller when it need to send a * conference query confirm to the node controller. It adds the message * to a queue of messages to be sent to the node controller in the next * heartbeat. */ GCCError CControlSAP::ConfQueryConfirm ( GCCNodeType node_type, PGCCAsymmetryIndicator asymmetry_indicator, CConfDescriptorListContainer *conference_list, CUserDataListContainer *user_data_list, GCCResult result, ConnectionHandle connection_handle ) { GCCError rc = GCC_NO_ERROR; DebugEntry(CControlSAP::ConfQueryConfirm); #ifdef GCCNC_DIRECT_CONFIRM GCCCtrlSapMsg Msg; Msg.message_type = GCC_QUERY_CONFIRM; GCCAsymmetryIndicator _AsymIndicator; if (asymmetry_indicator != NULL) { Msg.u.query_confirm.asymmetry_indicator = &_AsymIndicator; _AsymIndicator = *asymmetry_indicator; } else { Msg.u.query_confirm.asymmetry_indicator = NULL; } // Get the conference descriptor list if one exists if (conference_list != NULL) { rc = conference_list->LockConferenceDescriptorList(); if (rc == GCC_NO_ERROR) { conference_list->GetConferenceDescriptorList( &(Msg.u.query_confirm.conference_descriptor_list), &(Msg.u.query_confirm.number_of_descriptors)); } } else { Msg.u.query_confirm.conference_descriptor_list = NULL; Msg.u.query_confirm.number_of_descriptors = 0; } // Lock and Copy the user data if it exists LPBYTE pUserDataMemory = NULL; if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(Msg.u.query_confirm.number_of_user_data_members), &(Msg.u.query_confirm.user_data_list), &pUserDataMemory); } else { Msg.u.query_confirm.number_of_user_data_members = 0; Msg.u.query_confirm.user_data_list = NULL; } if (rc == GCC_NO_ERROR) { Msg.u.query_confirm.node_type = node_type; Msg.u.query_confirm.result = result; Msg.u.query_confirm.connection_handle = connection_handle; // Queue up the message for delivery to the Node Controller. SendCtrlSapMsg(&Msg); // clean up delete pUserDataMemory; } else { HandleResourceFailure(rc); } // clean up if (NULL != conference_list) { conference_list->UnLockConferenceDescriptorList(); } #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_QUERY_CONFIRM, TRUE))) { ::ZeroMemory(&(pMsgEx->Msg.u.query_confirm), sizeof(pMsgEx->Msg.u.query_confirm)); if (asymmetry_indicator != NULL) { DBG_SAVE_FILE_LINE pMsgEx->Msg.u.query_confirm.asymmetry_indicator = new GCCAsymmetryIndicator; if (pMsgEx->Msg.u.query_confirm.asymmetry_indicator != NULL) { *(pMsgEx->Msg.u.query_confirm.asymmetry_indicator) = *asymmetry_indicator; } else { rc = GCC_ALLOCATION_FAILURE; ERROR_OUT(("CControlSAP::ConfQueryConfirm: can't create GCCAsymmetryIndicator")); } } else { // pMsgEx->Msg.u.query_confirm.asymmetry_indicator = NULL; } // Get the conference descriptor list if one exists if (conference_list != NULL) { pMsgEx->pToDelete->conference_list = conference_list; rc = conference_list->LockConferenceDescriptorList(); if (rc == GCC_NO_ERROR) { conference_list->GetConferenceDescriptorList ( &(pMsgEx->Msg.u.query_confirm.conference_descriptor_list), &(pMsgEx->Msg.u.query_confirm.number_of_descriptors)); } } else { // pMsgEx->Msg.u.query_confirm.conference_descriptor_list = NULL; // pMsgEx->Msg.u.query_confirm.number_of_descriptors = 0; } // Lock and Copy the user data if it exists if (user_data_list != NULL) { rc = RetrieveUserDataList ( user_data_list, &(pMsgEx->Msg.u.query_confirm.number_of_user_data_members), &(pMsgEx->Msg.u.query_confirm.user_data_list), &(pMsgEx->pToDelete->user_data_list_memory)); } else { // pMsgEx->Msg.u.query_confirm.number_of_user_data_members = 0; // pMsgEx->Msg.u.query_confirm.user_data_list = NULL; } if (rc == GCC_NO_ERROR) { pMsgEx->Msg.u.query_confirm.node_type = node_type; pMsgEx->Msg.u.query_confirm.result = result; pMsgEx->Msg.u.query_confirm.connection_handle = connection_handle; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); } } else { rc = GCC_ALLOCATION_FAILURE; ERROR_OUT(("CControlSAP::ConfQueryConfirm: can't create GCCCtrlSapMsgEx")); } if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfQueryConfirm, rc); return rc; } /* * ConfJoinIndication () * * Public Function Description * This join indication is recevied from the owner object. This join * indication is designed to make the join response very flexible at the * node controller. The node controller can respond to this indication * by either creating a new conference and moving the joiner into it, * putting the joiner in the conference requested or putting the joiner * into a different conference that already exist. */ // LONCHANC: from GCCController, normal code path. GCCError CControlSAP::ConfJoinIndication ( GCCConfID conference_id, CPassword *convener_password, CPassword *password_challenge, LPWSTR pwszCallerID, TransportAddress calling_address, TransportAddress called_address, CUserDataListContainer *user_data_list, BOOL intermediate_node, ConnectionHandle connection_handle ) { PJoinResponseStructure join_info; GCCError rc; DebugEntry(CControlSAP::ConfJoinIndication); // First generate a Join Response Handle and add info to response list while (1) { m_nJoinResponseTag++; if (NULL == m_JoinResponseTagList2.Find(m_nJoinResponseTag)) break; } DBG_SAVE_FILE_LINE join_info = new JoinResponseStructure; if (join_info != NULL) { join_info->connection_handle = connection_handle; join_info->conference_id = conference_id; join_info->user_id = NULL; join_info->command_target_call = FALSE; m_JoinResponseTagList2.Append(m_nJoinResponseTag, join_info); // Queue up the message for delivery to the Node Controller. rc = QueueJoinIndication( m_nJoinResponseTag, conference_id, convener_password, password_challenge, pwszCallerID, calling_address, called_address, user_data_list, intermediate_node, connection_handle); } else { rc = GCC_ALLOCATION_FAILURE; ERROR_OUT(("CControlSAP::ConfJoinIndication: can't create JoinResponseStructure")); } DebugExitINT(CControlSAP::ConfJoinIndication, rc); return rc; } /* * ConfInviteIndication () * * Public Function Description * This function is called by the GCC Controller when it need to send a * conference invite indication to the node controller. It adds the message * to a queue of messages to be sent to the node controller in the next * heartbeat. */ GCCError CControlSAP::ConfInviteIndication ( GCCConfID conference_id, PGCCConferenceName conference_name, LPWSTR pwszCallerID, TransportAddress calling_address, TransportAddress called_address, BOOL fSecure, PDomainParameters domain_parameters, BOOL clear_password_required, BOOL conference_is_locked, BOOL conference_is_listed, BOOL conference_is_conductible, GCCTerminationMethod termination_method, PPrivilegeListData conductor_privilege_list, PPrivilegeListData conducted_mode_privilege_list, PPrivilegeListData non_conducted_privilege_list, LPWSTR pwszConfDescriptor, CUserDataListContainer *user_data_list, ConnectionHandle connection_handle ) { GCCError rc; DebugEntry(CControlSAP::ConfInviteIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_INVITE_INDICATION; // // Copy the information that needs to be sent to the node // controller into local memory that can be deleted once the // information to be sent to the application is flushed. Note that // if an error occurs in one call to "CopyDataToGCCMessage" then no // action is taken on subsequent calls to that routine. // // start with success rc = GCC_NO_ERROR; // Copy the conference name ::CSAP_CopyDataToGCCMessage_ConfName( conference_name, &(Msg.u.invite_indication.conference_name)); // Copy the Conductor Privilege List GCCConfPrivileges _ConductorPrivileges; ::CSAP_CopyDataToGCCMessage_PrivilegeList( conductor_privilege_list, &(Msg.u.invite_indication.conductor_privilege_list), &_ConductorPrivileges); // Copy the Conducted-mode Conference Privilege List GCCConfPrivileges _ConductedModePrivileges; ::CSAP_CopyDataToGCCMessage_PrivilegeList( conducted_mode_privilege_list, &(Msg.u.invite_indication.conducted_mode_privilege_list), &_ConductedModePrivileges); // Copy the Non-Conducted-mode Conference Privilege List GCCConfPrivileges _NonConductedPrivileges; ::CSAP_CopyDataToGCCMessage_PrivilegeList( non_conducted_privilege_list, &(Msg.u.invite_indication.non_conducted_privilege_list), &_NonConductedPrivileges); // Copy the Conference Descriptor ::CSAP_CopyDataToGCCMessage_IDvsDesc( pwszConfDescriptor, &(Msg.u.invite_indication.conference_descriptor)); // Copy the Caller Identifier ::CSAP_CopyDataToGCCMessage_IDvsDesc( pwszCallerID, &(Msg.u.invite_indication.caller_identifier)); // Copy the Calling Address ::CSAP_CopyDataToGCCMessage_Call( calling_address, &(Msg.u.invite_indication.calling_address)); // Copy the Called Address ::CSAP_CopyDataToGCCMessage_Call( called_address, &(Msg.u.invite_indication.called_address)); // Copy the Domain Parameters DomainParameters _DomainParams; ::CSAP_CopyDataToGCCMessage_DomainParams( domain_parameters, &(Msg.u.invite_indication.domain_parameters), &_DomainParams); // Copy the User Data LPBYTE pUserDataMemory = NULL; if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(Msg.u.invite_indication.number_of_user_data_members), &(Msg.u.invite_indication.user_data_list), &pUserDataMemory); ASSERT(GCC_NO_ERROR == rc); } else { Msg.u.invite_indication.number_of_user_data_members = 0; Msg.u.invite_indication.user_data_list = NULL; } if (GCC_NO_ERROR == rc) { Msg.u.invite_indication.conference_id = conference_id; Msg.u.invite_indication.clear_password_required = clear_password_required; Msg.u.invite_indication.conference_is_locked = conference_is_locked; Msg.u.invite_indication.conference_is_listed = conference_is_listed; Msg.u.invite_indication.conference_is_conductible = conference_is_conductible; Msg.u.invite_indication.termination_method = termination_method; Msg.u.invite_indication.connection_handle = connection_handle; Msg.u.invite_indication.fSecure = fSecure; SendCtrlSapMsg(&Msg); delete pUserDataMemory; } #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_INVITE_INDICATION, TRUE))) { ::ZeroMemory(&(pMsgEx->Msg.u.invite_indication), sizeof(pMsgEx->Msg.u.invite_indication)); } else { ERROR_OUT(("CControlSAP::ConfInviteIndication: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // start with success rc = GCC_NO_ERROR; // Copy the conference name ::CSAP_CopyDataToGCCMessage_ConfName( pMsgEx->pToDelete, conference_name, &(pMsgEx->Msg.u.invite_indication.conference_name), &rc); // Copy the Conductor Privilege List ::CSAP_CopyDataToGCCMessage_PrivilegeList( conductor_privilege_list, &(pMsgEx->Msg.u.invite_indication.conductor_privilege_list), &rc); pMsgEx->pToDelete->conductor_privilege_list = pMsgEx->Msg.u.invite_indication.conductor_privilege_list; // Copy the Conducted-mode Conference Privilege List ::CSAP_CopyDataToGCCMessage_PrivilegeList( conducted_mode_privilege_list, &(pMsgEx->Msg.u.invite_indication.conducted_mode_privilege_list), &rc); pMsgEx->pToDelete->conducted_mode_privilege_list = pMsgEx->Msg.u.invite_indication.conducted_mode_privilege_list; // Copy the Non-Conducted-mode Conference Privilege List ::CSAP_CopyDataToGCCMessage_PrivilegeList( non_conducted_privilege_list, &(pMsgEx->Msg.u.invite_indication.non_conducted_privilege_list), &rc); pMsgEx->pToDelete->non_conducted_privilege_list = pMsgEx->Msg.u.invite_indication.non_conducted_privilege_list; // Copy the Conference Descriptor ::CSAP_CopyDataToGCCMessage_IDvsDesc( FALSE, // conference descriptor pMsgEx->pToDelete, pwszConfDescriptor, &(pMsgEx->Msg.u.invite_indication.conference_descriptor), &rc); // Copy the Caller Identifier ::CSAP_CopyDataToGCCMessage_IDvsDesc( TRUE, // caller id pMsgEx->pToDelete, pwszCallerID, &(pMsgEx->Msg.u.invite_indication.caller_identifier), &rc); // Copy the Calling Address ::CSAP_CopyDataToGCCMessage_Call( TRUE, /// calling address pMsgEx->pToDelete, calling_address, &(pMsgEx->Msg.u.invite_indication.calling_address), &rc); // Copy the Called Address ::CSAP_CopyDataToGCCMessage_Call( FALSE, // called address pMsgEx->pToDelete, called_address, &(pMsgEx->Msg.u.invite_indication.called_address), &rc); // Copy the Domain Parameters ::CSAP_CopyDataToGCCMessage_DomainParams( pMsgEx->pToDelete, domain_parameters, &(pMsgEx->Msg.u.invite_indication.domain_parameters), &rc); if (GCC_NO_ERROR != rc) { ERROR_OUT(("CControlSAP::ConfInviteIndication: can't copy data to gcc message")); goto MyExit; } // Copy the User Data if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(pMsgEx->Msg.u.invite_indication.number_of_user_data_members), &(pMsgEx->Msg.u.invite_indication.user_data_list), &(pMsgEx->pToDelete->user_data_list_memory)); if (GCC_NO_ERROR != rc) { goto MyExit; } } else { // pMsgEx->Msg.u.invite_indication.number_of_user_data_members = 0; // pMsgEx->Msg.u.invite_indication.user_data_list = NULL; } pMsgEx->Msg.u.invite_indication.conference_id = conference_id; pMsgEx->Msg.u.invite_indication.clear_password_required = clear_password_required; pMsgEx->Msg.u.invite_indication.conference_is_locked = conference_is_locked; pMsgEx->Msg.u.invite_indication.conference_is_listed = conference_is_listed; pMsgEx->Msg.u.invite_indication.conference_is_conductible = conference_is_conductible; pMsgEx->Msg.u.invite_indication.termination_method = termination_method; pMsgEx->Msg.u.invite_indication.connection_handle = connection_handle; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); MyExit: if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfInviteIndication, rc); return rc; } #ifdef TSTATUS_INDICATION /* * GCCError TransportStatusIndication() * * Public Function Description * This function is called by the GCC Controller when it need to send a * transport status indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. This callback message uses Rogue Wave strings to * store the message information. These strings are held in a * TransportStatusInfo structure which is stored in a DataToBeDeleted * structure which is freed up after the callback is issued. */ GCCError CControlSAP::TransportStatusIndication ( PTransportStatus transport_status ) { GCCError rc; DebugEntry(CControlSAP::TransportStatusIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_TRANSPORT_STATUS_INDICATION; Msg.u.transport_status.device_identifier = transport_status->device_identifier; Msg.u.transport_status.remote_address = transport_status->remote_address; Msg.u.transport_status.message = transport_status->message; Msg.u.transport_status.state = transport_status->state; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_TRANSPORT_STATUS_INDICATION, TRUE))) { // ::ZeroMemory(&(pMsgEx->Msg.u.transport_status), sizeof(pMsgEx->Msg.u.transport_status)); pMsgEx->Msg.u.transport_status.device_identifier = ::My_strdupA(transport_status->device_identifier); pMsgEx->Msg.u.transport_status.remote_address = ::My_strdupA(transport_status->remote_address); pMsgEx->Msg.u.transport_status.message = ::My_strdupA(transport_status->message); pMsgEx->Msg.u.transport_status.state = transport_status->state; PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { ERROR_OUT(("CControlSAP::TransportStatusIndication: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::TransportStatusIndication, rc); return rc; } /* * StatusIndication() * * Public Function Description * This function is called by the GCC Controller when it need to send a * status indication to the node controller. It adds the message to a * queue of messages to be sent to the node controller in the next * heartbeat. * * Caveats * Note that we do not handle a resource error here to avoid an * endless loop that could occur when this routine is called from the * HandleResourceError() routine. */ GCCError CControlSAP::StatusIndication ( GCCStatusMessageType status_message_type, UINT parameter ) { GCCError rc; DebugEntry(CControlSAP::StatusIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_STATUS_INDICATION; Msg.u.status_indication.status_message_type = status_message_type; Msg.u.status_indication.parameter = parameter; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_STATUS_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.status_indication), sizeof(pMsgEx->Msg.u.status_indication)); pMsgEx->Msg.u.status_indication.status_message_type = status_message_type; pMsgEx->Msg.u.status_indication.parameter = parameter; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::StatusIndication, rc); return rc; } #endif // TSTATUS_INDICATION /* * GCCError ConnectionBrokenIndication () * * Public Function Description * This function is called by the GCC Controller when it need to send a * connection broken indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConnectionBrokenIndication ( ConnectionHandle connection_handle ) { GCCError rc; DebugEntry(CControlSAP::ConnectionBrokenIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_CONNECTION_BROKEN_INDICATION; Msg.u.connection_broken_indication.connection_handle = connection_handle; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONNECTION_BROKEN_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.connection_broken_indication), sizeof(pMsgEx->Msg.u.connection_broken_indication)); pMsgEx->Msg.u.connection_broken_indication.connection_handle = connection_handle; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConnectionBrokenIndication, rc); return rc; } /* * The following routines are virtual command target calls. */ /* * ConfCreateConfirm() * * Public Function Description * This function is called by the CConf when it need to send a * conference create confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfCreateConfirm ( PGCCConferenceName conference_name, GCCNumericString conference_modifier, GCCConfID conference_id, PDomainParameters domain_parameters, CUserDataListContainer *user_data_list, GCCResult result, ConnectionHandle connection_handle ) { GCCError rc; DebugEntry(CControlSAP::ConfCreateConfirm); #ifdef GCCNC_DIRECT_CONFIRM GCCCtrlSapMsg Msg; Msg.message_type = GCC_CREATE_CONFIRM; /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // start with success rc = GCC_NO_ERROR; // Copy the conference name ::CSAP_CopyDataToGCCMessage_ConfName( conference_name, &(Msg.u.create_confirm.conference_name)); // Copy the conference name modifier ::CSAP_CopyDataToGCCMessage_Modifier( conference_modifier, &(Msg.u.create_confirm.conference_modifier)); // Copy the Domain Parameters DomainParameters _DomainParams; ::CSAP_CopyDataToGCCMessage_DomainParams( domain_parameters, &(Msg.u.create_confirm.domain_parameters), &_DomainParams); // Copy the User Data LPBYTE pUserDataMemory = NULL; if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(Msg.u.create_confirm.number_of_user_data_members), &(Msg.u.create_confirm.user_data_list), &pUserDataMemory); } else { TRACE_OUT(("CControlSAP:ConfCreateConfirm: User Data List is NOT present")); Msg.u.create_confirm.number_of_user_data_members = 0; Msg.u.create_confirm.user_data_list = NULL; } if (GCC_NO_ERROR == rc) { Msg.nConfID = conference_id; Msg.u.create_confirm.conference_id = conference_id; Msg.u.create_confirm.result= result; Msg.u.create_confirm.connection_handle= connection_handle; SendCtrlSapMsg(&Msg); // clean up delete pUserDataMemory; } else { HandleResourceFailure(rc); } #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CREATE_CONFIRM, TRUE))) { ::ZeroMemory(&(pMsgEx->Msg.u.create_confirm), sizeof(pMsgEx->Msg.u.create_confirm)); } else { ERROR_OUT(("CControlSAP::ConfCreateConfirm: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // start with success rc = GCC_NO_ERROR; // Copy the conference name ::CSAP_CopyDataToGCCMessage_ConfName( pMsgEx->pToDelete, conference_name, &(pMsgEx->Msg.u.create_confirm.conference_name), &rc); // Copy the conference name modifier ::CSAP_CopyDataToGCCMessage_Modifier( FALSE, // conference modifier pMsgEx->pToDelete, conference_modifier, &(pMsgEx->Msg.u.create_confirm.conference_modifier), &rc); // Copy the Domain Parameters ::CSAP_CopyDataToGCCMessage_DomainParams( pMsgEx->pToDelete, domain_parameters, &(pMsgEx->Msg.u.create_confirm.domain_parameters), &rc); if (GCC_NO_ERROR != rc) { ERROR_OUT(("CControlSAP::ConfCreateConfirm: can't copy data to gcc message")); goto MyExit; } // Copy the User Data if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(pMsgEx->Msg.u.create_confirm.number_of_user_data_members), &(pMsgEx->Msg.u.create_confirm.user_data_list), &(pMsgEx->pToDelete->user_data_list_memory)); if (GCC_NO_ERROR != rc) { goto MyExit; } } else { TRACE_OUT(("CControlSAP:ConfCreateConfirm: User Data List is NOT present")); // pMsgEx->Msg.u.create_confirm.number_of_user_data_members = 0; // pMsgEx->Msg.u.create_confirm.user_data_list = NULL; } // Queue up the message for delivery to the Node Controller. pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.create_confirm.conference_id = conference_id; pMsgEx->Msg.u.create_confirm.result= result; pMsgEx->Msg.u.create_confirm.connection_handle= connection_handle; PostConfirmCtrlSapMsg(pMsgEx); MyExit: /* ** Clean up after any resource allocation error which may have occurred. */ if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfCreateConfirm, rc); return rc; } /* * ConfDisconnectIndication() * * Public Function Description * This function is called by the CConf when it need to send a * conference disconnect indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfDisconnectIndication ( GCCConfID conference_id, GCCReason reason, UserID disconnected_node_id ) { GCCError rc; DebugEntry(CControlSAP::ConfDisconnectIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_DISCONNECT_INDICATION; Msg.nConfID = conference_id; Msg.u.disconnect_indication.conference_id = conference_id; Msg.u.disconnect_indication.reason = reason; Msg.u.disconnect_indication.disconnected_node_id = disconnected_node_id; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_DISCONNECT_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.disconnect_indication), sizeof(pMsgEx->Msg.u.disconnect_indication)); pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.disconnect_indication.conference_id = conference_id; pMsgEx->Msg.u.disconnect_indication.reason = reason; pMsgEx->Msg.u.disconnect_indication.disconnected_node_id = disconnected_node_id; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfDisconnectIndication, rc); return rc; } /* * ConfDisconnectConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conference disconnect confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfDisconnectConfirm ( GCCConfID conference_id, GCCResult result ) { GCCError rc; DebugEntry(CControlSAP::ConfDisconnectConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_DISCONNECT_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_DISCONNECT_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.disconnect_confirm), sizeof(pMsgEx->Msg.u.disconnect_confirm)); pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.disconnect_confirm.conference_id = conference_id; pMsgEx->Msg.u.disconnect_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfDisconnectConfirm, rc); return rc; } /* * GCCError ConfJoinIndication() * * Public Function Description * This function is called by the CConf when it need to send a * conference join indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. * * Since this is received by the command target call we know that the * response must be routed back to the same conference. We must also * pass back the user_id when the response is made. */ // LONCHANC: from Conf2/MCSUser/ProcessJoinRequestPDU. // forwarded from an existing child node. GCCError CControlSAP::ForwardedConfJoinIndication ( UserID sender_id, GCCConfID conference_id, CPassword *convener_password, CPassword *password_challenge, LPWSTR pwszCallerID, CUserDataListContainer *user_data_list ) { GCCError rc = GCC_NO_ERROR; PJoinResponseStructure join_info; LPWSTR caller_id_ptr; DebugEntry(CControlSAP::ForwardedConfJoinIndication); // First generate a Join Response Handle and add info to response list while (1) { m_nJoinResponseTag++; if (NULL == m_JoinResponseTagList2.Find(m_nJoinResponseTag)) break; } // Create a new "info" structure to hold the join information. DBG_SAVE_FILE_LINE join_info = new JoinResponseStructure; if (join_info != NULL) { caller_id_ptr = pwszCallerID; join_info->connection_handle = NULL; join_info->conference_id = conference_id; join_info->user_id = sender_id; join_info->command_target_call = TRUE; m_JoinResponseTagList2.Append(m_nJoinResponseTag, join_info); // Queue up the message for delivery to the Node Controller. rc = QueueJoinIndication( m_nJoinResponseTag, conference_id, convener_password, password_challenge, caller_id_ptr, NULL, // Transport address not supported here NULL, // Transport address not supported here user_data_list, FALSE, // Not an intermediate node 0); } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } DebugExitINT(CControlSAP::ForwardedConfJoinIndication, rc); return rc; } /* * GCCError ConfJoinConfirm() * * Public Function Description * This function is called by the CConf when it need to send a * conference join confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfJoinConfirm ( PGCCConferenceName conference_name, GCCNumericString remote_modifier, GCCNumericString local_modifier, GCCConfID conference_id, CPassword *password_challenge, PDomainParameters domain_parameters, BOOL password_in_the_clear, BOOL conference_is_locked, BOOL conference_is_listed, BOOL conference_is_conductible, GCCTerminationMethod termination_method, PPrivilegeListData conductor_privilege_list, PPrivilegeListData conduct_mode_privilege_list, PPrivilegeListData non_conduct_privilege_list, LPWSTR pwszConfDescription, CUserDataListContainer *user_data_list, GCCResult result, ConnectionHandle connection_handle, PBYTE pbRemoteCred, DWORD cbRemoteCred ) { GCCError rc; DebugEntry(CControlSAP::ConfJoinConfirm); #ifdef GCCNC_DIRECT_CONFIRM GCCCtrlSapMsg Msg; Msg.message_type = GCC_JOIN_CONFIRM; /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // start with success rc = GCC_NO_ERROR; // Copy the conference name ::CSAP_CopyDataToGCCMessage_ConfName( conference_name, &(Msg.u.join_confirm.conference_name)); // Copy the remote modifier ::CSAP_CopyDataToGCCMessage_Modifier( remote_modifier, &(Msg.u.join_confirm.called_node_modifier)); // Copy the local conference name modifier ::CSAP_CopyDataToGCCMessage_Modifier( local_modifier, &(Msg.u.join_confirm.calling_node_modifier)); // Copy the Password challange ::CSAP_CopyDataToGCCMessage_Challenge( password_challenge, &(Msg.u.join_confirm.password_challenge)); // Copy the Domain Parameters DomainParameters _DomainParams; ::CSAP_CopyDataToGCCMessage_DomainParams( domain_parameters, &(Msg.u.join_confirm.domain_parameters), &_DomainParams); // Copy the Conductor Privilege List GCCConfPrivileges _ConductorPrivilegeList; ::CSAP_CopyDataToGCCMessage_PrivilegeList( conductor_privilege_list, &(Msg.u.join_confirm.conductor_privilege_list), &_ConductorPrivilegeList); // Copy the Conducted-mode Conference Privilege List GCCConfPrivileges _ConductedModePrivilegeList; ::CSAP_CopyDataToGCCMessage_PrivilegeList( conduct_mode_privilege_list, &(Msg.u.join_confirm.conducted_mode_privilege_list), &_ConductedModePrivilegeList); // Copy the Non-Conducted-mode Conference Privilege List GCCConfPrivileges _NonConductedModePrivilegeList; ::CSAP_CopyDataToGCCMessage_PrivilegeList( non_conduct_privilege_list, &(Msg.u.join_confirm.non_conducted_privilege_list), &_NonConductedModePrivilegeList); // Copy the Conference Descriptor ::CSAP_CopyDataToGCCMessage_IDvsDesc( pwszConfDescription, &(Msg.u.join_confirm.conference_descriptor)); // Copy the User Data LPBYTE pUserDataMemory = NULL; if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(Msg.u.join_confirm.number_of_user_data_members), &(Msg.u.join_confirm.user_data_list), &pUserDataMemory); } else { Msg.u.join_confirm.number_of_user_data_members = 0; Msg.u.join_confirm.user_data_list = NULL; } if (GCC_NO_ERROR == rc) { Msg.nConfID = conference_id; Msg.u.join_confirm.conference_id = conference_id; Msg.u.join_confirm.clear_password_required = password_in_the_clear; Msg.u.join_confirm.conference_is_locked = conference_is_locked; Msg.u.join_confirm.conference_is_listed = conference_is_listed; Msg.u.join_confirm.conference_is_conductible = conference_is_conductible; Msg.u.join_confirm.termination_method = termination_method; Msg.u.join_confirm.result = result; Msg.u.join_confirm.connection_handle = connection_handle; Msg.u.join_confirm.pb_remote_cred = pbRemoteCred; Msg.u.join_confirm.cb_remote_cred = cbRemoteCred; SendCtrlSapMsg(&Msg); // clean up delete pUserDataMemory; } else { HandleResourceFailure(rc); } #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_JOIN_CONFIRM, TRUE))) { ::ZeroMemory(&(pMsgEx->Msg.u.join_confirm), sizeof(pMsgEx->Msg.u.join_confirm)); } else { ERROR_OUT(("CControlSAP::ConfJoinConfirm: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // start with success rc = GCC_NO_ERROR; // Copy the conference name ::CSAP_CopyDataToGCCMessage_ConfName( pMsgEx->pToDelete, conference_name, &(pMsgEx->Msg.u.join_confirm.conference_name), &rc); // Copy the remote modifier ::CSAP_CopyDataToGCCMessage_Modifier( TRUE, // remote modifier pMsgEx->pToDelete, remote_modifier, &(pMsgEx->Msg.u.join_confirm.called_node_modifier), &rc); // Copy the local conference name modifier ::CSAP_CopyDataToGCCMessage_Modifier( FALSE, // conference modifier pMsgEx->pToDelete, local_modifier, &(pMsgEx->Msg.u.join_confirm.calling_node_modifier), &rc); // Copy the Password challange ::CSAP_CopyDataToGCCMessage_Challenge( pMsgEx->pToDelete, password_challenge, &(pMsgEx->Msg.u.join_confirm.password_challenge), &rc); // Copy the Domain Parameters ::CSAP_CopyDataToGCCMessage_DomainParams( pMsgEx->pToDelete, domain_parameters, &(pMsgEx->Msg.u.join_confirm.domain_parameters), &rc); // Copy the Conductor Privilege List ::CSAP_CopyDataToGCCMessage_PrivilegeList( conductor_privilege_list, &(pMsgEx->Msg.u.join_confirm.conductor_privilege_list), &rc); pMsgEx->pToDelete->conductor_privilege_list = pMsgEx->Msg.u.join_confirm.conductor_privilege_list; // Copy the Conducted-mode Conference Privilege List ::CSAP_CopyDataToGCCMessage_PrivilegeList( conduct_mode_privilege_list, &(pMsgEx->Msg.u.join_confirm.conducted_mode_privilege_list), &rc); pMsgEx->pToDelete->conducted_mode_privilege_list = pMsgEx->Msg.u.join_confirm.conducted_mode_privilege_list; // Copy the Non-Conducted-mode Conference Privilege List ::CSAP_CopyDataToGCCMessage_PrivilegeList( non_conduct_privilege_list, &(pMsgEx->Msg.u.join_confirm.non_conducted_privilege_list), &rc); pMsgEx->pToDelete->non_conducted_privilege_list = pMsgEx->Msg.u.join_confirm.non_conducted_privilege_list; // Copy the Conference Descriptor ::CSAP_CopyDataToGCCMessage_IDvsDesc( FALSE, // conference descriptor pMsgEx->pToDelete, pwszConfDescription, &(pMsgEx->Msg.u.join_confirm.conference_descriptor), &rc); if (GCC_NO_ERROR != rc) { goto MyExit; } // Copy the User Data if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(pMsgEx->Msg.u.join_confirm.number_of_user_data_members), &(pMsgEx->Msg.u.join_confirm.user_data_list), &(pMsgEx->pToDelete->user_data_list_memory)); if (GCC_NO_ERROR != rc) { goto MyExit; } } else { // pMsgEx->Msg.u.join_confirm.number_of_user_data_members = 0; // pMsgEx->Msg.u.join_confirm.user_data_list = NULL; } // Queue up the message for delivery to the Node Controller. pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.join_confirm.conference_id = conference_id; pMsgEx->Msg.u.join_confirm.clear_password_required = password_in_the_clear; pMsgEx->Msg.u.join_confirm.conference_is_locked = conference_is_locked; pMsgEx->Msg.u.join_confirm.conference_is_listed = conference_is_listed; pMsgEx->Msg.u.join_confirm.conference_is_conductible = conference_is_conductible; pMsgEx->Msg.u.join_confirm.termination_method = termination_method; pMsgEx->Msg.u.join_confirm.result = result; pMsgEx->Msg.u.join_confirm.connection_handle = connection_handle; PostConfirmCtrlSapMsg(pMsgEx); MyExit: if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfJoinConfirm, rc); return rc; } /* * GCCError ConfInviteConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conference invite confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfInviteConfirm ( GCCConfID conference_id, CUserDataListContainer *user_data_list, GCCResult result, ConnectionHandle connection_handle ) { GCCError rc = GCC_NO_ERROR; DebugEntry(CControlSAP::ConfInviteConfirm); #ifdef GCCNC_DIRECT_CONFIRM GCCCtrlSapMsg Msg; Msg.message_type = GCC_INVITE_CONFIRM; // Copy the User Data LPBYTE pUserDataMemory = NULL; if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(Msg.u.invite_confirm.number_of_user_data_members), &(Msg.u.invite_confirm.user_data_list), &pUserDataMemory); } else { Msg.u.invite_confirm.number_of_user_data_members = 0; Msg.u.invite_confirm.user_data_list = NULL; } if (GCC_NO_ERROR == rc) { Msg.nConfID = conference_id; Msg.u.invite_confirm.conference_id = conference_id; Msg.u.invite_confirm.result = result; Msg.u.invite_confirm.connection_handle = connection_handle; SendCtrlSapMsg(&Msg); // clean up delete pUserDataMemory; } else { HandleResourceFailure(rc); } #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_INVITE_CONFIRM, TRUE))) { ::ZeroMemory(&(pMsgEx->Msg.u.invite_confirm), sizeof(pMsgEx->Msg.u.invite_confirm)); } else { ERROR_OUT(("CControlSAP::ConfInviteConfirm: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } // Copy the User Data if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(pMsgEx->Msg.u.invite_confirm.number_of_user_data_members), &(pMsgEx->Msg.u.invite_confirm.user_data_list), &(pMsgEx->pToDelete->user_data_list_memory)); if (GCC_NO_ERROR != rc) { goto MyExit; } } else { // pMsgEx->Msg.u.invite_confirm.number_of_user_data_members = 0; // pMsgEx->Msg.u.invite_confirm.user_data_list = NULL; } pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.invite_confirm.conference_id = conference_id; pMsgEx->Msg.u.invite_confirm.result = result; pMsgEx->Msg.u.invite_confirm.connection_handle = connection_handle; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); MyExit: if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfInviteConfirm, rc); return rc; } /* * GCCError ConfTerminateIndication () * * Public Function Description * This function is called by the GCC Controller when it need to send a * conference terminate indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP:: ConfTerminateIndication ( GCCConfID conference_id, UserID requesting_node_id, GCCReason reason ) { GCCError rc; DebugEntry(CControlSAP::ConfTerminateIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_TERMINATE_INDICATION; Msg.nConfID = conference_id; Msg.u.terminate_indication.conference_id = conference_id; Msg.u.terminate_indication.requesting_node_id = requesting_node_id; Msg.u.terminate_indication.reason = reason; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_TERMINATE_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.terminate_indication), sizeof(pMsgEx->Msg.u.terminate_indication)); pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.terminate_indication.conference_id = conference_id; pMsgEx->Msg.u.terminate_indication.requesting_node_id = requesting_node_id; pMsgEx->Msg.u.terminate_indication.reason = reason; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfTerminateIndication, rc); return rc; } /* * ConfLockReport() * * Public Function Descrpition * This function is called by the CConf when it need to send a * conference lock report to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfLockReport ( GCCConfID conference_id, BOOL conference_is_locked ) { GCCError rc; GCCCtrlSapMsgEx *pMsgEx; DebugEntry(CControlSAP::ConfLockReport); // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_LOCK_REPORT_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.lock_report_indication), sizeof(pMsgEx->Msg.u.lock_report_indication)); pMsgEx->Msg.u.lock_report_indication.conference_id = conference_id; pMsgEx->Msg.u.lock_report_indication.conference_is_locked = conference_is_locked; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } DebugExitINT(CControlSAP::ConfLockReport, rc); return rc; } #endif // JASPER /* * ConfLockIndication() * * Public Function Descrpition: * This function is called by the CConf when it need to send a * conference lock indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfLockIndication ( GCCConfID conference_id, UserID source_node_id ) { GCCError rc; DebugEntry(CControlSAP::ConfLockIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_LOCK_INDICATION; Msg.u.lock_indication.conference_id = conference_id; Msg.u.lock_indication.requesting_node_id = source_node_id; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_LOCK_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.lock_indication), sizeof(pMsgEx->Msg.u.lock_indication)); pMsgEx->Msg.u.lock_indication.conference_id = conference_id; pMsgEx->Msg.u.lock_indication.requesting_node_id = source_node_id; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfLockIndication, rc); return rc; } /* * ConfLockConfirm() * * Public Function Descrpition * This function is called by the CConf when it need to send a * conference lock confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfLockConfirm ( GCCResult result, GCCConfID conference_id ) { GCCError rc; DebugEntry(CControlSAP::ConfLockConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_LOCK_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_LOCK_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.lock_confirm), sizeof(pMsgEx->Msg.u.lock_confirm)); pMsgEx->Msg.u.lock_confirm.conference_id = conference_id; pMsgEx->Msg.u.lock_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfLockConfirm, rc); return rc; } #endif // JASPER /* * ConfUnlockIndication() * * Public Function Description * This function is called by the CConf when it need to send a * conference unlock indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfUnlockIndication ( GCCConfID conference_id, UserID source_node_id ) { GCCError rc; DebugEntry(CControlSAP::ConfUnlockIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_UNLOCK_INDICATION; Msg.u.unlock_indication.conference_id = conference_id; Msg.u.unlock_indication.requesting_node_id = source_node_id; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_UNLOCK_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.unlock_indication), sizeof(pMsgEx->Msg.u.unlock_indication)); pMsgEx->Msg.u.unlock_indication.conference_id = conference_id; pMsgEx->Msg.u.unlock_indication.requesting_node_id = source_node_id; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfUnlockIndication, rc); return rc; } #endif // JASPER /* * ConfUnlockConfirm() * * Public Function Descrpition * This function is called by the CConf when it need to send a * conference unlock confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfUnlockConfirm ( GCCResult result, GCCConfID conference_id ) { GCCError rc; DebugEntry(CControlSAP::ConfUnlockConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_UNLOCK_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_UNLOCK_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.unlock_confirm), sizeof(pMsgEx->Msg.u.unlock_confirm)); pMsgEx->Msg.u.unlock_confirm.conference_id = conference_id; pMsgEx->Msg.u.unlock_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfUnlockConfirm, rc); return rc; } #endif // JASPER /* * ConfPermissionToAnnounce () * * Public Function Description * This function is called by the CConf when it need to send a * conference permission to announce to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfPermissionToAnnounce ( GCCConfID conference_id, UserID node_id ) { GCCError rc; GCCCtrlSapMsgEx *pMsgEx; DebugEntry(CControlSAP::ConfPermissionToAnnounce); // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_PERMIT_TO_ANNOUNCE_PRESENCE))) { // ::ZeroMemory(&(pMsgEx->Msg.u.permit_to_announce_presence), sizeof(pMsgEx->Msg.u.permit_to_announce_presence)); pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.permit_to_announce_presence.conference_id= conference_id; pMsgEx->Msg.u.permit_to_announce_presence.node_id = node_id; // // LONCHANC: We should treat it as a confirm, even though it is // an indication. When this node is a top provider, we may send this // message in the middle of doing something. In essence, it behaves // like a confirm. // // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } DebugExitINT(CControlSAP::ConfPermissionToAnnounce, rc); return rc; } /* * ConfAnnouncePresenceConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conference announce presence confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfAnnouncePresenceConfirm ( GCCConfID conference_id, GCCResult result ) { GCCError rc; DebugEntry(CControlSAP::ConfAnnouncePresenceConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_ANNOUNCE_PRESENCE_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_ANNOUNCE_PRESENCE_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.announce_presence_confirm), sizeof(pMsgEx->Msg.u.announce_presence_confirm)); pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.announce_presence_confirm.conference_id = conference_id; pMsgEx->Msg.u.announce_presence_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfAnnouncePresenceConfirm, rc); return rc; } /* * ConfTerminateConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conference terminate confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfTerminateConfirm ( GCCConfID conference_id, GCCResult result ) { GCCError rc; DebugEntry(CControlSAP::ConfTerminateConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_TERMINATE_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_TERMINATE_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.terminate_confirm), sizeof(pMsgEx->Msg.u.terminate_confirm)); pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.terminate_confirm.conference_id = conference_id; pMsgEx->Msg.u.terminate_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfTerminateConfirm, rc); return rc; } /* * ConfEjectUserIndication () * * Public Function Description * This function is called by the CConf when it need to send a * conference eject user indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfEjectUserIndication ( GCCConfID conference_id, GCCReason reason, UserID gcc_node_id ) { GCCError rc; DebugEntry(CControlSAP::ConfEjectUserIndication); #ifdef GCCNC_DIRECT_INDICATION // // WPARAM: reason, ejected node ID. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_EJECT_USER_INDICATION, reason, gcc_node_id, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_EJECT_USER_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.eject_user_indication), sizeof(pMsgEx->Msg.u.eject_user_indication)); pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.eject_user_indication.conference_id = conference_id; pMsgEx->Msg.u.eject_user_indication.ejected_node_id = gcc_node_id; pMsgEx->Msg.u.eject_user_indication.reason = reason; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfEjectUserIndication, rc); return rc; } /* * ConfEjectUserConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conference eject user confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfEjectUserConfirm ( GCCConfID conference_id, UserID ejected_node_id, GCCResult result ) { GCCError rc; DebugEntry(CControlSAP::ConfEjectUserConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: LOWORD=result. HIWORD=nid. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_EJECT_USER_CONFIRM, result, ejected_node_id, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_EJECT_USER_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.eject_user_confirm), sizeof(pMsgEx->Msg.u.eject_user_confirm)); pMsgEx->Msg.u.eject_user_confirm.conference_id = conference_id; pMsgEx->Msg.u.eject_user_confirm.ejected_node_id = ejected_node_id; pMsgEx->Msg.u.eject_user_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfEjectUserConfirm, rc); return rc; } #endif // JASPER /* * ConductorAssignConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conductor assign confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConductorAssignConfirm ( GCCResult result, GCCConfID conference_id ) { GCCError rc; DebugEntry(CControlSAP::ConductorAssignConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_CONDUCT_ASSIGN_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_ASSIGN_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_assign_confirm), sizeof(pMsgEx->Msg.u.conduct_assign_confirm)); pMsgEx->Msg.u.conduct_assign_confirm.conference_id = conference_id; pMsgEx->Msg.u.conduct_assign_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConductorAssignConfirm, rc); return rc; } #endif // JASPER /* * ConductorReleaseConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conductor release confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConductorReleaseConfirm ( GCCResult result, GCCConfID conference_id ) { GCCError rc; DebugEntry(CControlSAP::ConductorReleaseConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_CONDUCT_RELEASE_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_RELEASE_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_release_confirm), sizeof(pMsgEx->Msg.u.conduct_release_confirm)); pMsgEx->Msg.u.conduct_release_confirm.conference_id = conference_id; pMsgEx->Msg.u.conduct_release_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConductorReleaseConfirm, rc); return rc; } #endif // JASPER /* * ConductorPleaseIndication () * * Public Function Description * This function is called by the CConf when it need to send a * conductor please indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConductorPleaseIndication ( GCCConfID conference_id, UserID requester_node_id ) { GCCError rc; DebugEntry(CControlSAP::ConductorPleaseIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_CONDUCT_PLEASE_INDICATION; Msg.u.conduct_please_indication.conference_id = conference_id; Msg.u.conduct_please_indication.requester_node_id = requester_node_id; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_PLEASE_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_please_indication), sizeof(pMsgEx->Msg.u.conduct_please_indication)); pMsgEx->Msg.u.conduct_please_indication.conference_id = conference_id; pMsgEx->Msg.u.conduct_please_indication.requester_node_id = requester_node_id; // Queue up the message for delivery to the Node Controller. PostCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConductorPleaseIndication, rc); return rc; } #endif // JASPER /* * ConductorPleaseConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conductor please confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConductorPleaseConfirm ( GCCResult result, GCCConfID conference_id ) { GCCError rc; DebugEntry(CControlSAP::ConductorPleaseConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_CONDUCT_PLEASE_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_PLEASE_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_please_confirm), sizeof(pMsgEx->Msg.u.conduct_please_confirm)); pMsgEx->Msg.u.conduct_please_confirm.conference_id = conference_id; pMsgEx->Msg.u.conduct_please_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConductorPleaseConfirm, rc); return rc; } #endif // JASPER /* * ConductorGiveIndication () * * Public Function Description * This function is called by the CConf when it need to send a * conductor give indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConductorGiveIndication ( GCCConfID conference_id ) { GCCError rc; DebugEntry(CControlSAP::ConductorGiveIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_CONDUCT_GIVE_INDICATION; Msg.u.conduct_give_indication.conference_id = conference_id; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_GIVE_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_give_indication), sizeof(pMsgEx->Msg.u.conduct_give_indication)); pMsgEx->Msg.u.conduct_give_indication.conference_id = conference_id; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConductorGiveIndication, rc); return rc; } /* * ConductorGiveConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conductor give confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConductorGiveConfirm ( GCCResult result, GCCConfID conference_id, UserID recipient_node ) { GCCError rc; DebugEntry(CControlSAP::ConductorGiveConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: LOWORD=result. HIWORD=nid. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_CONDUCT_GIVE_CONFIRM, result, recipient_node, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_GIVE_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_give_confirm), sizeof(pMsgEx->Msg.u.conduct_give_confirm)); pMsgEx->Msg.u.conduct_give_confirm.conference_id = conference_id; pMsgEx->Msg.u.conduct_give_confirm.result = result; pMsgEx->Msg.u.conduct_give_confirm.recipient_node_id = recipient_node; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConductorGiveConfirm, rc); return rc; } #endif // JASPER /* * ConductorPermitAskIndication () * * Public Function Description * This function is called by the CConf when it need to send a * conductor permit ask indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConductorPermitAskIndication ( GCCConfID conference_id, BOOL grant_flag, UserID requester_id ) { GCCError rc; DebugEntry(CControlSAP::ConductorPermitAskIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_CONDUCT_ASK_INDICATION; Msg.u.conduct_permit_ask_indication.conference_id = conference_id; Msg.u.conduct_permit_ask_indication.permission_is_granted = grant_flag; Msg.u.conduct_permit_ask_indication.requester_node_id = requester_id; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_ASK_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_permit_ask_indication), sizeof(pMsgEx->Msg.u.conduct_permit_ask_indication)); pMsgEx->Msg.u.conduct_permit_ask_indication.conference_id = conference_id; pMsgEx->Msg.u.conduct_permit_ask_indication.permission_is_granted = grant_flag; pMsgEx->Msg.u.conduct_permit_ask_indication.requester_node_id = requester_id; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConductorPermitAskIndication, rc); return rc; } #endif // JASPER /* * ConductorPermitAskConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conductor permit ask confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConductorPermitAskConfirm ( GCCResult result, BOOL grant_permission, GCCConfID conference_id ) { GCCError rc; GCCCtrlSapMsgEx *pMsgEx; DebugEntry(CControlSAP::ConductorPermitAskConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: LOWORD=result. HIWORD=permission. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_CONDUCT_ASK_CONFIRM, result, grant_permission, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_ASK_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_permit_ask_confirm), sizeof(pMsgEx->Msg.u.conduct_permit_ask_confirm)); pMsgEx->Msg.u.conduct_permit_ask_confirm.conference_id = conference_id; pMsgEx->Msg.u.conduct_permit_ask_confirm.result = result; pMsgEx->Msg.u.conduct_permit_ask_confirm.permission_is_granted = grant_permission; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConductorPermitAskConfirm, rc); return rc; } #endif // JASPER /* * ConductorPermitGrantConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conductor permit grant confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConductorPermitGrantConfirm ( GCCResult result, GCCConfID conference_id ) { GCCError rc; DebugEntry(CControlSAP::ConductorPermitGrantConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_CONDUCT_GRANT_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_GRANT_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_permit_grant_confirm), sizeof(pMsgEx->Msg.u.conduct_permit_grant_confirm)); pMsgEx->Msg.u.conduct_permit_grant_confirm.conference_id = conference_id; pMsgEx->Msg.u.conduct_permit_grant_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConductorPermitGrantConfirm, rc); return rc; } #endif // JASPER /* * ConfTimeRemainingIndication () * * Public Function Description * This function is called by the CConf when it need to send a * conference time remaining indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfTimeRemainingIndication ( GCCConfID conference_id, UserID source_node_id, UserID node_id, UINT time_remaining ) { GCCError rc; DebugEntry(CControlSAP::ConfTimeRemainingIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_TIME_REMAINING_INDICATION; Msg.u.time_remaining_indication.conference_id = conference_id; Msg.u.time_remaining_indication.source_node_id= source_node_id; Msg.u.time_remaining_indication.node_id = node_id; Msg.u.time_remaining_indication.time_remaining= time_remaining; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else //GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_TIME_REMAINING_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.time_remaining_indication), sizeof(pMsgEx->Msg.u.time_remaining_indication)); pMsgEx->Msg.u.time_remaining_indication.conference_id = conference_id; pMsgEx->Msg.u.time_remaining_indication.source_node_id= source_node_id; pMsgEx->Msg.u.time_remaining_indication.node_id = node_id; pMsgEx->Msg.u.time_remaining_indication.time_remaining= time_remaining; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfTimeRemainingIndication, rc); return rc; } #endif // JASPER /* * ConfTimeRemainingConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conference time remaining confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfTimeRemainingConfirm ( GCCConfID conference_id, GCCResult result ) { GCCError rc; DebugEntry(CControlSAP::ConfTimeRemainingConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_TIME_REMAINING_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_TIME_REMAINING_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.time_remaining_confirm), sizeof(pMsgEx->Msg.u.time_remaining_confirm)); pMsgEx->Msg.u.time_remaining_confirm.conference_id = conference_id; pMsgEx->Msg.u.time_remaining_confirm.result= result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfTimeRemainingConfirm, rc); return rc; } #endif // JASPER /* * ConfTimeInquireIndication() * * Public Function Description * This function is called by the CConf when it need to send a * conference time inquire indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfTimeInquireIndication ( GCCConfID conference_id, BOOL time_is_conference_wide, UserID requesting_node_id ) { GCCError rc; DebugEntry(CControlSAP::ConfTimeInquireIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_TIME_INQUIRE_INDICATION; Msg.u.time_inquire_indication.conference_id = conference_id; Msg.u.time_inquire_indication.time_is_conference_wide = time_is_conference_wide; Msg.u.time_inquire_indication.requesting_node_id = requesting_node_id; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_TIME_INQUIRE_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.time_inquire_indication), sizeof(pMsgEx->Msg.u.time_inquire_indication)); pMsgEx->Msg.u.time_inquire_indication.conference_id = conference_id; pMsgEx->Msg.u.time_inquire_indication.time_is_conference_wide = time_is_conference_wide; pMsgEx->Msg.u.time_inquire_indication.requesting_node_id = requesting_node_id; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfTimeInquireIndication, rc); return rc; } /* * ConfTimeInquireConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conference time inquire confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfTimeInquireConfirm ( GCCConfID conference_id, GCCResult result ) { GCCError rc; DebugEntry(CControlSAP::ConfTimeInquireConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_TIME_INQUIRE_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_TIME_INQUIRE_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.time_inquire_confirm), sizeof(pMsgEx->Msg.u.time_inquire_confirm)); pMsgEx->Msg.u.time_inquire_confirm.conference_id = conference_id; pMsgEx->Msg.u.time_inquire_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfTimeInquireConfirm, rc); return rc; } #endif // JASPER /* * ConfExtendIndication () * * Public Function Description * This function is called by the CConf when it need to send a * conference extend indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfExtendIndication ( GCCConfID conference_id, UINT extension_time, BOOL time_is_conference_wide, UserID requesting_node_id ) { GCCError rc; DebugEntry(CControlSAP::ConfExtendIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_CONFERENCE_EXTEND_INDICATION; Msg.u.conference_extend_indication.conference_id = conference_id; Msg.u.conference_extend_indication.extension_time = extension_time; Msg.u.conference_extend_indication.time_is_conference_wide = time_is_conference_wide; Msg.u.conference_extend_indication.requesting_node_id = requesting_node_id; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONFERENCE_EXTEND_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conference_extend_indication), sizeof(pMsgEx->Msg.u.conference_extend_indication)); pMsgEx->Msg.u.conference_extend_indication.conference_id = conference_id; pMsgEx->Msg.u.conference_extend_indication.extension_time = extension_time; pMsgEx->Msg.u.conference_extend_indication.time_is_conference_wide = time_is_conference_wide; pMsgEx->Msg.u.conference_extend_indication.requesting_node_id = requesting_node_id; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfExtendIndication, rc); return rc; } #endif // JASPER /* * ConfExtendConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conference extend confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfExtendConfirm ( GCCConfID conference_id, UINT extension_time, GCCResult result ) { GCCError rc; GCCCtrlSapMsgEx *pMsgEx; DebugEntry(CControlSAP::ConfExtendConfirm); // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONFERENCE_EXTEND_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conference_extend_confirm), sizeof(pMsgEx->Msg.u.conference_extend_confirm)); pMsgEx->Msg.u.conference_extend_confirm.conference_id = conference_id; pMsgEx->Msg.u.conference_extend_confirm.extension_time = extension_time; pMsgEx->Msg.u.conference_extend_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } DebugExitINT(CControlSAP::ConfExtendConfirm, rc); return rc; } #endif // JASPER /* * ConfAssistanceIndication () * * Public Function Description * This function is called by the CConf when it need to send a * conference assistance indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfAssistanceIndication ( GCCConfID conference_id, CUserDataListContainer *user_data_list, UserID source_node_id ) { GCCError rc; DebugEntry(CControlSAP::ConfAssistanceIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_ASSISTANCE_INDICATION; rc = GCC_NO_ERROR; // Copy the User Data if it exists. LPBYTE pUserDataMemory = NULL; if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(Msg.u.conference_assist_indication.number_of_user_data_members), &(Msg.u.conference_assist_indication.user_data_list), &pUserDataMemory); ASSERT(GCC_NO_ERROR == rc); } else { Msg.u.conference_assist_indication.number_of_user_data_members = 0; Msg.u.conference_assist_indication.user_data_list = NULL; } if (GCC_NO_ERROR == rc) { Msg.u.conference_assist_indication.conference_id = conference_id; Msg.u.conference_assist_indication.source_node_id = source_node_id; SendCtrlSapMsg(&Msg); delete pUserDataMemory; } #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_ASSISTANCE_INDICATION))) { ::ZeroMemory(&(pMsgEx->Msg.u.conference_assist_indication), sizeof(pMsgEx->Msg.u.conference_assist_indication)); rc = GCC_NO_ERROR; // Copy the User Data if it exists. if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(pMsgEx->Msg.u.conference_assist_indication.number_of_user_data_members), &(pMsgEx->Msg.u.conference_assist_indication.user_data_list), &(pMsgEx->pToDelete->user_data_list_memory)); ASSERT(GCC_NO_ERROR == rc); } else { // pMsgEx->Msg.u.conference_assist_indication.number_of_user_data_members = 0; // pMsgEx->Msg.u.conference_assist_indication.user_data_list = NULL; } if (GCC_NO_ERROR == rc) { pMsgEx->Msg.u.conference_assist_indication.conference_id = conference_id; pMsgEx->Msg.u.conference_assist_indication.source_node_id = source_node_id; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); } } else { ERROR_OUT(("CControlSAP::ConfAssistanceIndication: can't create CreateCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } /* ** Clean up after any resource allocation error which may have occurred. */ if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfAssistanceIndication, rc); return rc; } #endif // JASPER /* * ConfAssistanceConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conference assistance confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfAssistanceConfirm ( GCCConfID conference_id, GCCResult result ) { GCCError rc; DebugEntry(CControlSAP::ConfAssistanceConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_ASSISTANCE_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_ASSISTANCE_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conference_assist_confirm), sizeof(pMsgEx->Msg.u.conference_assist_confirm)); pMsgEx->Msg.u.conference_assist_confirm.conference_id = conference_id; pMsgEx->Msg.u.conference_assist_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfAssistanceConfirm, rc); return rc; } #endif // JASPER /* * TextMessageIndication () * * Public Function Description * This function is called by the CConf when it need to send a * text message indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::TextMessageIndication ( GCCConfID conference_id, LPWSTR pwszTextMsg, UserID source_node_id ) { GCCError rc; DebugEntry(CControlSAP::TextMessageIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_TEXT_MESSAGE_INDICATION; Msg.u.text_message_indication.text_message = pwszTextMsg; Msg.u.text_message_indication.conference_id = conference_id; Msg.u.text_message_indication.source_node_id = source_node_id; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_TEXT_MESSAGE_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.text_message_indication), sizeof(pMsgEx->Msg.u.text_message_indication)); if (NULL != (pMsgEx->Msg.u.text_message_indication.text_message = ::My_strdupW(pwszTextMsg))) { pMsgEx->Msg.u.text_message_indication.conference_id = conference_id; pMsgEx->Msg.u.text_message_indication.source_node_id = source_node_id; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::TextMessageIndication, rc); return rc; } #endif // JASPER /* * TextMessageConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * text message confirm to the node controller. It adds the message * to a queue of messages to be sent to the node controller in the * next heartbeat. */ #ifdef JASPER GCCError CControlSAP::TextMessageConfirm ( GCCConfID conference_id, GCCResult result ) { GCCError rc; DebugEntry(CControlSAP::TextMessageConfirm); #ifdef GCCNC_DIRECT_CONFIRM // // WPARAM: result. // LPARAM: conf ID // PostAsynDirectConfirmMsg(GCC_TEXT_MESSAGE_CONFIRM, result, conference_id); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_TEXT_MESSAGE_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.text_message_confirm), sizeof(pMsgEx->Msg.u.text_message_confirm)); pMsgEx->Msg.u.text_message_confirm.conference_id = conference_id; pMsgEx->Msg.u.text_message_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::TextMessageConfirm, rc); return rc; } #endif // JASPER /* * ConfTransferIndication () * * Public Function Description * This function is called by the CConf when it need to send a * conference transfer indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfTransferIndication ( GCCConfID conference_id, PGCCConferenceName destination_conference_name, GCCNumericString destination_conference_modifier, CNetAddrListContainer *destination_address_list, CPassword *password ) { GCCError rc = GCC_NO_ERROR; DebugEntry(CControlSAP::ConfTransferIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_TRANSFER_INDICATION; // // Copy the information that needs to be sent to the node // controller into local memory that can be deleted once the // information to be sent to the application is flushed. Note that // if an error occurs in one call to "CopyDataToGCCMessage" then no // action is taken on subsequent calls to that routine. // // Copy the conference name ::CSAP_CopyDataToGCCMessage_ConfName( destination_conference_name, &(Msg.u.transfer_indication.destination_conference_name)); // Copy the conference name modifier ::CSAP_CopyDataToGCCMessage_Modifier( destination_conference_modifier, &(Msg.u.transfer_indication.destination_conference_modifier)); // Copy the Password ::CSAP_CopyDataToGCCMessage_Password( password, &(Msg.u.transfer_indication.password)); LPBYTE pDstAddrListData = NULL; if (destination_address_list != NULL) { // // First determine the size of the block required to hold all // of the network address list data. // UINT block_size = destination_address_list->LockNetworkAddressList(); DBG_SAVE_FILE_LINE if (NULL != (pDstAddrListData = new BYTE[block_size])) { destination_address_list->GetNetworkAddressListAPI( &(Msg.u.transfer_indication.number_of_destination_addresses), &(Msg.u.transfer_indication.destination_address_list), pDstAddrListData); } else { ERROR_OUT(("CControlSAP::ConfTransferIndication: can't create net addr memory, size=%u", (UINT) block_size)); rc = GCC_ALLOCATION_FAILURE; } // Unlock the network address list data. destination_address_list->UnLockNetworkAddressList(); } else { Msg.u.transfer_indication.number_of_destination_addresses = 0; Msg.u.transfer_indication.destination_address_list = NULL; } if (rc == GCC_NO_ERROR) { Msg.u.transfer_indication.conference_id = conference_id; SendCtrlSapMsg(&Msg); delete pDstAddrListData; } #else GCCCtrlSapMsgEx *pMsgEx; UINT block_size; /* ** Allocate the GCC callback message and fill it in with the ** appropriate values. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_TRANSFER_INDICATION, TRUE))) { ::ZeroMemory(&(pMsgEx->Msg.u.transfer_indication), sizeof(pMsgEx->Msg.u.transfer_indication)); /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // Copy the conference name ::CSAP_CopyDataToGCCMessage_ConfName( pMsgEx->pToDelete, destination_conference_name, &(pMsgEx->Msg.u.transfer_indication.destination_conference_name), &rc); // Copy the conference name modifier ::CSAP_CopyDataToGCCMessage_Modifier( FALSE, // conference modifier pMsgEx->pToDelete, destination_conference_modifier, &(pMsgEx->Msg.u.transfer_indication.destination_conference_modifier), &rc); // Copy the Password ::CSAP_CopyDataToGCCMessage_Password( FALSE, // non-convener password pMsgEx->pToDelete, password, &(pMsgEx->Msg.u.transfer_indication.password), &rc); if ((rc == GCC_NO_ERROR) && (destination_address_list != NULL)) { /* ** First determine the size of the block required to hold all ** of the network address list data. */ block_size = destination_address_list->LockNetworkAddressList(); DBG_SAVE_FILE_LINE if (NULL != (pMsgEx->pBuf = new BYTE[block_size])) { destination_address_list->GetNetworkAddressListAPI( &(pMsgEx->Msg.u.transfer_indication.number_of_destination_addresses), &(pMsgEx->Msg.u.transfer_indication.destination_address_list), pMsgEx->pBuf); } else { ERROR_OUT(("CControlSAP::ConfTransferIndication: can't create net addr memory, size=%u", (UINT) block_size)); rc = GCC_ALLOCATION_FAILURE; } // Unlock the network address list data. destination_address_list->UnLockNetworkAddressList(); } else { // pMsgEx->Msg.u.transfer_indication.number_of_destination_addresses = 0; // pMsgEx->Msg.u.transfer_indication.destination_address_list = NULL; } if (rc == GCC_NO_ERROR) { pMsgEx->Msg.u.transfer_indication.conference_id = conference_id; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); } } else { ERROR_OUT(("CControlSAP::ConfTransferIndication: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfTransferIndication, rc); return rc; } #endif // JASPER /* * ConfTransferConfirm () * * Public Function Description * This function is called by the CConf when it need to send a * conference transfer confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ #ifdef JASPER GCCError CControlSAP::ConfTransferConfirm ( GCCConfID conference_id, PGCCConferenceName destination_conference_name, GCCNumericString destination_conference_modifier, UINT number_of_destination_nodes, PUserID destination_node_list, GCCResult result ) { GCCError rc = GCC_NO_ERROR; GCCCtrlSapMsgEx *pMsgEx; UINT i; DebugEntry(CControlSAP::ConfTransferConfirm); /* ** Allocate the GCC callback message and fill it in with the ** appropriate values. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_TRANSFER_CONFIRM, TRUE))) { ::ZeroMemory(&(pMsgEx->Msg.u.transfer_confirm), sizeof(pMsgEx->Msg.u.transfer_confirm)); /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // Copy the conference name ::CSAP_CopyDataToGCCMessage_ConfName( pMsgEx->pToDelete, destination_conference_name, &(pMsgEx->Msg.u.transfer_confirm.destination_conference_name), &rc); // Copy the conference name modifier ::CSAP_CopyDataToGCCMessage_Modifier( FALSE, // conference modifier pMsgEx->pToDelete, destination_conference_modifier, &(pMsgEx->Msg.u.transfer_confirm.destination_conference_modifier), &rc); if ((rc == GCC_NO_ERROR) && (number_of_destination_nodes != 0)) { // Allocate memory to hold the list of nodes. DBG_SAVE_FILE_LINE if (NULL != (pMsgEx->pBuf = new BYTE[number_of_destination_nodes * sizeof (UserID)])) { /* * Retrieve the actual pointer to memory from the Memory * object. */ pMsgEx->Msg.u.transfer_confirm.destination_node_list = (UserID *) pMsgEx->pBuf; for (i = 0; i < number_of_destination_nodes; i++) { pMsgEx->Msg.u.transfer_confirm.destination_node_list[i] = destination_node_list[i]; } } else { ERROR_OUT(("CControlSAP::ConfTransferConfirm: Error allocating memory")); rc = GCC_ALLOCATION_FAILURE; } } if (rc == GCC_NO_ERROR) { pMsgEx->Msg.u.transfer_confirm.number_of_destination_nodes = number_of_destination_nodes; pMsgEx->Msg.u.transfer_confirm.conference_id = conference_id; pMsgEx->Msg.u.transfer_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); } } else { ERROR_OUT(("CControlSAP::ConfTransferConfirm: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(); } DebugExitINT(CControlSAP::ConfTransferConfirm, rc); return rc; } #endif // JASPER /* * ConfAddIndication () * * Public Function Description * This function is called by the CConf when it need to send a * conference add indication to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfAddIndication ( GCCConfID conference_id, GCCResponseTag add_response_tag, CNetAddrListContainer *network_address_list, CUserDataListContainer *user_data_list, UserID requesting_node ) { GCCError rc = GCC_NO_ERROR; DebugEntry(CControlSAP::ConfAddIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_ADD_INDICATION; // // First determine the size of the block required to hold all // of the network address list data. // UINT block_size = network_address_list->LockNetworkAddressList(); // // Add the size of the user data block if any user data exists // if (user_data_list != NULL) { block_size += user_data_list->LockUserDataList(); } // // Allocate memory to hold the user data and network addresses. // LPBYTE pData; DBG_SAVE_FILE_LINE if (NULL != (pData = new BYTE[block_size])) { // // Retrieve the network address list data from the container // and unlock the container data. // pData += network_address_list->GetNetworkAddressListAPI( &(Msg.u.add_indication.number_of_network_addresses), &(Msg.u.add_indication.network_address_list), pData); network_address_list->UnLockNetworkAddressList(); // // Retrieve the user data from the container if it exists // and unlock the container data. // if (user_data_list != NULL) { user_data_list->GetUserDataList( &(Msg.u.add_indication.number_of_user_data_members), &(Msg.u.add_indication.user_data_list), pData); user_data_list->UnLockUserDataList(); } else { Msg.u.add_indication.number_of_user_data_members = 0; Msg.u.add_indication.user_data_list = NULL; } Msg.u.add_indication.conference_id = conference_id; Msg.u.add_indication.requesting_node_id = requesting_node; Msg.u.add_indication.add_response_tag = add_response_tag; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; delete pData; } else { ERROR_OUT(("CControlSAP::ConfAddIndication: can't allocate buffer, size=%u", (UINT) block_size)); rc = GCC_ALLOCATION_FAILURE; } #else GCCCtrlSapMsgEx *pMsgEx; UINT block_size; LPBYTE memory_ptr; /* ** Allocate the GCC callback message and fill it in with the ** appropriate values. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_ADD_INDICATION))) { ::ZeroMemory(&(pMsgEx->Msg.u.add_indication), sizeof(pMsgEx->Msg.u.add_indication)); /* ** First determine the size of the block required to hold all ** of the network address list data. */ block_size = network_address_list->LockNetworkAddressList(); /* ** Add the size of the user data block if any user data exists */ if (user_data_list != NULL) { block_size += user_data_list->LockUserDataList(); } /* ** Allocate memory to hold the user data and network addresses. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx->pBuf = new BYTE[block_size])) { memory_ptr = pMsgEx->pBuf; /* * Retrieve the network address list data from the container * and unlock the container data. */ memory_ptr += network_address_list->GetNetworkAddressListAPI( &(pMsgEx->Msg.u.add_indication.number_of_network_addresses), &(pMsgEx->Msg.u.add_indication.network_address_list), memory_ptr); network_address_list->UnLockNetworkAddressList(); /* * Retrieve the user data from the container if it exists * and unlock the container data. */ if (user_data_list != NULL) { user_data_list->GetUserDataList( &(pMsgEx->Msg.u.add_indication.number_of_user_data_members), &(pMsgEx->Msg.u.add_indication.user_data_list), memory_ptr); user_data_list->UnLockUserDataList(); } else { // pMsgEx->Msg.u.add_indication.number_of_user_data_members = 0; // pMsgEx->Msg.u.add_indication.user_data_list = NULL; } pMsgEx->Msg.u.add_indication.conference_id = conference_id; pMsgEx->Msg.u.add_indication.requesting_node_id = requesting_node; pMsgEx->Msg.u.add_indication.add_response_tag = add_response_tag; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { ERROR_OUT(("CControlSAP::ConfAddIndication: can't allocate buffer, size=%u", (UINT) block_size)); rc = GCC_ALLOCATION_FAILURE; } } else { ERROR_OUT(("CControlSAP::ConfAddIndication: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfAddIndication, rc); return rc; } /* * ConfAddConfirm * * Public Function Description * This function is called by the CConf when it need to send a * conference add confirm to the node controller. It adds the * message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::ConfAddConfirm ( GCCConfID conference_id, CNetAddrListContainer *network_address_list, CUserDataListContainer *user_data_list, GCCResult result ) { GCCError rc = GCC_NO_ERROR; DebugEntry(CControlSAP::ConfAddConfirm); #ifdef GCCNC_DIRECT_CONFIRM GCCCtrlSapMsg Msg; Msg.message_type = GCC_ADD_CONFIRM; // // First determine the size of the block required to hold all // of the network address list data. // UINT cbDataSize = network_address_list->LockNetworkAddressList(); // // Add the size of the user data block if any user data exists // if (user_data_list != NULL) { cbDataSize += user_data_list->LockUserDataList(); } // // Allocate memory to hold the user data and network addresses. // DBG_SAVE_FILE_LINE LPBYTE pAllocated = new BYTE[cbDataSize]; LPBYTE pData; if (NULL != (pData = pAllocated)) { // // Retrieve the network address list data from the container // and unlock the container data. // pData += network_address_list->GetNetworkAddressListAPI( &(Msg.u.add_confirm.number_of_network_addresses), &(Msg.u.add_confirm.network_address_list), pData); network_address_list->UnLockNetworkAddressList(); // // Retrieve the user data from the container if it exists // and unlock the container data. // if (user_data_list != NULL) { user_data_list->GetUserDataList( &(Msg.u.add_confirm.number_of_user_data_members), &(Msg.u.add_confirm.user_data_list), pData); user_data_list->UnLockUserDataList(); } else { Msg.u.add_confirm.number_of_user_data_members = 0; Msg.u.add_confirm.user_data_list = NULL; } Msg.nConfID = conference_id; Msg.u.add_confirm.conference_id = conference_id; Msg.u.add_confirm.result = result; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; // clean up delete pAllocated; } else { ERROR_OUT(("CControlSAP::ConfAddConfirm: can't allocate buffer, size=%u", (UINT) cbDataSize)); rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(rc); } #else GCCCtrlSapMsgEx *pMsgEx; UINT block_size; LPBYTE memory_ptr; /* ** Allocate the GCC callback message and fill it in with the ** appropriate values. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_ADD_CONFIRM))) { ::ZeroMemory(&(pMsgEx->Msg.u.add_confirm), sizeof(pMsgEx->Msg.u.add_confirm)); /* ** First determine the size of the block required to hold all ** of the network address list data. */ block_size = network_address_list->LockNetworkAddressList(); /* ** Add the size of the user data block if any user data exists */ if (user_data_list != NULL) block_size += user_data_list->LockUserDataList(); /* ** Allocate memory to hold the user data and network addresses. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx->pBuf = (LPBYTE) new BYTE[block_size])) { memory_ptr = pMsgEx->pBuf; /* * Retrieve the network address list data from the container * and unlock the container data. */ memory_ptr += network_address_list->GetNetworkAddressListAPI( &(pMsgEx->Msg.u.add_confirm.number_of_network_addresses), &(pMsgEx->Msg.u.add_confirm.network_address_list), memory_ptr); network_address_list->UnLockNetworkAddressList(); /* * Retrieve the user data from the container if it exists * and unlock the container data. */ if (user_data_list != NULL) { user_data_list->GetUserDataList( &(pMsgEx->Msg.u.add_confirm.number_of_user_data_members), &(pMsgEx->Msg.u.add_confirm.user_data_list), memory_ptr); user_data_list->UnLockUserDataList(); } else { // pMsgEx->Msg.u.add_confirm.number_of_user_data_members = 0; // pMsgEx->Msg.u.add_confirm.user_data_list = NULL; } pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.add_confirm.conference_id = conference_id; pMsgEx->Msg.u.add_confirm.result = result; // Queue up the message for delivery to the Node Controller. PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { ERROR_OUT(("CControlSAP::ConfAddConfirm: can't allocate buffer, size=%u", (UINT) block_size)); rc = GCC_ALLOCATION_FAILURE; } } else { ERROR_OUT(("CControlSAP::ConfAddConfirm: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_CONFIRM DebugExitINT(CControlSAP::ConfAddConfirm, rc); return rc; } /* * SubInitializationCompleteIndication () * * Public Function Description * This function is called by the CConf when it need to send a * sub-initialization complete indication to the node controller. It adds * the message to a queue of messages to be sent to the node controller in * the next heartbeat. */ GCCError CControlSAP::SubInitializationCompleteIndication ( UserID user_id, ConnectionHandle connection_handle ) { GCCError rc; DebugEntry(CControlSAP::SubInitializationCompleteIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_SUB_INITIALIZED_INDICATION; Msg.u.conf_sub_initialized_indication.subordinate_node_id = user_id; Msg.u.conf_sub_initialized_indication.connection_handle =connection_handle; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; // // Allocate control sap message. // DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_SUB_INITIALIZED_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conf_sub_initialized_indication), sizeof(pMsgEx->Msg.u.conf_sub_initialized_indication)); pMsgEx->Msg.u.conf_sub_initialized_indication.subordinate_node_id = user_id; pMsgEx->Msg.u.conf_sub_initialized_indication.connection_handle =connection_handle; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::SubInitializationCompleteIndication, rc); return rc; } /* * Private member functions of the CControlSAP object. */ /* * BOOL CControlSAP::IsNumericNameValid( * GCCNumericString numeric_string) * * Public member function of CControlSAP. * * Function Description: * This routine is used to validate a numeric string by checking to make * sure that none of the constraints imposed by the ASN.1 specification * are violated. * * Formal Parameters: * numeric_string (i) The numeric string to validate. * * Return Value: * TRUE - The numeric string is valid. * FALSE - The numeric string violates an ASN.1 constraint. * * Side Effects: * None. * * Caveats: * None. */ BOOL CControlSAP::IsNumericNameValid ( GCCNumericString numeric_string ) { BOOL rc = TRUE; UINT numeric_string_length = 0; // // LONCHANC: We should change it such that the default is FALSE // because many cases except one can be FALSE. // if (numeric_string != NULL) { if (*numeric_string == 0) rc = FALSE; else { while (*numeric_string != 0) { /* ** Check to make sure the characters in the numeric string are ** within the allowable range. */ if ((*numeric_string < '0') || (*numeric_string > '9')) { rc = FALSE; break; } numeric_string++; numeric_string_length++; /* ** Check to make sure that the length of the string is within ** the allowable range. */ if (numeric_string_length > MAXIMUM_CONFERENCE_NAME_LENGTH) { rc = FALSE; break; } } } } else rc = FALSE; return rc; } /* * BOOL CControlSAP::IsTextNameValid (LPWSTR text_string) * * Public member function of CControlSAP. * * Function Description: * This routine is used to validate a text string by checking to make * sure that none of the constraints imposed by the ASN.1 specification * are violated. * * Formal Parameters: * text_string (i) The text string to validate. * * Return Value: * TRUE - The text string is valid. * FALSE - The text string violates an ASN.1 constraint. * * Side Effects: * None. * * Caveats: * None. */ BOOL CControlSAP::IsTextNameValid ( LPWSTR text_string ) { BOOL rc = TRUE; UINT text_string_length = 0; if (text_string != NULL) { /* ** Check to make sure that the length of the string is within ** the allowable range. */ while (*text_string != 0) { text_string++; text_string_length++; if (text_string_length > MAXIMUM_CONFERENCE_NAME_LENGTH) { rc = FALSE; break; } } } else rc = FALSE; return rc; } /* * GCCError CControlSAP::QueueJoinIndication( * GCCResponseTag response_tag, * GCCConfID conference_id, * CPassword *convener_password, * CPassword *password_challenge, * LPWSTR pwszCallerID, * TransportAddress calling_address, * TransportAddress called_address, * CUserDataListContainer *user_data_list, * BOOL intermediate_node, * ConnectionHandle connection_handle) * * Public member function of CControlSAP. * * Function Description: * This routine is used to place join indications into the queue of * messages to be delivered to the node controller. * * Formal Parameters: * response_tag (i) Unique tag associated with this join . * conference_id (i) The conference identifier. * convener_password (i) Password used to obtain convener privileges. * password_challenge (i) Password used to join the conference. * pwszCallerID (i) Identifier of party initiating call. * calling_address (i) Transport address of party making call. * called_address (i) Transport address of party being called. * user_data_list (i) User data carried in the join. * intermediate_node (i) Flag indicating whether join is made at * intermediate node. * connection_handle (i) Handle for the logical connection. * * Return Value: * GCC_NO_ERROR - Message successfully queued. * GCC_ALLOCATION_FAILURE - A resource allocation failure occurred. * * Side Effects: * None. * * Caveats: * None. */ GCCError CControlSAP::QueueJoinIndication ( GCCResponseTag response_tag, GCCConfID conference_id, CPassword *convener_password, CPassword *password_challenge, LPWSTR pwszCallerID, TransportAddress calling_address, TransportAddress called_address, CUserDataListContainer *user_data_list, BOOL intermediate_node, ConnectionHandle connection_handle ) { GCCError rc; DebugEntry(CControlSAP::QueueJoinIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_JOIN_INDICATION; /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // start with success rc = GCC_NO_ERROR; // Copy the Convener Password ::CSAP_CopyDataToGCCMessage_Password( convener_password, &(Msg.u.join_indication.convener_password)); // Copy the Password ::CSAP_CopyDataToGCCMessage_Challenge( password_challenge, &(Msg.u.join_indication.password_challenge)); // Copy the Caller Identifier ::CSAP_CopyDataToGCCMessage_IDvsDesc( pwszCallerID, &(Msg.u.join_indication.caller_identifier)); // Copy the Calling Address ::CSAP_CopyDataToGCCMessage_Call( calling_address, &(Msg.u.join_indication.calling_address)); // Copy the Called Address ::CSAP_CopyDataToGCCMessage_Call( called_address, &(Msg.u.join_indication.called_address)); // Copy the User Data if it exists. LPBYTE pUserDataMemory = NULL; if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(Msg.u.join_indication.number_of_user_data_members), &(Msg.u.join_indication.user_data_list), &pUserDataMemory); } else { Msg.u.join_indication.number_of_user_data_members = 0; Msg.u.join_indication.user_data_list = NULL; } if (GCC_NO_ERROR == rc) { /* ** Filling in the rest of the information that needs to be sent ** to the application. */ Msg.u.join_indication.join_response_tag = response_tag; Msg.u.join_indication.conference_id = conference_id ; Msg.u.join_indication.node_is_intermediate = intermediate_node; Msg.u.join_indication.connection_handle = connection_handle; SendCtrlSapMsg(&Msg); delete pUserDataMemory; if (NULL != convener_password) { convener_password->UnLockPasswordData(); } if (NULL != password_challenge) { password_challenge->UnLockPasswordData(); } } #else GCCCtrlSapMsgEx *pMsgEx; /* ** Allocate the GCC callback message and fill it in with the ** appropriate values. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_JOIN_INDICATION, TRUE))) { ::ZeroMemory(&(pMsgEx->Msg.u.join_indication), sizeof(pMsgEx->Msg.u.join_indication)); /* ** Copy the information that needs to be sent to the node ** controller into local memory that can be deleted once the ** information to be sent to the application is flushed. Note that ** if an error occurs in one call to "CopyDataToGCCMessage" then no ** action is taken on subsequent calls to that routine. */ // start with success rc = GCC_NO_ERROR; // Copy the Convener Password ::CSAP_CopyDataToGCCMessage_Password( TRUE, // convener password pMsgEx->pToDelete, convener_password, &(pMsgEx->Msg.u.join_indication.convener_password), &rc); // Copy the Password ::CSAP_CopyDataToGCCMessage_Challenge( pMsgEx->pToDelete, password_challenge, &(pMsgEx->Msg.u.join_indication.password_challenge), &rc); // Copy the Caller Identifier ::CSAP_CopyDataToGCCMessage_IDvsDesc( TRUE, // caller id pMsgEx->pToDelete, pwszCallerID, &(pMsgEx->Msg.u.join_indication.caller_identifier), &rc); // Copy the Calling Address ::CSAP_CopyDataToGCCMessage_Call( TRUE, // calling address pMsgEx->pToDelete, calling_address, &(pMsgEx->Msg.u.join_indication.calling_address), &rc); // Copy the Called Address ::CSAP_CopyDataToGCCMessage_Call( FALSE, // called address pMsgEx->pToDelete, called_address, &(pMsgEx->Msg.u.join_indication.called_address), &rc); if (GCC_NO_ERROR == rc) { // Copy the User Data if it exists. if (user_data_list != NULL) { rc = RetrieveUserDataList( user_data_list, &(pMsgEx->Msg.u.join_indication.number_of_user_data_members), &(pMsgEx->Msg.u.join_indication.user_data_list), &(pMsgEx->pToDelete->user_data_list_memory)); ASSERT(GCC_NO_ERROR == rc); } else { // pMsgEx->Msg.u.join_indication.number_of_user_data_members = 0; // pMsgEx->Msg.u.join_indication.user_data_list = NULL; } if (GCC_NO_ERROR == rc) { /* ** Filling in the rest of the information that needs to be sent ** to the application. */ pMsgEx->Msg.u.join_indication.join_response_tag = response_tag; pMsgEx->Msg.u.join_indication.conference_id = conference_id ; pMsgEx->Msg.u.join_indication.node_is_intermediate = intermediate_node; pMsgEx->Msg.u.join_indication.connection_handle = connection_handle; // Queue up the message for delivery to the Node Controller. PostIndCtrlSapMsg(pMsgEx); } } } else { ERROR_OUT(("CControlSAP::QueueJoinIndication: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } if (GCC_NO_ERROR != rc) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::QueueJoinIndication, rc); return rc; } /* * GCCError CControlSAP::RetrieveUserDataList( * CUserDataListContainer *user_data_list_object, * PUShort number_of_data_members, * PGCCUserData **user_data_list, * LPBYTE *pUserDataMemory) * * Public member function of CControlSAP. * * Function Description: * This routine is used to fill in a user data list using a CUserDataListContainer * container. The memory needed to hold the user data will be allocated * by this routine. * * Formal Parameters: * user_data_list_object (i) The CUserDataListContainer container holding the * user data. * number_of_data_members (o) The number of elements in the list of * user data. * user_data_list (o) The "API" user data list to fill in. * data_to_be_deleted (o) Structure which will hold the memory * allocated for the user data. * * Return Value: * GCC_NO_ERROR - User data successfully retrieved. * GCC_ALLOCATION_FAILURE - A resource allocation failure occurred. * * Side Effects: * None. * * Caveats: * None. */ GCCError CControlSAP::RetrieveUserDataList ( CUserDataListContainer *user_data_list_object, UINT *number_of_data_members, PGCCUserData **user_data_list, LPBYTE *ppUserDataMemory ) { GCCError rc = GCC_NO_ERROR; UINT user_data_length; DebugEntry(CControlSAP::RetrieveUserDataList); /* * Lock the user data list object in order to determine the amount of * memory to allocate to hold the user data. */ user_data_length = user_data_list_object->LockUserDataList (); DBG_SAVE_FILE_LINE if (NULL != (*ppUserDataMemory = new BYTE[user_data_length])) { /* * The CUserDataListContainer "Get" call will set the user_data_list * pointer equal to this memory pointer. */ user_data_list_object->GetUserDataList( number_of_data_members, user_data_list, *ppUserDataMemory); } else { ERROR_OUT(("CControlSAP::RetrieveUserDataList: Error allocating memory")); rc = GCC_ALLOCATION_FAILURE; } /* * Unlock the data for the user data list object. */ user_data_list_object->UnLockUserDataList (); DebugExitINT(CControlSAP::RetrieveUserDataList, rc); return rc; } /* ------ pure virtual in CBaseSap (shared with CAppSap) ------ */ /* * ConfRosterInquireConfirm() * * Public Function Description * This routine is called in order to return a requested conference * roster to an application or the node controller. */ GCCError CControlSAP::ConfRosterInquireConfirm ( GCCConfID conference_id, PGCCConferenceName conference_name, GCCNumericString conference_modifier, LPWSTR pwszConfDescriptor, CConfRoster *conference_roster, GCCResult result, GCCAppSapMsgEx **ppAppSapMsgEx ) { GCCCtrlSapMsgEx *pMsgEx; GCCError rc = GCC_NO_ERROR; UINT memory_block_size = 0; int name_unicode_string_length; int descriptor_unicode_string_length; LPBYTE pBuf = NULL; LPBYTE memory_pointer; DebugEntry(CControlSAP::ConfRosterInquireConfirm); ASSERT(NULL == ppAppSapMsgEx); /* ** Create a new message structure to hold the message to be delivered ** to the application or node controller. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_ROSTER_INQUIRE_CONFIRM))) { ::ZeroMemory(&(pMsgEx->Msg.u.conf_roster_inquire_confirm), sizeof(pMsgEx->Msg.u.conf_roster_inquire_confirm)); /* * Determine the length of the numeric portion of the conference name. */ if (conference_name->numeric_string != NULL) { memory_block_size += (::lstrlenA(conference_name->numeric_string) + 1); memory_block_size = ROUNDTOBOUNDARY(memory_block_size); } /* * Determine the length of the text portion of the conference name if it * exists. A UnicodeString object is created temporarily to determine * the length of the string. */ if (conference_name->text_string != NULL) { name_unicode_string_length = ROUNDTOBOUNDARY( (::lstrlenW(conference_name->text_string) + 1) * sizeof(WCHAR)); memory_block_size += name_unicode_string_length; } /* * Determine the length of the conference modifier. */ if (conference_modifier != NULL) { memory_block_size += (::lstrlenA(conference_modifier) + 1); memory_block_size = ROUNDTOBOUNDARY(memory_block_size); } /* * Determine the length of the conference descriptor. A UnicodeString * object is created temporarily to determine the length of the string. */ if (pwszConfDescriptor != NULL) { descriptor_unicode_string_length = ROUNDTOBOUNDARY( (::lstrlenW(pwszConfDescriptor) + 1) * sizeof(WCHAR)); memory_block_size += descriptor_unicode_string_length; } /* * Lock the data for the conference roster. The lock call will * return the length of the data to be serialized for the roster so * add that length to the total memory block size and allocate the * memory block. */ memory_block_size += conference_roster->LockConferenceRoster(); /* * If the memory was successfully allocated, get a pointer to the * memory. The first pointer in the roster inquire confirm message * will be set to this location and all serialized data written into * the memory block. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx->pBuf = new BYTE[memory_block_size])) { memory_pointer = pMsgEx->pBuf; /* * Write the conference name string(s) into memory and set the * message structure pointers. */ if (conference_name->numeric_string != NULL) { ::lstrcpyA((LPSTR)memory_pointer, (LPSTR)conference_name->numeric_string); pMsgEx->Msg.u.conf_roster_inquire_confirm.conference_name. numeric_string = (LPSTR) memory_pointer; memory_pointer += ROUNDTOBOUNDARY( ::lstrlenA(conference_name->numeric_string) + 1); } else { // pMsgEx->Msg.u.conf_roster_inquire_confirm.conference_name.numeric_string = NULL; } /* * Copy the text portion of the conference name if it exists. */ if (conference_name->text_string != NULL) { ::CopyMemory(memory_pointer, (LPSTR)conference_name->text_string, name_unicode_string_length); pMsgEx->Msg.u.conf_roster_inquire_confirm.conference_name.text_string = (LPWSTR)memory_pointer; memory_pointer += name_unicode_string_length; } else { // pMsgEx->Msg.u.conf_roster_inquire_confirm.conference_name.text_string = NULL; } /* * Copy the conference modifier is it exists */ if (conference_modifier != NULL) { ::lstrcpyA((LPSTR)memory_pointer, (LPSTR)conference_modifier); pMsgEx->Msg.u.conf_roster_inquire_confirm.conference_modifier = (LPSTR) memory_pointer; memory_pointer += ROUNDTOBOUNDARY(::lstrlenA(conference_modifier) + 1); } else { // pMsgEx->Msg.u.conf_roster_inquire_confirm.conference_modifier = NULL; } /* * Copy the conference descriptor. */ if (pwszConfDescriptor != NULL) { ::CopyMemory(memory_pointer, (LPSTR)pwszConfDescriptor, descriptor_unicode_string_length); pMsgEx->Msg.u.conf_roster_inquire_confirm.conference_descriptor = (LPWSTR) memory_pointer; memory_pointer += descriptor_unicode_string_length; } else { // pMsgEx->Msg.u.conf_roster_inquire_confirm.conference_descriptor = NULL; } /* * Retrieve the conference roster data from the roster object. * The roster object will serialize any referenced data into * the memory block passed in to the "Get" call. */ conference_roster->GetConfRoster( &pMsgEx->Msg.u.conf_roster_inquire_confirm.conference_roster, memory_pointer); pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.conf_roster_inquire_confirm.conference_id = conference_id; pMsgEx->Msg.u.conf_roster_inquire_confirm.result = result; /* * Add the message to the queue for delivery to the application or * node controller. */ PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { ERROR_OUT(("CControlSAP::ConfRosterInquireConfirm: can't allocate buffer, size=%u", (UINT) memory_block_size)); rc = GCC_ALLOCATION_FAILURE; } /* * Unlock the data for the conference roster. */ conference_roster->UnLockConferenceRoster(); } else { ERROR_OUT(("CControlSAP::ConfRosterInquireConfirm: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } if (rc != GCC_NO_ERROR) { FreeCtrlSapMsgEx(pMsgEx); ASSERT(GCC_ALLOCATION_FAILURE == rc); HandleResourceFailure(); } DebugExitINT(CControlSAP::ConfRosterInquireConfirm, rc); return (rc); } /* * AppRosterInquireConfirm() * * Public Function Description * This routine is called in order to return a requested list of * application rosters to an application or the node controller. */ GCCError CControlSAP::AppRosterInquireConfirm ( GCCConfID conference_id, CAppRosterMsg *roster_message, GCCResult result, GCCAppSapMsgEx **ppAppSapMsgEx ) { #ifdef JASPER GCCError rc = GCC_NO_ERROR; GCCCtrlSapMsgEx *pMsgEx; UINT number_of_rosters; LPBYTE pBuf = NULL; DebugEntry(CControlSAP::AppRosterInquireConfirm); ASSERT(NULL == ppAppSapMsgEx); /* ** Create a new message structure to hold the message to be delivered ** to the application or node controller. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_APP_ROSTER_INQUIRE_CONFIRM, TRUE))) { // ::ZeroMemory(&(pMsgEx->Msg.u.app_roster_inquire_confirm), sizeof(pMsgEx->Msg.u.app_roster_inquire_confirm)); /* * Lock the data for the roster message and retrieve the data. */ rc = roster_message->LockApplicationRosterMessage(); if (rc == GCC_NO_ERROR) { rc = roster_message->GetAppRosterMsg(&pBuf, &number_of_rosters); if (rc == GCC_NO_ERROR) { /* * Retrieve the memory pointer and save it in the list of * GCCApplicationRoster pointers. */ pMsgEx->Msg.u.app_roster_inquire_confirm.application_roster_list = (PGCCApplicationRoster *) pBuf; } else { /* * Cleanup after an error. */ roster_message->UnLockApplicationRosterMessage(); } } /* * If everything is OK up to here, send the message on up. */ if (rc == GCC_NO_ERROR) { pMsgEx->pToDelete->application_roster_message = roster_message; pMsgEx->Msg.u.app_roster_inquire_confirm.conference_id = conference_id; pMsgEx->Msg.u.app_roster_inquire_confirm.number_of_rosters = number_of_rosters; pMsgEx->Msg.u.app_roster_inquire_confirm.result = result; /* * Add the message to the queue for delivery to the application * or node controller. */ PostConfirmCtrlSapMsg(pMsgEx); } } else { ERROR_OUT(("CControlSAP::AppRosterInquireConfirm: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } if (rc != GCC_NO_ERROR) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } DebugExitINT(CControlSAP::AppRosterInquireConfirm, rc); return (rc); #else return GCC_NO_ERROR; #endif // JASPER } /* * ConductorInquireConfirm () * * Public Function Description * This routine is called in order to return conductorship information * which has been requested. * */ GCCError CControlSAP::ConductorInquireConfirm ( GCCNodeID conductor_node_id, GCCResult result, BOOL permission_flag, BOOL conducted_mode, GCCConfID conference_id ) { #ifdef JASPER GCCError rc; GCCCtrlSapMsgEx *pMsgEx; DebugEntry(CControlSAP::ConductorInquireConfirm); /* ** Create a new message structure to hold the message to be delivered ** to the application or node controller. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_INQUIRE_CONFIRM))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_inquire_confirm), sizeof(pMsgEx->Msg.u.conduct_inquire_confirm)); pMsgEx->Msg.u.conduct_inquire_confirm.conference_id = conference_id; pMsgEx->Msg.u.conduct_inquire_confirm.result = result; pMsgEx->Msg.u.conduct_inquire_confirm.mode_is_conducted = conducted_mode; pMsgEx->Msg.u.conduct_inquire_confirm.conductor_node_id = conductor_node_id; pMsgEx->Msg.u.conduct_inquire_confirm.permission_is_granted = permission_flag; /* * Add the message to the queue for delivery to the application or * node controller. */ PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } DebugExitINT(CControlSAP::ConductorInquireConfirm, rc); return rc; #else return GCC_NO_ERROR; #endif // JASPER } /* * AppInvokeConfirm () * * Public Function Description * This routine is called in order to confirm a call requesting application * invocation. */ GCCError CControlSAP::AppInvokeConfirm ( GCCConfID conference_id, CInvokeSpecifierListContainer *invoke_list, GCCResult result, GCCRequestTag nReqTag ) { GCCCtrlSapMsgEx *pMsgEx; GCCError rc = GCC_NO_ERROR; UINT invoke_list_memory_length; DebugEntry(CControlSAP::AppInvokeConfirm); /* ** Create a new message structure to hold the message to be delivered ** to the application or node controller. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_APPLICATION_INVOKE_CONFIRM))) { ::ZeroMemory(&(pMsgEx->Msg.u.application_invoke_confirm), sizeof(pMsgEx->Msg.u.application_invoke_confirm)); /* ** Determine the amount of memory necessary to hold the list of ** invoke specifiers and allocate that memory. */ invoke_list_memory_length = invoke_list->LockApplicationInvokeSpecifierList(); if (invoke_list_memory_length != 0) { /* * If the memory was successfully allocated, get a pointer * to the memory and save it in the app_protocol_entity_list * pointer of the GCC message. Call the * CInvokeSpecifierList object to fill in the * list. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx->pBuf = new BYTE[invoke_list_memory_length])) { pMsgEx->Msg.u.application_invoke_confirm.app_protocol_entity_list = (GCCAppProtocolEntity **) pMsgEx->pBuf; invoke_list->GetApplicationInvokeSpecifierList( &(pMsgEx->Msg.u.application_invoke_confirm.number_of_app_protocol_entities), pMsgEx->pBuf); pMsgEx->Msg.u.application_invoke_confirm.conference_id = conference_id; pMsgEx->Msg.u.application_invoke_confirm.result = result; /* * Add the message to the queue for delivery to the application * or node controller. */ PostConfirmCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { ERROR_OUT(("CControlSAP::AppInvokeConfirm: can't allocate buffer, size=%u", (UINT) invoke_list_memory_length)); rc = GCC_ALLOCATION_FAILURE; } } /* ** Unlock the data for the invoke specifier list. */ invoke_list->UnLockApplicationInvokeSpecifierList(); } else { ERROR_OUT(("CControlSAP::AppInvokeConfirm: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } if (rc != GCC_NO_ERROR) { FreeCtrlSapMsgEx(pMsgEx); ASSERT(GCC_ALLOCATION_FAILURE == rc); HandleResourceFailure(); } DebugExitINT(CControlSAP::AppInvokeConfirm, rc); return rc; } /* * AppInvokeIndication () * * Public Function Description * This routine is called in order to send an indication to an application * or node controller that a request for application invocation has been * made. */ GCCError CControlSAP::AppInvokeIndication ( GCCConfID conference_id, CInvokeSpecifierListContainer *invoke_list, GCCNodeID invoking_node_id ) { GCCError rc = GCC_NO_ERROR; DebugEntry(CControlSAP::AppInvokeIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_APPLICATION_INVOKE_INDICATION; UINT invoke_list_memory_length; /* ** Determine the amount of memory necessary to hold the list of ** invoke specifiers and allocate that memory. */ invoke_list_memory_length = invoke_list->LockApplicationInvokeSpecifierList(); if (invoke_list_memory_length != 0) { LPBYTE pBuf; /* * If the memory was successfully allocated, get a pointer * to the memory and save it in the app_protocol_entity_list * pointer of the GCC message. Call the * CInvokeSpecifierList object to fill in the * list. */ DBG_SAVE_FILE_LINE if (NULL != (pBuf = new BYTE[invoke_list_memory_length])) { Msg.u.application_invoke_indication.app_protocol_entity_list = (GCCAppProtocolEntity **) pBuf; invoke_list->GetApplicationInvokeSpecifierList( &(Msg.u.application_invoke_indication.number_of_app_protocol_entities), pBuf); Msg.u.application_invoke_indication.conference_id = conference_id; Msg.u.application_invoke_indication.invoking_node_id = invoking_node_id; SendCtrlSapMsg(&Msg); // rc = GCC_NO_ERROR; delete pBuf; } else { ERROR_OUT(("CControlSAP::AppInvokeIndication: can't allocate buffer, size=%u", (UINT) invoke_list_memory_length)); rc = GCC_ALLOCATION_FAILURE; } } /* ** Unlock the data for the invoke specifier list. */ invoke_list->UnLockApplicationInvokeSpecifierList (); #else GCCCtrlSapMsgEx *pMsgEx; UINT invoke_list_memory_length; /* ** Create a new message structure to hold the message to be delivered ** to the application or node controller. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_APPLICATION_INVOKE_INDICATION))) { ::ZeroMemory(&(pMsgEx->Msg.u.application_invoke_indication), sizeof(pMsgEx->Msg.u.application_invoke_indication)); /* ** Determine the amount of memory necessary to hold the list of ** invoke specifiers and allocate that memory. */ invoke_list_memory_length = invoke_list->LockApplicationInvokeSpecifierList(); if (invoke_list_memory_length != 0) { /* * If the memory was successfully allocated, get a pointer * to the memory and save it in the app_protocol_entity_list * pointer of the GCC message. Call the * CInvokeSpecifierList object to fill in the * list. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx->pBuf = new BYTE[invoke_list_memory_length])) { pMsgEx->Msg.u.application_invoke_indication.app_protocol_entity_list = (GCCAppProtocolEntity **) pMsgEx->pBuf; invoke_list->GetApplicationInvokeSpecifierList( &(pMsgEx->Msg.u.application_invoke_indication.number_of_app_protocol_entities), pMsgEx->pBuf); pMsgEx->Msg.u.application_invoke_indication.conference_id = conference_id; pMsgEx->Msg.u.application_invoke_indication.invoking_node_id = invoking_node_id; PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { ERROR_OUT(("CControlSAP::AppInvokeIndication: can't allocate buffer, size=%u", (UINT) invoke_list_memory_length)); rc = GCC_ALLOCATION_FAILURE; } } /* ** Unlock the data for the invoke specifier list. */ invoke_list->UnLockApplicationInvokeSpecifierList (); } else { ERROR_OUT(("CControlSAP::AppInvokeIndication: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } if (rc != GCC_NO_ERROR) { FreeCtrlSapMsgEx(pMsgEx); ASSERT(GCC_ALLOCATION_FAILURE == rc); HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::AppInvokeIndication, rc); return rc; } /* * ConfRosterReportIndication () * * Public Function Description * This routine is called in order to indicate to applications and the * node controller that the conference roster has been updated. */ GCCError CControlSAP::ConfRosterReportIndication ( GCCConfID conference_id, CConfRosterMsg *roster_message ) { GCCError rc = GCC_NO_ERROR; DebugEntry(CControlSAP::ConfRosterReportIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_ROSTER_REPORT_INDICATION; /* * Lock the conference roster message in order to force the object * to serialize the data into its internal memory. */ rc = roster_message->LockConferenceRosterMessage(); if (rc == GCC_NO_ERROR) { LPBYTE pBuf = NULL; /* * Retrieve the actual pointer to memory object that the * serialized conference roster is contained in from the * conference roster message. */ rc = roster_message->GetConferenceRosterMessage(&pBuf); if (rc == GCC_NO_ERROR) { Msg.nConfID = conference_id; Msg.u.conf_roster_report_indication.conference_id = conference_id; Msg.u.conf_roster_report_indication.conference_roster = (PGCCConferenceRoster) pBuf; SendCtrlSapMsg(&Msg); } else { ERROR_OUT(("CControlSAP::ConfRosterReportIndication: can't get conf roster message")); } roster_message->UnLockConferenceRosterMessage(); } else { ERROR_OUT(("CControlSAP::ConfRosterReportIndication: can't lock conf roster message")); } #else GCCCtrlSapMsgEx *pMsgEx; /* ** Create a new message structure to hold the message to be delivered ** to the application or node controller. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_ROSTER_REPORT_INDICATION, TRUE))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conf_roster_report_indication), sizeof(pMsgEx->Msg.u.conf_roster_report_indication)); /* * Lock the conference roster message in order to force the object * to serialize the data into its internal memory. */ rc = roster_message->LockConferenceRosterMessage(); if (rc == GCC_NO_ERROR) { LPBYTE pBuf = NULL; /* * Retrieve the actual pointer to memory object that the * serialized conference roster is contained in from the * conference roster message. */ rc = roster_message->GetConferenceRosterMessage(&pBuf); if (rc == GCC_NO_ERROR) { pMsgEx->Msg.u.conf_roster_report_indication.conference_roster = (PGCCConferenceRoster) pBuf; /* * Fill in the roster's conference ID and then queue up the * message. */ pMsgEx->Msg.nConfID = conference_id; pMsgEx->Msg.u.conf_roster_report_indication.conference_id = conference_id; pMsgEx->pToDelete->conference_roster_message = roster_message; PostIndCtrlSapMsg(pMsgEx); } else { ERROR_OUT(("CControlSAP::ConfRosterReportIndication: can't get conf roster message")); } } else { ERROR_OUT(("CControlSAP::ConfRosterReportIndication: can't lock conf roster message")); } } else { ERROR_OUT(("CControlSAP::ConfRosterReportIndication: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } if (rc != GCC_NO_ERROR) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConfRosterReportIndication, rc); return rc; } /* * AppRosterReportIndication() * * Public Function Description * This routine is called in order to indicate to applications and the * node controller that the list of application rosters has been updated. */ GCCError CControlSAP::AppRosterReportIndication ( GCCConfID conference_id, CAppRosterMsg *roster_message ) { GCCError rc = GCC_NO_ERROR; DebugEntry(CControlSAP::AppRosterReportIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_APP_ROSTER_REPORT_INDICATION; /* * Determine the amount of memory needed to hold the list of * application rosters and allocate that memory. */ rc = roster_message->LockApplicationRosterMessage(); if (rc == GCC_NO_ERROR) { LPBYTE pBuf = NULL; ULONG cRosters; rc = roster_message->GetAppRosterMsg(&pBuf, &cRosters); if (rc == GCC_NO_ERROR) { Msg.u.app_roster_report_indication.conference_id = conference_id; Msg.u.app_roster_report_indication.application_roster_list = (PGCCApplicationRoster *) pBuf; Msg.u.app_roster_report_indication.number_of_rosters = cRosters; SendCtrlSapMsg(&Msg); } else { ERROR_OUT(("CControlSAP: AppRosterReportIndication: GetAppRosterMsg failed")); } roster_message->UnLockApplicationRosterMessage(); } else { ERROR_OUT(("CControlSAP: AppRosterReportIndication: LockApplicationRosterMessage failed")); } #else GCCCtrlSapMsgEx *pMsgEx; LPBYTE pBuf = NULL; UINT cRosters; /* ** Create a new message structure to hold the message to be delivered ** to the application or node controller. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_APP_ROSTER_REPORT_INDICATION, TRUE))) { // ::ZeroMemory(&(pMsgEx->Msg.u.app_roster_report_indication), sizeof(pMsgEx->Msg.u.app_roster_report_indication)); /* * Determine the amount of memory needed to hold the list of * application rosters and allocate that memory. */ rc = roster_message->LockApplicationRosterMessage(); if (rc == GCC_NO_ERROR) { rc = roster_message->GetAppRosterMsg(&pBuf, &cRosters); if (rc == GCC_NO_ERROR) { /* * Save it in the list of GCCApplicationRoster pointers. */ pMsgEx->Msg.u.app_roster_report_indication.application_roster_list = (PGCCApplicationRoster *) pBuf; } else { /* * Cleanup after an error. */ ERROR_OUT(("CControlSAP: AppRosterReportIndication: GetAppRosterMsg failed")); roster_message->UnLockApplicationRosterMessage(); } } else { ERROR_OUT(("CControlSAP: AppRosterReportIndication: LockApplicationRosterMessage failed")); } /* * If everything is OK up to here, send the message on up. */ if (rc == GCC_NO_ERROR) { pMsgEx->Msg.u.app_roster_report_indication.conference_id = conference_id; pMsgEx->Msg.u.app_roster_report_indication.number_of_rosters = cRosters; pMsgEx->pToDelete->application_roster_message = roster_message; /* * Add the message to the queue for delivery to the application * or node controller. */ PostIndCtrlSapMsg(pMsgEx); } } else { ERROR_OUT(("CControlSAP: AppRosterReportIndication: Failed to allocate a GCC message")); rc = GCC_ALLOCATION_FAILURE; } if (rc != GCC_NO_ERROR) { FreeCtrlSapMsgEx(pMsgEx); HandleResourceFailure(rc); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::AppRosterReportIndication, rc); return rc; } /* ------ from CBaseSap ------ */ /* * ConductorAssignIndication () * * Public Function Description * This routine is called in order to send an indication to an application * or node controller that a request has been made to assign conductorship. */ GCCError CControlSAP::ConductorAssignIndication ( UserID conductor_node_id, GCCConfID conference_id ) { #ifdef JASPER GCCError rc; DebugEntry(CControlSAP::ConductorAssignIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_CONDUCT_ASSIGN_INDICATION; Msg.u.conduct_assign_indication.conference_id = conference_id; Msg.u.conduct_assign_indication.node_id = conductor_node_id; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; /* ** Create a new message structure to hold the message to be delivered ** to the application or node controller. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_ASSIGN_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_assign_indication), sizeof(pMsgEx->Msg.u.conduct_assign_indication)); pMsgEx->Msg.u.conduct_assign_indication.conference_id = conference_id; pMsgEx->Msg.u.conduct_assign_indication.node_id = conductor_node_id; /* * Add the message to the queue for delivery to the application or * node controller. */ PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConductorAssignIndication, rc); return rc; #else return GCC_NO_ERROR; #endif // JASPER } /* * ConductorReleaseIndication () * * Public Function Description * This routine is called in order to send an indication to an application * or node controller that a request for releasing conductorship has been * made. */ GCCError CControlSAP:: ConductorReleaseIndication ( GCCConfID conference_id ) { #ifdef JASPER GCCError rc; DebugEntry(CControlSAP::ConductorReleaseIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_CONDUCT_RELEASE_INDICATION; Msg.u.conduct_release_indication.conference_id = conference_id; SendCtrlSapMsg(&Msg); rc = GCC_NO_ERROR; #else GCCCtrlSapMsgEx *pMsgEx; /* ** Create a new message structure to hold the message to be delivered ** to the application or node controller. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_RELEASE_INDICATION))) { // ::ZeroMemory(&(pMsgEx->Msg.u.conduct_release_indication), sizeof(pMsgEx->Msg.u.conduct_release_indication)); pMsgEx->Msg.u.conduct_release_indication.conference_id = conference_id; /* * Add the message to the queue for delivery to the application or * node controller. */ PostIndCtrlSapMsg(pMsgEx); rc = GCC_NO_ERROR; } else { rc = GCC_ALLOCATION_FAILURE; HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConductorReleaseIndication, rc); return rc; #else return GCC_NO_ERROR; #endif // JASPER } /* * ConductorPermitGrantIndication () * * Public Function Description * This routine is called in order to send an indication to an application * or node controller that a request for permission from the conductor * has been made. */ GCCError CControlSAP::ConductorPermitGrantIndication ( GCCConfID conference_id, UINT number_granted, GCCNodeID *granted_node_list, UINT number_waiting, GCCNodeID *waiting_node_list, BOOL permission_is_granted ) { #ifdef JASPER GCCError rc = GCC_NO_ERROR; DebugEntry(CControlSAP::ConductorPermitGrantIndication); #ifdef GCCNC_DIRECT_INDICATION GCCCtrlSapMsg Msg; Msg.message_type = GCC_CONDUCT_GRANT_INDICATION; Msg.u.conduct_permit_grant_indication.conference_id = conference_id; Msg.u.conduct_permit_grant_indication.number_granted = number_granted; Msg.u.conduct_permit_grant_indication.granted_node_list = granted_node_list; Msg.u.conduct_permit_grant_indication.number_waiting = number_waiting; Msg.u.conduct_permit_grant_indication.waiting_node_list = waiting_node_list; Msg.u.conduct_permit_grant_indication.permission_is_granted = permission_is_granted; SendCtrlSapMsg(&Msg); #else GCCCtrlSapMsgEx *pMsgEx; int bulk_memory_size; LPBYTE memory_pointer; UINT i; /* ** Create a new message structure to hold the message to be delivered ** to the application or node controller. */ DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = CreateCtrlSapMsgEx(GCC_CONDUCT_GRANT_INDICATION))) { ::ZeroMemory(&(pMsgEx->Msg.u.conduct_permit_grant_indication), sizeof(pMsgEx->Msg.u.conduct_permit_grant_indication)); /* ** Here we determine if bulk memory is necessary. */ if ((number_granted != 0) || (number_waiting != 0)) { /* ** We must first determine how big the bulk memory block will be ** and allocate that memory. */ bulk_memory_size = (ROUNDTOBOUNDARY(sizeof(UserID)) * number_granted) + (ROUNDTOBOUNDARY(sizeof(UserID)) * number_waiting); DBG_SAVE_FILE_LINE if (NULL != (pMsgEx->pBuf = new BYTE[bulk_memory_size])) { memory_pointer = pMsgEx->pBuf; } else { ERROR_OUT(("CControlSAP::ConductorPermitGrantIndication: can't allocate buffer, size=%u", (UINT) bulk_memory_size)); rc = GCC_ALLOCATION_FAILURE; } } if (rc == GCC_NO_ERROR) { /* ** If there are any nodes in the permission list copy them over. */ if (number_granted != 0) { TRACE_OUT(("CControlSAP::ConductorPermitGrantIndication:" " number_granted = %d", number_granted)); pMsgEx->Msg.u.conduct_permit_grant_indication. granted_node_list = (PUserID)memory_pointer; for (i = 0; i < number_granted; i++) { pMsgEx->Msg.u.conduct_permit_grant_indication. granted_node_list[i] = granted_node_list[i]; } memory_pointer += ROUNDTOBOUNDARY(sizeof(UserID)) * number_granted; } else { // pMsgEx->Msg.u.conduct_permit_grant_indication.granted_node_list = NULL; } /* ** If there are any nodes in the waiting list copy them over. */ if (number_waiting != 0) { TRACE_OUT(("CControlSAP::ConductorPermitGrantIndication:" " number_waiting = %d", number_waiting)); pMsgEx->Msg.u.conduct_permit_grant_indication. waiting_node_list = (PUserID)memory_pointer; for (i = 0; i < number_waiting; i++) { pMsgEx->Msg.u.conduct_permit_grant_indication. waiting_node_list[i] = waiting_node_list[i]; } } else { // pMsgEx->Msg.u.conduct_permit_grant_indication.waiting_node_list = NULL; } pMsgEx->Msg.u.conduct_permit_grant_indication.conference_id = conference_id; pMsgEx->Msg.u.conduct_permit_grant_indication.number_granted = number_granted; pMsgEx->Msg.u.conduct_permit_grant_indication.number_waiting = number_waiting; pMsgEx->Msg.u.conduct_permit_grant_indication.permission_is_granted = permission_is_granted; /* * Add the message to the queue for delivery to the application or * node controller. */ PostIndCtrlSapMsg(pMsgEx); } } else { ERROR_OUT(("CControlSAP::ConductorPermitGrantIndication: can't create GCCCtrlSapMsgEx")); rc = GCC_ALLOCATION_FAILURE; } if (rc != GCC_NO_ERROR) { FreeCtrlSapMsgEx(pMsgEx); ASSERT(GCC_ALLOCATION_FAILURE == rc); HandleResourceFailure(); } #endif // GCCNC_DIRECT_INDICATION DebugExitINT(CControlSAP::ConductorPermitGrantIndication, rc); return (rc); #else return GCC_NO_ERROR; #endif // JASPER } GCCError CControlSAP::AppletInvokeRequest ( GCCConfID nConfID, UINT number_of_app_protcol_entities, GCCAppProtocolEntity **app_protocol_entity_list, UINT number_of_destination_nodes, UserID *list_of_destination_nodes ) { GCCAppProtEntityList ApeList; GCCSimpleNodeList NodeList; GCCRequestTag nReqTag; ApeList.cApes = number_of_app_protcol_entities; ApeList.apApes = app_protocol_entity_list; NodeList.cNodes = number_of_destination_nodes; NodeList.aNodeIDs = list_of_destination_nodes; return CBaseSap::AppInvoke(nConfID, &ApeList, &NodeList, &nReqTag); } GCCError CControlSAP::ConfRosterInqRequest ( GCCConfID nConfID ) { return CBaseSap::ConfRosterInquire(nConfID, NULL); } #ifdef JASPER GCCError CControlSAP::ConductorInquireRequest ( GCCConfID nConfID ) { return CBaseSap::ConductorInquire(nConfID); } #endif // JASPER // // LONCHANC: The following SAP_*** stuff are all app sap related // because FreeCallbackMessage() in CControlSAP does not handle // the DataToBeDeleted stuff. // /* * void CopyDataToGCCMessage( * SapCopyType copy_type, * PDataToBeDeleted data_to_be_deleted, * LPVOID source_ptr, * LPVOID destination_ptr, * PGCCError rc) * * Protected member function of CControlSAP. * * Function Description: * This routine is used to fill in the various components of the message * structures to be delivered to applications or the node controller. * * Formal Parameters: * copy_type (i) Enumerated type indicating what field is to be * copied. * data_to_be_deleted (o) Structure to hold part of the data to be * delivered in the message. * source_ptr (i) Pointer to structure to copy from. * destination_ptr (o) Pointer to structure to copy into. * rc (o) Return value for routine. * * Return Value: * None. * * Side Effects: * None. * * Caveats: * The return value should be setup before it is passed into this * routine. This allows the error checking to be done in one place * (this routine). */ void CSAP_CopyDataToGCCMessage_ConfName ( PDataToBeDeleted data_to_be_deleted, PGCCConferenceName source_conference_name, PGCCConferenceName destination_conference_name, PGCCError pRetCode ) { if (GCC_NO_ERROR == *pRetCode) { LPSTR pszNumeric; LPWSTR pwszText; if (source_conference_name != NULL) { if (source_conference_name->numeric_string != NULL) { /* * First copy the numeric conference name if one exists. */ if (NULL != (pszNumeric = ::My_strdupA(source_conference_name->numeric_string))) { destination_conference_name->numeric_string = (GCCNumericString) pszNumeric; data_to_be_deleted->pszNumericConfName = pszNumeric; } else { *pRetCode = GCC_ALLOCATION_FAILURE; } } else { // destination_conference_name->numeric_string = NULL; } /* * Next copy the text conference name if one exists. */ if ((source_conference_name->text_string != NULL) && (*pRetCode == GCC_NO_ERROR)) { if (NULL != (pwszText = ::My_strdupW(source_conference_name->text_string))) { destination_conference_name->text_string = pwszText; data_to_be_deleted->pwszTextConfName = pwszText; } else { *pRetCode = GCC_ALLOCATION_FAILURE; } } else { // destination_conference_name->text_string = NULL; } } else { // destination_conference_name->numeric_string = NULL; // destination_conference_name->text_string = NULL; } ASSERT(GCC_NO_ERROR == *pRetCode); } } void CSAP_CopyDataToGCCMessage_Modifier ( BOOL fRemoteModifier, PDataToBeDeleted data_to_be_deleted, GCCNumericString source_numeric_string, GCCNumericString *destination_numeric_string, PGCCError pRetCode ) { if (GCC_NO_ERROR == *pRetCode) { LPSTR numeric_ptr; if (source_numeric_string != NULL) { if (NULL != (numeric_ptr = ::My_strdupA(source_numeric_string))) { *destination_numeric_string = (GCCNumericString) numeric_ptr; if (fRemoteModifier) { data_to_be_deleted->pszRemoteModifier = numeric_ptr; } else { data_to_be_deleted->pszConfNameModifier = numeric_ptr; } TRACE_OUT(("CopyDataToGCCMessage_Modifier: modifier = %s", *destination_numeric_string)); } else { // *destination_numeric_string = NULL; *pRetCode = GCC_ALLOCATION_FAILURE; } } else { // *destination_numeric_string = NULL; } ASSERT(GCC_NO_ERROR == *pRetCode); } } void CSAP_CopyDataToGCCMessage_Password ( BOOL fConvener, PDataToBeDeleted data_to_be_deleted, CPassword *source_password, PGCCPassword *destination_password, PGCCError pRetCode ) { if (GCC_NO_ERROR == *pRetCode) { if (source_password != NULL) { source_password->LockPasswordData(); source_password->GetPasswordData (destination_password); if (fConvener) { data_to_be_deleted->convener_password = source_password; } else { data_to_be_deleted->password = source_password; } } else { // *destination_password = NULL; } ASSERT(GCC_NO_ERROR == *pRetCode); } } void CSAP_CopyDataToGCCMessage_Challenge ( PDataToBeDeleted data_to_be_deleted, CPassword *source_password, PGCCChallengeRequestResponse *password_challenge, PGCCError pRetCode ) { if (GCC_NO_ERROR == *pRetCode) { if (source_password != NULL) { source_password->LockPasswordData(); source_password->GetPasswordChallengeData (password_challenge); data_to_be_deleted->password = source_password; } else { // *password_challenge = NULL; } ASSERT(GCC_NO_ERROR == *pRetCode); } } void CSAP_CopyDataToGCCMessage_PrivilegeList ( PPrivilegeListData source_privilege_list_data, PGCCConferencePrivileges *destination_privilege_list, PGCCError pRetCode ) { if (GCC_NO_ERROR == *pRetCode) { if (source_privilege_list_data != NULL) { DBG_SAVE_FILE_LINE if (NULL != (*destination_privilege_list = new GCCConferencePrivileges)) { **destination_privilege_list = *(source_privilege_list_data->GetPrivilegeListData()); } else { *pRetCode = GCC_ALLOCATION_FAILURE; } } else { // *destination_privilege_list = NULL; } ASSERT(GCC_NO_ERROR == *pRetCode); } } void CSAP_CopyDataToGCCMessage_IDvsDesc ( BOOL fCallerID, PDataToBeDeleted data_to_be_deleted, LPWSTR source_text_string, LPWSTR *destination_text_string, PGCCError pRetCode ) { if (GCC_NO_ERROR == *pRetCode) { if (source_text_string != NULL) { if (NULL != (*destination_text_string = ::My_strdupW(source_text_string))) { if (fCallerID) { data_to_be_deleted->pwszCallerID = *destination_text_string; } else { data_to_be_deleted->pwszConfDescriptor = *destination_text_string; } } else { *pRetCode = GCC_ALLOCATION_FAILURE; } } else { // *destination_text_string = NULL; } ASSERT(GCC_NO_ERROR == *pRetCode); } } // // LONCHANC: TransportAddress is defined as LPSTR (i.e. char *) // void CSAP_CopyDataToGCCMessage_Call ( BOOL fCalling, PDataToBeDeleted data_to_be_deleted, TransportAddress source_transport_address, TransportAddress *destination_transport_address, PGCCError pRetCode ) { if (GCC_NO_ERROR == *pRetCode) { if (source_transport_address != NULL) { if (NULL != (*destination_transport_address = ::My_strdupA(source_transport_address))) { if (fCalling) { data_to_be_deleted->pszCallingAddress = *destination_transport_address ; } else { data_to_be_deleted->pszCalledAddress = *destination_transport_address ; } } else { *pRetCode = GCC_ALLOCATION_FAILURE; } } else { // *destination_transport_address = NULL; } ASSERT(GCC_NO_ERROR == *pRetCode); } } void CSAP_CopyDataToGCCMessage_DomainParams ( PDataToBeDeleted data_to_be_deleted, PDomainParameters source_domain_parameters, PDomainParameters *destination_domain_parameters, PGCCError pRetCode ) { if (GCC_NO_ERROR == *pRetCode) { if (source_domain_parameters != NULL) { DBG_SAVE_FILE_LINE if (NULL != (*destination_domain_parameters = new DomainParameters)) { **destination_domain_parameters = *source_domain_parameters; data_to_be_deleted->pDomainParams = *destination_domain_parameters; } else { *pRetCode = GCC_ALLOCATION_FAILURE; } } else { // *destination_domain_parameters = NULL; } ASSERT(GCC_NO_ERROR == *pRetCode); } } void CControlSAP::NotifyProc ( GCCCtrlSapMsgEx *pCtrlSapMsgEx ) { if (NULL != m_pfnNCCallback) { pCtrlSapMsgEx->Msg.user_defined = m_pNCData; (*m_pfnNCCallback)(&(pCtrlSapMsgEx->Msg)); } // // Free this callback message. // FreeCtrlSapMsgEx(pCtrlSapMsgEx); } void CControlSAP::WndMsgHandler ( UINT uMsg, WPARAM wParam, LPARAM lParam ) { ASSERT(uMsg >= CSAPCONFIRM_BASE); GCCCtrlSapMsg Msg; Msg.message_type = (GCCMessageType) (uMsg - CSAPCONFIRM_BASE); Msg.nConfID = (GCCConfID) lParam; GCCResult nResult = (GCCResult) LOWORD(wParam); switch (Msg.message_type) { case GCC_EJECT_USER_CONFIRM: #ifdef JASPER Msg.u.eject_user_confirm.conference_id = Msg.nConfID; Msg.u.eject_user_confirm.result = nResult; Msg.u.eject_user_confirm.ejected_node_id = (GCCNodeID) HIWORD(wParam); #endif // JASPER break; case GCC_CONDUCT_GIVE_CONFIRM: #ifdef JASPER Msg.u.conduct_give_confirm.conference_id = Msg.nConfID; Msg.u.conduct_give_confirm.result = nResult; Msg.u.conduct_give_confirm.recipient_node_id = (GCCNodeID) HIWORD(wParam); #endif // JASPER break; case GCC_CONDUCT_ASK_CONFIRM: #ifdef JASPER Msg.u.conduct_permit_ask_confirm.conference_id = Msg.nConfID; Msg.u.conduct_permit_ask_confirm.result = nResult; Msg.u.conduct_permit_ask_confirm.permission_is_granted = HIWORD(wParam);; #endif // JASPER break; case GCC_EJECT_USER_INDICATION: Msg.u.eject_user_indication.conference_id = Msg.nConfID; Msg.u.eject_user_indication.ejected_node_id = (GCCNodeID) HIWORD(wParam); Msg.u.eject_user_indication.reason = (GCCReason) LOWORD(wParam); break; // case GCC_DISCONNECT_CONFIRM: // case GCC_LOCK_CONFIRM: // case GCC_UNLOCK_CONFIRM: // case GCC_ANNOUNCE_PRESENCE_CONFIRM: // case GCC_TERMINATE_CONFIRM: // case GCC_CONDUCT_ASSIGN_CONFIRM: // case GCC_CONDUCT_RELEASE_CONFIRM: // case GCC_CONDUCT_PLEASE_CONFIRM: // case GCC_CONDUCT_GRANT_CONFIRM: // case GCC_TIME_REMAINING_CONFIRM: // case GCC_TIME_INQUIRE_CONFIRM: // case GCC_ASSISTANCE_CONFIRM: // case GCC_TEXT_MESSAGE_CONFIRM: default: // This is a shortcut to fill in conf id and gcc result. Msg.u.simple_confirm.conference_id = Msg.nConfID; Msg.u.simple_confirm.result = nResult; break; } SendCtrlSapMsg(&Msg); } GCCCtrlSapMsgEx * CControlSAP::CreateCtrlSapMsgEx ( GCCMessageType eMsgType, BOOL fUseToDelete ) { GCCCtrlSapMsgEx *pMsgEx; UINT cbSize = fUseToDelete ? sizeof(GCCCtrlSapMsgEx) + sizeof(DataToBeDeleted) : sizeof(GCCCtrlSapMsgEx); DBG_SAVE_FILE_LINE if (NULL != (pMsgEx = (GCCCtrlSapMsgEx *) new BYTE[cbSize])) { pMsgEx->Msg.message_type = eMsgType; pMsgEx->pBuf = NULL; if (fUseToDelete) { pMsgEx->pToDelete = (DataToBeDeleted *) (pMsgEx + 1); ::ZeroMemory(pMsgEx->pToDelete, sizeof(DataToBeDeleted)); } else { pMsgEx->pToDelete = NULL; } } return pMsgEx; } void CControlSAP::FreeCtrlSapMsgEx ( GCCCtrlSapMsgEx *pMsgEx ) { switch (pMsgEx->Msg.message_type) { case GCC_QUERY_INDICATION: delete pMsgEx->Msg.u.query_indication.asymmetry_indicator; break; #ifndef GCCNC_DIRECT_CONFIRM case GCC_QUERY_CONFIRM: delete pMsgEx->Msg.u.query_confirm.asymmetry_indicator; break; #endif #ifdef JASPER case GCC_TEXT_MESSAGE_INDICATION: delete pMsgEx->Msg.u.text_message_indication.text_message; break; #endif // JASPER #ifdef TSTATUS_INDICATION case GCC_TRANSPORT_STATUS_INDICATION: delete pMsgEx->Msg.u.transport_status.device_identifier; delete pMsgEx->Msg.u.transport_status.remote_address; delete pMsgEx->Msg.u.transport_status.message; break; #endif } // // Now free up the data to be deleted, // if (NULL != pMsgEx->pToDelete) { DataToBeDeleted *p = pMsgEx->pToDelete; delete p->pszNumericConfName; delete p->pwszTextConfName; delete p->pszConfNameModifier; delete p->pszRemoteModifier; delete p->pwszConfDescriptor; delete p->pwszCallerID; delete p->pszCalledAddress; delete p->pszCallingAddress; delete p->user_data_list_memory; delete p->pDomainParams; delete p->conductor_privilege_list; delete p->conducted_mode_privilege_list; delete p->non_conducted_privilege_list; if (p->convener_password != NULL) { p->convener_password->UnLockPasswordData(); } if (p->password != NULL) { p->password->UnLockPasswordData(); } if (p->conference_list != NULL) { p->conference_list->UnLockConferenceDescriptorList(); } if (p->conference_roster_message != NULL) { // // Set bulk memory back to NULL here since the conference // roster message object is responsible for freeing this up. // pMsgEx->pBuf = NULL; p->conference_roster_message->UnLockConferenceRosterMessage(); } if (p->application_roster_message != NULL) { // // Set bulk memory back to NULL here since the application // roster message object is responsible for freeing this up. // pMsgEx->pBuf = NULL; // // App roster indication can definitely be sent to app sap. // ::EnterCriticalSection(&g_csGCCProvider); p->application_roster_message->UnLockApplicationRosterMessage(); ::LeaveCriticalSection(&g_csGCCProvider); } } // // Next free up any bulk memory used. // delete pMsgEx->pBuf; // // Finally, free the structure itself. // delete pMsgEx; }