|
|
/****************************************************************************
* * $Archive: S:/STURGEON/SRC/CALLCONT/VCS/callcon2.c_v $ * * INTEL Corporation Prorietary Information * * This listing is supplied under the terms of a license agreement * with INTEL Corporation and may not be copied nor disclosed except * in accordance with the terms of that agreement. * * Copyright (c) 1996 Intel Corporation. * * $Revision: 1.35 $ * $Date: 03 Mar 1997 09:08:16 $ * $Author: MANDREWS $ * * Deliverable: * * Abstract: * * Notes: * ***************************************************************************/ #ifdef GATEKEEPER
#include "precomp.h"
#include "apierror.h"
#include "incommon.h"
#include "callcont.h"
#include "q931.h"
#include "ccmain.h"
#include "confman.h"
#include "listman.h"
#include "q931man.h"
#include "h245man.h"
#include "callman.h"
#include "userman.h"
#include "chanman.h"
#include "hangman.h"
#include "linkapi.h"
#include "h245api.h"
#include "ccutils.h"
#include "callman2.h"
#define HResultLeave(x) return x
extern CC_CONFERENCEID InvalidConferenceID;
//
// Complete CC_xxx Operations
//
HRESULT ListenReject (CC_HLISTEN hListen, HRESULT Reason) { HRESULT status; PLISTEN pListen; CC_LISTEN_CALLBACK_PARAMS ListenCallbackParams; ASSERT(GKIExists()); status = LockListen(hListen, &pListen); if (status == CC_OK) { ListenCallbackParams.hCall = CC_INVALID_HANDLE; ListenCallbackParams.pCallerAliasNames = NULL; ListenCallbackParams.pCalleeAliasNames = NULL; ListenCallbackParams.pNonStandardData = NULL; ListenCallbackParams.pszDisplay = NULL; ListenCallbackParams.pVendorInfo = NULL; ListenCallbackParams.ConferenceID = InvalidConferenceID; ListenCallbackParams.pCallerAddr = NULL; ListenCallbackParams.pCalleeAddr = NULL; ListenCallbackParams.dwListenToken = pListen->dwListenToken;
// Invoke the user callback -- the listen object is locked during the callback,
// but the associated call object is unlocked (to prevent deadlock if
// CC_AcceptCall() or CC_RejectCall() is called during the callback from a
// different thread, and the callback thread blocks pending completion of
// CC_AcceptCall() or CC_RejectCall())
InvokeUserListenCallback(pListen, Reason, &ListenCallbackParams);
// Need to validate the listen handle; the associated object may have been
// deleted during the user callback by this thread
if (ValidateListen(hListen) == CC_OK) { HQ931LISTEN hQ931Listen = pListen->hQ931Listen; UnlockListen(pListen); status = Q931CancelListen(hQ931Listen); if (LockListen(hListen, &pListen) == CC_OK) { FreeListen(pListen); } } }
HResultLeave(status); } // ListenReject()
HRESULT PlaceCallConfirm (void *pCallVoid, void *pConferenceVoid) { register PCALL pCall = (PCALL) pCallVoid; HRESULT status; ASSERT(GKIExists()); // Free Alias lists
if (pCall->GkiCall.pCalleeAliasNames != NULL) { Q931FreeAliasNames(pCall->GkiCall.pCalleeAliasNames); pCall->GkiCall.pCalleeAliasNames = NULL; } if (pCall->GkiCall.pCalleeExtraAliasNames != NULL) { Q931FreeAliasNames(pCall->GkiCall.pCalleeExtraAliasNames); pCall->GkiCall.pCalleeExtraAliasNames = NULL; }
if (pCall->pQ931PeerConnectAddr == NULL) { pCall->pQ931PeerConnectAddr = (PCC_ADDR)MemAlloc(sizeof(CC_ADDR)); if (pCall->pQ931PeerConnectAddr == NULL) return PlaceCallReject(pCallVoid, pConferenceVoid, CC_NO_MEMORY); }
pCall->pQ931PeerConnectAddr->nAddrType = CC_IP_BINARY; pCall->pQ931PeerConnectAddr->bMulticast = FALSE; pCall->pQ931PeerConnectAddr->Addr.IP_Binary.wPort = pCall->GkiCall.wPort; pCall->pQ931PeerConnectAddr->Addr.IP_Binary.dwAddr = ntohl(pCall->GkiCall.dwIpAddress);
status = PlaceCall(pCall, (PCONFERENCE)pConferenceVoid); if (status != CC_OK) PlaceCallReject(pCallVoid, pConferenceVoid, status); return status; } // PlaceCallConfirm()
HRESULT PlaceCallReject (void *pCallVoid, void *pConferenceVoid, HRESULT Reason) { register PCALL pCall = (PCALL) pCallVoid; register PCONFERENCE pConference = (PCONFERENCE) pConferenceVoid; CC_HCONFERENCE hConference; HRESULT status = CC_OK; CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams = {0}; CC_HCALL hCall; PCALL pCall2; ASSERT(GKIExists()); ASSERT(pCall != NULL); ASSERT(pConference != NULL);
// Free Alias lists
if (pCall->GkiCall.pCalleeAliasNames != NULL) { Q931FreeAliasNames(pCall->GkiCall.pCalleeAliasNames); pCall->GkiCall.pCalleeAliasNames = NULL; } if (pCall->GkiCall.pCalleeExtraAliasNames != NULL) { Q931FreeAliasNames(pCall->GkiCall.pCalleeExtraAliasNames); pCall->GkiCall.pCalleeExtraAliasNames = NULL; }
// Inform Call Control client of failure
ConnectCallbackParams.pNonStandardData = pCall->pPeerNonStandardData; ConnectCallbackParams.pszPeerDisplay = pCall->pszPeerDisplay; ConnectCallbackParams.bRejectReason = 0; ConnectCallbackParams.pTermCapList = pCall->pPeerH245TermCapList; ConnectCallbackParams.pH2250MuxCapability = pCall->pPeerH245H2250MuxCapability; ConnectCallbackParams.pTermCapDescriptors = pCall->pPeerH245TermCapDescriptors; ConnectCallbackParams.pLocalAddr = pCall->pQ931LocalConnectAddr; if (pCall->pQ931DestinationAddr == NULL) ConnectCallbackParams.pPeerAddr = pCall->pQ931PeerConnectAddr; else ConnectCallbackParams.pPeerAddr = pCall->pQ931DestinationAddr; ConnectCallbackParams.pVendorInfo = pCall->pPeerVendorInfo; if (pConference->ConferenceMode == MULTIPOINT_MODE) ConnectCallbackParams.bMultipointConference = TRUE; else ConnectCallbackParams.bMultipointConference = FALSE; ConnectCallbackParams.pConferenceID = &pConference->ConferenceID; ConnectCallbackParams.pMCAddress = pConference->pMultipointControllerAddr; ConnectCallbackParams.pAlternateAddress = NULL; ConnectCallbackParams.dwUserToken = pCall->dwUserToken; hConference = pConference->hConference; InvokeUserConferenceCallback(pConference, CC_CONNECT_INDICATION, Reason, &ConnectCallbackParams);
if (ValidateConference(hConference) == CC_OK) { // Start up an enqueued call, if one exists
for ( ; ; ) { status = RemoveEnqueuedCallFromConference(pConference, &hCall); if ((status != CC_OK) || (hCall == CC_INVALID_HANDLE)) break;
status = LockCall(hCall, &pCall2); if (status == CC_OK) { pCall2->CallState = PLACED;
status = PlaceCall(pCall2, pConference); UnlockCall(pCall2); if (status == CC_OK) break; } } }
HResultLeave(status); } // PlaceCallReject()
HRESULT AcceptCallConfirm (void *pCallVoid, void *pConferenceVoid) { CC_HCALL hCall = ((PCALL)pCallVoid)->hCall; CC_HCONFERENCE hConference = ((PCONFERENCE)pConferenceVoid)->hConference; HRESULT status; ASSERT(GKIExists()); status = AcceptCall((PCALL)pCallVoid, (PCONFERENCE)pConferenceVoid); LockConference(hConference, (PPCONFERENCE)&pConferenceVoid); LockCall(hCall, (PPCALL)&pCallVoid); if (status != CC_OK && pCallVoid != NULL && pConferenceVoid != NULL) AcceptCallReject(pCallVoid, pConferenceVoid, status); return status; } // AcceptCallConfirm()
HRESULT AcceptCallReject (void *pCallVoid, void *pConferenceVoid, HRESULT Reason) { register PCALL pCall = (PCALL) pCallVoid; register PCONFERENCE pConference = (PCONFERENCE) pConferenceVoid; HRESULT status = CC_OK; CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams = {0}; ASSERT(GKIExists()); status = Q931RejectCall(pCall->hQ931Call, // Q931 call handle
CC_REJECT_GATEKEEPER_RESOURCES, &pCall->ConferenceID, // Conference Identifier
NULL, // alternate address
pCall->pLocalNonStandardData);
ConnectCallbackParams.pNonStandardData = pCall->pPeerNonStandardData; ConnectCallbackParams.pszPeerDisplay = pCall->pszPeerDisplay; ConnectCallbackParams.bRejectReason = 0; ConnectCallbackParams.pTermCapList = pCall->pPeerH245TermCapList; ConnectCallbackParams.pH2250MuxCapability = pCall->pPeerH245H2250MuxCapability; ConnectCallbackParams.pTermCapDescriptors = pCall->pPeerH245TermCapDescriptors; ConnectCallbackParams.pLocalAddr = pCall->pQ931LocalConnectAddr; if (pCall->pQ931DestinationAddr == NULL) ConnectCallbackParams.pPeerAddr = pCall->pQ931PeerConnectAddr; else ConnectCallbackParams.pPeerAddr = pCall->pQ931DestinationAddr; if (pConference->ConferenceMode == MULTIPOINT_MODE) ConnectCallbackParams.bMultipointConference = TRUE; else ConnectCallbackParams.bMultipointConference = FALSE; ConnectCallbackParams.pVendorInfo = pCall->pPeerVendorInfo; ConnectCallbackParams.pConferenceID = &pConference->ConferenceID; ConnectCallbackParams.pMCAddress = pConference->pMultipointControllerAddr; ConnectCallbackParams.pAlternateAddress = NULL; ConnectCallbackParams.dwUserToken = pCall->dwUserToken;
InvokeUserConferenceCallback(pConference, CC_CONNECT_INDICATION, Reason, &ConnectCallbackParams);
HResultLeave(status); } // AcceptCallReject()
#if 0
HRESULT CancelCallConfirm (void *pCallVoid, void *pConferenceVoid) { PCALL pCall = (PCALL) pCallVoid; PCONFERENCE pConference = (PCONFERENCE) pConferenceVoid; HRESULT status; H245_INST_T H245Instance; HQ931CALL hQ931Call; CC_HCONFERENCE hConference; HRESULT SaveStatus; CC_HCALL hCall; ASSERT(GKIExists()); H245Instance = pCall->H245Instance; hQ931Call = pCall->hQ931Call; hConference = pCall->hConference; FreeCall(pCall);
if (H245Instance != H245_INVALID_ID) SaveStatus = H245ShutDown(H245Instance); else SaveStatus = H245_ERROR_OK;
if (SaveStatus == H245_ERROR_OK) { SaveStatus = Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON); // Q931Hangup may legitimately return CS_BAD_PARAM, because the Q.931 call object
// may have been deleted at this point
if (SaveStatus == CS_BAD_PARAM) SaveStatus = CC_OK; } else Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
// Start up an enqueued call, if one exists
for ( ; ; ) { status = RemoveEnqueuedCallFromConference(pConference, &hCall); if ((status != CC_OK) || (hCall == CC_INVALID_HANDLE)) break;
status = LockCall(hCall, &pCall); if (status == CC_OK) { pCall->CallState = PLACED;
status = PlaceCall(pCall, pConference); UnlockCall(pCall); if (status == CC_OK) break; } } UnlockConference(pConference);
if (SaveStatus != CC_OK) status = SaveStatus; HResultLeave(status); } // CancelCallConfirm()
HRESULT CancelCallReject (void *pCallVoid, void *pConferenceVoid) { // I don't care what the Gatekeeper says; I'm shutting down the call!
return CancelCallConfirm(pCallVoid, pConferenceVoid); } // CancelCallReject()
#endif
HRESULT OpenChannelConfirm (CC_HCHANNEL hChannel) { HRESULT status; PCHANNEL pChannel; PCONFERENCE pConference; WORD wNumCalls; PCC_HCALL CallList; HRESULT SaveStatus; unsigned i; PCALL pCall; ASSERT(GKIExists()); status = LockChannelAndConference(hChannel, &pChannel, &pConference); if (status == CC_OK) { // Open a logical channel for each established call
status = EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL); if (status == CC_OK) { SaveStatus = CC_OK; for (i = 0; i < wNumCalls; ++i) { if (LockCall(CallList[i], &pCall) == CC_OK) { status = H245OpenChannel(pCall->H245Instance, // H245 instance
pChannel->hChannel, // dwTransId
pChannel->wLocalChannelNumber, pChannel->pTxH245TermCap, // TxMode
pChannel->pTxMuxTable, // TxMux
H245_INVALID_PORT_NUMBER, // TxPort
pChannel->pRxH245TermCap, // RxMode
pChannel->pRxMuxTable, // RxMux
pChannel->pSeparateStack); if (status == H245_ERROR_OK) (pChannel->wNumOutstandingRequests)++; else SaveStatus = status; UnlockCall(pCall); } }
if (CallList != NULL) MemFree(CallList);
if (pChannel->wNumOutstandingRequests == 0) { // all open channel requests failed
FreeChannel(pChannel); } else { UnlockChannel(pChannel); }
if (SaveStatus != CC_OK) status = SaveStatus; } else { FreeChannel(pChannel); } UnlockConference(pConference); }
HResultLeave(status); } // OpenChannelConfirm()
HRESULT OpenChannelReject (CC_HCHANNEL hChannel, HRESULT Reason) { PCHANNEL pChannel; PCONFERENCE pConference; CC_HCONFERENCE hConference; HRESULT status; CC_TX_CHANNEL_OPEN_CALLBACK_PARAMS Params = {0}; ASSERT(GKIExists()); status = LockChannelAndConference(hChannel, &pChannel, &pConference); if (status == CC_OK) { // Inform Call Control client of failure
Params.hChannel = hChannel; Params.pPeerRTPAddr = pChannel->pPeerRTPAddr; Params.pPeerRTCPAddr = pChannel->pPeerRTCPAddr; Params.dwRejectReason = 0; Params.dwUserToken = pChannel->dwUserToken;
hConference = pConference->hConference; InvokeUserConferenceCallback(pConference, CC_TX_CHANNEL_OPEN_INDICATION, Reason, &Params);
if (ValidateChannel(hChannel) == CC_OK) FreeChannel(pChannel); if (ValidateConference(hConference) == CC_OK) UnlockConference(pConference); }
HResultLeave(status); } // OpenChannelReject()
HRESULT AcceptChannelConfirm(CC_HCHANNEL hChannel) { HRESULT status; PCHANNEL pChannel; PCONFERENCE pConference; CC_HCONFERENCE hConference; PCALL pCall; unsigned i; H245_MUX_T H245MuxTable; CC_ACCEPT_CHANNEL_CALLBACK_PARAMS Params; ASSERT(GKIExists()); status = LockChannelAndConference(hChannel, &pChannel, &pConference); if (status != CC_OK) HResultLeave(status);
status = LockCall(pChannel->hCall, &pCall); if (status != CC_OK) { UnlockChannel(pChannel); UnlockConference(pConference); HResultLeave(status); }
if (pChannel->wNumOutstandingRequests != 0) { PCC_ADDR pRTPAddr = pChannel->pLocalRTPAddr; PCC_ADDR pRTCPAddr = pChannel->pLocalRTCPAddr; if ((pChannel->bMultipointChannel) && (pConference->tsMultipointController == TS_TRUE)) { // Supply the RTP and RTCP addresses in the OpenLogicalChannelAck
if (pConference->pSessionTable != NULL) { for (i = 0; i < pConference->pSessionTable->wLength; ++i) { if (pConference->pSessionTable->SessionInfoArray[i].bSessionID == pChannel->bSessionID) { pRTPAddr = pConference->pSessionTable->SessionInfoArray[i].pRTPAddr; pRTCPAddr = pConference->pSessionTable->SessionInfoArray[i].pRTCPAddr; break; } } } }
H245MuxTable.Kind = H245_H2250ACK; H245MuxTable.u.H2250ACK.nonStandardList = NULL;
if (pRTPAddr != NULL) { if (pRTPAddr->bMulticast) H245MuxTable.u.H2250ACK.mediaChannel.type = H245_IP_MULTICAST; else H245MuxTable.u.H2250ACK.mediaChannel.type = H245_IP_UNICAST; H245MuxTable.u.H2250ACK.mediaChannel.u.ip.tsapIdentifier = pRTPAddr->Addr.IP_Binary.wPort; HostToH245IPNetwork(H245MuxTable.u.H2250ACK.mediaChannel.u.ip.network, pRTPAddr->Addr.IP_Binary.dwAddr); H245MuxTable.u.H2250ACK.mediaChannelPresent = TRUE; } else H245MuxTable.u.H2250ACK.mediaChannelPresent = FALSE;
if (pRTCPAddr != NULL) { if (pRTCPAddr->bMulticast) H245MuxTable.u.H2250ACK.mediaControlChannel.type = H245_IP_MULTICAST; else H245MuxTable.u.H2250ACK.mediaControlChannel.type = H245_IP_UNICAST; H245MuxTable.u.H2250ACK.mediaControlChannel.u.ip.tsapIdentifier = pRTCPAddr->Addr.IP_Binary.wPort; HostToH245IPNetwork(H245MuxTable.u.H2250ACK.mediaControlChannel.u.ip.network, pRTCPAddr->Addr.IP_Binary.dwAddr); H245MuxTable.u.H2250ACK.mediaControlChannelPresent = TRUE; } else H245MuxTable.u.H2250ACK.mediaControlChannelPresent = FALSE;
H245MuxTable.u.H2250ACK.dynamicRTPPayloadTypePresent = FALSE; H245MuxTable.u.H2250ACK.sessionIDPresent = TRUE; H245MuxTable.u.H2250ACK.sessionID = pChannel->bSessionID;
status = H245OpenChannelAccept(pCall->H245Instance, 0, // dwTransId
pChannel->wRemoteChannelNumber, // Rx channel
&H245MuxTable, 0, // Tx channel
NULL, // Tx mux
H245_INVALID_PORT_NUMBER,// Port
pChannel->pSeparateStack); if (status == CC_OK) pChannel->wNumOutstandingRequests = 0; else --(pChannel->wNumOutstandingRequests); }
pChannel->tsAccepted = TS_TRUE;
Params.hChannel = hChannel; if (status == CC_OK) UnlockChannel(pChannel); else FreeChannel(pChannel); UnlockCall(pCall);
hConference = pConference->hConference; InvokeUserConferenceCallback(pConference, CC_ACCEPT_CHANNEL_INDICATION, status, &Params); if (ValidateConference(hConference) == CC_OK) UnlockConference(pConference);
HResultLeave(status); } // AcceptChannelConfirm(void()
HRESULT AcceptChannelReject (CC_HCHANNEL hChannel, HRESULT Reason) { HRESULT status; PCHANNEL pChannel; PCONFERENCE pConference; CC_HCONFERENCE hConference; CC_ACCEPT_CHANNEL_CALLBACK_PARAMS Params; ASSERT(GKIExists()); status = LockChannelAndConference(hChannel, &pChannel, &pConference); if (status == CC_OK) { Params.hChannel = hChannel; FreeChannel(pChannel);
hConference = pConference->hConference; InvokeUserConferenceCallback(pConference, CC_ACCEPT_CHANNEL_INDICATION, Reason, &Params); if (ValidateConference(hConference) == CC_OK) UnlockConference(pConference); }
HResultLeave(status); } // AcceptChannelReject()
//
// Handle gratuitous messages from Gatekeeper
//
// Note: pCall assumed locked when called!
HRESULT Disengage(void *pCallVoid) { CC_HCALL hCall = ((PCALL)pCallVoid)->hCall; HRESULT status; UnlockCall((PCALL)pCallVoid); status = ProcessRemoteHangup(hCall, CC_INVALID_HANDLE, CC_REJECT_GATEKEEPER_TERMINATED); HResultLeave(status); } // Disengage()
// Note: pCall assumed locked when called!
HRESULT BandwidthShrunk(void *pCallVoid, void *pConferenceVoid, unsigned uBandwidthAllocated, long lBandwidthChange) { PCALL pCall = (PCALL) pCallVoid; PCONFERENCE pConference = (PCONFERENCE)pConferenceVoid; CC_BANDWIDTH_CALLBACK_PARAMS Params; ASSERT(GKIExists()); Params.hCall = pCall->hCall; Params.dwBandwidthTotal = uBandwidthAllocated; Params.lBandwidthChange = lBandwidthChange; InvokeUserConferenceCallback(pConference, CC_BANDWIDTH_CHANGED_INDICATION, CC_OK, &Params);
HResultLeave(CC_OK); } // BandwidthShrunk()
#else // GATEKEEPER
static char ch; // Kludge around warning C4206: nonstandard extension used : translation unit is empty
#endif // GATEKEEPER
|