encode.c

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

C
1,104
字号
/* * Copyright (C) 1997-2005 by Objective Systems, Inc. * * This software is furnished under an open source license and may be  * used and copied only in accordance with the terms of this license.  * The text of the license may generally be found in the root  * directory of this installation in the COPYING file.  It  * can also be viewed online at the following URL: * *   http://www.obj-sys.com/open/license.html * * Any redistributions of this file including modified versions must  * maintain this copyright notice. * *****************************************************************************/#include <stdlib.h>#include "ooasn1.h"static int encode16BitConstrainedString (OOCTXT* pctxt, Asn116BitCharString value, Asn116BitCharSet* pCharSet);static int encode2sCompBinInt (OOCTXT* pctxt, ASN1INT value);static int encodeNonNegBinInt (OOCTXT* pctxt, ASN1UINT value);static int encodeUnconsLength (OOCTXT* pctxt, ASN1UINT value);static int getIdentByteCount (ASN1UINT ident);int encodeBit (OOCTXT* pctxt, ASN1BOOL value){    int stat = ASN_OK;   /* If start of new byte, init to zero */   if (pctxt->buffer.bitOffset == 8) {      pctxt->buffer.data[pctxt->buffer.byteIndex] = 0;   }   /* Adjust bit offset and determine if at end of current byte */   if (--pctxt->buffer.bitOffset < 0) {      if (++pctxt->buffer.byteIndex >= pctxt->buffer.size) {         if ((stat = encodeExpandBuffer (pctxt, 1)) != ASN_OK) {            return stat;         }      }      pctxt->buffer.data[pctxt->buffer.byteIndex] = 0;      pctxt->buffer.bitOffset = 7;   }   /* Set single-bit value */   if (value) {      pctxt->buffer.data[pctxt->buffer.byteIndex] |=          ( 1 << pctxt->buffer.bitOffset );   }   /* If last bit in octet, set offsets to start new byte (ED, 9/7/01) */   if (pctxt->buffer.bitOffset == 0) {      pctxt->buffer.bitOffset = 8;      pctxt->buffer.byteIndex++;      pctxt->buffer.data[pctxt->buffer.byteIndex] = 0;   }   return stat;}int encodeBits (OOCTXT* pctxt, ASN1UINT value, ASN1UINT nbits){    int nbytes = (nbits + 7)/ 8, stat = ASN_OK;   if (nbits == 0) return stat;   /* If start of new byte, init to zero */   if (pctxt->buffer.bitOffset == 8) {      pctxt->buffer.data[pctxt->buffer.byteIndex] = 0;   }   /* Mask off unused bits from the front of the value */   if (nbits < (sizeof(ASN1UINT) * 8))      value &= ((1 << nbits) - 1);   /* If bits will fit in current byte, set them and return */   if (nbits < (unsigned)pctxt->buffer.bitOffset) {      pctxt->buffer.bitOffset -= nbits;      pctxt->buffer.data[pctxt->buffer.byteIndex] |=          ( value << pctxt->buffer.bitOffset );      return stat;   }   /* Check buffer space and allocate more memory if necessary */   stat = encodeCheckBuffer (pctxt, nbytes);   if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);   /* Set bits in remainder of the current byte and then loop   */   /* to set bits in subsequent bytes..                         */   nbits -= pctxt->buffer.bitOffset;   pctxt->buffer.data[pctxt->buffer.byteIndex++] |=       (ASN1OCTET)( value >> nbits );   pctxt->buffer.data[pctxt->buffer.byteIndex] = 0;    while (nbits >= 8) {      nbits -= 8;      pctxt->buffer.data[pctxt->buffer.byteIndex++] =          (ASN1OCTET)( value >> nbits );      pctxt->buffer.data[pctxt->buffer.byteIndex] = 0;    }   /* copy final partial byte */   pctxt->buffer.bitOffset = 8 - nbits;   if (nbits > 0) {      pctxt->buffer.data[pctxt->buffer.byteIndex] =          (ASN1OCTET)((value & ((1 << nbits)-1)) << pctxt->buffer.bitOffset);   }   else      pctxt->buffer.data[pctxt->buffer.byteIndex] = 0;   return stat;}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 encodeBitString (OOCTXT* pctxt, ASN1UINT numbits, const ASN1OCTET* data){   int enclen, octidx = 0, stat;   Asn1SizeCnst* pSizeList = pctxt->pSizeConstraint;   for (;;) {      if ((enclen = encodeLength (pctxt, numbits)) < 0) {         return LOG_ASN1ERR (pctxt, enclen);      }      if (enclen > 0) {         ASN1BOOL doAlign;         stat = bitAndOctetStringAlignmentTest             (pSizeList, numbits, TRUE, &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);         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      }      if (enclen < (int)numbits) {         numbits -= enclen;         octidx += (enclen/8);      }      else break;   }   return ASN_OK;}int encodeBMPString (OOCTXT* pctxt, ASN1BMPString value, Asn116BitCharSet* permCharSet){   Asn116BitCharSet charSet;   int stat;   /* Set character set */   init16BitCharSet (&charSet, BMP_FIRST, BMP_LAST, BMP_ABITS, BMP_UBITS);   if (permCharSet) {      set16BitCharSet (pctxt, &charSet, permCharSet);   }   /* Encode constrained string */   stat = encode16BitConstrainedString (pctxt, value, &charSet);   if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);   return stat;}int encodeByteAlign (OOCTXT* pctxt){   if (pctxt->buffer.bitOffset != 8) {      if ((pctxt->buffer.byteIndex + 1) >= pctxt->buffer.size) {         int stat = encodeExpandBuffer (pctxt, 1);         if (stat != ASN_OK) return (stat);      }      pctxt->buffer.byteIndex++;      pctxt->buffer.bitOffset = 8;      pctxt->buffer.data[pctxt->buffer.byteIndex] = 0;   }   return ASN_OK;}int encodeCheckBuffer (OOCTXT* pctxt, ASN1UINT nbytes){   int stat = ASN_OK;   /* Add one to required bytes because increment logic will always     */   /* init the byte at the incremented index to zero..                  */   if ( ( pctxt->buffer.byteIndex + nbytes + 1 ) >= pctxt->buffer.size ) {      if ((stat = encodeExpandBuffer (pctxt, nbytes+1)) != ASN_OK) {         return LOG_ASN1ERR (pctxt, stat);      }   }   return (stat);}int encodeConsInteger (OOCTXT* pctxt, ASN1INT value, ASN1INT lower, ASN1INT upper){    ASN1UINT range_value;   ASN1UINT adjusted_value;   int stat;   /* Check value against given range */   if (value < lower || value > upper) {      return ASN_E_CONSVIO;   }   /* Adjust range value based on lower/upper signed values and */   /* other possible conflicts..                                */   if ((upper > 0 && lower >= 0) || (upper <= 0 && lower < 0)) {      range_value = upper - lower;      adjusted_value = value - lower;   }   else {      range_value = upper + abs(lower);      adjusted_value = value + abs(lower);   }         if (range_value != ASN1UINT_MAX) { range_value += 1; }   if (range_value == 0 || lower > upper)      stat = ASN_E_RANGERR;   else if (lower != upper) {      stat = encodeConsWholeNumber (pctxt, adjusted_value, range_value);   }   else      stat = ASN_OK;   return stat;}int encodeConsUnsigned (OOCTXT* pctxt, ASN1UINT value, ASN1UINT lower, ASN1UINT upper){    ASN1UINT range_value;   ASN1UINT adjusted_value;   int stat;   /* Check for special case: if lower is 0 and upper is ASN1UINT_MAX,  */   /* set range to ASN1UINT_MAX; otherwise to upper - lower + 1         */   range_value = (lower == 0 && upper == ASN1UINT_MAX) ?      ASN1UINT_MAX : upper - lower + 1;   adjusted_value = value - lower;   if (lower != upper) {      stat = encodeConsWholeNumber (pctxt, adjusted_value, range_value);   }   else      stat = ASN_OK;   return stat;}int encodeConsWholeNumber (OOCTXT* pctxt, ASN1UINT adjusted_value, ASN1UINT range_value){    ASN1UINT nocts, range_bitcnt = getUIntBitCount (range_value - 1);   int stat;   if (adjusted_value >= range_value && range_value != ASN1UINT_MAX) {      return LOG_ASN1ERR (pctxt, ASN_E_RANGERR);   }   /* If range is <= 255, bit-field case (10.5.7a) */   if (range_value <= 255) {      return encodeBits (pctxt, adjusted_value, range_bitcnt);   }   /* If range is exactly 256, one-octet case (10.5.7b) */   else if (range_value == 256) {      stat = encodeByteAlign (pctxt);      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      return encodeBits (pctxt, adjusted_value, 8);   }   /* If range > 256 and <= 64k (65536), two-octet case (10.5.7c) */   else if (range_value <= 65536) {      stat = encodeByteAlign (pctxt);      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      return encodeBits (pctxt, adjusted_value, 16);   }   /* If range > 64k, indefinite-length case (10.5.7d) */   else {      /* Encode length determinant as a constrained whole number.    */      /* Constraint is 1 to max number of bytes needed to hold       */      /* the target integer value..                                  */      if (adjusted_value < 256) nocts = 1;      else if (adjusted_value < 65536) nocts = 2;      else if (adjusted_value < 0x1000000) nocts = 3;      else nocts = 4;      stat = encodeBits (pctxt, nocts - 1, 2);      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      stat = encodeByteAlign (pctxt);      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      return encodeNonNegBinInt (pctxt, adjusted_value);   }}int encodeConstrainedStringEx (OOCTXT* pctxt,                             const char* string,                             const char* charSet,                            ASN1UINT abits,  /* aligned char bits */                            ASN1UINT ubits,  /* unaligned char bits */                            ASN1UINT canSetBits){   ASN1UINT i, len = strlen(string);   int      stat;   /* 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, abits, psize)) {      stat = encodeByteAlign (pctxt);      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);   }   /* Encode data */   if (abits >= canSetBits && canSetBits > 4) {      for (i = 0; i < len; i++) {         if ((stat = encodeBits (pctxt, string[i], abits)) != ASN_OK)            return LOG_ASN1ERR (pctxt, stat);      }   }   else if (0 != charSet) {      ASN1UINT nchars = strlen(charSet), pos;      const char* ptr;      for (i = 0; i < len; i++) {         ptr = memchr (charSet, string[i], nchars);         if (0 == ptr)            return LOG_ASN1ERR (pctxt, ASN_E_CONSVIO);         else            pos = ptr - charSet;         if ((stat = encodeBits (pctxt, pos, abits)) != ASN_OK)            return LOG_ASN1ERR (pctxt, stat);      }   }   else return LOG_ASN1ERR (pctxt, ASN_E_INVPARAM);   return stat;}int encodeExpandBuffer (OOCTXT* pctxt, ASN1UINT nbytes){   if (pctxt->buffer.dynamic)   {      /* If dynamic encoding is enabled, expand the current buffer to   */      /* allow encoding to continue.                                    */      pctxt->buffer.size += ASN1MAX (ASN_K_ENCBUFSIZ, nbytes);      pctxt->buffer.data = (ASN1OCTET*) memHeapRealloc         (&pctxt->pMsgMemHeap, pctxt->buffer.data, pctxt->buffer.size);            if (!pctxt->buffer.data) return (ASN_E_NOMEM);      return (ASN_OK);   }   return (ASN_E_BUFOVFLW);}int encodeGetMsgBitCnt (OOCTXT* pctxt){   int numBitsInLastByte = 8 - pctxt->buffer.bitOffset;   return ((pctxt->buffer.byteIndex * 8) + numBitsInLastByte);}ASN1OCTET* encodeGetMsgPtr (OOCTXT* pctxt, int* pLength){   if (pLength) *pLength = getPERMsgLen (pctxt);   return pctxt->buffer.data;}int encodeIdent (OOCTXT* pctxt, ASN1UINT ident) {   ASN1UINT mask;   int nshifts = 0, stat;   if (ident !=0) {      ASN1UINT lv;      nshifts = getIdentByteCount (ident);      while (nshifts > 0) {         mask = ((ASN1UINT)0x7f) << (7 * (nshifts - 1));         nshifts--;         lv = (ASN1UINT)((ident & mask) >> (nshifts * 7));         if (nshifts != 0) { lv |= 0x80; }         if ((stat = encodeBits (pctxt, lv, 8)) != ASN_OK)            return LOG_ASN1ERR (pctxt, stat);      }   }   else {      /* encode a single zero byte */      if ((stat = encodeBits (pctxt, 0, 8)) != ASN_OK)         return LOG_ASN1ERR (pctxt, stat);   }   return ASN_OK;}int encodeLength (OOCTXT* pctxt, ASN1UINT value){    ASN1BOOL extendable;   Asn1SizeCnst* pSize =       checkSize (pctxt->pSizeConstraint, value, &extendable);   ASN1UINT lower = (pSize) ? pSize->lower : 0;   ASN1UINT upper = (pSize) ? pSize->upper : ASN1UINT_MAX;   int enclen, stat;   /* If size constraints exist and the given length did not fall       */   /* within the range of any of them, signal constraint violation      */   /* error..                                                           */   if (pctxt->pSizeConstraint && !pSize)       return LOG_ASN1ERR (pctxt, ASN_E_CONSVIO);   /* Reset the size constraint in the context block structure */   pctxt->pSizeConstraint = 0;   /* If size constraint is present and extendable, encode extension    */   /* bit..                                                             */   if (extendable) {      stat = (pSize) ?         encodeBit (pctxt, pSize->extended) : encodeBit (pctxt, 1);      if (stat != ASN_OK) return (stat);   }   /* If upper limit is less than 64k, constrained case */   if (upper < 65536) {      stat = (lower == upper) ? ASN_OK :         encodeConsWholeNumber (pctxt, value - lower, upper - lower + 1);      enclen = (stat == ASN_OK) ? value : stat;   }   else {      /* unconstrained case or Constrained with upper bound >= 64K*/      enclen = encodeUnconsLength (pctxt, value);   }   return enclen;}int encodeObjectIdentifier (OOCTXT* pctxt, ASN1OBJID* pvalue){   int len, stat;   ASN1UINT temp;   register int numids, i;

⌨️ 快捷键说明

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