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

📄 asn1_erl_driver.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 4 页
字号:
    }  return form;}/* * decode_value decodes the BER encoded length and value fields in the * in_buf and puts the value part in the decode_buf as an Erlang term * encoded by the Erlang extern format */int decode_value(int *ei_index,unsigned char *in_buf,		 int *ib_index,ErlDrvBinary **drv_binary,int form,		 int in_buf_len){  int maybe_ret;  char *decode_buf = (*drv_binary)->orig_bytes;  int len, lenoflen;  int indef = 0;  #ifdef ASN1_DEBUG    printf("decode_value1:ib_index=%d\n\r",*ib_index);#endif  if (((in_buf[*ib_index]) & 0x80) == ASN1_SHORT_DEFINITE_LENGTH) {    len = in_buf[*ib_index];    if (len > (in_buf_len - (*ib_index + 1)))      return ASN1_LEN_ERROR;  }  else if (in_buf[*ib_index] == ASN1_INDEFINITE_LENGTH)    indef = 1;  else /* long definite length */ {    lenoflen = (in_buf[*ib_index] & 0x7f); /*length of length */#ifdef ASN1_DEBUG     printf("decode_value,lenoflen:%d\r\n",lenoflen);#endif    len = 0;    while (lenoflen-- && (*ib_index <= in_buf_len)) {      (*ib_index)++;#ifdef ASN1_DEBUG       printf("decode_value1:ii=%d.\r\n",*ib_index);#endif      len = (len << 8) + in_buf[*ib_index];    }    if (len > (in_buf_len - (*ib_index + 1)))      return ASN1_LEN_ERROR;  }  (*ib_index)++;#ifdef ASN1_DEBUG   printf("decode_value2:ii=%d.\r\n",*ib_index);#endif  if (indef == 1)    { /* in this case it is desireably to check that indefinite length	 end bytes exist in inbuffer */      while (!(in_buf[*ib_index]==0 && in_buf[*ib_index + 1]==0)) {#ifdef ASN1_DEBUG	printf("decode_value while:ib_index=%d in_buf_len=%d\n\r",	 *ib_index,in_buf_len);#endif	if(*ib_index >= in_buf_len)	  return ASN1_INDEF_LEN_ERROR;	ei_encode_list_header(decode_buf,ei_index,1); /* 5 bytes */	if((maybe_ret=decode(drv_binary,ei_index,in_buf,			     ib_index,in_buf_len)) <= ASN1_ERROR)	  return maybe_ret;	decode_buf = (*drv_binary)->orig_bytes;      }      (*ib_index) += 2; /* skip the indefinite length end bytes */#ifdef ASN1_DEBUG       printf("decode_value3:ii=%d.\r\n",*ib_index);#endif      ei_encode_empty_list(decode_buf,ei_index); /* 1 byte */    }  else if (form == ASN1_CONSTRUCTED)    {      int end_index = *ib_index + len;      if(end_index > in_buf_len)	return ASN1_LEN_ERROR;      while (*ib_index < end_index) {#ifdef ASN1_DEBUG  	printf("decode_value3:*ib_index=%d, end_index=%d\n\r",*ib_index,end_index);#endif	ei_encode_list_header(decode_buf,ei_index,1); /* 5 bytes */	if((maybe_ret=decode(drv_binary,ei_index,in_buf,			     ib_index,in_buf_len))<=ASN1_ERROR)	  return maybe_ret;	decode_buf = (*drv_binary)->orig_bytes;      }      ei_encode_empty_list(decode_buf,ei_index); /* 1 byte */    }  else    {      if (((*drv_binary)->orig_size - *ei_index) < 10+len) { /* 5+len for the  binary*/	if (realloc_decode_buf(drv_binary,(*drv_binary)->orig_size * 2) == 	    ASN1_ERROR)	  return ASN1_ERROR;	decode_buf = (*drv_binary)->orig_bytes;      }      if((*ib_index + len) > in_buf_len)	return ASN1_LEN_ERROR;      ei_encode_binary(decode_buf,ei_index,&in_buf[*ib_index],len);      *ib_index = *ib_index + len;#ifdef ASN1_DEBUG       printf("decode_value4:ii=%d.\r\n",*ib_index);#endif    }  return ASN1_OK;}int realloc_decode_buf(ErlDrvBinary **drv_binary,int amount) {  ErlDrvBinary *tmp_bin;  if ((tmp_bin=driver_realloc_binary(*drv_binary,amount)) == NULL)    return ASN1_ERROR;  *drv_binary = tmp_bin;  return ASN1_OK;}/* * int decode_partial(drv_binary,in_buf,in_buf_len)  *//* * The in_buf contains two parts: first information about which value * will be decoded, as a sequence of tags and tag codes, then the * encoded BER value. First of all comes a length field that tells how * many following bytes contains the sequence of tags. Then starts the * BER encoded message. The tag sequence length field is a single * byte. The sequence of tags/tag codes may be one of the codes * ASN1_SKIPPED, ASN1_CHOOSEN and a tag or ASN1_OPTIONAL and a * tag. ASN1_SKIPPED means that the following tag is mandatory and is * skipped. ASN1_CHOOSEN means that the value of this tag shall, if * this was the last tag in tag sequence, be returned or be searched * in for the next tag. ASN1_OPTIONAL means that this tag shall be * skipped but it may be missing. Each tag in the tag sequence * correspond to a tag in the BER encoded message. If the decode * arives to a position where there is no matching tag, an error is * returned (if it wasn't the last tag and it was OPTIONAL). After the * right value has been detected it is returned in the out_buf. * */int decode_partial(ErlDrvBinary **drv_binary,unsigned char *in_buf, int in_buf_len){  char *out_buf = (*drv_binary)->orig_bytes;  int tag_index_val = 1;  int msg_index_val;  int *msg_index, *tag_index, tmp_index;  int tag_seq_length;  char tag_code; /* one of ASN1_SKIPPED, ASN1_OPTIONAL, ASN1_CHOOSEN */  int wanted_tag, next_tag;  int buf_end_index = in_buf_len;  int ret = 0, length, old_index;    tag_index = &tag_index_val;  tag_seq_length = in_buf[0];  msg_index = &msg_index_val;  *msg_index = tag_seq_length + 1;/*   printf("decode_partial 1: in_buf_len=%d, tag_index=%d, msg_index=%d\r\n,tag_seq_length=%d\r\n",in_buf_len,*tag_index,*msg_index,tag_seq_length); */  while(*tag_index < tag_seq_length) {    switch(in_buf[*tag_index]) {    case ASN1_SKIPPED:/*       printf("decode_partial ASN1_SKIPPED: in_buf[*msg_index]=%d\r\n",in_buf[*msg_index]); */      (*tag_index)++;/*       printf("decode_partial ASN1_SKIPPED 2: *msg_index=%d\r\n",*msg_index); */      skip_tag(in_buf,msg_index,buf_end_index);/*       printf("decode_partial ASN1_SKIPPED 3: *msg_index=%d\r\n",*msg_index); */      skip_length_and_value(in_buf,msg_index,buf_end_index);/*       printf("decode_partial ASN1_SKIPPED 4: *msg_index=%d\r\n",*msg_index); */      break;    case ASN1_OPTIONAL:      (*tag_index)++;/*       printf("decode_partial ASN1_OPTIONAL: in_buf[*tag_index]=%d\r\n",in_buf[*tag_index]); */      wanted_tag = in_buf[*tag_index];      (*tag_index)++;      tmp_index = *msg_index;      next_tag = get_tag(in_buf,msg_index,buf_end_index);      if (wanted_tag != next_tag) {	*msg_index = tmp_index;      } else 	skip_length_and_value(in_buf,msg_index,buf_end_index);      break;    case ASN1_CHOOSEN:/*       printf("decode_partial ASN1_CHOOSEN: in_buf[*msg_index]=%d, *msg_index=%d\r\n",in_buf[*msg_index],*msg_index); */      (*tag_index)++;      wanted_tag = in_buf[*tag_index];      (*tag_index)++;      old_index = *msg_index;/*       printf("decode_partial ASN1_CHOOSEN 2: *msg_index=%d\r\n",*msg_index); */      next_tag = get_tag(in_buf,msg_index,buf_end_index);/*       printf("decode_partial ASN1_CHOOSEN 3: *msg_index=%d\r\n,wanted_tag=%d, next_tag=%d\r\n",*msg_index,wanted_tag,next_tag); */      if (wanted_tag != next_tag)	return ASN1_NOVALUE; /* an empty binary will be returned to Erlang */      if (*tag_index == (tag_seq_length + 1)) { 	/* get the value and return*/	if((ret = get_value(out_buf,in_buf,msg_index,buf_end_index)) <= ASN1_ERROR)	  return ASN1_ERROR;	return ret;      }       else { 	/* calculate the length of the sub buffer and let *msg_index	   be at the value part of this BER encoded type*/	int indef;	indef = 0;	length = get_length(in_buf,msg_index,&indef,buf_end_index);/* 	printf("decode_partial ASN1_CHOOSEN 4: length=%d, *msg_index=%d\r\n",length,*msg_index); */	if ((length == 0) && (indef == 1)) {	  /* indefinite length of value */	  old_index = *msg_index;	  length = skip_length_and_value(in_buf,msg_index,buf_end_index);	  *msg_index = old_index;	  buf_end_index = *msg_index + length - 2; 	  /* remove two bytes due to indefinete length end zeros */	} else 	  buf_end_index = (*msg_index + length);      }      break;    default:      return ASN1_ERROR;    }  }  return ASN1_ERROR;}/* * int skip_tag(unsigned char *in_buf,int *index,int buf_len) * steps past the BER encoded tag in in_buf and updates *index. * Returns the number of skipped bytes. */int skip_tag(unsigned char *in_buf,int *index,int buf_len){  int start_index = *index;  if ((MASK(in_buf[*index],ASN1_TAG)) == 31){    do {      (*index)++;      if (*index >= buf_len)	return ASN1_ERROR;    }    while(in_buf[*index] >=128);  }  (*index)++;  return (*index - start_index);}/* * int skip_length_and_value(unsigned char *in_buf,int *index,int buf_len) * steps past the BER encoded length and value in in_buf and updates *index. * returns the length if the skipped "length value". * Returns the number of skipped bytes. */int skip_length_and_value(unsigned char *in_buf,int *index,int buf_len){  long len;  int indef = 0, lenoflen;  int start_index = *index;  if ((MASK(in_buf[*index],0x80)) == ASN1_SHORT_DEFINITE_LENGTH){    len = in_buf[*index];    if (len > (buf_len - (*index + 1)))      return ASN1_LEN_ERROR;  } else if (in_buf[*index] == ASN1_INDEFINITE_LENGTH)    indef = 1;  else /* long definite length */ {    lenoflen = (in_buf[*index] & 0x7f); /*length of length */    len = 0;    while (lenoflen--) {      (*index)++;      len = (len << 8) + in_buf[*index];    }    if (len > (buf_len - (*index + 1)))      return ASN1_LEN_ERROR;  }  (*index)++;  if (indef == 1)    {      while(!(in_buf[*index]==0 && in_buf[*index + 1]==0)) {	skip_tag(in_buf,index,buf_len);	skip_length_and_value(in_buf,index,buf_len);      }      (*index) += 2;    }  else     (*index) += len;  return (*index - start_index);}/* int get_tag(unsigned char *in_buf,int *index) * * assumes next byte/bytes in in_buf is an encoded BER tag. A tag * number has theoretically no upper limit in size. Here the tag * number is assumed to be less than 64K. Returns an integer value * on the format: * xxxxxxxx xxxxxxcc tttttttt tttttttt * the x-bits are 0 (insignificant) * the c-bits are the class of the tag * the t-bits are the tag number. This implies that the tag number * is limited to 64K-1 *  */int get_tag(unsigned char *in_buf,int *index,int buf_len){  int tag_no = 0,tmp_tag = 0;  tag_no = (MASK(in_buf[*index],ASN1_CLASSFORM));  if ((MASK(in_buf[*index],ASN1_TAG)) == ASN1_TAG) {    /* long form of tag */    do {      (*index)++;      if (*index >= buf_len)	return ASN1_TAG_ERROR;      tmp_tag = tmp_tag << 7;      tmp_tag += (MASK(in_buf[*index],ASN1_LONG_TAG));    } while (in_buf[*index] >= 128);    (*index)++;    tag_no = tag_no + tmp_tag;  } else {    tag_no += (MASK(in_buf[*index],ASN1_TAG));    (*index)++;  }  if (*index >= buf_len)    return ASN1_TAG_ERROR;  return tag_no;}/* * int get_value(char *out_buf,unsigned char *in_buf, *               int *msg_index,int in_buf_len) *//* assumes next byte/bytes in in_buf is an encoded BER value preceeded by a BER encoded length. Puts value in out_buf. */int get_value(char *out_buf,	      unsigned char *in_buf,	      int *msg_index,	      int in_buf_len){  int len, lenoflen, indef=0, skip_len;  int ret=0;  int start_index, out_index = 0;  /*   printf("get_value 1\n\r"); */  if (in_buf[*msg_index] < 0x80){ /* short definite length */    len = in_buf[*msg_index];/*     printf("short definite length\r\n"); */  } else if (in_buf[*msg_index] > 0x80) { /* long definite length */    lenoflen = (in_buf[*msg_index] & 0x7f); /*length of length */    len = 0;    while (lenoflen--) {      (*msg_index)++;      len = (len << 8) + in_buf[*msg_index];    }    if (len > (in_buf_len - (*msg_index + 1)))      return ASN1_LEN_ERROR;  } else     indef = 1;  (*msg_index)++;/*   printf("get_value 2: len = %d, *msg_index = %d\r\n",len,*msg_index); */  if (indef == 1) {    while(!(in_buf[*msg_index]==0 && in_buf[*msg_index + 1]==0)) {      start_index = *msg_index;      skip_len = skip_tag(in_buf,msg_index,in_buf_len);/*       printf("get_value 3: skip_len=%d,start_index=%d,*msg_index=%d\n\r", *//* 	     skip_len,start_index,*msg_index); */      memcpy(&out_buf[ret],&in_buf[start_index],skip_len);      ret += skip_len;      start_index = *msg_index;      skip_len = skip_length_and_value(in_buf,msg_index,in_buf_len);/*       printf("get_value 4: skip_len=%d,start_index=%d,*msg_index=%d\n\r", *//* 	     skip_len,start_index,*msg_index); */      memcpy(&out_buf[ret],&in_buf[start_index],skip_len);      ret += skip_len;    }    return ret;  }  else    memcpy(&out_buf[ret],&in_buf[*msg_index],len);  return len;}/* * int get_length(unsigned char *in_buf,int *msg_index) * assumes next byte/bytes contain a BER encoded length field, * which is decoded. The value of the length is returned. If it * is an indefinite length the *indef is set to one. */int get_length(unsigned char *in_buf,int *msg_index,	       int *indef,int in_buf_len){  int len=0, lenoflen;    if (in_buf[*msg_index] < 0x80) /* short definite length */    len = in_buf[*msg_index];  else if (in_buf[*msg_index] > 0x80) { /* long definite length */    lenoflen = (in_buf[*msg_index] & 0x7f); /*length of length */    len = 0;    while (lenoflen--) {      (*msg_index)++;      len = (len << 8) + in_buf[*msg_index];    }    if (len > (in_buf_len - (*msg_index + 1)))      return ASN1_LEN_ERROR;  } else     *indef = 1;  (*msg_index)++;  return len;}

⌨️ 快捷键说明

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