encode.c

来自「一个非常美妙的proxy。功能强大。基于sip的协议。如果还要的话」· C语言 代码 · 共 1,104 行 · 第 1/2 页

C
1,104
字号
   /* Calculate length in bytes and encode */   len = 1;  /* 1st 2 arcs require 1 byte */   numids = pvalue->numids;   for (i = 2; i < numids; i++) {      len += getIdentByteCount (pvalue->subid[i]);   }   /* PER encode length */   if ((stat = encodeLength (pctxt, (ASN1UINT)len)) < 0) {      return LOG_ASN1ERR (pctxt, stat);   }   /* Validate given object ID by applying ASN.1 rules */   if (0 == pvalue) return LOG_ASN1ERR (pctxt, ASN_E_INVOBJID);   if (numids < 2) return LOG_ASN1ERR (pctxt, ASN_E_INVOBJID);   if (pvalue->subid[0] > 2) return LOG_ASN1ERR (pctxt, ASN_E_INVOBJID);   if (pvalue->subid[0] != 2 && pvalue->subid[1] > 39)       return LOG_ASN1ERR (pctxt, ASN_E_INVOBJID);   /* Passed checks, encode object identifier */      /* Munge first two sub ID's and encode */   temp = ((pvalue->subid[0] * 40) + pvalue->subid[1]);   if ((stat = encodeIdent (pctxt, temp)) != ASN_OK)      return LOG_ASN1ERR (pctxt, stat);   /* Encode the remainder of the OID value */   for (i = 2; i < numids; i++) {      if ((stat = encodeIdent (pctxt, pvalue->subid[i])) != ASN_OK)         return LOG_ASN1ERR (pctxt, stat);   }   return ASN_OK;}int encodebitsFromOctet (OOCTXT* pctxt, ASN1OCTET value, ASN1UINT nbits){    int lshift = pctxt->buffer.bitOffset;   int rshift = 8 - pctxt->buffer.bitOffset;   int stat = ASN_OK;   ASN1OCTET mask;   if (nbits == 0) return ASN_OK;   /* Mask off unused bits from the end of the value */   if (nbits < 8) {      switch (nbits) {      case 1: mask = 0x80; break;      case 2: mask = 0xC0; break;      case 3: mask = 0xE0; break;      case 4: mask = 0xF0; break;      case 5: mask = 0xF8; break;      case 6: mask = 0xFC; break;      case 7: mask = 0xFE; break;      default:;      }      value &= mask;   }   /* If we are on a byte boundary, we can do a direct assignment */   if (pctxt->buffer.bitOffset == 8) {      pctxt->buffer.data[pctxt->buffer.byteIndex] = value;      if (nbits == 8) {         pctxt->buffer.byteIndex++;         pctxt->buffer.data[pctxt->buffer.byteIndex] = 0;      }      else         pctxt->buffer.bitOffset -= nbits;   }   /* Otherwise, need to set some bits in the first octet and   */   /* possibly some bits in the following octet..               */   else {      pctxt->buffer.data[pctxt->buffer.byteIndex] |=          (ASN1OCTET)(value >> rshift);      pctxt->buffer.bitOffset -= nbits;      if (pctxt->buffer.bitOffset < 0) {         pctxt->buffer.byteIndex++;         pctxt->buffer.data[pctxt->buffer.byteIndex] =             (ASN1OCTET)(value << lshift);         pctxt->buffer.bitOffset += 8;      }   }   return stat;}int encodeOctets (OOCTXT* pctxt, const ASN1OCTET* pvalue, ASN1UINT nbits){    int i = 0, stat;   int numFullOcts = nbits / 8;   if (nbits == 0) return 0;   /* Check buffer space and allocate more memory if necessary */   stat = encodeCheckBuffer (pctxt, numFullOcts + 1);   if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);   if (numFullOcts > 0) {      /* If the current bit offset is 8 (i.e. we don't have a      */      /* byte started), can copy the string directly to the        */      /* encode buffer..                                           */      if (pctxt->buffer.bitOffset == 8) {         memcpy (&pctxt->buffer.data[pctxt->buffer.byteIndex], pvalue,                  numFullOcts);         pctxt->buffer.byteIndex += numFullOcts;         pctxt->buffer.data[pctxt->buffer.byteIndex] = 0;         i = numFullOcts;      }      /* Else, copy bits */      else {         for (i = 0; i < numFullOcts; i++) {            stat = encodeBitsFromOctet (pctxt, pvalue[i], 8);            if (stat != ASN_OK) return stat;         }      }   }   /* Move remaining bits from the last octet to the output buffer */   if (nbits % 8 != 0) {      stat = encodeBitsFromOctet (pctxt, pvalue[i], nbits % 8);   }   return stat;}int encodeOctetString (OOCTXT* pctxt, ASN1UINT numocts, const ASN1OCTET* data){   int enclen, octidx = 0, stat;   Asn1SizeCnst* pSizeList = pctxt->pSizeConstraint;   for (;;) {      if ((enclen = encodeLength (pctxt, numocts)) < 0) {         return LOG_ASN1ERR (pctxt, enclen);      }      if (enclen > 0) {         ASN1BOOL doAlign;         stat = bitAndOctetStringAlignmentTest             (pSizeList, numocts, FALSE, &doAlign);         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);         if (doAlign) {            stat = encodeByteAlign (pctxt);            if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);         }         stat = encodeOctets (pctxt, &data[octidx], enclen * 8);         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      }      if (enclen < (int)numocts) {         numocts -= enclen;         octidx += enclen;      }      else break;   }   return ASN_OK;}int encodeOpenType (OOCTXT* pctxt, ASN1UINT numocts, const ASN1OCTET* data){   int enclen, octidx = 0, stat;   ASN1OCTET zeroByte = 0x00;   ASN1OpenType openType;   /* If open type contains length zero, add a single zero byte (10.1) */   if (numocts == 0) {      openType.numocts = 1;      openType.data = &zeroByte;   }   else {      openType.numocts = numocts;      openType.data = data;   }   /* Encode the open type */   for (;;) {      if ((enclen = encodeLength (pctxt, openType.numocts)) < 0) {         return LOG_ASN1ERR (pctxt, enclen);      }      stat = encodeByteAlign (pctxt);      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      stat = encodeOctets (pctxt, &openType.data[octidx], enclen * 8);      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      if (enclen < (int)openType.numocts) {         openType.numocts -= enclen;         octidx += enclen;      }      else break;   }   return ASN_OK;}int encodeOpenTypeExt (OOCTXT* pctxt, DList* pElemList){   DListNode* pnode;   ASN1OpenType* pOpenType;   int stat;   if (0 != pElemList) {      pnode = pElemList->head;      while (0 != pnode) {         if (0 != pnode->data) {            pOpenType = (ASN1OpenType*)pnode->data;            if (pOpenType->numocts > 0) {               stat = encodeByteAlign (pctxt);               if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);               stat = encodeOpenType                   (pctxt, pOpenType->numocts, pOpenType->data);               if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);            }         }         pnode = pnode->next;      }   }   return ASN_OK;}int encodeOpenTypeExtBits (OOCTXT* pctxt, DList* pElemList){   DListNode* pnode;   int stat;   if (0 != pElemList) {      pnode = pElemList->head;      while (0 != pnode) {         stat = encodeBit (pctxt, (ASN1BOOL)(0 != pnode->data));         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);         pnode = pnode->next;      }   }   return ASN_OK;}int encodeSemiConsInteger (OOCTXT* pctxt, ASN1INT value, ASN1INT lower){   int nbytes, stat;   int shift = ((sizeof(value) - 1) * 8) - 1;   ASN1UINT tempValue;   if (lower > ASN1INT_MIN)      value -= lower;      /* Calculate signed number value length */   for ( ; shift > 0; shift -= 8) {      tempValue = (value >> shift) & 0x1ff;      if (tempValue == 0 || tempValue == 0x1ff) continue;      else break;   }   nbytes = (shift + 9) / 8;   /* Encode length */   if ((stat = encodeLength (pctxt, nbytes)) < 0) {      return stat;   }   if ((stat = encodeByteAlign (pctxt)) != ASN_OK)      return stat;   /* Encode signed value */   stat = encode2sCompBinInt (pctxt, value);   return stat;}int encodeSemiConsUnsigned (OOCTXT* pctxt, ASN1UINT value, ASN1UINT lower){   int nbytes, stat;   int shift = ((sizeof(value) - 1) * 8) - 1;   ASN1UINT mask = 1UL << ((sizeof(value) * 8) - 1);   ASN1UINT tempValue;   value -= lower;   /* Calculate unsigned number value length */   for ( ; shift > 0; shift -= 8) {      tempValue = (value >> shift) & 0x1ff;      if (tempValue == 0) continue;      else break;   }   nbytes = (shift + 9) / 8;   /* If MS bit in unsigned number is set, add an extra zero byte */   if ((value & mask) != 0) nbytes++;   /* Encode length */   if ((stat = encodeLength (pctxt, nbytes)) < 0) {      return stat;   }      if ((stat = encodeByteAlign (pctxt)) != ASN_OK)      return stat;      /* Encode additional zero byte if necessary */   if (nbytes > sizeof(value)) {      stat = encodebitsFromOctet (pctxt, 0, 8);      if (stat != ASN_OK) return (stat);   }   /* Encode unsigned value */   stat = encodeNonNegBinInt (pctxt, value);   return stat;}int encodeSmallNonNegWholeNumber (OOCTXT* pctxt, ASN1UINT value){    int stat;   if (value < 64) {      stat = encodeBits (pctxt, value, 7);   }   else {      ASN1UINT len;      /* Encode a one-byte length determinant value */      if (value < 256) len = 1;      else if (value < 65536) len = 2;      else if (value < 0x1000000) len = 3;      else len = 4;      stat = encodeBits (pctxt, len, 8);      /* Byte-align and encode the value */      if (stat == ASN_OK) {         if ((stat = encodeByteAlign (pctxt)) == ASN_OK) {            stat = encodeBits (pctxt, value, len*8);         }      }   }   return stat;}int encodeVarWidthCharString (OOCTXT* pctxt, const char* value){   int         stat;   ASN1UINT    len = strlen (value);   /* note: need to save size constraint for use in alignCharStr     */   /* because it will be cleared in encodeLength from the context..        */   Asn1SizeCnst* psize = pctxt->pSizeConstraint;   /* Encode length */   stat = encodeLength (pctxt, len);   if (stat < 0) return LOG_ASN1ERR (pctxt, stat);   /* Byte align */   if (alignCharStr (pctxt, len, 8, psize)) {      stat = encodeByteAlign (pctxt);      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);   }   /* Encode data */   stat = encodeOctets (pctxt, (const ASN1OCTET*)value, len * 8);   if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);   return ASN_OK;}static int encode16BitConstrainedString (OOCTXT* pctxt, Asn116BitCharString value, Asn116BitCharSet* pCharSet){   ASN1UINT i, pos;   ASN1UINT nbits = pCharSet->alignedBits;   int stat;   /* Encode length */   stat = encodeLength (pctxt, value.nchars);   if (stat < 0) return LOG_ASN1ERR (pctxt, stat);   /* Byte align */   stat = encodeByteAlign (pctxt);   if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);   /* Encode data */   for (i = 0; i < value.nchars; i++) {      if (pCharSet->charSet.data == 0) {         stat = encodeBits             (pctxt, value.data[i] - pCharSet->firstChar, nbits);         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      }      else {         for (pos = 0; pos < pCharSet->charSet.nchars; pos++) {            if (value.data[i] == pCharSet->charSet.data[pos]) {               stat = encodeBits (pctxt, pos, nbits);               if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);               break;            }         }      }   }   return stat;}int encode2sCompBinInt (OOCTXT* pctxt, ASN1INT value){   /* 10.4.6  A minimum octet 2's-complement-binary-integer encoding    */   /* of the whole number has a field width that is a multiple of 8     */   /* bits and also satisifies the condition that the leading 9 bits    */   /* field shall not be all zeros and shall not be all ones.           */   /* first encode integer value into a local buffer */   ASN1OCTET lbuf[8], lb;   ASN1INT   i = sizeof(lbuf), temp = value;   memset (lbuf, 0, sizeof(lbuf));   do {      lb = temp % 256;      temp /= 256;      if (temp < 0 && lb != 0) temp--; /* two's complement adjustment */      lbuf[--i] = lb;   } while (temp != 0 && temp != -1);   /* If the value is positive and bit 8 of the leading byte is set,    */   /* copy a zero byte to the contents to signal a positive number..    */   if (value > 0 && (lb & 0x80) != 0) {      i--;   }   /* If the value is negative and bit 8 of the leading byte is clear,  */   /* copy a -1 byte (0xFF) to the contents to signal a negative        */   /* number..                                                          */   else if (value < 0 && ((lb & 0x80) == 0)) {      lbuf[--i] = 0xff;   }   /* Add the data to the encode buffer */   return encodeOctets (pctxt, &lbuf[i], (sizeof(lbuf) - i) * 8);}static int encodeNonNegBinInt (OOCTXT* pctxt, ASN1UINT value){   /* 10.3.6  A minimum octet non-negative binary integer encoding of   */   /* the whole number (which does not predetermine the number of       */   /* octets to be used for the encoding) has a field which is a        */   /* multiple of 8 bits and also satisifies the condition that the     */   /* leading eight bits of the field shall not be zero unless the      */   /* field is precisely 8 bits long.                                   */    ASN1UINT bitcnt = (value == 0) ? 1 : getUIntBitCount (value);   /* round-up to nearest 8-bit boundary */   bitcnt = (bitcnt + 7) & (~7);   /* encode bits */   return encodeBits (pctxt, value, bitcnt);}static int encodeUnconsLength (OOCTXT* pctxt, ASN1UINT value){   int enclen, stat;   stat = encodeByteAlign (pctxt);   if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);   /* 1 octet case */   if (value < 128) {      stat = encodeBits (pctxt, value, 8);      enclen = (stat == ASN_OK) ? value : stat;   }   /* 2 octet case */   else if (value < 16384) {      if ((stat = encodeBit (pctxt, 1)) == ASN_OK)         stat = encodeBits (pctxt, value, 15);      enclen = (stat == ASN_OK) ? value : stat;   }   /* fragmentation case */   else {      int multiplier = ASN1MIN (value/16384, 4);      encodeBit (pctxt, 1);  /* set bit 8 of first octet */      encodeBit (pctxt, 1);  /* set bit 7 of first octet */      stat = encodeBits (pctxt, multiplier, 6);      enclen = (stat == ASN_OK) ? 16384 * multiplier : stat;   }   return enclen;}static int getIdentByteCount (ASN1UINT ident) {   if (ident < (1u << 7)) {         /* 7 */      return 1;   }   else if (ident < (1u << 14)) {   /* 14 */      return 2;   }   else if (ident < (1u << 21)) {   /* 21 */      return 3;   }   else if (ident < (1u << 28)) {   /* 28 */      return 4;   }   return 5;}

⌨️ 快捷键说明

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