📄 q931.c
字号:
#include "rvstdio.h"
#include "rvlog.h"
#include "psyntreeStackApi.h"
#include "pvaltree.h"
#include "emanag.h"
#include "q931.h"
#ifdef __cplusplus
extern "C" {
#endif
static RvLogSource rvQ931LogSource;
static RvLogSource rvQ931ErrLogSource;
int qILog2(RvInt32 N)
{
int i=-1;
while(N) {i++;N>>=1;}
return i;
}
typedef enum
{
ROOT_LEVEL = 0,
MSG_LEVEL = 1,
OTHER_IES_LEVEL = 2,
IE_LEVEL = 3,
OCTET_LEVEL = 4,
FIELD_LEVEL = 5
} qLevels;
int Q931EInter(HPST synH,int nodeId,RvInt32 fieldId ,HPVT valH,int vNodeId,int level,RvUint8* buffer,int bit,int length)
{
int lengthBit=0;
pstTagClass tagClass;
pstNodeType type;
int numOfChildren;
int tag=pstGetTag(synH,nodeId,&tagClass);
if (tagClass==pstTagPrivate && tag!=emQ931)
{
int len, ret;
RvLogDebug(&rvQ931LogSource, (&rvQ931LogSource, "Private tag %d", tag));
ret = emEncodeExt(valH,vNodeId,buffer+bit/8,length,&len);
if (ret < 0)
{
RvLogError(&rvQ931ErrLogSource, (&rvQ931ErrLogSource,
"Q931EInter: Private tag encoding error (%d).", tag));
return RV_ERROR_UNKNOWN;
}
return bit+len*8;
}
if (tag != RV_ERROR_UNKNOWN)
{
/* See if we have to place a tag in front of the encoded element */
if ((tagClass == pstTagEmpty) || (tagClass == pstTagApplication))
{
buffer[bit/8] = (RvUint8)tag;
bit += 8;
}
if (level == IE_LEVEL)
{
/* It's an information element - we have to add a length as well... */
lengthBit = bit;
if (tagClass == pstTagApplication)
bit += 16;
else
bit += 8;
}
}
level++;
type=pstGetNodeType(synH,nodeId);
RvLogDebug(&rvQ931LogSource, (&rvQ931LogSource,
"Encoding %s: %s [%d].",
(fieldId>=0)?pstGetFieldNamePtr(synH, fieldId):"(null)", pstGetTokenName(type), bit));
numOfChildren=pstGetNumberOfChildren(synH,nodeId);
switch(type)
{
case pstSet:
{
int i;
pstChildExt child;
int childNodeId;
RvUint32* iter = pstGetChildExt(synH,nodeId,1,&child);
for (i=1;i<=numOfChildren;i++)
{
if (pvtGetChild(valH,vNodeId,child.fieldId,&childNodeId) < 0)
{
if ((child.isOptional == RV_TRUE) || (child.isDefault == RV_TRUE))
{
iter = pstGetBrotherExt(synH, i+1, iter, &child);
continue;
}
else
{
RvLogError(&rvQ931ErrLogSource, (&rvQ931ErrLogSource,
"Q931EInter: non optional Child not found [%d]%s.",
vNodeId,
pstGetFieldNamePtr(synH, child.fieldId)));
return RV_ERROR_UNKNOWN;
}
}
bit=Q931EInter(synH,child.nodeId,child.fieldId,valH,childNodeId,level,buffer,bit,length);
if(bit<0) return bit;
iter = pstGetBrotherExt(synH, i+1, iter, &child);
}
}
break;
case pstSequence:
{
int i;
int childNodeId;
pstChildExt child;
RvUint32* iter = pstGetChildExt(synH,nodeId,1,&child);
for (i=1;;i++)
{
if (pstGetIsExtended(synH,nodeId) && !(bit%8))
{
buffer[bit/8]=0x80;
bit++;
}
if (pvtGetChild(valH,vNodeId,child.fieldId,&childNodeId)==RV_ERROR_UNKNOWN)
{
if (child.isExtended)
{
if(bit%8==1)
{
bit--;
buffer[bit/8-1]|=0x80;
}
else
{
bit+=8-bit%8;
/* ?????????????? */
}
break;
}
else if ((child.isOptional == RV_TRUE) || (child.isDefault == RV_TRUE))
{
/* Optional field - ignore and go on */
if (i == numOfChildren)
break;
iter = pstGetBrotherExt(synH, i+1, iter, &child);
continue;
}
else
{
RvLogError(&rvQ931ErrLogSource, (&rvQ931ErrLogSource,
"Q931EInter: non optional Child not found [%d]%s->%s.",
vNodeId, pstGetFieldNamePtr(synH,fieldId),
pstGetFieldNamePtr(synH, child.fieldId)));
return RV_ERROR_UNKNOWN;
}
}
bit=Q931EInter(synH,child.nodeId,child.fieldId,valH,childNodeId,level,buffer,bit,length);
if(bit<0) return bit;
if (i==numOfChildren) break;
if (pstGetIsExtended(synH,nodeId) && !(bit%8)) buffer[bit/8-1]&=0x7f;
iter = pstGetBrotherExt(synH, i+1, iter, &child);
}
}
break;
case pstSequenceOf:
{
/* SEQUENCE OF in Q931 is handled as if it's not there. We use it to allow several
information elements with the same tag to be encoded/decoded together. */
int childNodeId;
int childSynNodeId;
RvPstFieldId childFieldId;
/* Loop through the array and encode each element as if it was a fresh one out
of the box. */
childNodeId = pvtChild(valH, vNodeId);
pvtGet(valH, childNodeId, &childFieldId, &childSynNodeId, NULL, NULL);
while (RV_PVT_NODEID_IS_VALID(childNodeId))
{
/* We go and encode our internal structures without increasing the level since we
don't want the SEQUENCE OF structure to show up in the encoding */
bit = Q931EInter(synH, childSynNodeId, childFieldId, valH, childNodeId, level-1, buffer, bit, length);
if (bit < 0)
return bit;
/* Get the next one */
childNodeId = pvtBrother(valH, childNodeId);
}
}
break;
case pstChoice:
{
int childNodeId=pvtChild(valH,vNodeId);
int childSynNodeId;
RvPstFieldId childFieldId;
if(childNodeId==RV_ERROR_UNKNOWN)
{
RvLogError(&rvQ931ErrLogSource, (&rvQ931ErrLogSource,
"perEncodeChoice: Value node does not exist. [%s]",
pstGetFieldNamePtr(synH, fieldId)));
return RV_ERROR_UNKNOWN;
}
pvtGet(valH,childNodeId,&childFieldId,&childSynNodeId,NULL,NULL);
bit=Q931EInter(synH,childSynNodeId,childFieldId,valH,childNodeId,level,buffer,bit,length);
if(bit<0) return bit;
}
break;
case pstInteger:
{
RvUint32 value;
int to , from, bits;
pstGetNodeRange( synH, nodeId, &from, &to);
bits=qILog2(to-from)+1;
pvtGet(valH,vNodeId,NULL,NULL,(RvInt32*)&value,NULL);
if (bits<=8) {buffer[bit/8]&=~(((1<<bits)-1)<<(8-(bit%8)-bits));buffer[bit/8]|=value<<(8-(bit%8)-bits);}
else if (bits==16)
{
buffer[bit/8]=(RvUint8)(value>>8);
buffer[bit/8+1]=(RvUint8)value;
}
bit+=bits;
}
break;
case pstIA5String:
case pstOctetString:
{
RvUint32 strLength;
if (bit%8) {bit+=7; bit-=bit%8;}
pvtGet(valH,vNodeId,NULL,NULL,(RvInt32*)&strLength,NULL);
pvtGetString(valH,vNodeId,(RvInt32)strLength,(char*)&(buffer[bit/8]));
bit+=((int)strLength)*8;
}
break;
case pstNull:
if(bit-lengthBit==8) bit-=8;
return bit;
default:
RvLogError(&rvQ931ErrLogSource, (&rvQ931ErrLogSource,
"Q931EInter: Unknown type (node=%d) - don't know how to encode.",
vNodeId));
return -1;
}
if (level == IE_LEVEL+1)
{
/* We should place the length value for this field... */
if (tagClass==pstTagApplication)
{
/* Application tags get a length of 2 bytes */
buffer[lengthBit/8]=(unsigned char)(((bit-lengthBit)/8-2)>>8);
buffer[lengthBit/8+1]=(unsigned char)((bit-lengthBit)/8-2);
}
else
{
/* Only one byte length for most fields... */
buffer[lengthBit/8]=(unsigned char)((bit-lengthBit)/8-1);
}
}
return bit;
}
int Q931Encode(HPVT valH,int vNodeId,RvUint8* buffer,int length,int*encoded)
{
HPST synH=pvtGetSynTree(valH, vNodeId);
int nodeId;
pvtGet(valH, vNodeId, NULL, &nodeId, NULL, NULL);
*encoded=Q931EInter(synH,nodeId,-1,valH,vNodeId,ROOT_LEVEL,buffer,0,length*8);
if(*encoded<0)
return(*encoded);
else
{
*encoded /= 8;
return 0;
}
}
int Q931DInter(HPST synH,int nodeId,RvInt32 fieldId,HPVT valH,int vNodeId,int level,RvUint8* buffer,int bit,int length)
{
int newBit, ret;
int tag = buffer[bit/8];
pstTagClass tagClass;
pstNodeType type;
int numOfChildren;
int stag;
type = pstGetNodeType(synH, nodeId);
if (type != pstSequenceOf)
{
/* "Regular node" - get the tag from it */
stag = pstGetTag(synH, nodeId, &tagClass);
}
else
{
/* It's a SEQUENCE OF - the tag is one step down */
stag = pstGetTag(synH, pstGetNodeOfId(synH, nodeId), &tagClass);
}
if (nodeId != RV_ERROR_UNKNOWN)
{
if (tagClass == pstTagPrivate && stag != emQ931)
{
int len;
ret = emDecodeExt(valH, vNodeId, fieldId, buffer + bit/8, (length/8) - (bit/8), &len);
if (ret >= 0)
return bit + len*8;
else
return ret;
}
if ((tagClass == pstTagEmpty || tagClass == pstTagApplication) && stag != RV_ERROR_UNKNOWN)
{
if (tag == stag)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -