615 lines
21 KiB
C
615 lines
21 KiB
C
/****************************************************************************
|
|
*
|
|
* $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
|
|
|
|
#pragma warning ( disable : 4057 4115 4201 4214 )
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#pragma warning ( default : 4115 4201 4214 )
|
|
#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 (DWORD hListen, HRESULT Reason)
|
|
{
|
|
HRESULT status;
|
|
PLISTEN pListen;
|
|
CC_LISTEN_CALLBACK_PARAMS ListenCallbackParams;
|
|
|
|
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;
|
|
|
|
// 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)Malloc(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(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;
|
|
|
|
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};
|
|
|
|
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;
|
|
|
|
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 (DWORD hChannel)
|
|
{
|
|
HRESULT status;
|
|
PCHANNEL pChannel;
|
|
PCONFERENCE pConference;
|
|
WORD wNumCalls;
|
|
PCC_HCALL CallList;
|
|
HRESULT SaveStatus;
|
|
unsigned i;
|
|
PCALL pCall;
|
|
|
|
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)
|
|
Free(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 (DWORD hChannel, HRESULT Reason)
|
|
{
|
|
PCHANNEL pChannel;
|
|
PCONFERENCE pConference;
|
|
CC_HCONFERENCE hConference;
|
|
HRESULT status;
|
|
CC_TX_CHANNEL_OPEN_CALLBACK_PARAMS Params = {0};
|
|
|
|
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(DWORD hChannel)
|
|
{
|
|
HRESULT status;
|
|
PCHANNEL pChannel;
|
|
PCONFERENCE pConference;
|
|
CC_HCONFERENCE hConference;
|
|
PCALL pCall;
|
|
unsigned i;
|
|
H245_MUX_T H245MuxTable;
|
|
CC_ACCEPT_CHANNEL_CALLBACK_PARAMS Params;
|
|
|
|
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 (DWORD hChannel, HRESULT Reason)
|
|
{
|
|
HRESULT status;
|
|
PCHANNEL pChannel;
|
|
PCONFERENCE pConference;
|
|
CC_HCONFERENCE hConference;
|
|
CC_ACCEPT_CHANNEL_CALLBACK_PARAMS Params;
|
|
|
|
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;
|
|
|
|
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
|