Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

830 lines
18 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
channel.c
Abstract:
Routines to manipulate H.245 logical channels.
Environment:
User Mode - Win32
Revision History:
--*/
///////////////////////////////////////////////////////////////////////////////
// //
// Include files //
// //
///////////////////////////////////////////////////////////////////////////////
#include "globals.h"
#include "termcaps.h"
#include "callback.h"
#include "line.h"
///////////////////////////////////////////////////////////////////////////////
// //
// Private procedures //
// //
///////////////////////////////////////////////////////////////////////////////
BOOL
H323ResetChannel(
PH323_CHANNEL pChannel
)
/*++
Routine Description:
Resets channel object original state for re-use.
Arguments:
pChannel - Pointer to channel object to reset.
Return Values:
Returns true if successful.
--*/
{
// change channel state to allocated
pChannel->nState = H323_CHANNELSTATE_ALLOCATED;
// initialize stream description
memset(&pChannel->Settings,0,sizeof(STREAMSETTINGS));
// uninitialize msp channel handle
pChannel->hmChannel = NULL;
// uninitialize channel handle
pChannel->hccChannel = UNINITIALIZED;
// reset local addresses and sync up RTCP ports
pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr = 0;
pChannel->ccLocalRTCPAddr.Addr.IP_Binary.dwAddr = 0;
pChannel->ccLocalRTCPAddr.Addr.IP_Binary.wPort =
pChannel->ccLocalRTPAddr.Addr.IP_Binary.wPort + 1;
// reset remote addresses (including port numbers)
pChannel->ccRemoteRTPAddr.Addr.IP_Binary.dwAddr = 0;
pChannel->ccRemoteRTPAddr.Addr.IP_Binary.wPort = 0;
pChannel->ccRemoteRTCPAddr.Addr.IP_Binary.dwAddr = 0;
pChannel->ccRemoteRTCPAddr.Addr.IP_Binary.wPort = 0;
// initialize caps
memset(&pChannel->ccTermCaps,0,sizeof(CC_TERMCAP));
// initialize other info
pChannel->bPayloadType = (BYTE)UNINITIALIZED;
pChannel->bSessionID = (BYTE)UNINITIALIZED;
// initialize direction
pChannel->fInbound = FALSE;
// success
return TRUE;
}
BOOL
H323AllocChannel(
PH323_CHANNEL * ppChannel
)
/*++
Routine Description:
Allocates new channel object.
Arguments:
ppChannel - Pointer to DWORD-sized value in which service provider
must place the newly allocated channel object.
Return Values:
Returns true if successful.
--*/
{
PH323_CHANNEL pChannel = NULL;
// allocate channel object
pChannel = H323HeapAlloc(sizeof(H323_CHANNEL));
// validate pointer
if (pChannel == NULL) {
H323DBG((
DEBUG_LEVEL_ERROR,
"could not allocate channel object.\n"
));
// failure
return FALSE;
}
H323DBG((
DEBUG_LEVEL_VERBOSE,
"channel 0x%08lx allocated.\n",
pChannel
));
// reset channel object
H323ResetChannel(pChannel);
// transfer pointer
*ppChannel = pChannel;
// success
return TRUE;
}
BOOL
H323FreeChannel(
PH323_CHANNEL pChannel
)
/*++
Routine Description:
Release memory associated with channel.
Arguments:
pChannel - Pointer to channel to release.
Return Values:
Returns true if successful.
--*/
{
// release memory
H323HeapFree(pChannel);
H323DBG((
DEBUG_LEVEL_VERBOSE,
"channel 0x%08lx released.\n",
pChannel
));
// success
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Public procedures //
// //
///////////////////////////////////////////////////////////////////////////////
BOOL
H323OpenChannel(
PH323_CHANNEL pChannel
)
/*++
Routine Description:
Opens channel to destination address.
Arguments:
pChannel - Pointer to channel to open.
Return Values:
Returns true if successful.
--*/
{
HRESULT hr;
// open channel
hr = CC_OpenChannel(
pChannel->pCall->hccConf, // hConference
&pChannel->hccChannel, // phChannel
pChannel->bSessionID, // bSessionID
0, // bAssociatedSessionID
TRUE, // bSilenceSuppression
&pChannel->ccTermCaps, // pTermCap
&pChannel->ccLocalRTCPAddr, // pLocalRTCPAddr
0, // bDynamicRTPPayloadType
0, // dwChannelBitRate
PtrToUlong(pChannel->pCall->hdCall) // dwUserToken
);
// validate
if (hr != CC_OK) {
H323DBG((
DEBUG_LEVEL_ERROR,
"error %s (0x%08lx) opening channel 0x%08lx.\n",
H323StatusToString((DWORD)hr), hr,
pChannel
));
// failure
return FALSE;
}
// change channel state to opening
pChannel->nState = H323_CHANNELSTATE_OPENING;
H323DBG((
DEBUG_LEVEL_VERBOSE,
"channel 0x%08lx opening.\n",
pChannel
));
// success
return TRUE;
}
BOOL
H323CloseChannel(
PH323_CHANNEL pChannel
)
/*++
Routine Description:
Closes channel.
Arguments:
pChannel - Pointer to channel to close.
Return Values:
Returns true if successful.
--*/
{
HRESULT hr;
// see if channel opened
if (H323IsChannelOpen(pChannel) &&
H323IsCallActive(pChannel->pCall)) {
// give peer close channel indication
hr = CC_CloseChannel(pChannel->hccChannel);
// validate status
if (hr != CC_OK) {
H323DBG((
DEBUG_LEVEL_ERROR,
"error %s (0x%08lx) closing channel 0x%08lx.\n",
H323StatusToString((DWORD)hr), hr,
pChannel
));
//
// Could not close channel so just
// mark as closed and continue...
//
}
}
// mark entry as allocated
H323FreeChannelFromTable(pChannel,pChannel->pCall->pChannelTable);
H323DBG((
DEBUG_LEVEL_VERBOSE,
"channel 0x%08lx closed.\n",
pChannel
));
// success
return TRUE;
}
BOOL
H323AllocChannelTable(
PH323_CHANNEL_TABLE * ppChannelTable
)
/*++
Routine Description:
Allocates table of channel objects.
Arguments:
ppChannelTable - Pointer to DWORD-sized value which service
provider must fill in with newly allocated table.
Return Values:
Returns true if successful.
--*/
{
PH323_CHANNEL_TABLE pChannelTable;
// allocate table from heap
pChannelTable = H323HeapAlloc(
sizeof(H323_CHANNEL_TABLE) +
sizeof(PH323_CHANNEL) * H323_DEFMEDIAPERCALL
);
// validate table pointer
if (pChannelTable == NULL) {
H323DBG((
DEBUG_LEVEL_ERROR,
"could not allocate channel table.\n"
));
// failure
return FALSE;
}
// initialize number of entries in table
pChannelTable->dwNumSlots = H323_DEFMEDIAPERCALL;
// transfer pointer to caller
*ppChannelTable = pChannelTable;
// success
return TRUE;
}
BOOL
H323FreeChannelTable(
PH323_CHANNEL_TABLE pChannelTable
)
/*++
Routine Description:
Deallocates table of channel objects.
Arguments:
pChannelTable - Pointer to channel table to release.
Return Values:
Returns true if successful.
--*/
{
DWORD i;
// loop through each object in table
for (i = 0; i < pChannelTable->dwNumSlots; i++) {
// validate object has been allocated
if (H323IsChannelAllocated(pChannelTable->pChannels[i])) {
// release memory for object
H323FreeChannel(pChannelTable->pChannels[i]);
}
}
// release memory for table
H323HeapFree(pChannelTable);
// success
return TRUE;
}
BOOL
H323CloseChannelTable(
PH323_CHANNEL_TABLE pChannelTable
)
/*++
Routine Description:
Closes table of channel objects.
Arguments:
pChannelTable - Pointer to channel table to close.
Return Values:
Returns true if successful.
--*/
{
DWORD i;
// loop through each object in table
for (i = 0; i < pChannelTable->dwNumSlots; i++) {
// validate object is in use
if (H323IsChannelInUse(pChannelTable->pChannels[i])) {
// close channel object
H323CloseChannel(pChannelTable->pChannels[i]);
}
}
// success
return TRUE;
}
BOOL
H323AllocChannelFromTable(
PH323_CHANNEL * ppChannel,
PH323_CHANNEL_TABLE * ppChannelTable,
PH323_CALL pCall
)
/*++
Routine Description:
Allocates channel object in table.
Arguments:
ppChannel - Specifies a pointer to a DWORD-sized value in which the
service provider must write the allocated channel object.
ppChannelTable - Pointer to pointer to channel table in which to
allocate channel from (expands table if necessary).
pCall - Pointer to containing call object.
Return Values:
Returns true if successful.
--*/
{
DWORD i;
PH323_CHANNEL pChannel = NULL;
PH323_CHANNEL_TABLE pChannelTable = *ppChannelTable;
// retrieve index to next entry
i = pChannelTable->dwNextAvailable;
// see if previously allocated entries available
if (pChannelTable->dwNumAllocated > pChannelTable->dwNumInUse) {
// search table looking for available entry
while (H323IsChannelInUse(pChannelTable->pChannels[i]) ||
!H323IsChannelAllocated(pChannelTable->pChannels[i])) {
// increment index and adjust to wrap
i = H323GetNextIndex(i, pChannelTable->dwNumSlots);
}
// retrieve pointer to object
pChannel = pChannelTable->pChannels[i];
// mark entry as being in use
pChannel->nState = H323_CHANNELSTATE_CLOSED;
// re-initialize rtp address
pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr =
H323IsCallInbound(pCall)
? pCall->ccCalleeAddr.Addr.IP_Binary.dwAddr
: pCall->ccCallerAddr.Addr.IP_Binary.dwAddr
;
// re-initialize rtcp address
pChannel->ccLocalRTCPAddr.Addr.IP_Binary.dwAddr =
pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr;
// increment number in use
pChannelTable->dwNumInUse++;
// adjust next available index
pChannelTable->dwNextAvailable =
H323GetNextIndex(i, pChannelTable->dwNumSlots);
// transfer pointer
*ppChannel = pChannel;
// success
return TRUE;
}
// see if table is full and more slots need to be allocated
if (pChannelTable->dwNumAllocated == pChannelTable->dwNumSlots) {
// attempt to double table
pChannelTable = H323HeapReAlloc(
pChannelTable,
sizeof(H323_CHANNEL_TABLE) +
pChannelTable->dwNumSlots * 2 * sizeof(PH323_CHANNEL)
);
// validate pointer
if (pChannelTable == NULL) {
H323DBG((
DEBUG_LEVEL_ERROR,
"could not expand channel table.\n"
));
// failure
return FALSE;
}
// adjust index into table
i = pChannelTable->dwNumSlots;
// adjust number of slots
pChannelTable->dwNumSlots *= 2;
// transfer pointer to caller
*ppChannelTable = pChannelTable;
}
// allocate new object
if (!H323AllocChannel(&pChannel)) {
// failure
return FALSE;
}
// search table looking for slot with no object allocated
while (H323IsChannelAllocated(pChannelTable->pChannels[i])) {
// increment index and adjust to wrap
i = H323GetNextIndex(i, pChannelTable->dwNumSlots);
}
// store pointer to object
pChannelTable->pChannels[i] = pChannel;
// mark entry as being in use
pChannel->nState = H323_CHANNELSTATE_CLOSED;
// initialize rtp address
pChannel->ccLocalRTPAddr.nAddrType = CC_IP_BINARY;
pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr =
H323IsCallInbound(pCall)
? pCall->ccCalleeAddr.Addr.IP_Binary.dwAddr
: pCall->ccCallerAddr.Addr.IP_Binary.dwAddr
;
pChannel->ccLocalRTPAddr.Addr.IP_Binary.wPort =
LOWORD(pCall->pLine->dwNextPort++);
pChannel->ccLocalRTPAddr.bMulticast = FALSE;
// initialize rtcp address
pChannel->ccLocalRTCPAddr.nAddrType = CC_IP_BINARY;
pChannel->ccLocalRTCPAddr.Addr.IP_Binary.dwAddr =
pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr;
pChannel->ccLocalRTCPAddr.Addr.IP_Binary.wPort =
LOWORD(pCall->pLine->dwNextPort++);
pChannel->ccLocalRTCPAddr.bMulticast = FALSE;
// increment number in use
pChannelTable->dwNumInUse++;
// increment number allocated
pChannelTable->dwNumAllocated++;
// adjust next available index
pChannelTable->dwNextAvailable =
H323GetNextIndex(i, pChannelTable->dwNumSlots);
#if DBG
{
DWORD dwIPAddr;
dwIPAddr = htonl(pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr);
H323DBG((
DEBUG_LEVEL_VERBOSE,
"channel 0x%08lx stored in slot %d (%s:%d).\n",
pChannel, i,
H323AddrToString(dwIPAddr),
pChannel->ccLocalRTPAddr.Addr.IP_Binary.wPort
));
}
#endif
// transfer pointer
*ppChannel = pChannel;
// success
return TRUE;
}
BOOL
H323FreeChannelFromTable(
PH323_CHANNEL pChannel,
PH323_CHANNEL_TABLE pChannelTable
)
/*++
Routine Description:
Deallocates channel object in table.
Arguments:
pChannel - Pointer to object to deallocate.
pChannelTable - Pointer to table containing object.
Return Values:
Returns true if successful.
--*/
{
// reset channel object
H323ResetChannel(pChannel);
// decrement entries in use
pChannelTable->dwNumInUse--;
// success
return TRUE;
}
BOOL
H323LookupChannelByHandle(
PH323_CHANNEL * ppChannel,
PH323_CHANNEL_TABLE pChannelTable,
CC_HCHANNEL hccChannel
)
/*++
Routine Description:
Looks up channel based on handle returned from call control module.
Arguments:
ppChannel - Specifies a pointer to a DWORD-sized value in which the
service provider must write the channel associated with the
call control handle specified.
pChannelTable - Pointer to channel table to search.
hccChannel - Handle return by call control module.
Return Values:
Returns true if successful.
--*/
{
DWORD i;
// loop through each channel in table
for (i = 0; i < pChannelTable->dwNumSlots; i++) {
// see if channel handle matches the one specified
if (H323IsChannelEqual(pChannelTable->pChannels[i],hccChannel)) {
// tranfer channel pointer to caller
*ppChannel = pChannelTable->pChannels[i];
// success
return TRUE;
}
}
// failure
return FALSE;
}
BOOL
H323LookupChannelBySessionID(
PH323_CHANNEL * ppChannel,
PH323_CHANNEL_TABLE pChannelTable,
BYTE bSessionID
)
/*++
Routine Description:
Looks up channel based on session ID negotiated.
Arguments:
ppChannel - Specifies a pointer to a DWORD-sized value in which the
service provider must write the channel associated with the
call control handle specified.
pChannelTable - Pointer to channel table to search.
bSessionID - session id.
Return Values:
Returns true if successful.
--*/
{
DWORD i;
// loop through each channel in table
for (i = 0; i < pChannelTable->dwNumSlots; i++) {
// see if channel handle matches the one specified
if (H323IsSessionIDEqual(pChannelTable->pChannels[i],bSessionID)) {
// tranfer channel pointer to caller
*ppChannel = pChannelTable->pChannels[i];
// success
return TRUE;
}
}
// failure
return FALSE;
}
BOOL
H323AreThereOutgoingChannels(
PH323_CHANNEL_TABLE pChannelTable,
BOOL fIgnoreOpenChannels
)
/*++
Routine Description:
Searchs for outgoing channel objects.
Arguments:
pChannelTable - Pointer to channel table to search.
fIgnoreOpenChannels - Restricts search to unopened channels.
Return Values:
Returns true if successful.
--*/
{
DWORD i;
BOOL fFoundOk = FALSE;
// loop through each channel in table
for (i = 0; i < pChannelTable->dwNumSlots; i++) {
// see if channel is in use and outbound
if (H323IsChannelInUse(pChannelTable->pChannels[i]) &&
!H323IsChannelInbound(pChannelTable->pChannels[i]) &&
(!H323IsChannelOpen(pChannelTable->pChannels[i]) ||
!fIgnoreOpenChannels)) {
// success
return TRUE;
}
}
// failure
return FALSE;
}