📄 asn1_erl_driver.c
字号:
ret = CEIL(desired_no,8);/* printf("ret = %d\n\r",ret); */ }/* printf("*unused = %d\n\r",*unused); */ *input_ptr = in_ptr; return ret;}/* insert_octets_as_bits_exact_len */intinsert_octets_as_bits_exact_len(int desired_len, int in_buff_len, unsigned char **in_ptr, unsigned char **ptr, int *unused){ int ret = 0; int ret2 = 0; if (desired_len == in_buff_len) { if ((ret = insert_octets_as_bits(in_buff_len,in_ptr,ptr,unused)) == ASN1_ERROR) return ASN1_ERROR; } else if(desired_len > in_buff_len) { if((ret = insert_octets_as_bits(in_buff_len,in_ptr,ptr,unused)) == ASN1_ERROR) return ASN1_ERROR; /* now pad with zero bits *//* printf("~npad_bits: called with %d bits padding~n~n~r",desired_len - in_buff_len); */ if ((ret2=pad_bits(desired_len - in_buff_len,ptr,unused)) == ASN1_ERROR) return ASN1_ERROR; } else {/* desired_len < no_bits */ if ((ret=insert_octets_as_bits(desired_len,in_ptr,ptr,unused)) == ASN1_ERROR) return ASN1_ERROR; /* now remove no_bits - desired_len bytes from in buffer */ *in_ptr += (in_buff_len - desired_len); } return (ret+ret2);}/* insert_octets_as_bits takes no_bytes bytes from the buffer that input_ptr points at and inserts the least significant bit of it in the buffer that output_ptr points at. Each byte in the input buffer must be 1 or 0 otherwise the function returns ASN1_ERROR. The output buffer is concatenated without alignment. */int insert_octets_as_bits(int no_bytes, unsigned char **input_ptr, unsigned char **output_ptr, int *unused){ unsigned char *in_ptr = *input_ptr; unsigned char *ptr = *output_ptr; int used_bits = 8 - *unused; while (no_bytes > 0) { switch (*++in_ptr) { case 0: if(*unused == 1){ *unused = 8; *++ptr = 0x00; } else (*unused)--; break; case 1: if(*unused == 1){ *ptr = *ptr | 1; *unused = 8; *++ptr = 0x00; } else { *ptr = *ptr | (1 << (*unused - 1)); (*unused)--; } break; default: return ASN1_ERROR; } no_bytes--; } *input_ptr = in_ptr; *output_ptr = ptr; return ((used_bits+no_bytes) / 8); /*return number of new bytes in completed buffer */}/* insert_octets inserts bytes from the input buffer, *input_ptr, into the output buffer, *output_ptr. Before the first byte is inserted the input buffer is aligned. */int insert_octets(int no_bytes, unsigned char **input_ptr, unsigned char **output_ptr, int *unused){ unsigned char *in_ptr = *input_ptr; unsigned char *ptr = *output_ptr; int ret = 0; if (*unused != 8) {/* must align before octets are added */ *++ptr = 0x00; ret++; *unused = 8; } while(no_bytes > 0) { *ptr = *(++in_ptr); *++ptr = 0x00; /* *unused = *unused - 1; */ no_bytes--; } *input_ptr = in_ptr; *output_ptr = ptr; return (ret + no_bytes);}/* insert_octets_unaligned inserts bytes from the input buffer, *input_ptr, into the output buffer, *output_ptr.No alignment is done. */int insert_octets_unaligned(int no_bytes, unsigned char **input_ptr, unsigned char **output_ptr, int unused){ unsigned char *in_ptr = *input_ptr; unsigned char *ptr = *output_ptr; int n = no_bytes; unsigned char val; while (n > 0) { if (unused == 8) { *ptr = *++in_ptr; *++ptr = 0x00; }else { val = *++in_ptr; *ptr = *ptr | val >> (8 - unused); *++ptr = 0x00; *ptr = val << unused; } n--; } *input_ptr = in_ptr; *output_ptr = ptr; return no_bytes;}int insert_octets_except_unused(int no_bytes, unsigned char **input_ptr, unsigned char **output_ptr, int *unused, int in_unused){ unsigned char *in_ptr = *input_ptr; unsigned char *ptr = *output_ptr; int val, no_bits; int ret = 0; if (in_unused == 0){/* printf("%d: insert_octets_except_unused: if\n\r",__LINE__); */ if ((ret = insert_octets_unaligned(no_bytes,&in_ptr,&ptr, *unused)) == ASN1_ERROR) return ASN1_ERROR; } else {/* printf("%d: insert_octets_except_unused: else\n\r",__LINE__); */ if ((ret=insert_octets_unaligned(no_bytes - 1,&in_ptr,&ptr,*unused)) != ASN1_ERROR) { val = (int) *(++in_ptr); no_bits = 8 - in_unused; /* no_bits is always less than *unused since the buffer is octet aligned after insert:octets call, so the following if clasuse is obsolete I think */ if(no_bits < *unused){ *ptr = *ptr | (val >> (8 - *unused)); *unused = *unused - no_bits; } else if (no_bits == *unused) { *ptr = *ptr | (val >> (8 - *unused)); *++ptr = 0x00; ret++; *unused = 8; } else { *ptr = *ptr | (val >> (8 - *unused)); *++ptr = 0x00; ret++; *ptr = *ptr | (val << *unused); *unused = 8 - (no_bits - *unused); } } else return ASN1_ERROR; } *input_ptr = in_ptr; *output_ptr = ptr;/* printf("%d: insert_octets_except_unused: ret=%d\n\r",__LINE__,ret); */ return ret;}/* * * This section defines functionality for the partial decode of a * BER encoded message * *//* * int decode(ErlDrvBinary **drv_binary,unsigned char *decode_buf, * unsigned char *in_buf, int in_buf_len) * drv_binary is a pointer to a pointer to an allocated driver binary. * in_buf is a pointer into the buffer of incoming bytes. * in_buf_len is the length of the incoming buffer. * The function reads the bytes in the incoming buffer and structures * it in a nested way as Erlang terms. The buffer contains data in the * order tag - length - value. Tag, length and value has the following * format: * A tag is normally one byte but may be of any length, if the tag number * is greater than 30. +----------+ * |CL|C|NNNNN| * +----------+ * If NNNNN is 31 then will the 7 l.s.b of each of the following tag number * bytes contain the tag number. Each tag number byte that is not the last one * has the m.s.b. set to 1. * The length can be short definite length (sdl), long definite length (ldl) * or indefinite length (il). * sdl: +---------+ the L bits is the length * |0|LLLLLLL| * +---------+ * ldl: +---------+ +---------+ +---------+ +-----------+ * |1|lllllll| |first len| | | |the Nth len| * +---------+ +---------+ +---------+ ... +-----------+ * The first byte tells how many len octets will follow, max 127 * il: +---------+ +----------------------+ +--------+ +--------+ * |1|0000000| |content octets (Value)| |00000000| |00000000| * +---------+ +----------------------+ +--------+ +--------+ * The value octets are preceded by one octet and followed by two * exactly as above. The value must be some tag-length-value encoding. * * The function returns a value in Erlnag term format: * {{TagNo,Value},Rest} * TagNo is an integer ((CL bsl 16) + tag number) which limits the tag number * to 65535. * Value is a binary if the C bit in tag was unset, otherwise (if tag was * constructed) Value is a list, List. * List is like: [{TagNo,Value},{TagNo,Value},...] * Rest is a binary, i.e. the undecoded part of the buffer. Most often Rest * is the empty binary. * If some error occured during the decoding of the in_buf an error is returned. */int decode_begin(ErlDrvBinary **drv_binary,unsigned char *in_buf, int in_buf_len, unsigned int *err_pos){ int maybe_ret; char *decode_buf = (*drv_binary)->orig_bytes; int ei_index = 0; int ib_index = 0; /* ei_index is the index used by the ei functions to encode an Erlang term into the buffer decode_buf */ /* ib_index is the index were to read the next byte from in_buf */#ifdef ASN1_DEBUG printf("decode_begin1: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);#endif /* the first byte must be a "version magic" */ if(ei_encode_version(decode_buf,&ei_index) == ASN1_ERROR) return ASN1_ERROR; /* 1 byte */#ifdef ASN1_DEBUG printf("decode_begin2: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);#endif if (ei_encode_tuple_header(decode_buf,&ei_index,2) == ASN1_ERROR) return ASN1_ERROR; /* 2 bytes */#ifdef ASN1_DEBUG printf("decode_begin3: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);#endif if((maybe_ret=decode(drv_binary,&ei_index,in_buf,&ib_index,in_buf_len)) <= ASN1_ERROR) { *err_pos = ib_index;#ifdef ASN1_DEBUG printf("err_pos=%d,ib_index=%d\r\n",*err_pos,ib_index);#endif return maybe_ret; }; decode_buf = (*drv_binary)->orig_bytes; /* maybe a realloc during decode_value */#ifdef ASN1_DEBUG printf("decode_begin4: in_buf_len=%d, ei_index=%d, ib_index=%d\n\r", in_buf_len,ei_index,ib_index);#endif /* "{{TagNo,Value},Rest}" */ if (ei_encode_binary(decode_buf,&ei_index,&(in_buf[ib_index]),in_buf_len-ib_index) == ASN1_ERROR) /* at least 5 bytes */ return ASN1_ERROR;#ifdef ASN1_DEBUG printf("decode_begin5: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);#endif return ei_index;}int decode(ErlDrvBinary **drv_binary,int *ei_index,unsigned char *in_buf, int *ib_index, int in_buf_len){ int maybe_ret; char *decode_buf = (*drv_binary)->orig_bytes; int form;#ifdef ASN1_DEBUG printf("decode 1\n\r");#endif if (((*drv_binary)->orig_size - *ei_index) < 19) {/* minimum amount of bytes */ /* allocate more memory */ if (realloc_decode_buf(drv_binary,(*drv_binary)->orig_size * 2) == ASN1_ERROR) return ASN1_ERROR; decode_buf = (*drv_binary)->orig_bytes; }/* printf("decode 2\n\r"); */ /* "{" */ if (ei_encode_tuple_header(decode_buf,ei_index,2) == ASN1_ERROR) return ASN1_ERROR; /* 2 bytes */#ifdef ASN1_DEBUG printf("decode 3:orig_size=%d, ei_index=%d, ib_index=%d\n\r",(*drv_binary)->orig_size,*ei_index,*ib_index);#endif /*buffer must hold at least two bytes*/ if ((*ib_index +2) > in_buf_len) return ASN1_VALUE_ERROR; /* "{{TagNo," */ if ((form = decode_tag(decode_buf,ei_index,in_buf,in_buf_len,ib_index)) <= ASN1_ERROR) return form; /* 5 bytes */#ifdef ASN1_DEBUG printf("i_i=%d,in_buf_len=%d\r\n",*ei_index,in_buf_len);#endif if (*ib_index >= in_buf_len){ return ASN1_TAG_ERROR; }#ifdef ASN1_DEBUG printf("decode 5 ib_index=%d\n\r",*ib_index);#endif /* buffer must hold at least one byte (0 as length and nothing as value) */ /* "{{TagNo,Value}," */ if ((maybe_ret=decode_value(ei_index,in_buf,ib_index,drv_binary,form, in_buf_len)) <= ASN1_ERROR) return maybe_ret; /* at least 5 bytes */#ifdef ASN1_DEBUG printf("decode 7\n\r");#endif return *ei_index;}/* * decode_tag decodes the BER encoded tag in in_buf and puts it in the * decode_buf encoded by the Erlang extern format as an Erlang term. */int decode_tag(char *decode_buf,int *db_index,unsigned char *in_buf, int in_buf_len, int *ib_index){ int tag_no, tmp_tag, form; /* first get the class of tag and bit shift left 16*/ tag_no = ((MASK(in_buf[*ib_index],ASN1_CLASS)) << 10); form = (MASK(in_buf[*ib_index],ASN1_FORM));#ifdef ASN1_DEBUG printf("decode_tag0:ii=%d, tag_no=%d, form=%d.\r\n", *ib_index,tag_no,form);#endif /* then get the tag number */ if((tmp_tag = (int) INVMASK(in_buf[*ib_index],ASN1_CLASSFORM)) < 31) { ei_encode_ulong(decode_buf,db_index,tag_no+tmp_tag); /* usual case */ (*ib_index)++;#ifdef ASN1_DEBUG printf("decode_tag1:ii=%d.\r\n",*ib_index);#endif } else { int n = 0; /* n is used to check that the 64K limit is not exceeded*/#ifdef ASN1_DEBUG printf("decode_tag1:ii=%d, in_buf_len=%d.\r\n",*ib_index,in_buf_len);#endif /* should check that at least three bytes are left in in-buffer,at least two tag byte and at least one length byte */ if ((*ib_index +3) > in_buf_len) return ASN1_VALUE_ERROR; (*ib_index)++;#ifdef ASN1_DEBUG printf("decode_tag2:ii=%d.\r\n",*ib_index);#endif /* The tag is in the following bytes in in_buf as 1ttttttt 1ttttttt ... 0ttttttt, where the t-bits is the tag number*/ /* In practice is the tag size limited to 64K, i.e. 16 bits. If the tag is greater then 64K return an error */ while (((tmp_tag = (int)in_buf[*ib_index]) >= 128) && n < 2){ /* m.s.b. = 1 */ tag_no = tag_no + (MASK(tmp_tag,ASN1_LONG_TAG) << 7); (*ib_index)++;#ifdef ASN1_DEBUG printf("decode_tag3:ii=%d.\r\n",*ib_index);#endif n++; }; if ((n==2) && in_buf[*ib_index] > 3) return ASN1_TAG_ERROR; /* tag number > 64K */ tag_no = tag_no + in_buf[*ib_index]; (*ib_index)++;#ifdef ASN1_DEBUG printf("decode_tag4:ii=%d.\r\n",*ib_index);#endif ei_encode_ulong(decode_buf,db_index,tag_no);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -