⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 per.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
***********************************************************************************

NOTICE:
This document contains information that is proprietary to RADVISION LTD..
No part of this publication may be reproduced in any form whatsoever without
written prior approval by RADVISION LTD..

RADVISION LTD. reserves the right to revise this publication and make changes
without obligation to notify any person of such revisions or changes.

***********************************************************************************
*/

/*
    per.c

    Ron S.
    14 May 1996

    *****************************************************
    *** Encoding Rules are ASN.1 PER BASIC - ALIGNED. ***
    *****************************************************


    Encoding/Decoding of the following ASN complex types:
    - Sequence
    - Sequence OF
    - Set OF
    - Choice

    Encoding: MSGV --> bitBuf
    Decoding: bitBuf --> MSGV

    Algorithm:
    ----------

    > Encoding(msgv, buf, tree)

    - Clear tmp and func lists.
    - Clear buf.
    - Add root node to func list.
    - while (not end_of_func_list) do
    - Clear tmp list.
    - tmp <- Encode head of func list.
    - func <- tmp + func
    - endwhile


    > EncodeFuncListNode(msgv, buf, tree, node)

    - switch (type of node)
    - Encode node by type:
    - Add encoding bits to buf.
    - Add child nodes to tmp list as needed.


    > Decoding(msgv, buf, tree)
    This is done much the same way aw the encoding procedure. Only the input is taken from
    the bit buffer and the value tree is generated.


  Notes:
  ------
  1. NULL object has no bit encoding and so there shall be no node of NULL type in
  the value tree.
  2. This is a non - reentrent code. Using tmp list as global variable for the encoding/
  decoding process.
  3. The output data structures shall have enough space to contain the encoding/decoding
  result.
  4. ALthough the process is recursive, it is implemented by a queue(func list) that
  holds an ordered list of the nodes to be processed.


  Parameters:
  -----------
  asnH: asn handler.
  deleted: number of bits deleted from bit buffer after last processing procedure.
  msgv: Message Values handler. The value tree.
  buf: bit buffer. Holds the message in ASN PER encoding(Decoding). Has sufficient space to
  hold the complete encoding(Encoding).
  tree: The syntax tree structure.
  type: Encode/Decode, determines which kind of operation to do.
  func: function node. The current node to process.
  parent: path to node in value tree.
  structEnum: enumeration of structure in the syntax tree.
  index: of child. Used for set - of nodes.
  path: path of structure in the syntax tree.
  vtPath: path of current node in value tree.
*/

#include "rvmemory.h"
#include "rvlog.h"

#include "coderbitbuffer.h"
#include "copybits.h"
#include "pvaltreeStackApi.h"
#include "psyntreeStackApi.h"
#include "emanag.h"

#include "per.h"
#include "perseq.h"
#include "perseqof.h"
#include "perchoic.h"
#include "perchrst.h"
#include "peroctst.h"
#include "perBitString.h"
#include "peroid.h"
#include "perintr.h"


#ifdef __cplusplus
extern "C" {
#endif


/********************** MACROS **********************/

#define MAX_FUNC_NODES   30
#define IS_OPEN_TYPE(nodeId)(wasTypeResolvedInRunTime || pstGetIsOpenType(per->hSyn,(nodeId)))

#define nprn(s) ((s)?(s):"(null)")


/*** static variables ***/
RvLogSource rvPerLogSource; /* PER log source */
RvLogSource rvPerErrLogSource; /* PERERR log source */

/* Maximum size of buffers for encoding/decoding */
static int         perMaxBufSize = 0;

static RvUint32   timesTlsInitialized = 0;
static RvUint32   rvPerTlsIndex;
static RvUint32   timesPerConstructed = 0;



/********************************************************************************************
 * coderFreeThreadBuffer
 * An exit callback of a specific thread for CODER.
 * This function frees the allocation of the encode/decode buffer
 * context  - The pointer to the buffer to free
 ********************************************************************************************/
void coderFreeThreadBuffer(IN RvThread* thread, IN void*   context, IN RvUint32 index)
{
    THREAD_CoderLocalStorage* coderTls = (THREAD_CoderLocalStorage *)context;
    RV_UNUSED_ARG(thread);
    RV_UNUSED_ARG(index);

    if (context == NULL)
        return;

    if(coderTls->buffer)
        RvMemoryFree(coderTls->buffer);
    RvMemoryFree(coderTls);
}


/************************************************************************
 * perBufferInit
 * purpose: Create the local storage for the buffer to use for PER
 *          encode/decode procedures
 * input  : none
 * output : none
 * return : none
 ************************************************************************/
void perBufferInit(void)
{
    if(timesTlsInitialized == 0)
    {
        if(RvThreadCreateVar(coderFreeThreadBuffer, "RvAsnPER", &rvPerTlsIndex) != RV_OK)
            return;
    }
    timesTlsInitialized++;
}

/************************************************************************
 * perGetBuffer
 * purpose: Returns the buffer to use for PER encode/decode procedures
 * input  : none
 * output : none
 * return : Pointer to the buffer on success
 *          NULL on failure
 ************************************************************************/
THREAD_CoderLocalStorage* perGetBuffer(void)
{
    THREAD_CoderLocalStorage*   coderTls;

    if((timesTlsInitialized <= 0) ||
        (RvThreadGetVar(rvPerTlsIndex, (void**)&coderTls) != RV_OK))
        return NULL;

    if(coderTls == NULL)
    {
        RvMemoryAlloc(NULL, (void**)&coderTls, sizeof(THREAD_CoderLocalStorage));
        memset((void*)coderTls, 0, sizeof(THREAD_CoderLocalStorage));
        RvThreadSetVar(rvPerTlsIndex, (void*)coderTls);
    }

    if ((coderTls->buffer != NULL) && ((int)coderTls->bufferSize < perMaxBufSize))
    {
        /* Current allocation too small - make sure we fix this situation... */
        RvMemoryFree(coderTls->buffer);
        coderTls->buffer = NULL;
    }

    if (coderTls->buffer == NULL)
    {
        coderTls->bufferSize = perMaxBufSize;
        if(RvMemoryAlloc(NULL, (void**)&coderTls->buffer, coderTls->bufferSize) != RV_OK)
            return NULL;
    }

    return coderTls;
}

/************************************************************************
 * perBufferEnd
 * purpose: close down the local storage
 * input  : none
 * output : none
 * return : void
 ************************************************************************/
void perBufferEnd(void)
{
    timesTlsInitialized--;
    if(timesTlsInitialized == 0)
        RvThreadDeleteVar(rvPerTlsIndex);
}

/*_____________________________________________________________________*/
/*_________________________________INFORMATION_________________________*/
/*_____________________________________________________________________*/

/*
Desc: put bits in head of dest buffer.
Returns: Number of bits extracted from buffer.
*/
RvInt32
bbGet2Left(IN  HPER     hPer,
           IN  RvUint32 fromBitPosition, /* in buffer */
           IN  RvUint32 numOfBitsToGet,
           OUT RvUint8* dest) /* destination buffer */
{
    perStruct *per =(perStruct *)hPer;
    bbStruct *bb =(bbStruct *)(per->hBB);
    RvUint32 actualLength;

    if (!bb || !dest)
        return RV_ERROR_UNKNOWN;
    actualLength = RvMin(numOfBitsToGet, bb->bitsInUse - fromBitPosition);

    if (actualLength > per->buf->bufferSize * 8)
    {
        per->encodingDecodingErrorBitMask = per->encodingDecodingErrorBitMask | encDecErrorsMessageIsInvalid;
        return RV_ERROR_UNKNOWN;
    }

    memcpyb(dest, 0, bb->octets, fromBitPosition, actualLength);
    return actualLength;
}


/*
Desc: put bits in tail of dest buffer.
Note: Length of dest buffer is the minimum number of bytes needed to hold
the numOfBitsToGet bits.
Returns: Number of bits extracted from buffer.
*/
RvInt32
bbGet2Right(HPER hPer,
            IN RvUint32 fromBitPosition, /* in buffer */
            IN RvUint32 numOfBitsToGet,
            OUT RvUint8 *dest) /* destination buffer */
{
    perStruct *per =(perStruct *)hPer;
    bbStruct *bb =(bbStruct *)(per->hBB);
    RvUint32 actualLength;

    if (!bb || !dest)
        return RV_ERROR_UNKNOWN;
    actualLength = RvMin(numOfBitsToGet, bb->bitsInUse - fromBitPosition);

    if (actualLength>MAX_INT_SIZE*8)
    {
        per->encodingDecodingErrorBitMask = per->encodingDecodingErrorBitMask | encDecErrorsMessageIsInvalid;
        return RV_ERROR_UNKNOWN;
    }

    memcpyb(dest, (8 - numOfBitsToGet%8)%8, bb->octets, fromBitPosition, actualLength);
    return actualLength;
}












/*______________________________low level____________________________________________*/


/*
Desc: Production of the complete encoding.
Padding the field - list encoding for octet alignment.
10.1

*/
int
perEncodeComplete(IN  HPER hPer, IN int bitsInUse)
{
    perStruct *per =(perStruct *)hPer;
    int  len;
    RvUint8 ch = 0;

    /* -- 10.1.3 */
    if (bitsInUse>0)
        len =(int)((8 - bitsInUse%8)%8); /* bits for alignment */
    else
        len = 8;

    return bbAddTail(per->hBB, (RvUint8 *)&ch, len, RV_FALSE); /* align encoding */
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -