|
|
/*++
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; }
|