|
|
/****************************************************************************
* * $Archive: S:/STURGEON/SRC/Q931/VCS/q931pdu.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.67.1.1 $ * $Date: 20 Jun 1997 14:13:22 $ * $Author: MANDREWS $ * * Deliverable: * * Abstract: Parser routines for Q931 PDUs * * Notes: * ***************************************************************************/ #pragma comment (exestr, "$Workfile: q931pdu.c $ $Revision: 1.67.1.1 $")
// [ ] Do another integration of own q931test area.
// [ ] Alias values displayed in tracing routines.
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// STANDARDS ISSUES
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// [ ] !!! EndpointType contains MC info, so Setup_UUIE doesnt need MC field !!!
// [ ] !!! Need to decide how CallType is to be used !!!
// [ ] !!! ALERTING message is missing the ConferenceID field !!!
// [ ] !!! Place needed for Caller and Callee transport addr, or else explanation of how this information is available round-trip !!!
// [ ] !!! FACILITY message is missing the protocolIdentifier field !!!
//------------------------------------------------------------------------------
// Note: These parsing details have not yet been supported:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// 1) variable octet fields having extending groups,
// extending indications, or escape for extensions. (See 4.5.1)
// 2) codeset recognition and exclusion based on SHIFT (See 4.5.2)
// 3) correct ignoring of escapes for nationally specific message types.
// 4) The call reference value is 2 bytes long sizeof(WORD).
// A call reference of 0 means, the message pertains to all
// calls on the same data link.
//------------------------------------------------------------------------------
#pragma warning ( disable : 4100 4115 4201 4214 4514 )
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <string.h>
#include "q931asn.h"
#include "q931asn1.h"
#include "common.h"
#include "q931.h"
#include "isrg.h"
#include "utils.h"
#include "q931pdu.h"
#ifdef UNICODE_TRACE
// We include this header to fix problems with macro expansion when Unicode is turned on.
#include "unifix.h"
#endif
//==========================================================
// CALLED PARTY FIELD DEFINITIONS
//==========================================================
// called party encoding bits...
#define CALLED_PARTY_EXT_BIT 0x80
// called party number type
#define CALLED_PARTY_TYPE_UNKNOWN 0x00
// ...other types are not defined because they are not used...
// called party numbering plan
#define CALLED_PARTY_PLAN_E164 0x01
// ...other plans are not defined because they are not used...
//==========================================================
// BEARER FIELD DEFINITIONS
//==========================================================
// bearer encoding bits...
#define BEAR_EXT_BIT 0x80
// bearer coding standards...
#define BEAR_CCITT 0x00
// ...others not needed...
// bearer information transfer capability...
#define BEAR_UNRESTRICTED_DIGITAL 0x08
// ...others not needed...
// bearer transfer mode...
#define BEAR_CIRCUIT_MODE 0x00
#define BEAR_PACKET_MODE 0x40
// ...others not needed...
// bearer information transfer rate...
#define BEAR_NO_CIRCUIT_RATE 0x00
#define BEAR_MULTIRATE 0x18
// ...others not needed...
// bearer layer1 protocol...
#define BEAR_LAYER1_INDICATOR 0x20
#define BEAR_LAYER1_H221_H242 0x05
// ...others not needed...
#define Q931_PROTOCOL_ID1 0
#define Q931_PROTOCOL_ID2 0
#define Q931_PROTOCOL_ID3 8
#define Q931_PROTOCOL_ID4 2250
#define Q931_PROTOCOL_ID5 0
#define Q931_PROTOCOL_ID6 1
static struct ObjectID_ ProtocolId1; static struct ObjectID_ ProtocolId2; static struct ObjectID_ ProtocolId3; static struct ObjectID_ ProtocolId4; static struct ObjectID_ ProtocolId5; static struct ObjectID_ ProtocolId6;
static struct _seqof1 TempProtocol;
MESSAGEIDTYPE MessageSet[] = { ALERTINGMESSAGETYPE, PROCEEDINGMESSAGETYPE, CONNECTMESSAGETYPE, CONNECTACKMESSAGETYPE, PROGRESSMESSAGETYPE, SETUPMESSAGETYPE, SETUPACKMESSAGETYPE,
RESUMEMESSAGETYPE, RESUMEACKMESSAGETYPE, RESUMEREJMESSAGETYPE, SUSPENDMESSAGETYPE, SUSPENDACKMESSAGETYPE, SUSPENDREJMESSAGETYPE, USERINFOMESSAGETYPE,
DISCONNECTMESSAGETYPE, RELEASEMESSAGETYPE, RELEASECOMPLMESSAGETYPE, RESTARTMESSAGETYPE, RESTARTACKMESSAGETYPE,
SEGMENTMESSAGETYPE, CONGCTRLMESSAGETYPE, INFORMATIONMESSAGETYPE, NOTIFYMESSAGETYPE, STATUSMESSAGETYPE, STATUSENQUIRYMESSAGETYPE,
HOLDMESSAGETYPE, HOLDACKMESSAGETYPE, HOLDREJECTMESSAGETYPE, RETRIEVEMESSAGETYPE, RETRIEVEACKMESSAGETYPE, RETRIEVEREJECTMESSAGETYPE, FACILITYMESSAGETYPE, REGISTERMESSAGETYPE };
//====================================================================================
//====================================================================================
static CS_STATUS AliasToSeqof(struct _seqof3 **ppTarget, PCC_ALIASNAMES pSource) { if (ppTarget == NULL) { return CS_BAD_PARAM; } *ppTarget = NULL; if (pSource == NULL) { return CS_OK; } if (pSource && (pSource->wCount)) { struct _seqof3 *ListHead = NULL; struct _seqof3 *CurrentNode = NULL; LPWSTR pData = NULL; // UNICODE STRING
int SourceItem; WORD x;
for (SourceItem = pSource->wCount - 1; SourceItem >= 0; SourceItem--) { BOOL Cleanup = FALSE;
// first do the required memory allocations...
CurrentNode = (struct _seqof3 *)Malloc(sizeof(struct _seqof3)); if (CurrentNode == NULL) { Cleanup = TRUE; } else { if (pSource->pItems[SourceItem].wType == CC_ALIAS_H323_ID) { if ((pSource->pItems[SourceItem].wDataLength != 0) && (pSource->pItems[SourceItem].pData != NULL)) { pData = (LPWSTR)Malloc(pSource->pItems[SourceItem].wDataLength * sizeof(WCHAR)); if (pData == NULL) { Free(CurrentNode); Cleanup = TRUE; } } } } if (Cleanup) { for (CurrentNode = ListHead; CurrentNode; CurrentNode = ListHead) { ListHead = CurrentNode->next; if (CurrentNode->value.choice == h323_ID_chosen) { if (CurrentNode->value.u.h323_ID.value) { Free(CurrentNode->value.u.h323_ID.value); } } Free(CurrentNode); } return CS_NO_MEMORY; }
// then do the required memory copying.
if (pSource->pItems[SourceItem].wType == CC_ALIAS_H323_ID) { CurrentNode->value.choice = h323_ID_chosen; if ((pSource->pItems[SourceItem].wDataLength != 0) && (pSource->pItems[SourceItem].pData != NULL)) { CurrentNode->value.u.h323_ID.length = pSource->pItems[SourceItem].wDataLength; for (x = 0; x < pSource->pItems[SourceItem].wDataLength; x++) { pData[x] = pSource->pItems[SourceItem].pData[x]; } CurrentNode->value.u.h323_ID.value = pData; } else { CurrentNode->value.u.h323_ID.length = 0; CurrentNode->value.u.h323_ID.value = NULL; } } else if (pSource->pItems[SourceItem].wType == CC_ALIAS_H323_PHONE) { CurrentNode->value.choice = e164_chosen; if ((pSource->pItems[SourceItem].wDataLength != 0) && (pSource->pItems[SourceItem].pData != NULL)) { for (x = 0; x < pSource->pItems[SourceItem].wDataLength; x++) { CurrentNode->value.u.e164[x] = (BYTE)(pSource->pItems[SourceItem].pData[x]); } CurrentNode->value.u.e164[pSource->pItems[SourceItem].wDataLength] = '\0'; } else { CurrentNode->value.u.e164[0] = '\0'; } } CurrentNode->next = ListHead; ListHead = CurrentNode; } *ppTarget = ListHead; } return CS_OK; }
//====================================================================================
//====================================================================================
static CS_STATUS AliasWithPrefixToSeqof(struct _seqof3 **ppTarget, PCC_ALIASNAMES pSource) { if (ppTarget == NULL) { return CS_BAD_PARAM; } *ppTarget = NULL; if (pSource == NULL) { return CS_OK; } if (pSource && (pSource->wCount)) { struct _seqof3 *ListHead = NULL; struct _seqof3 *CurrentNode = NULL; int SourceItem;
for (SourceItem = pSource->wCount - 1; SourceItem >= 0; SourceItem--) { PCC_ALIASITEM pItem = &pSource->pItems[SourceItem]; LPWSTR pData = NULL; // UNICODE STRING
BOOL Cleanup = FALSE; unsigned uPrefixLength; unsigned uDataLength; unsigned x; if (pItem->pPrefix != NULL && pItem->wPrefixLength > 0) { uPrefixLength = (unsigned) pItem->wPrefixLength; } else { uPrefixLength = 0; }
if (pItem->pData != NULL && pItem->wDataLength > 0) { uDataLength = (unsigned) pItem->wDataLength; } else { uDataLength = 0; }
// first do the required memory allocations...
CurrentNode = (struct _seqof3 *)Malloc(sizeof(struct _seqof3)); if (CurrentNode == NULL) { Cleanup = TRUE; } else { if (pItem->wType == CC_ALIAS_H323_ID) { #ifdef USE_PREFIX_FOR_H323_ID
if (uPrefixLength != 0 || uDataLength != 0) { pData = (LPWSTR)Malloc((uPrefixLength + uDataLength) * sizeof(WCHAR)); #else
if (uDataLength != 0) { pData = (LPWSTR)Malloc((uDataLength) * sizeof(WCHAR)); #endif
if (pData == NULL) { Free(CurrentNode); Cleanup = TRUE; } } } } if (Cleanup) { for (CurrentNode = ListHead; CurrentNode; CurrentNode = ListHead) { ListHead = CurrentNode->next; if (CurrentNode->value.choice == h323_ID_chosen) { if (CurrentNode->value.u.h323_ID.value) { Free(CurrentNode->value.u.h323_ID.value); } } Free(CurrentNode); } return CS_NO_MEMORY; }
// then do the required memory copying.
switch (pItem->wType) { case CC_ALIAS_H323_ID: CurrentNode->value.choice = h323_ID_chosen; #ifdef USE_PREFIX_FOR_H323_ID
if (uPrefixLength != 0 || uDataLength != 0) { CurrentNode->value.u.h323_ID.length = (WORD)(uPrefixLength + uDataLength); for (x = 0; x < uPrefixLength; ++x) { pData[x] = pItem->pPrefix[x]; } for (x = 0; x < uDataLength; ++x) { pData[uPrefixLength + x] = pItem->pData[x]; } #else
if (uDataLength != 0) { CurrentNode->value.u.h323_ID.length = (WORD)(uDataLength); for (x = 0; x < uDataLength; ++x) { pData[x] = pItem->pData[x]; } #endif
CurrentNode->value.u.h323_ID.value = pData; } else { CurrentNode->value.u.h323_ID.length = 0; CurrentNode->value.u.h323_ID.value = NULL; } break;
case CC_ALIAS_H323_PHONE: CurrentNode->value.choice = e164_chosen; for (x = 0; x < uPrefixLength; ++x) { CurrentNode->value.u.e164[x] = (BYTE)(pItem->pPrefix[x]); } for (x = 0; x < uDataLength; ++x) { CurrentNode->value.u.e164[uPrefixLength + x] = (BYTE)(pItem->pData[x]); } for (x = uDataLength + uPrefixLength; x < sizeof(CurrentNode->value.u.e164); ++x) { CurrentNode->value.u.e164[x] = 0; } break;
default: Free(CurrentNode); for (CurrentNode = ListHead; CurrentNode; CurrentNode = ListHead) { ListHead = CurrentNode->next; if (CurrentNode->value.choice == h323_ID_chosen) { if (CurrentNode->value.u.h323_ID.value) { Free(CurrentNode->value.u.h323_ID.value); } } Free(CurrentNode); } return CS_BAD_PARAM; } // switch
CurrentNode->next = ListHead; ListHead = CurrentNode; } *ppTarget = ListHead; } return CS_OK; }
//====================================================================================
//====================================================================================
static CS_STATUS SeqofToAlias(PCC_ALIASNAMES *ppTarget, struct _seqof3 *pSource) { struct _seqof3 *ListHead = NULL; struct _seqof3 *CurrentNode = NULL; WORD wCount; WORD x = 0; PCC_ALIASITEM p = NULL; CS_STATUS status = CS_OK;
if (ppTarget == NULL) { return CS_BAD_PARAM; } *ppTarget = NULL; if (pSource == NULL) { return CS_OK; }
wCount = 0; for (CurrentNode = pSource; CurrentNode; CurrentNode = CurrentNode->next) { wCount++; }
*ppTarget = (PCC_ALIASNAMES)Malloc(sizeof(CC_ALIASNAMES)); if (*ppTarget == NULL) { return CS_NO_MEMORY; }
(*ppTarget)->pItems = (PCC_ALIASITEM)Malloc(wCount * sizeof(CC_ALIASITEM)); if ((*ppTarget)->pItems == NULL) { Free(*ppTarget); *ppTarget = NULL; return CS_NO_MEMORY; }
p = (*ppTarget)->pItems;
for (CurrentNode = pSource; CurrentNode; CurrentNode = CurrentNode->next) { WORD y;
p[x].wPrefixLength = 0; p[x].pPrefix = NULL;
switch (CurrentNode->value.choice) { case h323_ID_chosen: p[x].wType = CC_ALIAS_H323_ID; if ((CurrentNode->value.u.h323_ID.length != 0) && (CurrentNode->value.u.h323_ID.value != NULL)) { p[x].wDataLength = (WORD)CurrentNode->value.u.h323_ID.length; p[x].pData = (LPWSTR)Malloc(CurrentNode->value.u.h323_ID.length * sizeof(p[x].pData[0])); if (p[x].pData != NULL) { for (y = 0; y < CurrentNode->value.u.h323_ID.length; y++) { p[x].pData[y] = (WCHAR)((CurrentNode->value.u.h323_ID.value)[y]); } x++; } else { status = CS_NO_MEMORY; } } break;
case e164_chosen: p[x].wType = CC_ALIAS_H323_PHONE; p[x].wDataLength = (WORD)strlen(CurrentNode->value.u.e164); p[x].pData = (LPWSTR)Malloc((p[x].wDataLength+1) * sizeof(p[x].pData[0])); if (p[x].pData != NULL) { for (y = 0; y < p[x].wDataLength; y++) { p[x].pData[y] = CurrentNode->value.u.e164[y]; } p[x].pData[p[x].wDataLength] = 0; x++; } else { status = CS_NO_MEMORY; } break;
default: // we don't currently handle other alias types
break; } // switch
if (status != CS_OK) { // Free everything that has been allocated so far...
for (y = 0; y < x; y++) { Free(p[y].pData); } Free(p); Free(*ppTarget); *ppTarget = NULL; return status; } }
// any aliases?
if (x > 0) {
// save number of aliases
(*ppTarget)->wCount = x;
} else {
//
// Note Q931FreeAliasNames does not free CC_ALIASNAMES structure
// when wCount is set to zero
//
Free(p); Free(*ppTarget); *ppTarget = NULL; }
return CS_OK; }
//====================================================================================
//====================================================================================
static CS_STATUS FreeSeqof(struct _seqof3 *pSource) { struct _seqof3 *CurrentNode = NULL;
for (CurrentNode = pSource; CurrentNode; CurrentNode = pSource) { pSource = CurrentNode->next; if (CurrentNode->value.choice == h323_ID_chosen) { if (CurrentNode->value.u.h323_ID.value) { Free(CurrentNode->value.u.h323_ID.value); } } Free(CurrentNode); } return CS_OK; }
//====================================================================================
//====================================================================================
static CS_STATUS Q931CopyAliasItemToAliasAddr(AliasAddress *pTarget, PCC_ALIASITEM pSource) { AliasAddress *pNewAddress = NULL; WORD x;
if (pTarget == NULL) { return CS_BAD_PARAM; } if (pSource == NULL) { return CS_BAD_PARAM; }
pNewAddress = pTarget;
if (pSource->wType == CC_ALIAS_H323_ID) { pNewAddress->choice = h323_ID_chosen; if ((pSource->wDataLength != 0) && (pSource->pData != NULL)) { LPWSTR pData = NULL; // UNICODE STRING
pData = (LPWSTR)Malloc(pSource->wDataLength * sizeof(WCHAR)); if (pData == NULL) { return CS_NO_MEMORY; } pNewAddress->u.h323_ID.length = pSource->wDataLength; for (x = 0; x < pSource->wDataLength; x++) { pData[x] = pSource->pData[x]; } pNewAddress->u.h323_ID.value = pData; } else { pNewAddress->u.h323_ID.length = 0; pNewAddress->u.h323_ID.value = NULL; } } else if (pSource->wType == CC_ALIAS_H323_PHONE) { pNewAddress->choice = e164_chosen; if ((pSource->wDataLength != 0) && (pSource->pData != NULL)) { for (x = 0; x < pSource->wDataLength; x++) { pNewAddress->u.e164[x] = (BYTE)(pSource->pData[x]); } pNewAddress->u.e164[pSource->wDataLength] = '\0'; } else { pNewAddress->u.e164[0] = '\0'; } }
return CS_OK; }
//====================================================================================
//====================================================================================
static CS_STATUS Q931AliasAddrToAliasItem(PCC_ALIASITEM *ppTarget, AliasAddress *pSource) { PCC_ALIASITEM pNewItem = NULL; WORD y;
if (ppTarget == NULL) { return CS_BAD_PARAM; } if (pSource == NULL) { *ppTarget = NULL; return CS_OK; }
pNewItem = (PCC_ALIASITEM)Malloc(sizeof(CC_ALIASITEM)); if (pNewItem == NULL) { *ppTarget = NULL; return CS_NO_MEMORY; } memset(pNewItem, 0, sizeof(*pNewItem));
switch (pSource->choice) { case h323_ID_chosen: pNewItem->wType = CC_ALIAS_H323_ID; if ((pSource->u.h323_ID.length != 0) && (pSource->u.h323_ID.value != NULL)) { // convert the text from UNICODE to ascii.
pNewItem->wDataLength = (WORD)pSource->u.h323_ID.length; pNewItem->pData = (LPWSTR)Malloc(pSource->u.h323_ID.length * sizeof(pNewItem->pData[0])); if (pNewItem->pData == NULL) { Free(pNewItem); return CS_NO_MEMORY; } for (y = 0; y < pSource->u.h323_ID.length; y++) { pNewItem->pData[y] = (WCHAR)((pSource->u.h323_ID.value)[y]); } } break;
case e164_chosen: pNewItem->wType = CC_ALIAS_H323_PHONE; pNewItem->wDataLength = (WORD)strlen(pSource->u.e164); pNewItem->pData = (LPWSTR)Malloc((pNewItem->wDataLength + 1) * sizeof(pNewItem->pData[0])); if (pNewItem->pData == NULL) { Free(pNewItem); return CS_NO_MEMORY; } for (y = 0; y < pNewItem->wDataLength; y++) { pNewItem->pData[y] = pSource->u.e164[y]; } pNewItem->pData[pNewItem->wDataLength] = 0; break;
default: Free(pNewItem); *ppTarget = NULL; return CS_BAD_PARAM; } // switch
*ppTarget = pNewItem; return CS_OK; }
//====================================================================================
//====================================================================================
static CS_STATUS Q931ClearAliasAddr(AliasAddress *pSource) { if (pSource) { if (pSource->choice == h323_ID_chosen) { if (pSource->u.h323_ID.value) { Free(pSource->u.h323_ID.value); } } } return CS_OK; }
//------------------------------------------------------------------------------
// Parse and return a single octet encoded value, See Q931 section 4.5.1.
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// Ident Pointer to space for field identifier
// Value Pointer to space for field value
//------------------------------------------------------------------------------
static HRESULT ParseSingleOctetType1( PBUFFERDESCR BufferDescriptor, BYTE *Ident, BYTE *Value) { // There has to be at least 1 byte in the stream to be
// able to parse the single octet value
if (BufferDescriptor->Length < 1) { return CS_ENDOFINPUT; }
// low bits (0, 1, 2, 3) of the byte are the value
*Value = (BYTE)(*BufferDescriptor->BufferPtr & TYPE1VALUEMASK);
// higher bits (4, 5, 6) are the identifier. bit 7 is always 1,
// and is not returned as part of the id.
*Ident = (BYTE)((*BufferDescriptor->BufferPtr & 0x70) >> 4);
BufferDescriptor->BufferPtr++; BufferDescriptor->Length--;
return CS_OK; }
//------------------------------------------------------------------------------
// Parse and return a single octet encoded value, See Q931 section 4.5.1.
// This octet has no value, only an identifier.
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer containing the
// length and a pointer to the raw bytes of the input stream.
// Ident Pointer to space for field identifier
//------------------------------------------------------------------------------
static HRESULT ParseSingleOctetType2( PBUFFERDESCR BufferDescriptor, BYTE *Ident) { // There has to be at least 1 byte in the stream to be
// able to parse the single octet value
if (BufferDescriptor->Length < 1) { return CS_ENDOFINPUT; }
// low 7 bits of the byte are the identifier
*Ident = (BYTE)(*BufferDescriptor->BufferPtr & 0x7f);
BufferDescriptor->BufferPtr++; BufferDescriptor->Length--;
return CS_OK; }
//------------------------------------------------------------------------------
// Parse and return a variable length Q931 field see Q931 section 4.5.1.
//
// Parameters :
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// Ident Pointer to space for field identifier
// Length Pointer to space for the length
// Contents Pointer to space for the bytes of the field
//------------------------------------------------------------------------------
static HRESULT ParseVariableOctet( PBUFFERDESCR BufferDescriptor, BYTE *Ident, BYTE *Length, BYTE *Contents) { register int i; BYTE *Tempptr;
// There has to be at least 2 bytes in order just to get
// the length and the identifier
// able to parse the single octet value
if (BufferDescriptor->Length < 2) { return CS_ENDOFINPUT; }
// low 7 bits of the first byte are the identifier
*Ident= (BYTE)(*BufferDescriptor->BufferPtr & 0x7f);
BufferDescriptor->BufferPtr++; BufferDescriptor->Length--;
// The next byte is the length
*Length = *BufferDescriptor->BufferPtr; BufferDescriptor->BufferPtr++; BufferDescriptor->Length--;
if (BufferDescriptor->Length < *Length) { return CS_ENDOFINPUT; }
Tempptr = Contents; for (i = 0; i < *Length; i++) { // Copy the bytes out of the rest of the buffer
*Tempptr = *BufferDescriptor->BufferPtr; BufferDescriptor->BufferPtr++; BufferDescriptor->Length--; Tempptr++; } return CS_OK; }
//------------------------------------------------------------------------------
// Parse and return a variable length Q931 field see Q931 section 4.5.1.
//------------------------------------------------------------------------------
static HRESULT ParseVariableASN( PBUFFERDESCR BufferDescriptor, BYTE *Ident, BYTE *ProtocolDiscriminator, WORD *UserInformationLength, // Length of the User Information.
BYTE *UserInformation) // Bytes of the User Information.
{ register int i; BYTE *Tempptr; WORD ContentsLength; // Length of the full UserUser contents.
*UserInformationLength = 0;
// There has to be at least 4 bytes for the IE identifier,
// the contents length, and the protocol discriminator (1 + 2 + 1).
if (BufferDescriptor->Length < 4) { return CS_ENDOFINPUT; }
// low 7 bits of the first byte are the identifier
*Ident= (BYTE)(*BufferDescriptor->BufferPtr & 0x7f); BufferDescriptor->BufferPtr++; BufferDescriptor->Length--;
// The next 2 bytes are the length
ContentsLength = *(BufferDescriptor->BufferPtr); BufferDescriptor->BufferPtr++; BufferDescriptor->Length--; ContentsLength = (WORD)((ContentsLength << 8) + *BufferDescriptor->BufferPtr); BufferDescriptor->BufferPtr++; BufferDescriptor->Length--;
if (BufferDescriptor->Length < ContentsLength) { return CS_ENDOFINPUT; }
// The next byte is the protocol discriminator.
*ProtocolDiscriminator = *BufferDescriptor->BufferPtr; BufferDescriptor->BufferPtr++; BufferDescriptor->Length--;
if (ContentsLength > 0) { *UserInformationLength = (WORD)(ContentsLength - 1); }
Tempptr = UserInformation; for (i = 0; i < *UserInformationLength; i++) { // Copy the bytes out of the rest of the buffer
*Tempptr = *BufferDescriptor->BufferPtr; BufferDescriptor->BufferPtr++; BufferDescriptor->Length--; Tempptr++; } return CS_OK; }
//------------------------------------------------------------------------------
// Get the identifier of the next field from the buffer and
// return it. The buffer pointer is not incremented, To
// parse the field and extract its values, the above functions
// should be used. See Q931 table 4-3 for the encodings of the
// identifiers.
//
// Parameters:
// BufferPtr Pointer to the buffer space
//------------------------------------------------------------------------------
static BYTE GetNextIdent( void *BufferPtr) { FIELDIDENTTYPE Ident;
// Extract the first byte from the buffer
Ident= (*(FIELDIDENTTYPE *)BufferPtr);
// This value can be returned as the identifier as long
// as it is not a single Octet - Type 1 element.
// Those items must have the value removed from them
// before they can be returned.
if ((Ident & 0x80) && ((Ident & TYPE1IDENTMASK) != 0xA0)) { return (BYTE)(Ident & TYPE1IDENTMASK); }
return Ident; }
//------------------------------------------------------------------------------
// Parse and return a protocol discriminator. See Q931 section 4.2.
// The octet pointed to by **BufferPtr is the protocol Discriminator.
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// Discrim Pointer to space for discriminator
//------------------------------------------------------------------------------
static HRESULT ParseProtocolDiscriminator( PBUFFERDESCR BufferDescriptor, PDTYPE *Discrim) { // There has to be at least enough bytes left in the
// string for the operation
if (BufferDescriptor->Length < sizeof(PDTYPE)) { return CS_MESSAGE_TOO_SHORT; }
*Discrim = *(PDTYPE *)BufferDescriptor->BufferPtr; if (*Discrim != Q931PDVALUE) { return CS_INVALID_PROTOCOL; }
BufferDescriptor->BufferPtr += sizeof(PDTYPE); BufferDescriptor->Length -= sizeof(PDTYPE); return CS_OK; }
//------------------------------------------------------------------------------
// Parse and return a variable length Q931 call reference see
// Q931 section 4.3.
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// Length Pointer to space for the length
// Contents Pointer to space for the bytes of the field
//------------------------------------------------------------------------------
static HRESULT ParseCallReference( PBUFFERDESCR BufferDescriptor, CRTYPE *CallReference) { register int i; BYTE Length;
// There has to be at least enough bytes left in the
// string for the length byte
if (BufferDescriptor->Length < 1) { return CS_MESSAGE_TOO_SHORT; }
// low 4 bits of the first byte are the length.
// the rest of the bits are zeroes.
Length = (BYTE)(*BufferDescriptor->BufferPtr & 0x0f);
BufferDescriptor->BufferPtr++; BufferDescriptor->Length--;
// There has to be at least enough bytes left in the
// string for the operation
if (BufferDescriptor->Length < Length) { return CS_MESSAGE_TOO_SHORT; }
*CallReference = 0; // length can be 0, so initialize here first...
for (i = 0; i < Length; i++) { if (i < sizeof(CRTYPE)) { // Copy the bytes out of the rest of the buffer
*CallReference = (WORD)((*CallReference << 8) + *BufferDescriptor->BufferPtr); } BufferDescriptor->BufferPtr++; BufferDescriptor->Length--; }
// note: the high order bit of the value represents callee relationship.
return CS_OK; }
//------------------------------------------------------------------------------
// Parse and return a message type. See Q931 section 4.4.
// The octet pointed to by **BufferPtr is the message type.
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// MessageType Pointer to space for message type
//------------------------------------------------------------------------------
static HRESULT ParseMessageType( PBUFFERDESCR BufferDescriptor, MESSAGEIDTYPE *MessageType) { register int i;
// There has to be at least enough bytes left in the
// string for the operation
if (BufferDescriptor->Length < sizeof(MESSAGEIDTYPE)) { return CS_MESSAGE_TOO_SHORT; }
*MessageType = (BYTE)(*((MESSAGEIDTYPE *)BufferDescriptor->BufferPtr) & MESSAGETYPEMASK); for (i = 0; i < sizeof(MessageSet) / sizeof(MESSAGEIDTYPE); i++) { if (MessageSet[i] == *MessageType) { break; } } if (i >= sizeof(MessageSet) / sizeof(MESSAGEIDTYPE)) { return CS_INVALID_MESSAGE_TYPE; }
BufferDescriptor->BufferPtr += sizeof(MESSAGEIDTYPE); BufferDescriptor->Length -= sizeof(MESSAGEIDTYPE); return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional shift field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer containing the
// length and a pointer to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed shift message information.
//------------------------------------------------------------------------------
static HRESULT ParseShift( PBUFFERDESCR BufferDescriptor, PSHIFTIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(SHIFTIE)); if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_SHIFT) { FieldStruct->Present = TRUE; return ParseSingleOctetType1(BufferDescriptor, &Ident, &FieldStruct->Value); } else { FieldStruct->Present = FALSE; } return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional facility ie field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed facility
// information.
//------------------------------------------------------------------------------
static HRESULT ParseFacility( PBUFFERDESCR BufferDescriptor, PFACILITYIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(FACILITYIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_FACILITY) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional more data field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed field information
//------------------------------------------------------------------------------
static HRESULT ParseMoreData( PBUFFERDESCR BufferDescriptor, PMOREDATAIE FieldStruct) { BYTE Ident;
memset(FieldStruct, 0, sizeof(MOREDATAIE)); if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_MORE) { FieldStruct->Present = TRUE; return ParseSingleOctetType2(BufferDescriptor, &Ident); } else { FieldStruct->Present = FALSE; }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional sending clomplete field. Q931 section 4.4.
// The octet pointed to by **BufferPtr is the message type.
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// MessageType Pointer to space for message type
//------------------------------------------------------------------------------
static HRESULT ParseSendingComplete( PBUFFERDESCR BufferDescriptor, PSENDCOMPLIE FieldStruct) { BYTE Ident;
memset(FieldStruct, 0, sizeof(SENDCOMPLIE)); if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_SENDINGCOMPLETE) { FieldStruct->Present = TRUE; return ParseSingleOctetType2(BufferDescriptor, &Ident); } else { FieldStruct->Present = FALSE; }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional congestion level field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed congestion
// level information.
//------------------------------------------------------------------------------
static HRESULT ParseCongestionLevel( PBUFFERDESCR BufferDescriptor, PCONGESTIONIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(CONGESTIONIE)); if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_CONGESTION) { FieldStruct->Present = TRUE; return ParseSingleOctetType1(BufferDescriptor, &Ident, &FieldStruct->Value); } else { FieldStruct->Present = FALSE; }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional repeat indicator field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed repeat
// information.
//------------------------------------------------------------------------------
static HRESULT ParseRepeatIndicator( PBUFFERDESCR BufferDescriptor, PREPEATIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(REPEATIE)); if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_REPEAT) { FieldStruct->Present = TRUE; return ParseSingleOctetType1(BufferDescriptor, &Ident, &FieldStruct->Value); } else { FieldStruct->Present = FALSE; }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional segmented message field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed segmented message
// information.
//------------------------------------------------------------------------------
static HRESULT ParseSegmented( PBUFFERDESCR BufferDescriptor, PSEGMENTEDIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(SEGMENTEDIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_SEGMENTED) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional bearer capability field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed bearer capability
// information.
//------------------------------------------------------------------------------
static HRESULT ParseBearerCapability( PBUFFERDESCR BufferDescriptor, PBEARERCAPIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(BEARERCAPIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_BEARERCAP) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional cause field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed cause
// information.
//------------------------------------------------------------------------------
static HRESULT ParseCause( PBUFFERDESCR BufferDescriptor, PCAUSEIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(CAUSEIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_CAUSE) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional call identity field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed call identity
// information.
//------------------------------------------------------------------------------
static HRESULT ParseCallIdentity( PBUFFERDESCR BufferDescriptor, PCALLIDENTIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(CALLIDENTIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_CALLIDENT) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional call state field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed call state
// information.
//------------------------------------------------------------------------------
static HRESULT ParseCallState( PBUFFERDESCR BufferDescriptor, PCALLSTATEIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(CALLSTATEIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_CALLSTATE) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional channel identification field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed channel identity
// information.
//------------------------------------------------------------------------------
static HRESULT ParseChannelIdentification( PBUFFERDESCR BufferDescriptor, PCHANIDENTIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(CHANIDENTIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_CHANNELIDENT) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional progress indication field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed progress
// information.
//------------------------------------------------------------------------------
static HRESULT ParseProgress( PBUFFERDESCR BufferDescriptor, PPROGRESSIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(PROGRESSIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_PROGRESS) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional network specific facilities field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed network facitlities
// information.
//------------------------------------------------------------------------------
static HRESULT ParseNetworkSpec( PBUFFERDESCR BufferDescriptor, PNETWORKIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(NETWORKIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_NETWORKSPEC) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional notification indicator field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parse notification indicator
// information.
//------------------------------------------------------------------------------
static HRESULT ParseNotificationIndicator( PBUFFERDESCR BufferDescriptor, PNOTIFICATIONINDIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(NOTIFICATIONINDIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_NOTIFICATION) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional display field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed display
// information.
//------------------------------------------------------------------------------
static HRESULT ParseDisplay( PBUFFERDESCR BufferDescriptor, PDISPLAYIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(DISPLAYIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_DISPLAY) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional date/time field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed date/time
// information.
//------------------------------------------------------------------------------
static HRESULT ParseDate( PBUFFERDESCR BufferDescriptor, PDATEIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(DATEIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_DATE) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional keypad field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed keypad
// information.
//------------------------------------------------------------------------------
static HRESULT ParseKeypad( PBUFFERDESCR BufferDescriptor, PKEYPADIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(KEYPADIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_KEYPAD) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional signal field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed signal
// information.
//------------------------------------------------------------------------------
static HRESULT ParseSignal( PBUFFERDESCR BufferDescriptor, PSIGNALIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(SIGNALIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_SIGNAL) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional information rate field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed information rate
// information.
//------------------------------------------------------------------------------
static HRESULT ParseInformationRate( PBUFFERDESCR BufferDescriptor, PINFORATEIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(INFORATEIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_INFORMATIONRATE) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional end to end transit delay field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed end to end
// information.
//------------------------------------------------------------------------------
static HRESULT ParseEndToEndDelay( PBUFFERDESCR BufferDescriptor, PENDTOENDDELAYIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(ENDTOENDDELAYIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_ENDTOENDDELAY) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional transit delay field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed transit delay
// information.
//------------------------------------------------------------------------------
static HRESULT ParseTransitDelay( PBUFFERDESCR BufferDescriptor, PTRANSITDELAYIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(TRANSITDELAYIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_TRANSITDELAY) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional packet layer binary params field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParsePacketLayerParams( PBUFFERDESCR BufferDescriptor, PPLBINARYPARAMSIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(PLBINARYPARAMSIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_PLBINARYPARAMS) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional packet layer window size field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParsePacketLayerWindowSize( PBUFFERDESCR BufferDescriptor, PPLWINDOWSIZEIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(PLWINDOWSIZEIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_PLWINDOWSIZE) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional packet size field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parse packet size
// information.
//------------------------------------------------------------------------------
static HRESULT ParsePacketSize( PBUFFERDESCR BufferDescriptor, PPACKETSIZEIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(PACKETSIZEIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_PACKETSIZE) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional closed user group field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseClosedUserGroup( PBUFFERDESCR BufferDescriptor, PCLOSEDUGIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(CLOSEDUGIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_CLOSEDUG) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional reverse charge field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseReverseCharge( PBUFFERDESCR BufferDescriptor, PREVERSECHARGEIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(REVERSECHARGEIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_REVCHARGE) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional calling party number field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseCallingPartyNumber( PBUFFERDESCR BufferDescriptor, PCALLINGNUMBERIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(CALLINGNUMBERIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_CALLINGNUMBER) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional calling party subaddress field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseCallingPartySubaddress( PBUFFERDESCR BufferDescriptor, PCALLINGSUBADDRIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(CALLINGSUBADDRIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_CALLINGSUBADDR) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional called party number field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseCalledPartyNumber( PBUFFERDESCR BufferDescriptor, PCALLEDNUMBERIE FieldStruct) { memset(FieldStruct, 0, sizeof(PCALLEDNUMBERIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_CALLEDNUMBER) { register int i; BYTE RemainingLength = 0; BYTE *Tempptr; // Need 3 bytes for the ident (1), length (1),
// and type + plan (1) fields.
if (BufferDescriptor->Length < 3) { return CS_ENDOFINPUT; }
// skip the ie identifier...
BufferDescriptor->BufferPtr++; BufferDescriptor->Length--;
// Get the length of the contents following the length field.
RemainingLength = *BufferDescriptor->BufferPtr; BufferDescriptor->BufferPtr++; BufferDescriptor->Length--;
// make sure we have at least that much length left...
if (BufferDescriptor->Length < RemainingLength) { return CS_ENDOFINPUT; }
// Get the type + plan fields.
if (*(BufferDescriptor->BufferPtr) & 0x80) { FieldStruct->NumberType = (BYTE)(*BufferDescriptor->BufferPtr & 0xf0); FieldStruct->NumberingPlan = (BYTE)(*BufferDescriptor->BufferPtr & 0x0f); BufferDescriptor->BufferPtr++; BufferDescriptor->Length--; RemainingLength--; }
FieldStruct->PartyNumberLength = RemainingLength; FieldStruct->Present = TRUE;
Tempptr = FieldStruct->PartyNumbers; for (i = 0; i < RemainingLength; i++) { // Copy the bytes out of the rest of the buffer
*Tempptr = *(BufferDescriptor->BufferPtr); BufferDescriptor->BufferPtr++; BufferDescriptor->Length--; Tempptr++; } *Tempptr = (BYTE)0; } return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional called party subaddress field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseCalledPartySubaddress( PBUFFERDESCR BufferDescriptor, PCALLEDSUBADDRIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(CALLEDSUBADDRIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_CALLEDSUBADDR) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional redirecting number field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseRedirectingNumber( PBUFFERDESCR BufferDescriptor, PREDIRECTINGIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(REDIRECTINGIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_REDIRECTING) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional transit network selection field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseTransitNetwork( PBUFFERDESCR BufferDescriptor, PTRANSITNETIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(TRANSITNETIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_TRANSITNET) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional restart indicator field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseRestart( PBUFFERDESCR BufferDescriptor, PRESTARTIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(PRESTARTIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_RESTART) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional lower layer compatibility field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseLowLayerCompatibility( PBUFFERDESCR BufferDescriptor, PLLCOMPATIBILITYIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(LLCOMPATIBILITYIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_LLCOMPATIBILITY) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional higher layer compatibility field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseHighLayerCompatibility( PBUFFERDESCR BufferDescriptor, PHLCOMPATIBILITYIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(HLCOMPATIBILITYIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_HLCOMPATIBILITY) { HRESULT ParseResult; ParseResult = ParseVariableOctet(BufferDescriptor, &Ident, &FieldStruct->Length, &FieldStruct->Contents[0]); if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->Length > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse an optional user to user field
//
// Parameters:
// BufferPtr Pointer to a descriptor of the buffer
// containing the length and a pointer
// to the raw bytes of the input stream.
// FieldStruct Pointer to space for parsed
// information.
//------------------------------------------------------------------------------
static HRESULT ParseUserToUser( PBUFFERDESCR BufferDescriptor, PUSERUSERIE FieldStruct) { BYTE Ident; memset(FieldStruct, 0, sizeof(USERUSERIE)); FieldStruct->Present = FALSE; if (GetNextIdent(BufferDescriptor->BufferPtr) == IDENT_USERUSER) { HRESULT ParseResult;
ParseResult = ParseVariableASN(BufferDescriptor, &Ident, &(FieldStruct->ProtocolDiscriminator), &(FieldStruct->UserInformationLength), &(FieldStruct->UserInformation[0]));
if (ParseResult != CS_OK) { return ParseResult; } if (FieldStruct->UserInformationLength > 0) { FieldStruct->Present = TRUE; } }
return CS_OK; }
//------------------------------------------------------------------------------
// Parse the next Q931 field in the given message
//
// Parameters:
// BufferDescriptor Pointer to buffer descriptor of a
// the network packet of the 931 message
// Message Pointer to space for parsed information.
//------------------------------------------------------------------------------
static HRESULT ParseQ931Field( PBUFFERDESCR BufferDescriptor, PQ931MESSAGE Message) { FIELDIDENTTYPE Ident;
Ident = GetNextIdent(BufferDescriptor->BufferPtr); switch (Ident) { case IDENT_SHIFT: return ParseShift(BufferDescriptor, &Message->Shift); case IDENT_FACILITY: return ParseFacility(BufferDescriptor, &Message->Facility); case IDENT_MORE: return ParseMoreData(BufferDescriptor, &Message->MoreData); case IDENT_SENDINGCOMPLETE: return ParseSendingComplete(BufferDescriptor, &Message->SendingComplete); case IDENT_CONGESTION: return ParseCongestionLevel(BufferDescriptor, &Message->CongestionLevel); case IDENT_REPEAT: return ParseRepeatIndicator(BufferDescriptor, &Message->RepeatIndicator); case IDENT_SEGMENTED: return ParseSegmented(BufferDescriptor, &Message->SegmentedMessage); case IDENT_BEARERCAP: return ParseBearerCapability(BufferDescriptor, &Message->BearerCapability); case IDENT_CAUSE: return ParseCause(BufferDescriptor, &Message->Cause); case IDENT_CALLIDENT: return ParseCallIdentity(BufferDescriptor, &Message->CallIdentity); case IDENT_CALLSTATE: return ParseCallState(BufferDescriptor, &Message->CallState); case IDENT_CHANNELIDENT: return ParseChannelIdentification(BufferDescriptor, &Message->ChannelIdentification); case IDENT_PROGRESS: return ParseProgress(BufferDescriptor, &Message->ProgressIndicator); case IDENT_NETWORKSPEC: return ParseNetworkSpec(BufferDescriptor, &Message->NetworkFacilities); case IDENT_NOTIFICATION: return ParseNotificationIndicator(BufferDescriptor, &Message->NotificationIndicator); case IDENT_DISPLAY: return ParseDisplay(BufferDescriptor, &Message->Display); case IDENT_DATE: return ParseDate(BufferDescriptor, &Message->Date); case IDENT_KEYPAD: return ParseKeypad(BufferDescriptor, &Message->Keypad); case IDENT_SIGNAL: return ParseSignal(BufferDescriptor, &Message->Signal); case IDENT_INFORMATIONRATE: return ParseInformationRate(BufferDescriptor, &Message->InformationRate); case IDENT_ENDTOENDDELAY: return ParseEndToEndDelay(BufferDescriptor, &Message->EndToEndTransitDelay); case IDENT_TRANSITDELAY: return ParseTransitDelay(BufferDescriptor, &Message->TransitDelay); case IDENT_PLBINARYPARAMS: return ParsePacketLayerParams(BufferDescriptor, &Message->PacketLayerBinaryParams); case IDENT_PLWINDOWSIZE: return ParsePacketLayerWindowSize(BufferDescriptor, &Message->PacketLayerWindowSize); case IDENT_PACKETSIZE: return ParsePacketSize(BufferDescriptor, &Message->PacketSize); case IDENT_CLOSEDUG: return ParseClosedUserGroup(BufferDescriptor, &Message->ClosedUserGroup); case IDENT_REVCHARGE: return ParseReverseCharge(BufferDescriptor, &Message->ReverseChargeIndication); case IDENT_CALLINGNUMBER: return ParseCallingPartyNumber(BufferDescriptor, &Message->CallingPartyNumber); case IDENT_CALLINGSUBADDR: return ParseCallingPartySubaddress(BufferDescriptor, &Message->CallingPartySubaddress); case IDENT_CALLEDNUMBER: return ParseCalledPartyNumber(BufferDescriptor, &Message->CalledPartyNumber); case IDENT_CALLEDSUBADDR: return ParseCalledPartySubaddress(BufferDescriptor, &Message->CalledPartySubaddress); case IDENT_REDIRECTING: return ParseRedirectingNumber(BufferDescriptor, &Message->RedirectingNumber); case IDENT_TRANSITNET: return ParseTransitNetwork(BufferDescriptor, &Message->TransitNetworkSelection); case IDENT_RESTART: return ParseRestart(BufferDescriptor, &Message->RestartIndicator); case IDENT_LLCOMPATIBILITY: return ParseLowLayerCompatibility(BufferDescriptor, &Message->LowLayerCompatibility); case IDENT_HLCOMPATIBILITY: return ParseHighLayerCompatibility(BufferDescriptor, &Message->HighLayerCompatibility); case IDENT_USERUSER: return ParseUserToUser(BufferDescriptor, &Message->UserToUser); default: return CS_INVALID_FIELD; } }
//------------------------------------------------------------------------------
// Parse a generic Q931 message and place the fields of the buffer
// into the appropriate structure fields.
//
// Parameters:
// BufferDescriptor Pointer to buffer descriptor of an
// input packet containing the 931 message.
// Message Pointer to space for parsed output information.
//------------------------------------------------------------------------------
HRESULT Q931ParseMessage( BYTE *CodedBufferPtr, DWORD CodedBufferLength, PQ931MESSAGE Message) { HRESULT Result; BUFFERDESCR BufferDescriptor;
BufferDescriptor.Length = CodedBufferLength; BufferDescriptor.BufferPtr = CodedBufferPtr;
memset(Message, 0, sizeof(Q931MESSAGE));
if ((Result = ParseProtocolDiscriminator(&BufferDescriptor, &Message->ProtocolDiscriminator)) != CS_OK) { return Result; }
if ((Result = ParseCallReference(&BufferDescriptor, &Message->CallReference)) != CS_OK) { return Result; }
if ((Result = ParseMessageType(&BufferDescriptor, &Message->MessageType)) != CS_OK) { return Result; }
while (BufferDescriptor.Length) { Result = ParseQ931Field(&BufferDescriptor, Message); if (Result != CS_OK) { return Result; } } return CS_OK; }
//==============================================================================
//==============================================================================
//==============================================================================
// BELOW HERE ARE THE OUTPUT ROUTINES...
//==============================================================================
//==============================================================================
//==============================================================================
//------------------------------------------------------------------------------
// Write the protocol discriminator. See Q931 section 4.2.
//------------------------------------------------------------------------------
static HRESULT WriteProtocolDiscriminator( PBUFFERDESCR BufferDescriptor) { BufferDescriptor->Length += sizeof(PDTYPE); if (BufferDescriptor->BufferPtr) { *(PDTYPE *)BufferDescriptor->BufferPtr = Q931PDVALUE; BufferDescriptor->BufferPtr += sizeof(PDTYPE); } return CS_OK; }
//------------------------------------------------------------------------------
// Write a variable length Q931 call reference. See Q931 section 4.3.
//------------------------------------------------------------------------------
static HRESULT WriteCallReference( PBUFFERDESCR BufferDescriptor, CRTYPE *CallReference) { register int i;
// space for the length byte
BufferDescriptor->Length++;
// the length byte
if (BufferDescriptor->BufferPtr != NULL) { *BufferDescriptor->BufferPtr = (BYTE)sizeof(CRTYPE); BufferDescriptor->BufferPtr++; }
for (i = 0; i < sizeof(CRTYPE); i++) { // Copy the value bytes to the buffer
BufferDescriptor->Length++; if (BufferDescriptor->BufferPtr != NULL) { *BufferDescriptor->BufferPtr = (BYTE)(((*CallReference) >> ((sizeof(CRTYPE) - 1 -i) * 8)) & 0xff); BufferDescriptor->BufferPtr++; } } return CS_OK; }
//------------------------------------------------------------------------------
// Write a Q931 message type. See Q931 section 4.4.
//------------------------------------------------------------------------------
static HRESULT WriteMessageType( PBUFFERDESCR BufferDescriptor, MESSAGEIDTYPE *MessageType) { register int i;
for (i = 0; i < sizeof(MessageSet) / sizeof(MESSAGEIDTYPE); i++) { if (MessageSet[i] == *MessageType) { break; } } if (i >= sizeof(MessageSet) / sizeof(MESSAGEIDTYPE)) { return CS_INVALID_MESSAGE_TYPE; }
BufferDescriptor->Length += sizeof(MESSAGEIDTYPE); if (BufferDescriptor->BufferPtr != NULL) { *(MESSAGEIDTYPE *)(BufferDescriptor->BufferPtr) = (BYTE)(*MessageType & MESSAGETYPEMASK); BufferDescriptor->BufferPtr += sizeof(MESSAGEIDTYPE); } return CS_OK; }
//------------------------------------------------------------------------------
// Write a single octet encoded value, See Q931 section 4.5.1.
//------------------------------------------------------------------------------
static HRESULT WriteSingleOctetType1( PBUFFERDESCR BufferDescriptor, BYTE Ident, BYTE Value) { BufferDescriptor->Length++; if (BufferDescriptor->BufferPtr) { *BufferDescriptor->BufferPtr = (BYTE)(0x80 | Ident | (Value & TYPE1VALUEMASK)); BufferDescriptor->BufferPtr++; } return CS_OK; }
//------------------------------------------------------------------------------
// Write a single octet encoded value, See Q931 section 4.5.1.
//------------------------------------------------------------------------------
static HRESULT WriteSingleOctetType2( PBUFFERDESCR BufferDescriptor, BYTE Ident) { BufferDescriptor->Length++; if (BufferDescriptor->BufferPtr) { *BufferDescriptor->BufferPtr = (BYTE)(0x80 | Ident); BufferDescriptor->BufferPtr++; } return CS_OK; }
//------------------------------------------------------------------------------
// Parse and return a variable length Q931 field see Q931 section 4.5.1.
//------------------------------------------------------------------------------
static HRESULT WriteVariableOctet( PBUFFERDESCR BufferDescriptor, BYTE Ident, BYTE Length, BYTE *Contents) { register int i; BYTE *Tempptr;
if (Contents == NULL) { Length = 0; }
// space for the length and the identifier bytes
BufferDescriptor->Length += 2;
// the id byte, then the length byte
if (BufferDescriptor->BufferPtr != NULL) { // low 7 bits of the first byte are the identifier
*BufferDescriptor->BufferPtr = (BYTE)(Ident & 0x7f); BufferDescriptor->BufferPtr++; *BufferDescriptor->BufferPtr = Length; BufferDescriptor->BufferPtr++; }
Tempptr = Contents; for (i = 0; i < Length; i++) { // Copy the value bytes to the buffer
BufferDescriptor->Length++; if (BufferDescriptor->BufferPtr != NULL) { *BufferDescriptor->BufferPtr = *Tempptr; BufferDescriptor->BufferPtr++; Tempptr++; } } return CS_OK; }
//------------------------------------------------------------------------------
//Write out the Party number.
//------------------------------------------------------------------------------
static HRESULT WritePartyNumber( PBUFFERDESCR BufferDescriptor, BYTE Ident, BYTE NumberType, BYTE NumberingPlan, BYTE PartyNumberLength, BYTE *PartyNumbers) { register int i; BYTE *Tempptr;
if (PartyNumbers == NULL) { PartyNumberLength = 0; }
// space for the ident (1), length (1), and type + plan (1) fields.
BufferDescriptor->Length += 3;
// write the fields out.
if (BufferDescriptor->BufferPtr != NULL) { // low 7 bits of byte 1 are the ie identifier
*BufferDescriptor->BufferPtr = (BYTE)(Ident & 0x7f); BufferDescriptor->BufferPtr++;
// byte 2 is the ie contents length following the length field.
*BufferDescriptor->BufferPtr = (BYTE)(PartyNumberLength + 1); BufferDescriptor->BufferPtr++;
// byte 3 is the type and plan field.
*BufferDescriptor->BufferPtr = (BYTE)(NumberType | NumberingPlan); BufferDescriptor->BufferPtr++; }
Tempptr = PartyNumbers; for (i = 0; i < PartyNumberLength; i++) { // Copy the value bytes to the buffer
BufferDescriptor->Length++; if (BufferDescriptor->BufferPtr != NULL) { *BufferDescriptor->BufferPtr = *Tempptr; BufferDescriptor->BufferPtr++; Tempptr++; } } return CS_OK; }
//------------------------------------------------------------------------------
// Parse and return a variable length Q931 field see Q931 section 4.5.1.
//------------------------------------------------------------------------------
static HRESULT WriteVariableASN( PBUFFERDESCR BufferDescriptor, BYTE Ident, WORD UserInformationLength, BYTE *UserInformation) { register int i; BYTE *Tempptr; WORD ContentsLength = (WORD)(UserInformationLength + 1);
// There has to be at least 4 bytes for the IE identifier,
// the contents length, and the protocol discriminator (1 + 2 + 1).
BufferDescriptor->Length += 4;
if (BufferDescriptor->BufferPtr != NULL) { // low 7 bits of the first byte are the identifier
*BufferDescriptor->BufferPtr = (BYTE)(Ident & 0x7f); BufferDescriptor->BufferPtr++;
// write the contents length bytes.
*BufferDescriptor->BufferPtr = (BYTE)(ContentsLength >> 8); BufferDescriptor->BufferPtr++; *BufferDescriptor->BufferPtr = (BYTE)ContentsLength; BufferDescriptor->BufferPtr++;
// write the protocol discriminator byte.
*(BufferDescriptor->BufferPtr) = Q931_PROTOCOL_X209; BufferDescriptor->BufferPtr++; }
Tempptr = UserInformation; for (i = 0; i < UserInformationLength; i++) { // Copy the value bytes to the buffer
BufferDescriptor->Length++; if (BufferDescriptor->BufferPtr != NULL) { *BufferDescriptor->BufferPtr = *Tempptr; BufferDescriptor->BufferPtr++; Tempptr++; } } return CS_OK; }
//------------------------------------------------------------------------------
// Write the Q931 fields to the encoding buffer.
//
// Parameters:
// BufferDescriptor Pointer to buffer descriptor for
// the encoded output buffer.
// Message Pointer to space for parsed input information.
//------------------------------------------------------------------------------
static HRESULT WriteQ931Fields( PBUFFERDESCR BufferDescriptor, PQ931MESSAGE Message) { // write the required information elements...
WriteProtocolDiscriminator(BufferDescriptor); WriteCallReference(BufferDescriptor, &Message->CallReference); WriteMessageType(BufferDescriptor, &Message->MessageType);
// try to write all other information elements...
// don't write this message.
#if 0
if (Message->Shift.Present) { WriteSingleOctetType1(BufferDescriptor, IDENT_SHIFT, Message->Shift.Value); } #endif
if (Message->Facility.Present) { WriteVariableOctet(BufferDescriptor, IDENT_FACILITY, Message->Facility.Length, Message->Facility.Contents); }
if (Message->MoreData.Present) { WriteSingleOctetType2(BufferDescriptor, IDENT_MORE); } if (Message->SendingComplete.Present) { WriteSingleOctetType2(BufferDescriptor, IDENT_SENDINGCOMPLETE); } if (Message->CongestionLevel.Present) { WriteSingleOctetType1(BufferDescriptor, IDENT_CONGESTION, Message->CongestionLevel.Value); } if (Message->RepeatIndicator.Present) { WriteSingleOctetType1(BufferDescriptor, IDENT_REPEAT, Message->RepeatIndicator.Value); }
if (Message->SegmentedMessage.Present && Message->SegmentedMessage.Length) { WriteVariableOctet(BufferDescriptor, IDENT_SEGMENTED, Message->SegmentedMessage.Length, Message->SegmentedMessage.Contents); } if (Message->BearerCapability.Present && Message->BearerCapability.Length) { WriteVariableOctet(BufferDescriptor, IDENT_BEARERCAP, Message->BearerCapability.Length, Message->BearerCapability.Contents); } if (Message->Cause.Present && Message->Cause.Length) { WriteVariableOctet(BufferDescriptor, IDENT_CAUSE, Message->Cause.Length, Message->Cause.Contents); } if (Message->CallIdentity.Present && Message->CallIdentity.Length) { WriteVariableOctet(BufferDescriptor, IDENT_CALLIDENT, Message->CallIdentity.Length, Message->CallIdentity.Contents); } if (Message->CallState.Present && Message->CallState.Length) { WriteVariableOctet(BufferDescriptor, IDENT_CALLSTATE, Message->CallState.Length, Message->CallState.Contents); } if (Message->ChannelIdentification.Present && Message->ChannelIdentification.Length) { WriteVariableOctet(BufferDescriptor, IDENT_CHANNELIDENT, Message->ChannelIdentification.Length, Message->ChannelIdentification.Contents); } if (Message->ProgressIndicator.Present && Message->ProgressIndicator.Length) { WriteVariableOctet(BufferDescriptor, IDENT_PROGRESS, Message->ProgressIndicator.Length, Message->ProgressIndicator.Contents); } if (Message->NetworkFacilities.Present && Message->NetworkFacilities.Length) { WriteVariableOctet(BufferDescriptor, IDENT_NETWORKSPEC, Message->NetworkFacilities.Length, Message->NetworkFacilities.Contents); } if (Message->NotificationIndicator.Present && Message->NotificationIndicator.Length) { WriteVariableOctet(BufferDescriptor, IDENT_NOTIFICATION, Message->NotificationIndicator.Length, Message->NotificationIndicator.Contents); } if (Message->Display.Present && Message->Display.Length) { WriteVariableOctet(BufferDescriptor, IDENT_DISPLAY, Message->Display.Length, Message->Display.Contents); } if (Message->Date.Present && Message->Date.Length) { WriteVariableOctet(BufferDescriptor, IDENT_DATE, Message->Date.Length, Message->Date.Contents); } if (Message->Keypad.Present && Message->Keypad.Length) { WriteVariableOctet(BufferDescriptor, IDENT_KEYPAD, Message->Keypad.Length, Message->Keypad.Contents); } if (Message->Signal.Present && Message->Signal.Length) { WriteVariableOctet(BufferDescriptor, IDENT_SIGNAL, Message->Signal.Length, Message->Signal.Contents); } if (Message->InformationRate.Present && Message->InformationRate.Length) { WriteVariableOctet(BufferDescriptor, IDENT_INFORMATIONRATE, Message->InformationRate.Length, Message->InformationRate.Contents); } if (Message->EndToEndTransitDelay.Present && Message->EndToEndTransitDelay.Length) { WriteVariableOctet(BufferDescriptor, IDENT_ENDTOENDDELAY, Message->EndToEndTransitDelay.Length, Message->EndToEndTransitDelay.Contents); } if (Message->TransitDelay.Present && Message->TransitDelay.Length) { WriteVariableOctet(BufferDescriptor, IDENT_TRANSITDELAY, Message->TransitDelay.Length, Message->TransitDelay.Contents); } if (Message->PacketLayerBinaryParams.Present && Message->PacketLayerBinaryParams.Length) { WriteVariableOctet(BufferDescriptor, IDENT_PLBINARYPARAMS, Message->PacketLayerBinaryParams.Length, Message->PacketLayerBinaryParams.Contents); } if (Message->PacketLayerWindowSize.Present && Message->PacketLayerWindowSize.Length) { WriteVariableOctet(BufferDescriptor, IDENT_PLWINDOWSIZE, Message->PacketLayerWindowSize.Length, Message->PacketLayerWindowSize.Contents); } if (Message->PacketSize.Present && Message->PacketSize.Length) { WriteVariableOctet(BufferDescriptor, IDENT_PACKETSIZE, Message->PacketSize.Length, Message->PacketSize.Contents); } if (Message->ClosedUserGroup.Present && Message->ClosedUserGroup.Length) { WriteVariableOctet(BufferDescriptor, IDENT_CLOSEDUG, Message->ClosedUserGroup.Length, Message->ClosedUserGroup.Contents); } if (Message->ReverseChargeIndication.Present && Message->ReverseChargeIndication.Length) { WriteVariableOctet(BufferDescriptor, IDENT_REVCHARGE, Message->ReverseChargeIndication.Length, Message->ReverseChargeIndication.Contents); } if (Message->CallingPartyNumber.Present && Message->CallingPartyNumber.Length) { WriteVariableOctet(BufferDescriptor, IDENT_CALLINGNUMBER, Message->CallingPartyNumber.Length, Message->CallingPartyNumber.Contents); } if (Message->CallingPartySubaddress.Present && Message->CallingPartySubaddress.Length) { WriteVariableOctet(BufferDescriptor, IDENT_CALLINGSUBADDR, Message->CallingPartySubaddress.Length, Message->CallingPartySubaddress.Contents); } if (Message->CalledPartyNumber.Present) { WritePartyNumber(BufferDescriptor, IDENT_CALLEDNUMBER, Message->CalledPartyNumber.NumberType, Message->CalledPartyNumber.NumberingPlan, Message->CalledPartyNumber.PartyNumberLength, Message->CalledPartyNumber.PartyNumbers); } if (Message->CalledPartySubaddress.Present && Message->CalledPartySubaddress.Length) { WriteVariableOctet(BufferDescriptor, IDENT_CALLEDSUBADDR, Message->CalledPartySubaddress.Length, Message->CalledPartySubaddress.Contents); } if (Message->RedirectingNumber.Present && Message->RedirectingNumber.Length) { WriteVariableOctet(BufferDescriptor, IDENT_REDIRECTING, Message->RedirectingNumber.Length, Message->RedirectingNumber.Contents); } if (Message->TransitNetworkSelection.Present && Message->TransitNetworkSelection.Length) { WriteVariableOctet(BufferDescriptor, IDENT_TRANSITNET, Message->TransitNetworkSelection.Length, Message->TransitNetworkSelection.Contents); } if (Message->RestartIndicator.Present && Message->RestartIndicator.Length) { WriteVariableOctet(BufferDescriptor, IDENT_RESTART, Message->RestartIndicator.Length, Message->RestartIndicator.Contents); } if (Message->LowLayerCompatibility.Present && Message->LowLayerCompatibility.Length) { WriteVariableOctet(BufferDescriptor, IDENT_LLCOMPATIBILITY, Message->LowLayerCompatibility.Length, Message->LowLayerCompatibility.Contents); } if (Message->HighLayerCompatibility.Present && Message->HighLayerCompatibility.Length) { WriteVariableOctet(BufferDescriptor, IDENT_HLCOMPATIBILITY, Message->HighLayerCompatibility.Length, Message->HighLayerCompatibility.Contents); } if (Message->UserToUser.Present && Message->UserToUser.UserInformationLength) { WriteVariableASN(BufferDescriptor, IDENT_USERUSER, Message->UserToUser.UserInformationLength, Message->UserToUser.UserInformation); } return CS_OK; }
//------------------------------------------------------------------------------
// Parse a generic Q931 message and place the fields of the
// of the buffer into the appropriate field structure.
//
// Parameters:
// BufferDescriptor Pointer to buffer descriptor of a
// the network packet of the 931 message
// Message Pointer to space for parsed information.
//------------------------------------------------------------------------------
HRESULT Q931MakeEncodedMessage( PQ931MESSAGE Message, BYTE **CodedBufferPtr, DWORD *CodedBufferLength) { BUFFERDESCR BufferDescriptor; BYTE *OutBuffer = NULL; DWORD Pass1Length = 0;
if ((CodedBufferPtr == NULL) || (CodedBufferLength == NULL)) { return CS_BAD_PARAM; }
BufferDescriptor.Length = 0; BufferDescriptor.BufferPtr = NULL;
WriteQ931Fields(&BufferDescriptor, Message); if (BufferDescriptor.Length == 0) { return CS_NO_FIELD_DATA; }
Pass1Length = BufferDescriptor.Length;
OutBuffer = (BYTE *)Malloc(BufferDescriptor.Length + 1000); if (OutBuffer == NULL) { return CS_NO_MEMORY; }
BufferDescriptor.Length = 0; BufferDescriptor.BufferPtr = OutBuffer;
WriteQ931Fields(&BufferDescriptor, Message);
if (Pass1Length != BufferDescriptor.Length) { // this is a serious error, since memory may have been overrun.
return CS_BAD_PARAM; }
*CodedBufferPtr = OutBuffer; *CodedBufferLength = BufferDescriptor.Length;
return CS_OK; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931SetupEncodePDU( WORD wCallReference, char *pszDisplay, char *pszCalledPartyNumber, DWORD dwBandwidth, BINARY_STRING *pUserUserData, BYTE **CodedBufferPtr, DWORD *CodedBufferLength) { Q931MESSAGE *pMessage; HRESULT Result = CS_OK; BYTE bBandwidth;
pMessage = (Q931MESSAGE *)Malloc(sizeof(Q931MESSAGE)); if (pMessage == NULL) { return CS_NO_MEMORY; }
// fill in the required fields for the setup message.
memset(pMessage, 0, sizeof(Q931MESSAGE)); pMessage->ProtocolDiscriminator = Q931PDVALUE; pMessage->CallReference = wCallReference; pMessage->MessageType = SETUPMESSAGETYPE;
pMessage->BearerCapability.Present = TRUE; pMessage->BearerCapability.Length = 4; pMessage->BearerCapability.Contents[0] = (BYTE)(BEAR_EXT_BIT | BEAR_CCITT | BEAR_UNRESTRICTED_DIGITAL); pMessage->BearerCapability.Contents[1] = (BYTE)(BEAR_CIRCUIT_MODE | BEAR_MULTIRATE); bBandwidth = (BYTE)(dwBandwidth / 64000); if ((dwBandwidth % 64000) != 0) bBandwidth++; pMessage->BearerCapability.Contents[2] = (BYTE)(BEAR_EXT_BIT | bBandwidth); pMessage->BearerCapability.Contents[3] = (BYTE)(BEAR_EXT_BIT | BEAR_LAYER1_INDICATOR | BEAR_LAYER1_H221_H242);
if (pszDisplay && *pszDisplay) { pMessage->Display.Present = TRUE; pMessage->Display.Length = (BYTE)(strlen(pszDisplay) + 1); strcpy((char *)pMessage->Display.Contents, pszDisplay); }
if (pszCalledPartyNumber && *pszCalledPartyNumber) { WORD wLen = (WORD)strlen(pszCalledPartyNumber); pMessage->CalledPartyNumber.Present = TRUE;
pMessage->CalledPartyNumber.NumberType = (BYTE)(CALLED_PARTY_EXT_BIT | CALLED_PARTY_TYPE_UNKNOWN); pMessage->CalledPartyNumber.NumberingPlan = (BYTE)(CALLED_PARTY_PLAN_E164); pMessage->CalledPartyNumber.PartyNumberLength = (BYTE)wLen; memcpy(pMessage->CalledPartyNumber.PartyNumbers, pszCalledPartyNumber, wLen); }
if (pUserUserData && pUserUserData->ptr) { if (pUserUserData->length > sizeof(pMessage->UserToUser.UserInformation)) { Free(pMessage); return CS_BAD_PARAM; } pMessage->UserToUser.Present = TRUE; pMessage->UserToUser.UserInformationLength = (pUserUserData->length); memcpy(pMessage->UserToUser.UserInformation, pUserUserData->ptr, pUserUserData->length); } Result = Q931MakeEncodedMessage(pMessage, CodedBufferPtr, CodedBufferLength);
Free(pMessage); return Result; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931ReleaseCompleteEncodePDU( WORD wCallReference, BYTE *pbCause, BINARY_STRING *pUserUserData, BYTE **CodedBufferPtr, DWORD *CodedBufferLength) { Q931MESSAGE *pMessage; HRESULT Result = CS_OK;
if (pbCause) { switch (*pbCause) { case CAUSE_VALUE_NORMAL_CLEAR: case CAUSE_VALUE_USER_BUSY: case CAUSE_VALUE_NO_ANSWER: case CAUSE_VALUE_REJECTED: case CAUSE_VALUE_NOT_IMPLEMENTED: case CAUSE_VALUE_INVALID_CRV: case CAUSE_VALUE_IE_MISSING: case CAUSE_VALUE_IE_CONTENTS: case CAUSE_VALUE_TIMER_EXPIRED: break; default: return CS_BAD_PARAM; break; } }
pMessage = (Q931MESSAGE *)Malloc(sizeof(Q931MESSAGE)); if (pMessage == NULL) { return CS_NO_MEMORY; }
// fill in the required fields for the setup message.
memset(pMessage, 0, sizeof(Q931MESSAGE)); pMessage->ProtocolDiscriminator = Q931PDVALUE; pMessage->CallReference = wCallReference; pMessage->MessageType = RELEASECOMPLMESSAGETYPE;
if (pbCause) { pMessage->Cause.Present = TRUE; pMessage->Cause.Length = 3; pMessage->Cause.Contents[0] = (BYTE)(CAUSE_CODING_CCITT | CAUSE_LOCATION_USER); pMessage->Cause.Contents[1] = (BYTE)(CAUSE_RECOMMENDATION_Q931); pMessage->Cause.Contents[2] = (BYTE)(CAUSE_EXT_BIT | *pbCause); } else { pMessage->Cause.Present = FALSE; }
if (pUserUserData && pUserUserData->ptr) { if (pUserUserData->length > sizeof(pMessage->UserToUser.UserInformation)) { Free(pMessage); return CS_BAD_PARAM; } pMessage->UserToUser.Present = TRUE; pMessage->UserToUser.UserInformationLength = (pUserUserData->length); memcpy(pMessage->UserToUser.UserInformation, pUserUserData->ptr, pUserUserData->length); } Result = Q931MakeEncodedMessage(pMessage, CodedBufferPtr, CodedBufferLength);
Free(pMessage); return Result; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931ConnectEncodePDU( WORD wCallReference, char *pszDisplay, DWORD dwBandwidth, BINARY_STRING *pUserUserData, BYTE **CodedBufferPtr, DWORD *CodedBufferLength) { Q931MESSAGE *pMessage; HRESULT Result = CS_OK; BYTE bBandwidth;
pMessage = (Q931MESSAGE *)Malloc(sizeof(Q931MESSAGE)); if (pMessage == NULL) { return CS_NO_MEMORY; }
// fill in the required fields for the setup message.
memset(pMessage, 0, sizeof(Q931MESSAGE)); pMessage->ProtocolDiscriminator = Q931PDVALUE; pMessage->CallReference = wCallReference; pMessage->MessageType = CONNECTMESSAGETYPE;
pMessage->BearerCapability.Present = TRUE; pMessage->BearerCapability.Length = 4; pMessage->BearerCapability.Contents[0] = (BYTE)(BEAR_EXT_BIT | BEAR_CCITT | BEAR_UNRESTRICTED_DIGITAL); pMessage->BearerCapability.Contents[1] = (BYTE)(BEAR_CIRCUIT_MODE | BEAR_MULTIRATE); bBandwidth = (BYTE)(dwBandwidth / 64000); if ((dwBandwidth % 64000) != 0) bBandwidth++; pMessage->BearerCapability.Contents[2] = (BYTE)(BEAR_EXT_BIT | bBandwidth); pMessage->BearerCapability.Contents[3] = (BYTE)(BEAR_EXT_BIT | BEAR_LAYER1_INDICATOR | BEAR_LAYER1_H221_H242);
if (pszDisplay && *pszDisplay) { pMessage->Display.Present = TRUE; pMessage->Display.Length = (BYTE)strlen(pszDisplay); strcpy((char *)pMessage->Display.Contents, pszDisplay); }
if (pUserUserData && pUserUserData->ptr) { if (pUserUserData->length > sizeof(pMessage->UserToUser.UserInformation)) { Free(pMessage); return CS_BAD_PARAM; } pMessage->UserToUser.Present = TRUE; pMessage->UserToUser.UserInformationLength = (pUserUserData->length); memcpy(pMessage->UserToUser.UserInformation, pUserUserData->ptr, pUserUserData->length); } Result = Q931MakeEncodedMessage(pMessage, CodedBufferPtr, CodedBufferLength);
Free(pMessage); return Result; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931ProceedingEncodePDU( WORD wCallReference, BINARY_STRING *pUserUserData, BYTE **CodedBufferPtr, DWORD *CodedBufferLength) { Q931MESSAGE *pMessage; HRESULT Result = CS_OK;
pMessage = (Q931MESSAGE *)Malloc(sizeof(Q931MESSAGE)); if (pMessage == NULL) { return CS_NO_MEMORY; }
// fill in the required fields for the setup message.
memset(pMessage, 0, sizeof(Q931MESSAGE)); pMessage->ProtocolDiscriminator = Q931PDVALUE; pMessage->CallReference = wCallReference; pMessage->MessageType = PROCEEDINGMESSAGETYPE;
if (pUserUserData && pUserUserData->ptr) { if (pUserUserData->length > sizeof(pMessage->UserToUser.UserInformation)) { Free(pMessage); return CS_BAD_PARAM; } pMessage->UserToUser.Present = TRUE; pMessage->UserToUser.UserInformationLength = (pUserUserData->length); memcpy(pMessage->UserToUser.UserInformation, pUserUserData->ptr, pUserUserData->length); } Result = Q931MakeEncodedMessage(pMessage, CodedBufferPtr, CodedBufferLength);
Free(pMessage); return Result; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931AlertingEncodePDU( WORD wCallReference, BINARY_STRING *pUserUserData, BYTE **CodedBufferPtr, DWORD *CodedBufferLength) { Q931MESSAGE *pMessage; HRESULT Result = CS_OK;
pMessage = (Q931MESSAGE *)Malloc(sizeof(Q931MESSAGE)); if (pMessage == NULL) { return CS_NO_MEMORY; }
// fill in the required fields for the setup message.
memset(pMessage, 0, sizeof(Q931MESSAGE)); pMessage->ProtocolDiscriminator = Q931PDVALUE; pMessage->CallReference = wCallReference; pMessage->MessageType = ALERTINGMESSAGETYPE;
if (pUserUserData && pUserUserData->ptr) { if (pUserUserData->length > sizeof(pMessage->UserToUser.UserInformation)) { Free(pMessage); return CS_BAD_PARAM; } pMessage->UserToUser.Present = TRUE; pMessage->UserToUser.UserInformationLength = (pUserUserData->length); memcpy(pMessage->UserToUser.UserInformation, pUserUserData->ptr, pUserUserData->length); } Result = Q931MakeEncodedMessage(pMessage, CodedBufferPtr, CodedBufferLength);
Free(pMessage); return Result; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931FacilityEncodePDU( WORD wCallReference, BINARY_STRING *pUserUserData, BYTE **CodedBufferPtr, DWORD *CodedBufferLength) { Q931MESSAGE *pMessage; HRESULT Result = CS_OK;
pMessage = (Q931MESSAGE *)Malloc(sizeof(Q931MESSAGE)); if (pMessage == NULL) { return CS_NO_MEMORY; }
// fill in the required fields for the setup message.
memset(pMessage, 0, sizeof(Q931MESSAGE)); pMessage->ProtocolDiscriminator = Q931PDVALUE; pMessage->CallReference = wCallReference; pMessage->MessageType = FACILITYMESSAGETYPE;
// The facility ie is encoded as present, but empty...
pMessage->Facility.Present = TRUE; pMessage->Facility.Length = 0; pMessage->Facility.Contents[0] = 0;
if (pUserUserData && pUserUserData->ptr) { if (pUserUserData->length > sizeof(pMessage->UserToUser.UserInformation)) { Free(pMessage); return CS_BAD_PARAM; } pMessage->UserToUser.Present = TRUE; pMessage->UserToUser.UserInformationLength = (pUserUserData->length); memcpy(pMessage->UserToUser.UserInformation, pUserUserData->ptr, pUserUserData->length); } Result = Q931MakeEncodedMessage(pMessage, CodedBufferPtr, CodedBufferLength);
Free(pMessage); return Result; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931StatusEncodePDU( WORD wCallReference, char *pszDisplay, BYTE bCause, BYTE bCallState, BYTE **CodedBufferPtr, DWORD *CodedBufferLength) { Q931MESSAGE *pMessage; HRESULT Result = CS_OK;
pMessage = (Q931MESSAGE *)Malloc(sizeof(Q931MESSAGE)); if (pMessage == NULL) { return CS_NO_MEMORY; }
// fill in the required fields for the setup message.
memset(pMessage, 0, sizeof(Q931MESSAGE)); pMessage->ProtocolDiscriminator = Q931PDVALUE; pMessage->CallReference = wCallReference; pMessage->MessageType = STATUSMESSAGETYPE;
if (pszDisplay && *pszDisplay) { pMessage->Display.Present = TRUE; pMessage->Display.Length = (BYTE)(strlen(pszDisplay) + 1); strcpy((char *)pMessage->Display.Contents, pszDisplay); }
pMessage->Cause.Present = TRUE; pMessage->Cause.Length = 3; pMessage->Cause.Contents[0] = (BYTE)(CAUSE_CODING_CCITT | CAUSE_LOCATION_USER); pMessage->Cause.Contents[1] = (BYTE)(CAUSE_RECOMMENDATION_Q931); pMessage->Cause.Contents[2] = (BYTE)(CAUSE_EXT_BIT | bCause);
pMessage->CallState.Present = TRUE; pMessage->CallState.Length = 1; pMessage->CallState.Contents[0] = (BYTE)(bCallState);
Result = Q931MakeEncodedMessage(pMessage, CodedBufferPtr, CodedBufferLength);
Free(pMessage); return Result; } #if(0)
//========================================================================
//========================================================================
//========================================================================
// THIS IS THE ASN PART...
//========================================================================
//========================================================================
//========================================================================
static ERROR_MAP EncodeErrorMap[] = { PDU_ENCODED, __TEXT("PDU successfully encoded"), MORE_BUF, __TEXT("User-provided output buffer too small"), PDU_RANGE, __TEXT("PDU specified out of range"), BAD_ARG, __TEXT("Bad pointer was passed"), BAD_VERSION, __TEXT("Versions of encoder and table do not match"), OUT_MEMORY, __TEXT("Memory-allocation error"), BAD_CHOICE, __TEXT("Unknown selector for a choice"), BAD_OBJID, __TEXT("Object identifier conflicts with x.208"), BAD_PTR, __TEXT("Unexpected NULL pointer in input buffer"), BAD_TIME, __TEXT("Bad value in time type"), MEM_ERROR, __TEXT("Memory violation signal trapped"), BAD_TABLE, __TEXT("Table was bad, but not NULL"), TOO_LONG, __TEXT("Type was longer than constraint"), CONSTRAINT_VIOLATED, __TEXT("Constraint violation error occured"), FATAL_ERROR, __TEXT("Serious internal error"), ACCESS_SERIALIZATION_ERROR, __TEXT("Thread access to global data failed"), NULL_TBL, __TEXT("NULL control table pointer"), NULL_FCN, __TEXT("Encoder called via a NULL pointer"), BAD_ENCRULES, __TEXT("Unknown encoding rules"), UNAVAIL_ENCRULES, __TEXT("Encoding rules requested are not implemented"), UNIMPLEMENTED, __TEXT("Type was not implemented yet"), // LOAD_ERR, __TEXT("Unable to load DLL"),
CANT_OPEN_TRACE_FILE, __TEXT("Error when opening a trace file"), TRACE_FILE_ALREADY_OPEN, __TEXT("Trace file has been opened"), TABLE_MISMATCH, __TEXT("Control table mismatch"), 0, NULL };
static ERROR_MAP DecodeErrorMap[] = { PDU_DECODED, __TEXT("PDU successfully decoded"), MORE_BUF, __TEXT("User-provided output buffer too small"), NEGATIVE_UINTEGER, __TEXT("The first unsigned bit of the encoding is 1"), PDU_RANGE, __TEXT("Pdu specified out of range"), MORE_INPUT, __TEXT("Unexpected end of input buffer"), DATA_ERROR, __TEXT("An error exists in the encoded data"), BAD_VERSION, __TEXT("Versions of encoder and table do not match"), OUT_MEMORY, __TEXT("Memory-allocation error"), PDU_MISMATCH, __TEXT("The PDU tag does not match data"), LIMITED, __TEXT("Size implementation limit exceeded"), CONSTRAINT_VIOLATED, __TEXT("Constraint violation error occured"), ACCESS_SERIALIZATION_ERROR, __TEXT("Thread access to global data failed"), NULL_TBL, __TEXT("NULL control table pointer"), NULL_FCN, __TEXT("Encoder called via a NULL pointer"), BAD_ENCRULES, __TEXT("Unknown encoding rules"), UNAVAIL_ENCRULES, __TEXT("Encoding rules requested are not implemented"), UNIMPLEMENTED, __TEXT("The type was not implemented yet"), // LOAD_ERR, __TEXT("Unable to load DLL"),
CANT_OPEN_TRACE_FILE, __TEXT("Error when opening a trace file"), TRACE_FILE_ALREADY_OPEN, __TEXT("The trace file has been opened"), TABLE_MISMATCH, __TEXT("Control table mismatch"), 0, NULL };
#endif // if(0)
//====================================================================================
//====================================================================================
#ifdef UNICODE_TRACE
LPWSTR #else
LPSTR #endif
ErrorToTextASN(ERROR_MAP *Map, int nErrorCode) { register int nIndex = 0;
if (Map != NULL) { for (nIndex = 0; Map[nIndex].pszErrorText; nIndex++) { if (Map[nIndex].nErrorCode == nErrorCode) { return Map[nIndex].pszErrorText; } } } return __TEXT("Unknown ASN.1 Error"); }
#if 0
//------------------------------------------------------------------------
//------------------------------------------------------------------------
int ASN1LinePrint(FILE *stream, const char *format, ...) { va_list marker; char buf[300]; int i;
va_start(marker, format); i = wsprintf(buf, format, marker); va_end(marker);
// TRACE the buf...
QTRACE((buf));
return i; } #endif
//------------------------------------------------------------------------
//------------------------------------------------------------------------
HRESULT Q931InitPER() { // initialize TELES ASN.1 module structure
if (Q931_InitModule() != ASN1_SUCCESS) { ASSERT(FALSE); return CS_SUBSYSTEM_FAILURE; }
// note: init of world struct moved to CreateCallObject()
ProtocolId1.value = Q931_PROTOCOL_ID1; ProtocolId1.next = &ProtocolId2; ProtocolId2.value = Q931_PROTOCOL_ID2; ProtocolId2.next = &ProtocolId3; ProtocolId3.value = Q931_PROTOCOL_ID3; ProtocolId3.next = &ProtocolId4; ProtocolId4.value = Q931_PROTOCOL_ID4; ProtocolId4.next = &ProtocolId5; ProtocolId5.value = Q931_PROTOCOL_ID5; ProtocolId5.next = &ProtocolId6; ProtocolId6.value = Q931_PROTOCOL_ID6; ProtocolId6.next = NULL;
// gateway protocol supported. For now, hard-coded to only 1: H323.
TempProtocol.next = NULL; TempProtocol.value.choice = h323_chosen;
return CS_OK; }
//------------------------------------------------------------------------
//------------------------------------------------------------------------
HRESULT Q931DeInitPER() { // clean up TELES ASN.1 module structure
Q931_TermModule(); return CS_OK; }
#define USE_ASN1_ENCODING 5
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931SetupEncodeASN( PCC_NONSTANDARDDATA pNonStandardData, CC_ADDR *pCallerAddr, // this data is not yet passed in the PDU...
CC_ADDR *pCalleeAddr, WORD wGoal, WORD wCallType, BOOL bCallerIsMC, CC_CONFERENCEID *pConferenceID, PCC_ALIASNAMES pCallerAliasList, PCC_ALIASNAMES pCalleeAliasList, PCC_ALIASNAMES pExtraAliasList, PCC_ALIASITEM pExtensionAliasItem, PCC_VENDORINFO pVendorInfo, BOOL bIsTerminal, BOOL bIsGateway, ASN1_CODER_INFO *pWorld, BYTE **ppEncodedBuf, DWORD *pdwEncodedLength) { int rc; H323_UserInformation UserInfo;
*ppEncodedBuf = NULL; *pdwEncodedLength = 0;
memset(&UserInfo, 0, sizeof(H323_UserInformation));
UserInfo.bit_mask = 0;
// make sure the user_data_present flag is turned off.
UserInfo.bit_mask &= (~user_data_present);
if (pNonStandardData) { UserInfo.h323_uu_pdu.bit_mask |= H323_UU_PDU_nnStndrdDt_present; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice = h221NonStandard_chosen; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = pNonStandardData->bCountryCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension = pNonStandardData->bExtension; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = pNonStandardData->wManufacturerCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length = pNonStandardData->sData.wOctetStringLength; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value = pNonStandardData->sData.pOctetString; } else { UserInfo.h323_uu_pdu.bit_mask &= (~H323_UU_PDU_nnStndrdDt_present); }
UserInfo.h323_uu_pdu.h323_message_body.choice = setup_chosen; UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask = 0;
UserInfo.h323_uu_pdu.h323_message_body.u.setup.protocolIdentifier = &ProtocolId1;
if (pCallerAliasList) { CS_STATUS AliasResult = CS_OK; AliasResult = AliasToSeqof((struct _seqof3 **)&(UserInfo.h323_uu_pdu. h323_message_body.u.setup.sourceAddress), pCallerAliasList); if (AliasResult != CS_OK) { return CS_NO_MEMORY; } UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask |= (sourceAddress_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask &= (~sourceAddress_present); }
UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.bit_mask = 0;
if (pVendorInfo) { UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.bit_mask |= vendor_present; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.bit_mask = 0; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.vendor.t35CountryCode = pVendorInfo->bCountryCode; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.vendor.t35Extension = pVendorInfo->bExtension; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.vendor.manufacturerCode = pVendorInfo->wManufacturerCode; if (pVendorInfo->pProductNumber && pVendorInfo->pProductNumber->pOctetString && pVendorInfo->pProductNumber->wOctetStringLength) { UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.bit_mask |= productId_present; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.productId.length = pVendorInfo->pProductNumber->wOctetStringLength; memcpy(UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.productId.value, pVendorInfo->pProductNumber->pOctetString, pVendorInfo->pProductNumber->wOctetStringLength); } if (pVendorInfo->pVersionNumber && pVendorInfo->pVersionNumber->pOctetString && pVendorInfo->pVersionNumber->wOctetStringLength) { UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.bit_mask |= versionId_present; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.versionId.length = pVendorInfo->pVersionNumber->wOctetStringLength; memcpy(UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.versionId.value, pVendorInfo->pVersionNumber->pOctetString, pVendorInfo->pVersionNumber->wOctetStringLength); } }
if (bIsTerminal) { UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.bit_mask |= terminal_present; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.terminal.bit_mask = 0; }
if (bIsGateway) { UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.bit_mask |= gateway_present; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.gateway.bit_mask = protocol_present; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.gateway.protocol = &TempProtocol; }
UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.mc = (ASN1_BOOL)bCallerIsMC; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceInfo.undefinedNode = 0;
if (pCalleeAliasList) { CS_STATUS AliasResult = CS_OK; AliasResult = AliasWithPrefixToSeqof((struct _seqof3 **)&(UserInfo.h323_uu_pdu. h323_message_body.u.setup.destinationAddress), pCalleeAliasList); if (AliasResult != CS_OK) { FreeSeqof((struct _seqof3 *)UserInfo.h323_uu_pdu. h323_message_body.u.setup.sourceAddress); UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceAddress = NULL; return CS_NO_MEMORY; } UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask |= (destinationAddress_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask &= (~destinationAddress_present); }
if (pExtraAliasList) { CS_STATUS AliasResult = CS_OK; AliasResult = AliasWithPrefixToSeqof((struct _seqof3 **)&(UserInfo.h323_uu_pdu. h323_message_body.u.setup.destExtraCallInfo), pExtraAliasList); if (AliasResult != CS_OK) { FreeSeqof((struct _seqof3 *)UserInfo.h323_uu_pdu.h323_message_body.u.setup.destinationAddress); UserInfo.h323_uu_pdu.h323_message_body.u.setup.destinationAddress = NULL; FreeSeqof((struct _seqof3 *)UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceAddress); UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceAddress = NULL; return CS_NO_MEMORY; } UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask |= (destExtraCallInfo_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask &= (~destExtraCallInfo_present); }
if (pCalleeAddr) { DWORD a = pCalleeAddr->Addr.IP_Binary.dwAddr; UserInfo.h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.choice = ipAddress_chosen; UserInfo.h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.u.ipAddress.ip.length = 4; UserInfo.h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.u.ipAddress.port = pCalleeAddr->Addr.IP_Binary.wPort; UserInfo.h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.u.ipAddress.ip.value[0] = ((BYTE *)&a)[3]; UserInfo.h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.u.ipAddress.ip.value[1] = ((BYTE *)&a)[2]; UserInfo.h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.u.ipAddress.ip.value[2] = ((BYTE *)&a)[1]; UserInfo.h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.u.ipAddress.ip.value[3] = ((BYTE *)&a)[0]; UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask |= (destCallSignalAddress_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask &= (~destCallSignalAddress_present); }
UserInfo.h323_uu_pdu.h323_message_body.u.setup.activeMC = (ASN1_BOOL)bCallerIsMC;
if (pConferenceID != NULL) { UserInfo.h323_uu_pdu.h323_message_body.u.setup.conferenceID.length = sizeof(UserInfo.h323_uu_pdu.h323_message_body.u.setup.conferenceID.value); memcpy(UserInfo.h323_uu_pdu.h323_message_body.u.setup.conferenceID.value, pConferenceID->buffer, UserInfo.h323_uu_pdu.h323_message_body.u.setup.conferenceID.length); }
switch (wGoal) { case CSG_INVITE: UserInfo.h323_uu_pdu.h323_message_body.u.setup.conferenceGoal.choice = invite_chosen; break; case CSG_JOIN: UserInfo.h323_uu_pdu.h323_message_body.u.setup.conferenceGoal.choice = join_chosen; break; default: UserInfo.h323_uu_pdu.h323_message_body.u.setup.conferenceGoal.choice = create_chosen; } // switch
switch (wCallType) { case CC_CALLTYPE_1_N: UserInfo.h323_uu_pdu.h323_message_body.u.setup.callType.choice = oneToN_chosen; break; case CC_CALLTYPE_N_1: UserInfo.h323_uu_pdu.h323_message_body.u.setup.callType.choice = nToOne_chosen; break; case CC_CALLTYPE_N_N: UserInfo.h323_uu_pdu.h323_message_body.u.setup.callType.choice = nToN_chosen; break; default: UserInfo.h323_uu_pdu.h323_message_body.u.setup.callType.choice = pointToPoint_chosen; } // switch
if (pCallerAddr) { DWORD a = pCallerAddr->Addr.IP_Binary.dwAddr; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.choice = ipAddress_chosen; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.u.ipAddress.ip.length = 4; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.u.ipAddress.port = pCallerAddr->Addr.IP_Binary.wPort; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.u.ipAddress.ip.value[0] = ((BYTE *)&a)[3]; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.u.ipAddress.ip.value[1] = ((BYTE *)&a)[2]; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.u.ipAddress.ip.value[2] = ((BYTE *)&a)[1]; UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.u.ipAddress.ip.value[3] = ((BYTE *)&a)[0]; UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask |= (sourceCallSignalAddress_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask &= (~sourceCallSignalAddress_present); }
if (pExtensionAliasItem) { CS_STATUS AliasResult = CS_OK; AliasResult = Q931CopyAliasItemToAliasAddr(&(UserInfo.h323_uu_pdu. h323_message_body.u.setup.remoteExtensionAddress), pExtensionAliasItem); if (AliasResult != CS_OK) { FreeSeqof((struct _seqof3 *)UserInfo.h323_uu_pdu.h323_message_body.u.setup.destExtraCallInfo); UserInfo.h323_uu_pdu.h323_message_body.u.setup.destExtraCallInfo = NULL; FreeSeqof((struct _seqof3 *)UserInfo.h323_uu_pdu.h323_message_body.u.setup.destinationAddress); UserInfo.h323_uu_pdu.h323_message_body.u.setup.destinationAddress = NULL; FreeSeqof((struct _seqof3 *)UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceAddress); UserInfo.h323_uu_pdu.h323_message_body.u.setup.sourceAddress = NULL; return CS_NO_MEMORY; } UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask |= (remoteExtensionAddress_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.setup.bit_mask &= (~remoteExtensionAddress_present); }
rc = Q931_Encode(pWorld, (void *) &UserInfo, H323_UserInformation_PDU, ppEncodedBuf, pdwEncodedLength);
// Free the alias name structures from the UserInfo area.
FreeSeqof((struct _seqof3 *)UserInfo.h323_uu_pdu.h323_message_body.u. setup.sourceAddress); FreeSeqof((struct _seqof3 *)UserInfo.h323_uu_pdu.h323_message_body.u. setup.destinationAddress); FreeSeqof((struct _seqof3 *)UserInfo.h323_uu_pdu.h323_message_body.u. setup.destExtraCallInfo); Q931ClearAliasAddr(&(UserInfo.h323_uu_pdu.h323_message_body.u.setup.remoteExtensionAddress));
if (ASN1_FAILED(rc)) { ASSERT(FALSE); return CS_SUBSYSTEM_FAILURE; }
return CS_OK; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
void Q931FreeEncodedBuffer(ASN1_CODER_INFO *pWorld, BYTE *pEncodedBuf) { ASN1_FreeEncoded(pWorld->pEncInfo, pEncodedBuf); }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931ReleaseCompleteEncodeASN( PCC_NONSTANDARDDATA pNonStandardData, CC_CONFERENCEID *pConferenceID, // not passed in PDU!
BYTE *pbReason, ASN1_CODER_INFO *pWorld, BYTE **ppEncodedBuf, DWORD *pdwEncodedLength) { int rc; H323_UserInformation UserInfo;
*ppEncodedBuf = NULL; *pdwEncodedLength = 0;
memset(&UserInfo, 0, sizeof(H323_UserInformation));
UserInfo.bit_mask = 0;
// make sure the user_data_present flag is turned off.
UserInfo.bit_mask &= (~user_data_present);
UserInfo.h323_uu_pdu.bit_mask = 0;
if (pNonStandardData) { UserInfo.h323_uu_pdu.bit_mask |= H323_UU_PDU_nnStndrdDt_present; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice = h221NonStandard_chosen; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = pNonStandardData->bCountryCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension = pNonStandardData->bExtension; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = pNonStandardData->wManufacturerCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length = pNonStandardData->sData.wOctetStringLength; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value = pNonStandardData->sData.pOctetString; } else { UserInfo.h323_uu_pdu.bit_mask &= (~H323_UU_PDU_nnStndrdDt_present); }
UserInfo.h323_uu_pdu.h323_message_body.choice = releaseComplete_chosen;
UserInfo.h323_uu_pdu.h323_message_body.u.releaseComplete.protocolIdentifier = &ProtocolId1;
if (pbReason) { unsigned short choice = 0;
UserInfo.h323_uu_pdu.h323_message_body.u.releaseComplete.bit_mask |= (reason_present); switch (*pbReason) { case CC_REJECT_NO_BANDWIDTH: choice = noBandwidth_chosen; break; case CC_REJECT_GATEKEEPER_RESOURCES: choice = gatekeeperResources_chosen; break; case CC_REJECT_UNREACHABLE_DESTINATION: choice = unreachableDestination_chosen; break; case CC_REJECT_DESTINATION_REJECTION: choice = destinationRejection_chosen; break; case CC_REJECT_INVALID_REVISION: choice = invalidRevision_chosen; break; case CC_REJECT_NO_PERMISSION: choice = noPermission_chosen; break; case CC_REJECT_UNREACHABLE_GATEKEEPER: choice = unreachableGatekeeper_chosen; break; case CC_REJECT_GATEWAY_RESOURCES: choice = gatewayResources_chosen; break; case CC_REJECT_BAD_FORMAT_ADDRESS: choice = badFormatAddress_chosen; break; case CC_REJECT_ADAPTIVE_BUSY: choice = adaptiveBusy_chosen; break; case CC_REJECT_IN_CONF: choice = inConf_chosen; break; case CC_REJECT_CALL_DEFLECTION: choice = facilityCallDeflection_chosen; break; case CC_REJECT_UNDEFINED_REASON: choice = RlsCmpltRsn_undfndRsn_chosen; break; case CC_REJECT_USER_BUSY: choice = inConf_chosen; break; default: return CS_BAD_PARAM; break; } UserInfo.h323_uu_pdu.h323_message_body.u.releaseComplete.reason.choice = choice; }
rc = Q931_Encode(pWorld, (void *) &UserInfo, H323_UserInformation_PDU, ppEncodedBuf, pdwEncodedLength);
if (ASN1_FAILED(rc)) { ASSERT(FALSE); return CS_SUBSYSTEM_FAILURE; }
return CS_OK; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931ConnectEncodeASN( PCC_NONSTANDARDDATA pNonStandardData, CC_CONFERENCEID *pConferenceID, // must be able to support 16 byte conf id's!
CC_ADDR *h245Addr, PCC_ENDPOINTTYPE pEndpointType, ASN1_CODER_INFO *pWorld, BYTE **ppEncodedBuf, DWORD *pdwEncodedLength) { int rc; H323_UserInformation UserInfo;
*ppEncodedBuf = NULL; *pdwEncodedLength = 0;
memset(&UserInfo, 0, sizeof(H323_UserInformation)); UserInfo.bit_mask = 0;
// make sure the user_data_present flag is turned off.
UserInfo.bit_mask &= (~user_data_present);
UserInfo.h323_uu_pdu.bit_mask = 0;
if (pNonStandardData) { UserInfo.h323_uu_pdu.bit_mask |= H323_UU_PDU_nnStndrdDt_present; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice = h221NonStandard_chosen; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = pNonStandardData->bCountryCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension = pNonStandardData->bExtension; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = pNonStandardData->wManufacturerCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length = pNonStandardData->sData.wOctetStringLength; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value = pNonStandardData->sData.pOctetString; } else { UserInfo.h323_uu_pdu.bit_mask &= (~H323_UU_PDU_nnStndrdDt_present); }
UserInfo.h323_uu_pdu.h323_message_body.choice = connect_chosen;
UserInfo.h323_uu_pdu.h323_message_body.u.connect.protocolIdentifier = &ProtocolId1;
if (h245Addr != NULL) { DWORD a = h245Addr->Addr.IP_Binary.dwAddr; UserInfo.h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.choice = ipAddress_chosen; UserInfo.h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.u.ipAddress.ip.length = 4; UserInfo.h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.u.ipAddress.port = h245Addr->Addr.IP_Binary.wPort; UserInfo.h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.u.ipAddress.ip.value[0] = ((BYTE *)&a)[3]; UserInfo.h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.u.ipAddress.ip.value[1] = ((BYTE *)&a)[2]; UserInfo.h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.u.ipAddress.ip.value[2] = ((BYTE *)&a)[1]; UserInfo.h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.u.ipAddress.ip.value[3] = ((BYTE *)&a)[0]; UserInfo.h323_uu_pdu.h323_message_body.u.connect.bit_mask |= (Cnnct_UUIE_h245Address_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.connect.bit_mask &= (~Cnnct_UUIE_h245Address_present); }
UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.bit_mask = 0;
if (pEndpointType) { PCC_VENDORINFO pVendorInfo = pEndpointType->pVendorInfo; if (pVendorInfo) { UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.bit_mask |= vendor_present; UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.bit_mask = 0; UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.vendor.t35CountryCode = pVendorInfo->bCountryCode; UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.vendor.t35Extension = pVendorInfo->bExtension; UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.vendor.manufacturerCode = pVendorInfo->wManufacturerCode;
if (pVendorInfo->pProductNumber && pVendorInfo->pProductNumber->pOctetString && pVendorInfo->pProductNumber->wOctetStringLength) { UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.bit_mask |= productId_present; UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.productId.length = pVendorInfo->pProductNumber->wOctetStringLength; memcpy(UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.productId.value, pVendorInfo->pProductNumber->pOctetString, pVendorInfo->pProductNumber->wOctetStringLength); } if (pVendorInfo->pVersionNumber && pVendorInfo->pVersionNumber->pOctetString && pVendorInfo->pVersionNumber->wOctetStringLength) { UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.bit_mask |= versionId_present; UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.versionId.length = pVendorInfo->pVersionNumber->wOctetStringLength; memcpy(UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.versionId.value, pVendorInfo->pVersionNumber->pOctetString, pVendorInfo->pVersionNumber->wOctetStringLength); } } if (pEndpointType->bIsTerminal) { UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.bit_mask |= terminal_present; UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.terminal.bit_mask = 0; } if (pEndpointType->bIsGateway) { UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.bit_mask |= gateway_present; UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.gateway.bit_mask = protocol_present; UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.gateway.protocol = &TempProtocol; } }
UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.mc = 0; UserInfo.h323_uu_pdu.h323_message_body.u.connect.destinationInfo.undefinedNode = 0;
if (pConferenceID != NULL) { UserInfo.h323_uu_pdu.h323_message_body.u.connect.conferenceID.length = sizeof(UserInfo.h323_uu_pdu.h323_message_body.u.connect.conferenceID.value); memcpy(UserInfo.h323_uu_pdu.h323_message_body.u.connect.conferenceID.value, pConferenceID->buffer, UserInfo.h323_uu_pdu.h323_message_body.u.connect.conferenceID.length); }
rc = Q931_Encode(pWorld, (void *) &UserInfo, H323_UserInformation_PDU, ppEncodedBuf, pdwEncodedLength);
if (ASN1_FAILED(rc)) { ASSERT(FALSE); return CS_SUBSYSTEM_FAILURE; }
return CS_OK; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931AlertingEncodeASN( PCC_NONSTANDARDDATA pNonStandardData, CC_ADDR *h245Addr, PCC_ENDPOINTTYPE pEndpointType, ASN1_CODER_INFO *pWorld, BYTE **ppEncodedBuf, DWORD *pdwEncodedLength) { int rc; H323_UserInformation UserInfo;
*ppEncodedBuf = NULL; *pdwEncodedLength = 0;
memset(&UserInfo, 0, sizeof(H323_UserInformation)); UserInfo.bit_mask = 0;
// make sure the user_data_present flag is turned off.
UserInfo.bit_mask &= (~user_data_present);
UserInfo.h323_uu_pdu.bit_mask = 0;
if (pNonStandardData) { UserInfo.h323_uu_pdu.bit_mask |= H323_UU_PDU_nnStndrdDt_present; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice = h221NonStandard_chosen; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = pNonStandardData->bCountryCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension = pNonStandardData->bExtension; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = pNonStandardData->wManufacturerCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length = pNonStandardData->sData.wOctetStringLength; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value = pNonStandardData->sData.pOctetString; } else { UserInfo.h323_uu_pdu.bit_mask &= (~H323_UU_PDU_nnStndrdDt_present); }
UserInfo.h323_uu_pdu.h323_message_body.choice = alerting_chosen;
UserInfo.h323_uu_pdu.h323_message_body.u.alerting.protocolIdentifier = &ProtocolId1;
UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.bit_mask = 0; if (pEndpointType) { PCC_VENDORINFO pVendorInfo = pEndpointType->pVendorInfo; if (pVendorInfo) { UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.bit_mask |= vendor_present; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.vendor.bit_mask = 0; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.vendor.vendor.t35CountryCode = pVendorInfo->bCountryCode; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.vendor.vendor.t35Extension = pVendorInfo->bExtension; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.vendor.vendor.manufacturerCode = pVendorInfo->wManufacturerCode;
if (pVendorInfo->pProductNumber && pVendorInfo->pProductNumber->pOctetString && pVendorInfo->pProductNumber->wOctetStringLength) { UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.vendor.bit_mask |= productId_present; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.vendor.productId.length = pVendorInfo->pProductNumber->wOctetStringLength; memcpy(UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.vendor.productId.value, pVendorInfo->pProductNumber->pOctetString, pVendorInfo->pProductNumber->wOctetStringLength); } if (pVendorInfo->pVersionNumber && pVendorInfo->pVersionNumber->pOctetString && pVendorInfo->pVersionNumber->wOctetStringLength) { UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.vendor.bit_mask |= versionId_present; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.vendor.versionId.length = pVendorInfo->pVersionNumber->wOctetStringLength; memcpy(UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.vendor.versionId.value, pVendorInfo->pVersionNumber->pOctetString, pVendorInfo->pVersionNumber->wOctetStringLength); } } if (pEndpointType->bIsTerminal) { UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.bit_mask = terminal_present; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.terminal.bit_mask = 0; } if (pEndpointType->bIsGateway) { UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.bit_mask = gateway_present; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.gateway.bit_mask = protocol_present; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.gateway.protocol = &TempProtocol; } }
UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.mc = 0; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.destinationInfo.undefinedNode = 0;
if (h245Addr != NULL) { DWORD a = h245Addr->Addr.IP_Binary.dwAddr; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.choice = ipAddress_chosen; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.u.ipAddress.ip.length = 4; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.u.ipAddress.port = h245Addr->Addr.IP_Binary.wPort; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[0] = ((BYTE *)&a)[3]; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[1] = ((BYTE *)&a)[2]; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[2] = ((BYTE *)&a)[1]; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[3] = ((BYTE *)&a)[0]; UserInfo.h323_uu_pdu.h323_message_body.u.alerting.bit_mask |= (CPg_UUIE_h245Addrss_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.alerting.bit_mask &= (~CPg_UUIE_h245Addrss_present); }
rc = Q931_Encode(pWorld, (void *) &UserInfo, H323_UserInformation_PDU, ppEncodedBuf, pdwEncodedLength);
if (ASN1_FAILED(rc)) { ASSERT(FALSE); return CS_SUBSYSTEM_FAILURE; }
return CS_OK; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931ProceedingEncodeASN( PCC_NONSTANDARDDATA pNonStandardData, CC_ADDR *h245Addr, PCC_ENDPOINTTYPE pEndpointType, ASN1_CODER_INFO *pWorld, BYTE **ppEncodedBuf, DWORD *pdwEncodedLength) { int rc; H323_UserInformation UserInfo;
*ppEncodedBuf = NULL; *pdwEncodedLength = 0;
memset(&UserInfo, 0, sizeof(H323_UserInformation)); UserInfo.bit_mask = 0;
// make sure the user_data_present flag is turned off.
UserInfo.bit_mask &= (~user_data_present);
UserInfo.h323_uu_pdu.bit_mask = 0;
if (pNonStandardData) { UserInfo.h323_uu_pdu.bit_mask |= H323_UU_PDU_nnStndrdDt_present; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice = h221NonStandard_chosen; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = pNonStandardData->bCountryCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension = pNonStandardData->bExtension; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = pNonStandardData->wManufacturerCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length = pNonStandardData->sData.wOctetStringLength; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value = pNonStandardData->sData.pOctetString; } else { UserInfo.h323_uu_pdu.bit_mask &= (~H323_UU_PDU_nnStndrdDt_present); }
UserInfo.h323_uu_pdu.h323_message_body.choice = callProceeding_chosen;
UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.protocolIdentifier = &ProtocolId1;
if (h245Addr != NULL) { DWORD a = h245Addr->Addr.IP_Binary.dwAddr; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.choice = ipAddress_chosen; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.u.ipAddress.ip.length = 4; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.u.ipAddress.port = h245Addr->Addr.IP_Binary.wPort; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[0] = ((BYTE *)&a)[3]; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[1] = ((BYTE *)&a)[2]; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[2] = ((BYTE *)&a)[1]; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[3] = ((BYTE *)&a)[0]; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.bit_mask |= (CPg_UUIE_h245Addrss_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.bit_mask &= (~CPg_UUIE_h245Addrss_present); }
UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.bit_mask = 0; if (pEndpointType) { PCC_VENDORINFO pVendorInfo = pEndpointType->pVendorInfo; if (pVendorInfo) { UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.bit_mask |= vendor_present; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.vendor.bit_mask = 0; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.vendor.vendor.t35CountryCode = pVendorInfo->bCountryCode; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.vendor.vendor.t35Extension = pVendorInfo->bExtension; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.vendor.vendor.manufacturerCode = pVendorInfo->wManufacturerCode;
if (pVendorInfo->pProductNumber && pVendorInfo->pProductNumber->pOctetString && pVendorInfo->pProductNumber->wOctetStringLength) { UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.vendor.bit_mask |= productId_present; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.vendor.productId.length = pVendorInfo->pProductNumber->wOctetStringLength; memcpy(UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.vendor.productId.value, pVendorInfo->pProductNumber->pOctetString, pVendorInfo->pProductNumber->wOctetStringLength); } if (pVendorInfo->pVersionNumber && pVendorInfo->pVersionNumber->pOctetString && pVendorInfo->pVersionNumber->wOctetStringLength) { UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.vendor.bit_mask |= versionId_present; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.vendor.versionId.length = pVendorInfo->pVersionNumber->wOctetStringLength; memcpy(UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.vendor.versionId.value, pVendorInfo->pVersionNumber->pOctetString, pVendorInfo->pVersionNumber->wOctetStringLength); } } if (pEndpointType->bIsTerminal) { UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.bit_mask = terminal_present; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.terminal.bit_mask = 0; } if (pEndpointType->bIsGateway) { UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.bit_mask = gateway_present; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.gateway.bit_mask = protocol_present; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.gateway.protocol = &TempProtocol; } }
UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.mc = 0; UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding.destinationInfo.undefinedNode = 0;
rc = Q931_Encode(pWorld, (void *) &UserInfo, H323_UserInformation_PDU, ppEncodedBuf, pdwEncodedLength);
if (ASN1_FAILED(rc)) { ASSERT(FALSE); return CS_SUBSYSTEM_FAILURE; }
return CS_OK; }
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
HRESULT Q931FacilityEncodeASN( PCC_NONSTANDARDDATA pNonStandardData, CC_ADDR *AlternativeAddr, BYTE bReason, CC_CONFERENCEID *pConferenceID, PCC_ALIASNAMES pAlternativeAliasList, ASN1_CODER_INFO *pWorld, BYTE **ppEncodedBuf, DWORD *pdwEncodedLength) { int rc; H323_UserInformation UserInfo;
*ppEncodedBuf = NULL; *pdwEncodedLength = 0;
memset(&UserInfo, 0, sizeof(H323_UserInformation));
UserInfo.bit_mask = 0;
// make sure the user_data_present flag is turned off.
UserInfo.bit_mask &= (~user_data_present);
if (pNonStandardData) { UserInfo.h323_uu_pdu.bit_mask |= H323_UU_PDU_nnStndrdDt_present; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice = h221NonStandard_chosen; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = pNonStandardData->bCountryCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension = pNonStandardData->bExtension; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = pNonStandardData->wManufacturerCode; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length = pNonStandardData->sData.wOctetStringLength; UserInfo.h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value = pNonStandardData->sData.pOctetString; } else { UserInfo.h323_uu_pdu.bit_mask &= (~H323_UU_PDU_nnStndrdDt_present); }
UserInfo.h323_uu_pdu.h323_message_body.choice = facility_chosen;
UserInfo.h323_uu_pdu.h323_message_body.u.facility.protocolIdentifier = &ProtocolId1;
if (AlternativeAddr != NULL) { DWORD a = AlternativeAddr->Addr.IP_Binary.dwAddr; UserInfo.h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.choice = ipAddress_chosen; UserInfo.h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.u.ipAddress.ip.length = 4; UserInfo.h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.u.ipAddress.port = AlternativeAddr->Addr.IP_Binary.wPort; UserInfo.h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.u.ipAddress.ip.value[0] = ((BYTE *)&a)[3]; UserInfo.h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.u.ipAddress.ip.value[1] = ((BYTE *)&a)[2]; UserInfo.h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.u.ipAddress.ip.value[2] = ((BYTE *)&a)[1]; UserInfo.h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.u.ipAddress.ip.value[3] = ((BYTE *)&a)[0]; UserInfo.h323_uu_pdu.h323_message_body.u.facility.bit_mask |= (alternativeAddress_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.facility.bit_mask &= (~alternativeAddress_present); }
if (pAlternativeAliasList) { CS_STATUS AliasResult = CS_OK; AliasResult = AliasToSeqof((struct _seqof3 **)&(UserInfo.h323_uu_pdu. h323_message_body.u.facility.alternativeAliasAddress), pAlternativeAliasList); if (AliasResult != CS_OK) { return CS_NO_MEMORY; } UserInfo.h323_uu_pdu.h323_message_body.u.facility.bit_mask |= (alternativeAliasAddress_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.facility.bit_mask &= (~alternativeAliasAddress_present); }
if (pConferenceID != NULL) { UserInfo.h323_uu_pdu.h323_message_body.u.facility.conferenceID.length = sizeof(UserInfo.h323_uu_pdu.h323_message_body.u.facility.conferenceID.value); memcpy(UserInfo.h323_uu_pdu.h323_message_body.u.facility.conferenceID.value, pConferenceID->buffer, UserInfo.h323_uu_pdu.h323_message_body.u.facility.conferenceID.length); UserInfo.h323_uu_pdu.h323_message_body.u.facility.bit_mask |= (conferenceID_present); } else { UserInfo.h323_uu_pdu.h323_message_body.u.facility.bit_mask &= (~conferenceID_present); }
switch (bReason) { case CC_REJECT_ROUTE_TO_GATEKEEPER: UserInfo.h323_uu_pdu.h323_message_body.u.facility.reason.choice = routeCallToGatekeeper_chosen; break; case CC_REJECT_CALL_FORWARDED: UserInfo.h323_uu_pdu.h323_message_body.u.facility.reason.choice = callForwarded_chosen; break; case CC_REJECT_ROUTE_TO_MC: UserInfo.h323_uu_pdu.h323_message_body.u.facility.reason.choice = routeCallToMC_chosen; break; default: UserInfo.h323_uu_pdu.h323_message_body.u.facility.reason.choice = RlsCmpltRsn_undfndRsn_chosen; } // switch
rc = Q931_Encode(pWorld, (void *) &UserInfo, H323_UserInformation_PDU, ppEncodedBuf, pdwEncodedLength);
// Free the alias name structures from the UserInfo area.
FreeSeqof((struct _seqof3 *)UserInfo.h323_uu_pdu.h323_message_body.u. facility.alternativeAliasAddress);
if (ASN1_FAILED(rc)) { ASSERT(FALSE); return CS_SUBSYSTEM_FAILURE; } return CS_OK; }
//------------------------------------------------------------------------
//------------------------------------------------------------------------
BOOL Q931ValidPduVersion(struct ObjectID_ *id) { // not sure what version checking to put here
#if 0
if ((id != NULL) && (id->value == 0) && (id->next != NULL) && (id->next->value <= 1)) { return TRUE; } return FALSE; #else
return TRUE; #endif
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
HRESULT Q931SetupParseASN( ASN1_CODER_INFO *pWorld, BYTE *pEncodedBuf, DWORD dwEncodedLength, Q931_SETUP_ASN *pParsedData) { int PDU = H323_UserInformation_PDU; char *pDecodedBuf = NULL; H323_UserInformation *pUserInfo; struct ObjectID_ *id; int Result;
if (pParsedData == NULL) { return CS_BAD_PARAM; }
Result = Q931_Decode(pWorld, (void **) &pDecodedBuf, PDU, pEncodedBuf, dwEncodedLength);
if (ASN1_FAILED(Result) || (pDecodedBuf == NULL)) { ASSERT(FALSE); // trace and return an decoding error of some sort.
// Note: some values of Result should cause CS_SUBSYSTEM_FAILURE return.
return CS_BAD_PARAM; }
// validate some basic things about the PDU...
pUserInfo = (H323_UserInformation *)pDecodedBuf;
// validate that this is a H323 PDU.
if (PDU != H323_UserInformation_PDU) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU user-data uses ASN encoding.
if (((pUserInfo->bit_mask & user_data_present) != 0) && (pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU is H323 Setup information.
if (pUserInfo->h323_uu_pdu.h323_message_body.choice != setup_chosen) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
id = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.protocolIdentifier; if (!Q931ValidPduVersion(id)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_INCOMPATIBLE_VERSION; }
// make sure that the conference id is formed correctly.
if (pUserInfo->h323_uu_pdu.h323_message_body.u.setup.conferenceID.length > sizeof(pUserInfo->h323_uu_pdu.h323_message_body.u.setup.conferenceID.value)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
#if 0
if (pUserInfo->h323_uu_pdu.h323_message_body.u.setup.conferenceGoal.choice != create_chosen) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_OPTION_NOT_IMPLEMENTED; } if (pUserInfo->h323_uu_pdu.h323_message_body.u.setup.callType.choice != pointToPoint_chosen) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_OPTION_NOT_IMPLEMENTED; } #endif
// parse the message contained in pUserInfo.
memset(pParsedData, 0, sizeof(Q931_SETUP_ASN)); pParsedData->SourceAddr.bMulticast = FALSE; pParsedData->CallerAddr.bMulticast = FALSE; pParsedData->CalleeDestAddr.bMulticast = FALSE; pParsedData->CalleeAddr.bMulticast = FALSE;
// no validation of sourceInfo needed.
pParsedData->EndpointType.pVendorInfo = NULL; if (pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.bit_mask & (vendor_present)) { pParsedData->EndpointType.pVendorInfo = &(pParsedData->VendorInfo); pParsedData->VendorInfo.bCountryCode = (BYTE)pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.vendor.t35CountryCode; pParsedData->VendorInfo.bExtension = (BYTE)pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.vendor.t35Extension; pParsedData->VendorInfo.wManufacturerCode = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.vendor.manufacturerCode; if (pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.bit_mask & (productId_present)) { pParsedData->VendorInfo.pProductNumber = Malloc(sizeof(CC_OCTETSTRING)); if (pParsedData->VendorInfo.pProductNumber == NULL) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } pParsedData->VendorInfo.pProductNumber->wOctetStringLength = (WORD) min(pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.productId.length, CC_MAX_PRODUCT_LENGTH - 1); memcpy(pParsedData->bufProductValue, pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.productId.value, pParsedData->VendorInfo.pProductNumber->wOctetStringLength); pParsedData->bufProductValue[pParsedData->VendorInfo.pProductNumber->wOctetStringLength] = '\0'; pParsedData->VendorInfo.pProductNumber->pOctetString = pParsedData->bufProductValue; } if (pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.bit_mask & (versionId_present)) { pParsedData->VendorInfo.pVersionNumber = Malloc(sizeof(CC_OCTETSTRING)); if (pParsedData->VendorInfo.pVersionNumber == NULL) { Free(pParsedData->VendorInfo.pProductNumber); freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } pParsedData->VendorInfo.pVersionNumber->wOctetStringLength = (WORD) min(pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.versionId.length, CC_MAX_VERSION_LENGTH - 1); memcpy(pParsedData->bufVersionValue, pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.vendor.versionId.value, pParsedData->VendorInfo.pVersionNumber->wOctetStringLength); pParsedData->bufVersionValue[pParsedData->VendorInfo.pVersionNumber->wOctetStringLength] = '\0'; pParsedData->VendorInfo.pVersionNumber->pOctetString = pParsedData->bufVersionValue; } }
pParsedData->EndpointType.bIsTerminal = FALSE; if (pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.bit_mask & (terminal_present)) { pParsedData->EndpointType.bIsTerminal = TRUE; } pParsedData->EndpointType.bIsGateway = FALSE; if (pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceInfo.bit_mask & (gateway_present)) { pParsedData->EndpointType.bIsGateway = TRUE; }
if ((pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nnStndrdDt_present) != 0) { pParsedData->NonStandardDataPresent = TRUE; if (pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice == h221NonStandard_chosen) { pParsedData->NonStandardData.bCountryCode = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode); pParsedData->NonStandardData.bExtension = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension); pParsedData->NonStandardData.wManufacturerCode = pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode; } pParsedData->NonStandardData.sData.wOctetStringLength = (WORD) pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length; pParsedData->NonStandardData.sData.pOctetString = (BYTE *)Malloc(pParsedData->NonStandardData.sData.wOctetStringLength); if (pParsedData->NonStandardData.sData.pOctetString == NULL) { Free(pParsedData->VendorInfo.pProductNumber); Free(pParsedData->VendorInfo.pVersionNumber); freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } memcpy(pParsedData->NonStandardData.sData.pOctetString, pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value, pParsedData->NonStandardData.sData.wOctetStringLength); } else { pParsedData->NonStandardDataPresent = FALSE; }
//RMO. ignore the h245 address.
{ CS_STATUS AliasResult = CS_OK;
// parse the sourceAddress aliases here...
AliasResult = SeqofToAlias(&(pParsedData->pCallerAliasList), (struct _seqof3 *)pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceAddress); if (AliasResult != CS_OK) { if (pParsedData->NonStandardData.sData.pOctetString != NULL) Free(pParsedData->NonStandardData.sData.pOctetString); Free(pParsedData->VendorInfo.pProductNumber); Free(pParsedData->VendorInfo.pVersionNumber); freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; }
// parse the destinationAddress aliases here...
AliasResult = SeqofToAlias(&(pParsedData->pCalleeAliasList), (struct _seqof3 *)pUserInfo->h323_uu_pdu.h323_message_body.u.setup.destinationAddress); if (AliasResult != CS_OK) { Q931FreeAliasNames(pParsedData->pCallerAliasList); if (pParsedData->NonStandardData.sData.pOctetString != NULL) Free(pParsedData->NonStandardData.sData.pOctetString); pParsedData->pCallerAliasList = NULL; Free(pParsedData->VendorInfo.pProductNumber); Free(pParsedData->VendorInfo.pVersionNumber); freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; }
// parse the destExtraCallInfo aliases here...
AliasResult = SeqofToAlias(&(pParsedData->pExtraAliasList), (struct _seqof3 *)pUserInfo->h323_uu_pdu.h323_message_body.u.setup.destExtraCallInfo); if (AliasResult != CS_OK) { Q931FreeAliasNames(pParsedData->pCalleeAliasList); Q931FreeAliasNames(pParsedData->pCallerAliasList); if (pParsedData->NonStandardData.sData.pOctetString != NULL) Free(pParsedData->NonStandardData.sData.pOctetString); pParsedData->pCallerAliasList = NULL; Free(pParsedData->VendorInfo.pProductNumber); Free(pParsedData->VendorInfo.pVersionNumber); freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; }
// parse the remoteExtensionAddress aliases here...
if ((pUserInfo->h323_uu_pdu.h323_message_body.u.setup.bit_mask & remoteExtensionAddress_present) != 0) { AliasResult = Q931AliasAddrToAliasItem(&(pParsedData->pExtensionAliasItem), &(pUserInfo->h323_uu_pdu.h323_message_body.u.setup.remoteExtensionAddress)); if (AliasResult != CS_OK) { Q931FreeAliasNames(pParsedData->pExtraAliasList); Q931FreeAliasNames(pParsedData->pCalleeAliasList); Q931FreeAliasNames(pParsedData->pCallerAliasList); pParsedData->pCallerAliasList = NULL; if (pParsedData->NonStandardData.sData.pOctetString != NULL) Free(pParsedData->NonStandardData.sData.pOctetString); Free(pParsedData->VendorInfo.pProductNumber); Free(pParsedData->VendorInfo.pVersionNumber); freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } } }
if ((pUserInfo->h323_uu_pdu.h323_message_body.u.setup.bit_mask & destCallSignalAddress_present) != 0) { BYTE *a = (BYTE *)(&(pParsedData->CalleeDestAddr.Addr.IP_Binary.dwAddr)); pParsedData->CalleeDestAddr.nAddrType = CC_IP_BINARY; pParsedData->CalleeDestAddr.Addr.IP_Binary.wPort = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.u.ipAddress.port; a[3] = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.u.ipAddress.ip.value[0]; a[2] = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.u.ipAddress.ip.value[1]; a[1] = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.u.ipAddress.ip.value[2]; a[0] = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.destCallSignalAddress.u.ipAddress.ip.value[3]; pParsedData->CalleeDestAddrPresent = TRUE; }
if ((pUserInfo->h323_uu_pdu.h323_message_body.u.setup.bit_mask & sourceCallSignalAddress_present) != 0) { BYTE *a = (BYTE *)(&(pParsedData->SourceAddr.Addr.IP_Binary.dwAddr)); pParsedData->SourceAddr.nAddrType = CC_IP_BINARY; pParsedData->SourceAddr.Addr.IP_Binary.wPort = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.u.ipAddress.port; a[3] = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.u.ipAddress.ip.value[0]; a[2] = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.u.ipAddress.ip.value[1]; a[1] = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.u.ipAddress.ip.value[2]; a[0] = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.sourceCallSignalAddress.u.ipAddress.ip.value[3]; pParsedData->SourceAddrPresent = TRUE; }
pParsedData->bCallerIsMC = pUserInfo->h323_uu_pdu.h323_message_body.u.setup.activeMC;
memcpy(pParsedData->ConferenceID.buffer, pUserInfo->h323_uu_pdu.h323_message_body.u.setup.conferenceID.value, pUserInfo->h323_uu_pdu.h323_message_body.u.setup.conferenceID.length);
switch (pUserInfo->h323_uu_pdu.h323_message_body.u.setup.conferenceGoal.choice) { case invite_chosen: pParsedData->wGoal = CSG_INVITE; break; case join_chosen: pParsedData->wGoal = CSG_JOIN; break; default: pParsedData->wGoal = CSG_CREATE; } // switch
switch (pUserInfo->h323_uu_pdu.h323_message_body.u.setup.callType.choice) { case oneToN_chosen: pParsedData->wCallType = CC_CALLTYPE_1_N; break; case nToOne_chosen: pParsedData->wCallType = CC_CALLTYPE_N_1; break; case nToN_chosen: pParsedData->wCallType = CC_CALLTYPE_N_N; break; default: pParsedData->wCallType = CC_CALLTYPE_PT_PT; } // switch
// Free the PDU data.
Result = freePDU(pWorld, PDU, pDecodedBuf, q931asn); ASSERT(ASN1_SUCCEEDED(Result)); return CS_OK; }
//------------------------------------------------------------------------
//------------------------------------------------------------------------
HRESULT Q931ReleaseCompleteParseASN( ASN1_CODER_INFO *pWorld, BYTE *pEncodedBuf, DWORD dwEncodedLength, Q931_RELEASE_COMPLETE_ASN *pParsedData) { int PDU = H323_UserInformation_PDU; char *pDecodedBuf = NULL; H323_UserInformation *pUserInfo; struct ObjectID_ *id; int Result;
if (pParsedData == NULL) { return CS_BAD_PARAM; }
Result = Q931_Decode(pWorld, (void **) &pDecodedBuf, PDU, pEncodedBuf, dwEncodedLength);
if (ASN1_FAILED(Result) || (pDecodedBuf == NULL)) { ASSERT(FALSE); // trace and return an decoding error of some sort.
// Note: some values of Result should cause CS_SUBSYSTEM_FAILURE return.
return CS_BAD_PARAM; }
// validate some basic things about the PDU...
pUserInfo = (H323_UserInformation *)pDecodedBuf;
// validate that this is a H323 PDU.
if (PDU != H323_UserInformation_PDU) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU user-data uses ASN encoding.
if (((pUserInfo->bit_mask & user_data_present) != 0) && (pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU is H323 Release Complete information.
if (pUserInfo->h323_uu_pdu.h323_message_body.choice != releaseComplete_chosen) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
id = pUserInfo->h323_uu_pdu.h323_message_body.u.releaseComplete.protocolIdentifier; if (!Q931ValidPduVersion(id)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_INCOMPATIBLE_VERSION; }
// parse the message contained in pUserInfo.
memset(pParsedData, 0, sizeof(Q931_RELEASE_COMPLETE_ASN));
if ((pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nnStndrdDt_present) != 0) { pParsedData->NonStandardDataPresent = TRUE; if (pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice == h221NonStandard_chosen) { pParsedData->NonStandardData.bCountryCode = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode); pParsedData->NonStandardData.bExtension = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension); pParsedData->NonStandardData.wManufacturerCode = pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode; } pParsedData->NonStandardData.sData.wOctetStringLength = (WORD) pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length; pParsedData->NonStandardData.sData.pOctetString = (BYTE *)Malloc(pParsedData->NonStandardData.sData.wOctetStringLength); if (pParsedData->NonStandardData.sData.pOctetString == NULL) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } memcpy(pParsedData->NonStandardData.sData.pOctetString, pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value, pParsedData->NonStandardData.sData.wOctetStringLength); } else { pParsedData->NonStandardDataPresent = FALSE; }
if (pUserInfo->h323_uu_pdu.h323_message_body.u.releaseComplete.bit_mask & reason_present) { switch (pUserInfo->h323_uu_pdu.h323_message_body.u.releaseComplete.reason.choice) { case noBandwidth_chosen: pParsedData->bReason = CC_REJECT_NO_BANDWIDTH; break; case gatekeeperResources_chosen: pParsedData->bReason = CC_REJECT_GATEKEEPER_RESOURCES; break; case unreachableDestination_chosen: pParsedData->bReason = CC_REJECT_UNREACHABLE_DESTINATION; break; case destinationRejection_chosen: pParsedData->bReason = CC_REJECT_DESTINATION_REJECTION; break; case invalidRevision_chosen: pParsedData->bReason = CC_REJECT_INVALID_REVISION; break; case noPermission_chosen: pParsedData->bReason = CC_REJECT_NO_PERMISSION; break; case unreachableGatekeeper_chosen: pParsedData->bReason = CC_REJECT_UNREACHABLE_GATEKEEPER; break; case gatewayResources_chosen: pParsedData->bReason = CC_REJECT_GATEWAY_RESOURCES; break; case badFormatAddress_chosen: pParsedData->bReason = CC_REJECT_BAD_FORMAT_ADDRESS; break; case adaptiveBusy_chosen: pParsedData->bReason = CC_REJECT_ADAPTIVE_BUSY; break; case inConf_chosen: pParsedData->bReason = CC_REJECT_IN_CONF; break; case facilityCallDeflection_chosen: pParsedData->bReason = CC_REJECT_CALL_DEFLECTION; break; default: pParsedData->bReason = CC_REJECT_UNDEFINED_REASON; } // switch
} else { pParsedData->bReason = CC_REJECT_UNDEFINED_REASON; }
// Free the PDU data.
Result = freePDU(pWorld, PDU, pDecodedBuf, q931asn); ASSERT(ASN1_SUCCEEDED(Result)); return CS_OK; }
//------------------------------------------------------------------------
//------------------------------------------------------------------------
HRESULT Q931ConnectParseASN( ASN1_CODER_INFO *pWorld, BYTE *pEncodedBuf, DWORD dwEncodedLength, Q931_CONNECT_ASN *pParsedData) { int PDU = H323_UserInformation_PDU; char *pDecodedBuf = NULL; H323_UserInformation *pUserInfo; struct ObjectID_ *id; int Result;
if (pParsedData == NULL) { return CS_BAD_PARAM; }
Result = Q931_Decode(pWorld, (void **) &pDecodedBuf, PDU, pEncodedBuf, dwEncodedLength);
if (ASN1_FAILED(Result) || (pDecodedBuf == NULL)) { ASSERT(FALSE); // trace and return an decoding error of some sort.
// Note: some values of Result should cause CS_SUBSYSTEM_FAILURE return.
return CS_BAD_PARAM; }
// validate some basic things about the PDU...
pUserInfo = (H323_UserInformation *)pDecodedBuf;
// validate that this is a H323 PDU.
if (PDU != H323_UserInformation_PDU) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU user-data uses ASN encoding.
if (((pUserInfo->bit_mask & user_data_present) != 0) && (pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU is H323 Connect information.
if (pUserInfo->h323_uu_pdu.h323_message_body.choice != connect_chosen) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
id = pUserInfo->h323_uu_pdu.h323_message_body.u.connect.protocolIdentifier; if (!Q931ValidPduVersion(id)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_INCOMPATIBLE_VERSION; }
// make sure that the conference id is formed correctly.
if (pUserInfo->h323_uu_pdu.h323_message_body.u.connect.conferenceID.length > sizeof(pUserInfo->h323_uu_pdu.h323_message_body.u.connect.conferenceID.value)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// parse the message contained in pUserInfo.
memset(pParsedData, 0, sizeof(Q931_CONNECT_ASN)); pParsedData->h245Addr.bMulticast = FALSE;
if ((pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nnStndrdDt_present) != 0) { pParsedData->NonStandardDataPresent = TRUE; if (pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice == h221NonStandard_chosen) { pParsedData->NonStandardData.bCountryCode = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode); pParsedData->NonStandardData.bExtension = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension); pParsedData->NonStandardData.wManufacturerCode = pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode; } pParsedData->NonStandardData.sData.wOctetStringLength = (WORD) pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length; pParsedData->NonStandardData.sData.pOctetString = (BYTE *)Malloc(pParsedData->NonStandardData.sData.wOctetStringLength); if (pParsedData->NonStandardData.sData.pOctetString == NULL) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } memcpy(pParsedData->NonStandardData.sData.pOctetString, pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value, pParsedData->NonStandardData.sData.wOctetStringLength); } else { pParsedData->NonStandardDataPresent = FALSE; }
if ((pUserInfo->h323_uu_pdu.h323_message_body.u.connect.bit_mask & Cnnct_UUIE_h245Address_present) != 0) { BYTE *a = (BYTE *)(&(pParsedData->h245Addr.Addr.IP_Binary.dwAddr)); pParsedData->h245Addr.nAddrType = CC_IP_BINARY; pParsedData->h245Addr.Addr.IP_Binary.wPort = pUserInfo->h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.u.ipAddress.port; a[3] = pUserInfo->h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.u.ipAddress.ip.value[0]; a[2] = pUserInfo->h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.u.ipAddress.ip.value[1]; a[1] = pUserInfo->h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.u.ipAddress.ip.value[2]; a[0] = pUserInfo->h323_uu_pdu.h323_message_body.u.connect.Cnnct_UUIE_h245Address.u.ipAddress.ip.value[3]; pParsedData->h245AddrPresent = TRUE; } else { pParsedData->h245AddrPresent = FALSE; }
// no validation of destinationInfo needed.
pParsedData->EndpointType.pVendorInfo = NULL; if (pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.bit_mask & (vendor_present)) { pParsedData->EndpointType.pVendorInfo = &(pParsedData->VendorInfo); pParsedData->VendorInfo.bCountryCode = (BYTE)pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.vendor.t35CountryCode; pParsedData->VendorInfo.bExtension = (BYTE)pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.vendor.t35Extension; pParsedData->VendorInfo.wManufacturerCode = pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.vendor.manufacturerCode;
if (pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.bit_mask & (productId_present)) { pParsedData->VendorInfo.pProductNumber = Malloc(sizeof(CC_OCTETSTRING)); if (pParsedData->VendorInfo.pProductNumber == NULL) { if (pParsedData->NonStandardData.sData.pOctetString != NULL) Free(pParsedData->NonStandardData.sData.pOctetString); freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } pParsedData->VendorInfo.pProductNumber->wOctetStringLength = (WORD) min(pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.productId.length, CC_MAX_PRODUCT_LENGTH - 1); memcpy(pParsedData->bufProductValue, pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.productId.value, pParsedData->VendorInfo.pProductNumber->wOctetStringLength); pParsedData->bufProductValue[pParsedData->VendorInfo.pProductNumber->wOctetStringLength] = '\0'; pParsedData->VendorInfo.pProductNumber->pOctetString = pParsedData->bufProductValue; } if (pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.bit_mask & (versionId_present)) { pParsedData->VendorInfo.pVersionNumber = Malloc(sizeof(CC_OCTETSTRING)); if (pParsedData->VendorInfo.pVersionNumber == NULL) { if (pParsedData->NonStandardData.sData.pOctetString != NULL) Free(pParsedData->NonStandardData.sData.pOctetString); Free(pParsedData->VendorInfo.pProductNumber); freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } pParsedData->VendorInfo.pVersionNumber->wOctetStringLength = (WORD) min(pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.versionId.length, CC_MAX_VERSION_LENGTH - 1); memcpy(pParsedData->bufVersionValue, pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.vendor.versionId.value, pParsedData->VendorInfo.pVersionNumber->wOctetStringLength); pParsedData->bufVersionValue[pParsedData->VendorInfo.pVersionNumber->wOctetStringLength] = '\0'; pParsedData->VendorInfo.pVersionNumber->pOctetString = pParsedData->bufVersionValue; }
}
pParsedData->EndpointType.bIsTerminal = FALSE; if (pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.bit_mask & (terminal_present)) { pParsedData->EndpointType.bIsTerminal = TRUE; } pParsedData->EndpointType.bIsGateway = FALSE; if (pUserInfo->h323_uu_pdu.h323_message_body.u.connect.destinationInfo.bit_mask & (gateway_present)) { pParsedData->EndpointType.bIsGateway = TRUE; }
memcpy(pParsedData->ConferenceID.buffer, pUserInfo->h323_uu_pdu.h323_message_body.u.connect.conferenceID.value, pUserInfo->h323_uu_pdu.h323_message_body.u.connect.conferenceID.length);
// Free the PDU data.
Result = freePDU(pWorld, PDU, pDecodedBuf, q931asn); ASSERT(ASN1_SUCCEEDED(Result)); return CS_OK; }
//------------------------------------------------------------------------
//------------------------------------------------------------------------
HRESULT Q931AlertingParseASN( ASN1_CODER_INFO *pWorld, BYTE *pEncodedBuf, DWORD dwEncodedLength, Q931_ALERTING_ASN *pParsedData) { int PDU = H323_UserInformation_PDU; char *pDecodedBuf = NULL; H323_UserInformation *pUserInfo; struct ObjectID_ *id; int Result;
if (pParsedData == NULL) { return CS_BAD_PARAM; }
Result = Q931_Decode(pWorld, (void **) &pDecodedBuf, PDU, pEncodedBuf, dwEncodedLength);
if (ASN1_FAILED(Result) || (pDecodedBuf == NULL)) { ASSERT(FALSE); // trace and return an decoding error of some sort.
// Note: some values of Result should cause CS_SUBSYSTEM_FAILURE return.
return CS_BAD_PARAM; }
// validate some basic things about the PDU...
pUserInfo = (H323_UserInformation *)pDecodedBuf;
// validate that this is a H323 PDU.
if (PDU != H323_UserInformation_PDU) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU user-data uses ASN encoding.
if (((pUserInfo->bit_mask & user_data_present) != 0) && (pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU is H323 Alerting information.
if (pUserInfo->h323_uu_pdu.h323_message_body.choice != alerting_chosen) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
id = pUserInfo->h323_uu_pdu.h323_message_body.u.alerting.protocolIdentifier; if (!Q931ValidPduVersion(id)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_INCOMPATIBLE_VERSION; }
// parse the message contained in pUserInfo.
memset(pParsedData, 0, sizeof(Q931_ALERTING_ASN)); pParsedData->h245Addr.bMulticast = FALSE;
if ((pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nnStndrdDt_present) != 0) { pParsedData->NonStandardDataPresent = TRUE; if (pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice == h221NonStandard_chosen) { pParsedData->NonStandardData.bCountryCode = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode); pParsedData->NonStandardData.bExtension = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension); pParsedData->NonStandardData.wManufacturerCode = pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode; } pParsedData->NonStandardData.sData.wOctetStringLength = (WORD) pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length; pParsedData->NonStandardData.sData.pOctetString = (BYTE *)Malloc(pParsedData->NonStandardData.sData.wOctetStringLength); if (pParsedData->NonStandardData.sData.pOctetString == NULL) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } memcpy(pParsedData->NonStandardData.sData.pOctetString, pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value, pParsedData->NonStandardData.sData.wOctetStringLength); } else { pParsedData->NonStandardDataPresent = FALSE; }
if ((pUserInfo->h323_uu_pdu.h323_message_body.u.alerting.bit_mask & CPg_UUIE_h245Addrss_present) != 0) { BYTE *a = (BYTE *)(&(pParsedData->h245Addr.Addr.IP_Binary.dwAddr)); pParsedData->h245Addr.nAddrType = CC_IP_BINARY; pParsedData->h245Addr.Addr.IP_Binary.wPort = pUserInfo->h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.u.ipAddress.port; a[3] = pUserInfo->h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[0]; a[2] = pUserInfo->h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[1]; a[1] = pUserInfo->h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[2]; a[0] = pUserInfo->h323_uu_pdu.h323_message_body.u.alerting.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[3]; }
//RMO. ignore the destinationInfo field.
// Free the PDU data.
Result = freePDU(pWorld, PDU, pDecodedBuf, q931asn); ASSERT(ASN1_SUCCEEDED(Result)); return CS_OK; }
//------------------------------------------------------------------------
//------------------------------------------------------------------------
HRESULT Q931ProceedingParseASN( ASN1_CODER_INFO *pWorld, BYTE *pEncodedBuf, DWORD dwEncodedLength, Q931_CALL_PROCEEDING_ASN *pParsedData) { int PDU = H323_UserInformation_PDU; char *pDecodedBuf = NULL; H323_UserInformation *pUserInfo; struct ObjectID_ *id; int Result;
if (pParsedData == NULL) { return CS_BAD_PARAM; }
Result = Q931_Decode(pWorld, (void **) &pDecodedBuf, PDU, pEncodedBuf, dwEncodedLength);
if (ASN1_FAILED(Result) || (pDecodedBuf == NULL)) { ASSERT(FALSE); // trace and return an decoding error of some sort.
// Note: some values of Result should cause CS_SUBSYSTEM_FAILURE return.
return CS_BAD_PARAM; }
// validate some basic things about the PDU...
pUserInfo = (H323_UserInformation *)pDecodedBuf;
// validate that this is a H323 PDU.
if (PDU != H323_UserInformation_PDU) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU user-data uses ASN encoding.
if (((pUserInfo->bit_mask & user_data_present) != 0) && (pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU is H323 Call Proceeding information.
if (pUserInfo->h323_uu_pdu.h323_message_body.choice != callProceeding_chosen) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
id = pUserInfo->h323_uu_pdu.h323_message_body.u.callProceeding.protocolIdentifier; if (!Q931ValidPduVersion(id)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_INCOMPATIBLE_VERSION; }
// parse the message contained in pUserInfo.
memset(pParsedData, 0, sizeof(Q931_CALL_PROCEEDING_ASN)); pParsedData->h245Addr.bMulticast = FALSE;
if ((pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nnStndrdDt_present) != 0) { pParsedData->NonStandardDataPresent = TRUE; if (pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice == h221NonStandard_chosen) { pParsedData->NonStandardData.bCountryCode = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode); pParsedData->NonStandardData.bExtension = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension); pParsedData->NonStandardData.wManufacturerCode = pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode; } pParsedData->NonStandardData.sData.wOctetStringLength = (WORD) pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length; pParsedData->NonStandardData.sData.pOctetString = (BYTE *)Malloc(pParsedData->NonStandardData.sData.wOctetStringLength); if (pParsedData->NonStandardData.sData.pOctetString == NULL) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } memcpy(pParsedData->NonStandardData.sData.pOctetString, pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value, pParsedData->NonStandardData.sData.wOctetStringLength); } else { pParsedData->NonStandardDataPresent = FALSE; }
if ((pUserInfo->h323_uu_pdu.h323_message_body.u.callProceeding.bit_mask & CPg_UUIE_h245Addrss_present) != 0) { BYTE *a = (BYTE *)(&(pParsedData->h245Addr.Addr.IP_Binary.dwAddr)); pParsedData->h245Addr.nAddrType = CC_IP_BINARY; pParsedData->h245Addr.Addr.IP_Binary.wPort = pUserInfo->h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.u.ipAddress.port; a[3] = pUserInfo->h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[0]; a[2] = pUserInfo->h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[1]; a[1] = pUserInfo->h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[2]; a[0] = pUserInfo->h323_uu_pdu.h323_message_body.u.callProceeding.CPg_UUIE_h245Addrss.u.ipAddress.ip.value[3]; }
//RMO. ignore the destinationInfo field.
// Free the PDU data.
Result = freePDU(pWorld, PDU, pDecodedBuf, q931asn); ASSERT(ASN1_SUCCEEDED(Result)); return CS_OK; }
//------------------------------------------------------------------------
//------------------------------------------------------------------------
HRESULT Q931FacilityParseASN( ASN1_CODER_INFO *pWorld, BYTE *pEncodedBuf, DWORD dwEncodedLength, Q931_FACILITY_ASN *pParsedData) { int PDU = H323_UserInformation_PDU; char *pDecodedBuf = NULL; H323_UserInformation *pUserInfo; int Result;
if (pParsedData == NULL) { return CS_BAD_PARAM; }
Result = Q931_Decode(pWorld, (void **) &pDecodedBuf, PDU, pEncodedBuf, dwEncodedLength);
if (ASN1_FAILED(Result) || (pDecodedBuf == NULL)) { ASSERT(FALSE); // trace and return an decoding error of some sort.
// Note: some values of Result should cause CS_SUBSYSTEM_FAILURE return.
return CS_BAD_PARAM; }
// validate some basic things about the PDU...
pUserInfo = (H323_UserInformation *)pDecodedBuf;
// validate that this is a H323 PDU.
if (PDU != H323_UserInformation_PDU) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU user-data uses ASN encoding.
if (((pUserInfo->bit_mask & user_data_present) != 0) && (pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
// validate that the PDU is H323 Facility information.
if (pUserInfo->h323_uu_pdu.h323_message_body.choice != facility_chosen) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; }
{ struct ObjectID_ *id;
id = pUserInfo->h323_uu_pdu.h323_message_body.u.facility.protocolIdentifier; if (!Q931ValidPduVersion(id)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_INCOMPATIBLE_VERSION; } }
// if there is a conference id, make sure that it is formed correctly.
if ((pUserInfo->h323_uu_pdu.h323_message_body.u.facility.bit_mask & conferenceID_present) != 0) { if (pUserInfo->h323_uu_pdu.h323_message_body.u.facility.conferenceID.length > sizeof(pUserInfo->h323_uu_pdu.h323_message_body.u.facility.conferenceID.value)) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_BAD_PARAM; } }
// parse the message contained in pUserInfo.
memset(pParsedData, 0, sizeof(Q931_FACILITY_ASN)); pParsedData->AlternativeAddr.bMulticast = FALSE;
if ((pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nnStndrdDt_present) != 0) { pParsedData->NonStandardDataPresent = TRUE; if (pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.choice == h221NonStandard_chosen) { pParsedData->NonStandardData.bCountryCode = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35CountryCode); pParsedData->NonStandardData.bExtension = (BYTE)(pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.t35Extension); pParsedData->NonStandardData.wManufacturerCode = pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.nonStandardIdentifier.u.h221NonStandard.manufacturerCode; } pParsedData->NonStandardData.sData.wOctetStringLength = (WORD) pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.length; pParsedData->NonStandardData.sData.pOctetString = (BYTE *)Malloc(pParsedData->NonStandardData.sData.wOctetStringLength); if (pParsedData->NonStandardData.sData.pOctetString == NULL) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } memcpy(pParsedData->NonStandardData.sData.pOctetString, pUserInfo->h323_uu_pdu.H323_UU_PDU_nnStndrdDt.data.value, pParsedData->NonStandardData.sData.wOctetStringLength); } else { pParsedData->NonStandardDataPresent = FALSE; }
if ((pUserInfo->h323_uu_pdu.h323_message_body.u.facility.bit_mask & alternativeAddress_present) != 0) { BYTE *a = (BYTE *)(&(pParsedData->AlternativeAddr.Addr.IP_Binary.dwAddr)); pParsedData->AlternativeAddr.nAddrType = CC_IP_BINARY; pParsedData->AlternativeAddr.Addr.IP_Binary.wPort = pUserInfo->h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.u.ipAddress.port; a[3] = pUserInfo->h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.u.ipAddress.ip.value[0]; a[2] = pUserInfo->h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.u.ipAddress.ip.value[1]; a[1] = pUserInfo->h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.u.ipAddress.ip.value[2]; a[0] = pUserInfo->h323_uu_pdu.h323_message_body.u.facility.alternativeAddress.u.ipAddress.ip.value[3]; }
if ((pUserInfo->h323_uu_pdu.h323_message_body.u.facility.bit_mask & alternativeAliasAddress_present) != 0) { CS_STATUS AliasResult = CS_OK;
// parse the sourceAddress aliases here...
AliasResult = SeqofToAlias(&(pParsedData->pAlternativeAliasList), (struct _seqof3 *)pUserInfo->h323_uu_pdu.h323_message_body.u.facility.alternativeAliasAddress); if (AliasResult != CS_OK) { freePDU(pWorld, PDU, pDecodedBuf, q931asn); return CS_NO_MEMORY; } }
if ((pUserInfo->h323_uu_pdu.h323_message_body.u.facility.bit_mask & conferenceID_present) != 0) { memcpy(pParsedData->ConferenceID.buffer, pUserInfo->h323_uu_pdu.h323_message_body.u.facility.conferenceID.value, pUserInfo->h323_uu_pdu.h323_message_body.u.facility.conferenceID.length); pParsedData->ConferenceIDPresent = TRUE; }
switch (pUserInfo->h323_uu_pdu.h323_message_body.u.facility.reason.choice) { case routeCallToGatekeeper_chosen: pParsedData->bReason = CC_REJECT_ROUTE_TO_GATEKEEPER; break; case callForwarded_chosen: pParsedData->bReason = CC_REJECT_CALL_FORWARDED; break; case routeCallToMC_chosen: pParsedData->bReason = CC_REJECT_ROUTE_TO_MC; break; default: pParsedData->bReason = CC_REJECT_UNDEFINED_REASON; } // switch
// Free the PDU data.
Result = freePDU(pWorld, PDU, pDecodedBuf, q931asn); ASSERT(ASN1_SUCCEEDED(Result)); return CS_OK; }
// THE FOLLOWING IS ADDED FOR TELES ASN.1 INTEGRATION
int Q931_InitModule(void) { Q931ASN_Module_Startup(); return (Q931ASN_Module != NULL) ? ASN1_SUCCESS : ASN1_ERR_MEMORY; }
int Q931_TermModule(void) { Q931ASN_Module_Cleanup(); return ASN1_SUCCESS; }
int Q931_InitWorld(ASN1_CODER_INFO *pWorld) { int rc;
ZeroMemory(pWorld, sizeof(*pWorld));
if (Q931ASN_Module == NULL) { return ASN1_ERR_BADARGS; }
rc = ASN1_CreateEncoder( Q931ASN_Module, // ptr to mdule
&(pWorld->pEncInfo), // ptr to encoder info
NULL, // buffer ptr
0, // buffer size
NULL); // parent ptr
if (rc == ASN1_SUCCESS) { ASSERT(pWorld->pEncInfo != NULL); rc = ASN1_CreateDecoder( Q931ASN_Module, // ptr to mdule
&(pWorld->pDecInfo), // ptr to decoder info
NULL, // buffer ptr
0, // buffer size
NULL); // parent ptr
ASSERT(pWorld->pDecInfo != NULL); }
if (rc != ASN1_SUCCESS) { Q931_TermWorld(pWorld); }
return rc; }
int Q931_TermWorld(ASN1_CODER_INFO *pWorld) { if (Q931ASN_Module == NULL) { return ASN1_ERR_BADARGS; }
ASN1_CloseEncoder(pWorld->pEncInfo); ASN1_CloseDecoder(pWorld->pDecInfo);
ZeroMemory(pWorld, sizeof(*pWorld));
return ASN1_SUCCESS; }
int Q931_Encode(ASN1_CODER_INFO *pWorld, void *pStruct, int nPDU, BYTE **ppEncoded, DWORD *pcbEncodedSize) { ASN1encoding_t pEncInfo = pWorld->pEncInfo; int rc = ASN1_Encode( pEncInfo, // ptr to encoder info
pStruct, // pdu data structure
nPDU, // pdu id
ASN1ENCODE_ALLOCATEBUFFER, // flags
NULL, // do not provide buffer
0); // buffer size if provided
if (ASN1_SUCCEEDED(rc)) { ASSERT(rc == ASN1_SUCCESS); *pcbEncodedSize = pEncInfo->len; // len of encoded data in buffer
*ppEncoded = pEncInfo->buf; // buffer to encode into
} else { ASSERT(FALSE); *pcbEncodedSize = 0; *ppEncoded = NULL; } return rc; }
int Q931_Decode(ASN1_CODER_INFO *pWorld, void **ppStruct, int nPDU, BYTE *pEncoded, DWORD cbEncodedSize) { ASN1decoding_t pDecInfo = pWorld->pDecInfo; int rc = ASN1_Decode( pDecInfo, // ptr to encoder info
ppStruct, // pdu data structure
nPDU, // pdu id
ASN1DECODE_SETBUFFER, // flags
pEncoded, // do not provide buffer
cbEncodedSize); // buffer size if provided
if (ASN1_SUCCEEDED(rc)) { ASSERT(rc == ASN1_SUCCESS); } else { ASSERT(FALSE); *ppStruct = NULL; } return rc; }
|