windows-nt/Source/XPSP1/NT/enduser/netmeeting/t120/mst120/omcscode.cpp
2020-09-26 16:20:57 +08:00

934 lines
26 KiB
C++

#include "precomp.h"
DEBUG_FILEZONE(ZONE_T120_MCSNC);
/*
* omcscode.cpp
*
* Copyright (c) 1993 - 1996 by DataBeam Corporation, Lexington, KY
*
* Abstract:
* This is the implementation file for the CMCSCoder class. This class
* is responsible for encoding and decoding T.125 PDU's using ASN.1
* encoding rules via the ASN.1 toolkit. This class is also capable
* of determining the size of both the encoded and decoded PDU's and is
* capable of making copies of each of the PDU's.
*
* Private Instance Variables:
* Encoding_Rules_Type
* This variable holds the type of encoding rules which are currently
* being utilized.
*
* Private Member Functions:
*
* Copy***
* Private member functions exist which are capable of making complete
* copies of the decoded "Send Data" PDU data structures. These
* routines copy not only the data contained within the structure but
* also any data which is referenced by the pointers held within the
* structure.
*
* SetEncodingRules
* This routine is used to switch between using Basic Encoding Rules
* (BER) and Packed Encoding Rules (PER). This routine also updates
* the private instance variables used to hold values for the minimum
* and maximum amount of overhead associated with the "send data" PDUs.
*
* Caveats:
* None.
*
* Author:
* John B. O'Nan
*/
#include "omcscode.h"
/*
* Macros.
*/
#define BOOLEAN_TAG 0x01
#define INTEGER_TAG 0x02
#define BIT_STRING_TAG 0x03
#define OCTET_STRING_TAG 0x04
#define ENUMERATED_TAG 0x0a
#define SEQUENCE 0x30
#define SETOF 0x31
#define INDEFINITE_LENGTH 0x80
#define ONE_BYTE_LENGTH 0x81
#define TWO_BYTE_LENGTH 0x82
#define THREE_BYTE_LENGTH 0x83
#define FOUR_BYTE_LENGTH 0x84
#define END_OF_CONTENTS 0x00
#define CONSTRUCTED_TAG_ZERO 0xa0
#define CONSTRUCTED_TAG_ONE 0xa1
#define CONSTRUCTED_TAG_TWO 0xa2
#define CONSTRUCTED_TAG_THREE 0xa3
#define CONSTRUCTED_TAG_FOUR 0xa4
/*
* This is a global variable that has a pointer to the one MCS coder that
* is instantiated by the MCS Controller. Most objects know in advance
* whether they need to use the MCS or the GCC coder, so, they do not need
* this pointer in their constructors.
*/
CMCSCoder *g_MCSCoder;
/*
* The following array contains a template for the X.224 data header.
* The 5 of the 7 bytes that it initializes are actually sent to the
* wire. Bytes 3 and 4 will be set to contain the size of the PDU.
* The array is only used when we encode a data PDU.
*/
UChar g_X224Header[] = { 3, 0, 0, 0, 2, DATA_PACKET, EOT_BIT };
/*
* CMCSCoder ()
*
* Public
*
* Functional Description:
* This is the constructor for the CMCSCoder class. It initializes
* the ASN.1 encoder/decoder, saves the current encoding rules type,
* and sets values for the highest and lowest overhead in the "send data"
* PDU's.
*/
CMCSCoder::CMCSCoder ()
:m_pEncInfo(NULL),
m_pDecInfo(NULL)
{
Encoding_Rules_Type = BASIC_ENCODING_RULES;
// lonchanc: We should move Init out of constructor. However,
// to minimize the changes in the GCC/MCS code, we put it here for now.
// Otherwise, we need to change MCS and Packet interfaces.
// We will move it out and call Init() separately.
Init();
}
BOOL CMCSCoder::Init ( void )
{
BOOL fRet = FALSE;
MCSPDU_Module_Startup();
if (MCSPDU_Module != NULL)
{
if (ASN1_CreateEncoder(
MCSPDU_Module, // ptr to mdule
&m_pEncInfo, // ptr to encoder info
NULL, // buffer ptr
0, // buffer size
NULL) // parent ptr
== ASN1_SUCCESS)
{
ASSERT(m_pEncInfo != NULL);
m_pEncInfo->cbExtraHeader = PROTOCOL_OVERHEAD_X224;
fRet = (ASN1_CreateDecoder(
MCSPDU_Module, // ptr to mdule
&m_pDecInfo, // ptr to decoder info
NULL, // buffer ptr
0, // buffer size
NULL) // parent ptr
== ASN1_SUCCESS);
ASSERT(fRet && m_pDecInfo != NULL);
}
}
ASSERT(fRet);
return fRet;
}
/*
* ~CMCSCoder ()
*
* Public
*
* Functional Description:
* This is a virtual destructor. It is used to clean up after ASN.1.
*/
CMCSCoder::~CMCSCoder ()
{
if (MCSPDU_Module != NULL)
{
ASN1_CloseEncoder(m_pEncInfo);
ASN1_CloseDecoder(m_pDecInfo);
MCSPDU_Module_Cleanup();
}
}
/*
* void Encode ()
*
* Public
*
* Functional Description:
* This function encodes MCS protocol data units (PDU's) into ASN.1
* compliant byte streams using the ASN.1 toolkit.
* The encode happens in a coder-allocated buffer.
*/
BOOL CMCSCoder::Encode(LPVOID pdu_structure,
int pdu_type,
UINT rules_type,
LPBYTE *encoding_buffer,
UINT *encoding_buffer_length)
{
BOOL fRet = TRUE;
BOOL send_data_pdu = FALSE;
int return_value;
//UINT encoding_length;
UShort initiator;
LPBYTE buffer_pointer;
PSendDataRequestPDU send_data;
UINT PDUChoice;
BOOL bBufferAllocated;
PMemory memory;
/*
* Check to make sure the encoding rules type is properly set.
*/
ASSERT(rules_type == PACKED_ENCODING_RULES || pdu_type == CONNECT_MCS_PDU);
if (pdu_type == DOMAIN_MCS_PDU)
{
/*
* Set PDUChoice to the type of MCS PDU we need to encode.
* Also, determine if this is a data PDU.
*/
PDUChoice = (unsigned int) ((PDomainMCSPDU) pdu_structure)->choice;
if ((PDUChoice == SEND_DATA_REQUEST_CHOSEN) ||
(PDUChoice == SEND_DATA_INDICATION_CHOSEN) ||
(PDUChoice == UNIFORM_SEND_DATA_REQUEST_CHOSEN) ||
(PDUChoice == UNIFORM_SEND_DATA_INDICATION_CHOSEN)) {
send_data_pdu = TRUE;
send_data = &((PDomainMCSPDU) pdu_structure)->u.send_data_request;
bBufferAllocated = (*encoding_buffer == NULL);
if (bBufferAllocated) {
// We have to allocate the encoded buffer.
DBG_SAVE_FILE_LINE
memory = AllocateMemory (NULL,
send_data->user_data.length + MAXIMUM_PROTOCOL_OVERHEAD,
SEND_PRIORITY);
if (memory != NULL) {
buffer_pointer = *encoding_buffer = (LPBYTE) memory->GetPointer();
}
else {
WARNING_OUT (("CMCSCoder::Encode: Failed to allocate space for "
"encoded data PDU for send."));
fRet = FALSE;
ASSERT (*encoding_buffer == NULL);
goto MyExit;
}
}
else {
// All the space needed here has been pre-allocated
buffer_pointer = *encoding_buffer;
}
}
/*
* Check if this is a data PDU
*/
if (send_data_pdu)
{
#ifdef ENABLE_BER
/*
* If we are currently using Basic Encoding Rules.
*/
if (Encoding_Rules_Type == BASIC_ENCODING_RULES)
{
/*
* The long variant of length must be used if the octet string
* is longer than 127 bytes. The upper bit of the length byte
* is set and the lower bits indicate the number of length bytes
* which will follow.
*/
*(buffer_pointer--) = (UChar)send_data->user_data.length;
if (send_data->user_data.length > 127)
{
*(buffer_pointer--) = (UChar)(send_data->user_data.length >> 8);
*(buffer_pointer--) = TWO_BYTE_LENGTH;
encoding_length = 3;
}
else
{
encoding_length = 1;
}
/*
* Encode the "user data" octet string.
*/
*(buffer_pointer--) = OCTET_STRING_TAG;
/*
* Encode the "segmentation" bit string field. The identifier
* is followed by a length of 2 and a byte indicating that 6
* bits are unused in the actual bit string byte.
*/
*(buffer_pointer--) = (UChar) send_data->segmentation;
*(buffer_pointer--) = 0x06;
*(buffer_pointer--) = 0x02;
*(buffer_pointer--) = BIT_STRING_TAG;
/*
* Encode the enumerated "data priority" field.
*/
*(buffer_pointer--) = (UChar)send_data->data_priority;
*(buffer_pointer--) = 0x01;
*(buffer_pointer--) = ENUMERATED_TAG;
/*
* Encode the integer "channel ID" field.
*/
*(buffer_pointer--) = (UChar)send_data->channel_id;
if (send_data->channel_id < 128)
{
*(buffer_pointer--) = 0x01;
encoding_length += 10;
}
else if (send_data->channel_id < 32768L)
{
*(buffer_pointer--) = (UChar)(send_data->channel_id >> 8);
*(buffer_pointer--) = 0x02;
encoding_length += 11;
}
else
{
*(buffer_pointer--) = (UChar)(send_data->channel_id >> 8);
*(buffer_pointer--) = (UChar)(send_data->channel_id >> 16);
*(buffer_pointer--) = 0x03;
encoding_length += 12;
}
*(buffer_pointer--) = INTEGER_TAG;
/*
* Encode the integer "initiator" field.
*/
*(buffer_pointer--) = (UChar)send_data->initiator;
*(buffer_pointer--) = (UChar)(send_data->initiator >> 8);
if (send_data->initiator < 32768L)
{
*(buffer_pointer--) = 0x02;
encoding_length += 4;
}
else
{
*(buffer_pointer--) = (UChar)(send_data->initiator >> 16);
*(buffer_pointer--) = 0x03;
encoding_length += 5;
}
*(buffer_pointer--) = INTEGER_TAG;
*(buffer_pointer--) = INDEFINITE_LENGTH;
switch (PDUChoice)
{
case SEND_DATA_REQUEST_CHOSEN:
*buffer_pointer = SEND_DATA_REQUEST;
break;
case SEND_DATA_INDICATION_CHOSEN:
*buffer_pointer = SEND_DATA_INDICATION;
break;
case UNIFORM_SEND_DATA_REQUEST_CHOSEN:
*buffer_pointer = UNIFORM_SEND_DATA_REQUEST;
break;
case UNIFORM_SEND_DATA_INDICATION_CHOSEN:
*buffer_pointer = UNIFORM_SEND_DATA_INDICATION;
break;
}
// Set the returned pointer to the beginning of the encoded packet
PUChar temp = *encoding_buffer;
*encoding_buffer = buffer_pointer;
/*
* Encode the end-of-contents marker for the "Send Data" PDU.
* This goes after the data, at the end of the PDU.
*/
buffer_pointer = temp + (send_data->user_data.length +
(MAXIMUM_PROTOCOL_OVERHEAD_FRONT + 1));
*(buffer_pointer++) = END_OF_CONTENTS;
*buffer_pointer = END_OF_CONTENTS;
// Set the returned length of the encoded packet
*encoding_buffer_length =
encoding_length + send_data->user_data.length + 5;
}
/*
* If we are currently using Packed Encoding Rules.
*/
else
#endif // ENABLE_BER
{
// Move the ptr past the X.224 header.
buffer_pointer += sizeof(X224_DATA_PACKET);
switch (PDUChoice)
{
case SEND_DATA_REQUEST_CHOSEN:
*buffer_pointer = PER_SEND_DATA_REQUEST;
break;
case SEND_DATA_INDICATION_CHOSEN:
*buffer_pointer = PER_SEND_DATA_INDICATION;
break;
case UNIFORM_SEND_DATA_REQUEST_CHOSEN:
*buffer_pointer = PER_UNIFORM_SEND_DATA_REQUEST;
break;
case UNIFORM_SEND_DATA_INDICATION_CHOSEN:
*buffer_pointer = PER_UNIFORM_SEND_DATA_INDICATION;
break;
}
buffer_pointer++;
/*
* Encode the integer "initiator" field. The lower bound must
* first be subtracted from the value to encode.
*/
initiator = send_data->initiator - INITIATOR_LOWER_BOUND;
*(buffer_pointer++) = (UChar) (initiator >> 8);
*(buffer_pointer++) = (UChar) initiator;
/*
* Encode the integer "channel ID" field.
*/
*(buffer_pointer++) = (UChar)(send_data->channel_id >> 8);
*(buffer_pointer++) = (UChar)(send_data->channel_id);
/*
* Encode the "priority" and "segmentation" fields.
*/
*(buffer_pointer++) = (UChar)((send_data->data_priority << 6) |
(send_data->segmentation >> 2));
/*
* Encode the "user data" octet string. The octet strings are
* encoded differently depending upon their length.
*/
ASSERT (send_data->user_data.length < 16384);
if (send_data->user_data.length <= 127)
{
*encoding_buffer_length = MAXIMUM_PROTOCOL_OVERHEAD - 1;
}
else
{
*(buffer_pointer++) = (UChar)(send_data->user_data.length >> 8) |
INDEFINITE_LENGTH;
*encoding_buffer_length = MAXIMUM_PROTOCOL_OVERHEAD;
}
*buffer_pointer++ = (UChar)send_data->user_data.length;
initiator = (UShort) (*encoding_buffer_length + send_data->user_data.length);
// Set the returned length of the encoded PDU.
if (bBufferAllocated || (send_data->segmentation & SEGMENTATION_BEGIN)) {
/*
* If the Encode operation allocates the space needed, or the space
* was allocated by MCSGetBufferRequest (by a client) and this is
* the 1st segment of the data in the buffer, the whole encoded PDU
* is in contiguous space. The total PDU size is returned in this
* case.
* However, in the case where the space was allocated by MCSGetBufferRequest,
* the PDUs after the 1st one, will put the X.224 and MCS headers in
* a separate piece of memory (whose length is returned here), and the
* data is still in the pre-allocated space.
*/
*encoding_buffer_length = (UINT) initiator;
}
/*
* If the space was not preallocated, we need to copy the data
* into the space allocated by the encoder.
*/
if (bBufferAllocated) {
// We now need to copy the data into the encoded data PDU.
memcpy (buffer_pointer, send_data->user_data.value,
send_data->user_data.length);
// Update the data ptr in the data packet
send_data->user_data.value = (ASN1octet_t *) buffer_pointer;
}
}
}
}
if (send_data_pdu == FALSE)
{
SetEncodingRules (rules_type);
return_value = ASN1_Encode(m_pEncInfo, // ptr to encoder info
pdu_structure, // pdu data structure
pdu_type, // pdu id
ASN1ENCODE_ALLOCATEBUFFER, // flags
NULL, // do not provide buffer
0); // buffer size if provided
if (ASN1_FAILED(return_value))
{
ERROR_OUT(("CMCSCoder::Encode: ASN1_Encode failed, err=%d", return_value));
ASSERT(FALSE);
fRet = FALSE;
goto MyExit;
}
ASSERT(return_value == ASN1_SUCCESS);
/*
* The encoded buffers returned by ASN.1 have preallocated the space
* needed for the X.224 header.
*/
// len of encoded data in buffer
*encoding_buffer_length = m_pEncInfo->len;
initiator = (UShort) *encoding_buffer_length;
// buffer to encode into
*encoding_buffer = m_pEncInfo->buf;
}
// Now, add the X.224 header
buffer_pointer = *encoding_buffer;
memcpy (buffer_pointer, g_X224Header, PROTOCOL_OVERHEAD_X224);
AddRFCSize (buffer_pointer, initiator);
MyExit:
return fRet;
}
/*
* void Decode ()
*
* Public
*
* Functional Description:
* This function decodes ASN.1 compliant byte streams into the
* appropriate MCS PDU structures using the ASN.1 toolkit.
*
* NOTE: For data PDUs, do NOT access pdecoding_buffer_length. It's set
* to NULL.
*/
BOOL CMCSCoder::Decode(LPBYTE encoded_buffer,
UINT encoded_buffer_length,
int pdu_type,
UINT rules_type,
LPVOID *pdecoding_buffer,
UINT *pdecoding_buffer_length)
{
BOOL fRet = TRUE;
BOOL send_data_pdu = FALSE;
ASN1optionparam_s OptParam;
/*
* Check to make sure the encoding rules type is properly set.
*/
ASSERT(rules_type == PACKED_ENCODING_RULES || pdu_type == CONNECT_MCS_PDU);
if (pdu_type == DOMAIN_MCS_PDU)
{
UChar length;
unsigned int short_data;
PUChar buffer_pointer;
PSendDataRequestPDU send_data;
PDomainMCSPDU decoding_pdu;
ASN1choice_t choice;
buffer_pointer = encoded_buffer;
#ifdef ENABLE_BER
/*
* If we are currently using Basic Encoding Rules.
*/
if (Encoding_Rules_Type == BASIC_ENCODING_RULES)
{
switch (*(buffer_pointer++))
{
case SEND_DATA_REQUEST:
((PDomainMCSPDU) decoding_buffer)->choice =
SEND_DATA_REQUEST_CHOSEN;
send_data_pdu = TRUE;
break;
case SEND_DATA_INDICATION:
((PDomainMCSPDU) decoding_buffer)->choice =
SEND_DATA_INDICATION_CHOSEN;
send_data_pdu = TRUE;
break;
case UNIFORM_SEND_DATA_REQUEST:
((PDomainMCSPDU) decoding_buffer)->choice =
UNIFORM_SEND_DATA_REQUEST_CHOSEN;
send_data_pdu = TRUE;
break;
case UNIFORM_SEND_DATA_INDICATION:
((PDomainMCSPDU) decoding_buffer)->choice =
UNIFORM_SEND_DATA_INDICATION_CHOSEN;
send_data_pdu = TRUE;
break;
}
if (send_data_pdu )
{
/*
* Get the pointer to the "Send Data" PDU.
*/
send_data = &((PDomainMCSPDU) decoding_buffer)->
u.send_data_request;
/*
* Retrieve one byte for the length and check to see which
* length variant is being used. If the long variant is being
* used, move the buffer pointer past the length and set the
* flag indicating that the indefinite length is not being used.
*/
length = *buffer_pointer;
switch (length)
{
case ONE_BYTE_LENGTH:
buffer_pointer += 3;
break;
case TWO_BYTE_LENGTH:
buffer_pointer += 4;
break;
case THREE_BYTE_LENGTH:
buffer_pointer += 5;
break;
case FOUR_BYTE_LENGTH:
buffer_pointer += 6;
break;
default:
buffer_pointer += 2;
}
/*
* Decode the integer "initiator" field. Increment the data
* pointer past the integer identifier and retrieve the length
* of the integer.
*/
length = *(buffer_pointer++);
ASSERT ((length == 1) || (length == 2));
if (length == 1)
send_data->initiator = (UserID) *(buffer_pointer++);
else if (length == 2)
{
send_data->initiator = ((UserID) *(buffer_pointer++)) << 8;
send_data->initiator |= (UserID) *(buffer_pointer++);
}
else
{
TRACE_OUT(("CMCSCoder::Decode: initiator field is longer than 2 bytes (%d bytes) in MCS Data packet.", (UINT) length));
}
/*
* Decode the integer "channel ID" field. Increment the data
* pointer past the integer identifier and retrieve the length
* of the integer.
*/
buffer_pointer++;
length = *(buffer_pointer++);
ASSERT ((length == 1) || (length == 2));
if (length == 1)
send_data->channel_id = (ChannelID) *(buffer_pointer++);
else if (length == 2)
{
send_data->channel_id = ((ChannelID) *buffer_pointer++) << 8;
send_data->channel_id |= (ChannelID) *(buffer_pointer++);
}
else
{
TRACE_OUT(("CMCSCoder::Decode: channel_id field is longer than 2 bytes (%d bytes) in MCS Data packet.", (UINT) length));
}
/*
* Decode the enumerated "data priority" field. Increment the
* data pointer past the identifier and length.
*/
buffer_pointer+=2;
send_data->data_priority =(PDUPriority)*buffer_pointer;
/*
* Decode the bit string "segmentation" field. Increment the
* data pointer past the bit string identifier, length, and the
* "unused bits" byte and retrieve the "segmentation" flag.
*/
buffer_pointer += 4;
send_data->segmentation = *buffer_pointer;
/*
* Decode the "user data" octet string. Increment the data
* pointer past the identifier.
*/
buffer_pointer += 2;
/*
* Check to see which variant of the length is being used and
* then retrieve the length.
*/
length = *(buffer_pointer++);
if (length & INDEFINITE_LENGTH)
{
if (length == ONE_BYTE_LENGTH)
send_data->user_data.length = (unsigned int) *(buffer_pointer++);
/*
* A length identifier of 0x82 indicates that two bytes are
* being used to hold the actual length so retrieve the two
* bytes to form the length.
*/
else if (length == TWO_BYTE_LENGTH)
{
send_data->user_data.length =
((unsigned int) *(buffer_pointer++)) << 8;
send_data->user_data.length |=
(unsigned int) *(buffer_pointer++);
}
}
else
send_data->user_data.length = (unsigned int) length;
// buffer_pointer now points to the 1st data byte
send_data->user_data.value = buffer_pointer;
*pulDataOffset = buffer_pointer - encoded_buffer;
}
}
/*
* If we are currently using Packed Encoding Rules.
*/
else
#endif // ENABLE_BER
{
switch (*(buffer_pointer++))
{
case PER_SEND_DATA_REQUEST:
choice = SEND_DATA_REQUEST_CHOSEN;
send_data_pdu = TRUE;
break;
case PER_SEND_DATA_INDICATION:
choice = SEND_DATA_INDICATION_CHOSEN;
send_data_pdu = TRUE;
break;
case PER_UNIFORM_SEND_DATA_REQUEST:
choice = UNIFORM_SEND_DATA_REQUEST_CHOSEN;
send_data_pdu = TRUE;
break;
case PER_UNIFORM_SEND_DATA_INDICATION:
choice = UNIFORM_SEND_DATA_INDICATION_CHOSEN;
send_data_pdu = TRUE;
break;
}
if (send_data_pdu)
{
decoding_pdu = (PDomainMCSPDU) pdecoding_buffer;
// Store the choice field
decoding_pdu->choice = choice;
/*
* Get the pointer to the "Send Data" PDU.
*/
send_data = &decoding_pdu->u.send_data_request;
/*
* Decode the integer "initiator" field.
*/
short_data = ((unsigned int) *(buffer_pointer++)) << 8;
short_data |= (unsigned int) *(buffer_pointer++);
send_data->initiator = (UserID) short_data + INITIATOR_LOWER_BOUND;
/*
* Decode the integer "channel ID" field.
*/
send_data->channel_id = ((ChannelID) *(buffer_pointer++)) << 8;
send_data->channel_id |= (ChannelID) *(buffer_pointer++);
/*
* Decode the enumerated "data priority" field and the
* "segmentation" field.
*/
send_data->data_priority =
(PDUPriority)((*buffer_pointer >> 6) & 0x03);
send_data->segmentation = (*(buffer_pointer++) << 2) & 0xc0;
/*
* Decode the "user data" octet string. Check to see which
* variant of the length is being used and then retrieve the
* length.
*/
length = *(buffer_pointer++);
if (length & INDEFINITE_LENGTH)
{
ASSERT ((length & 0x40) == 0);
/*
* If bit 7 is set the length is greater than 127 but
* less than 16K.
*
* ChristTs: We no longer handle the case where the data length
* was higher than 16K. Our Max PDU size is 4K.
*/
short_data = (unsigned int) ((length & 0x3f) << 8);
send_data->user_data.length =
short_data | ((unsigned int) *(buffer_pointer++));
}
/*
* If bit 7 is not set then the length is less than 128 and is
* contained in the retrieved byte.
*/
else
{
send_data->user_data.length = (UShort) length;
}
// buffer_pointer now points to the 1st data byte
send_data->user_data.value = buffer_pointer;
}
}
}
if (send_data_pdu == FALSE)
{
int return_value;
//void *pDecodedData;
SetEncodingRules (rules_type);
return_value = ASN1_Decode(m_pDecInfo,// ptr to decoder info
pdecoding_buffer, // destination buffer
pdu_type, // pdu type
ASN1DECODE_SETBUFFER, // flags
encoded_buffer, // source buffer
encoded_buffer_length); // source buffer size
if (ASN1_FAILED(return_value))
{
ERROR_OUT(("CMCSCoder::Decode: ASN1_Decode failed, err=%d", return_value));
ASSERT(FALSE);
fRet = FALSE;
goto MyExit;
}
OptParam.eOption = ASN1OPT_GET_DECODED_BUFFER_SIZE;
return_value = ASN1_GetDecoderOption(m_pDecInfo, &OptParam);
if (ASN1_FAILED(return_value))
{
ERROR_OUT(("CMCSCoder::Decode: ASN1_GetDecoderOption failed, err=%d", return_value));
ASSERT(FALSE);
fRet = FALSE;
goto MyExit;
}
*pdecoding_buffer_length = OptParam.cbRequiredDecodedBufSize;
ASSERT((return_value == ASN1_SUCCESS) && (*pdecoding_buffer_length > 0));
}
MyExit:
return fRet;
}
/*
* PacketCoderError ReverseDirection ()
*
* Private
*
* Functional Description:
* This routine is used to convert data request PDU's into data indication
* PDU's and vice versa.
*/
Void CMCSCoder::ReverseDirection (LPBYTE encoded_buffer)
{
encoded_buffer += PROTOCOL_OVERHEAD_X224;
switch (*encoded_buffer)
{
case PER_SEND_DATA_REQUEST:
*encoded_buffer = PER_SEND_DATA_INDICATION;
break;
case PER_SEND_DATA_INDICATION:
*encoded_buffer = PER_SEND_DATA_REQUEST;
break;
case PER_UNIFORM_SEND_DATA_REQUEST:
*encoded_buffer = PER_UNIFORM_SEND_DATA_INDICATION;
break;
case PER_UNIFORM_SEND_DATA_INDICATION:
*encoded_buffer = PER_UNIFORM_SEND_DATA_REQUEST;
break;
default:
ASSERT (FALSE);
break;
}
}
/*
* void SetEncodingRules ()
*
* Private
*
* Functional Description:
* This function is used to set the type (basic or packed) of encoding
* rules to be used.
*/
void CMCSCoder::SetEncodingRules (UINT rules_type)
{
/*
* If the rules type is changing, set our rules instance variable and reset
* the variables which hold the amount of overhead associated with the
* "SendData" PDU's.
*/
Encoding_Rules_Type = rules_type;
}
/*
* BOOL IsMCSDataPacket ()
*
* Public
*
* Functional Description:
* This function determines whether the encoded packet is an MCS Data packet
* or not.
*
* Return value:
* TRUE, if the packet is an MCS Data packet. FALSE, otherwise.
*/
BOOL CMCSCoder::IsMCSDataPacket(LPBYTE encoded_buffer, UINT rules_type)
{
UChar identifier;
/*
* Retrieve the identifier from the encoded data.
*/
identifier = *encoded_buffer;
if (rules_type == BASIC_ENCODING_RULES)
{
if ( (identifier == SEND_DATA_REQUEST) ||
(identifier == SEND_DATA_INDICATION) ||
(identifier == UNIFORM_SEND_DATA_REQUEST) ||
(identifier == UNIFORM_SEND_DATA_INDICATION))
{
return TRUE;
}
}
else
{
if ( (identifier == PER_SEND_DATA_REQUEST) ||
(identifier == PER_SEND_DATA_INDICATION) ||
(identifier == PER_UNIFORM_SEND_DATA_REQUEST) ||
(identifier == PER_UNIFORM_SEND_DATA_INDICATION))
{
return TRUE;
}
}
return FALSE;
}
void CMCSCoder::FreeEncoded(LPBYTE encoded_buffer)
{
ASN1_FreeEncoded(m_pEncInfo, encoded_buffer);
}
void CMCSCoder::FreeDecoded (int pdu_type, LPVOID decoded_buffer)
{
ASN1_FreeDecoded(m_pDecInfo, decoded_buffer, pdu_type);
}