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

📄 asn1_erl_driver.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 4 页
字号:
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ */#include <stdlib.h>#include <stdio.h>#include <string.h>#include "erl_driver.h"#include "ei.h"/* #define ASN1_DEBUG 1 */#define ASN1_OK 0#define ASN1_ERROR -1#define ASN1_COMPL_ERROR 1#define ASN1_MEMORY_ERROR 0#define ASN1_DECODE_ERROR 2#define ASN1_TAG_ERROR -3#define ASN1_LEN_ERROR -4#define ASN1_INDEF_LEN_ERROR -5#define ASN1_VALUE_ERROR -6#define ASN1_CLASS 0xc0#define ASN1_FORM 0x20#define ASN1_CLASSFORM (ASN1_CLASS | ASN1_FORM)#define ASN1_TAG 0x1f#define ASN1_LONG_TAG 0x7f#define ASN1_INDEFINITE_LENGTH 0x80#define ASN1_SHORT_DEFINITE_LENGTH 0#define ASN1_PRIMITIVE 0#define ASN1_CONSTRUCTED 0x20#define ASN1_COMPLETE 1#define ASN1_BER_TLV_DECODE 2#define ASN1_BER_TLV_PARTIAL_DECODE 3#define ASN1_NOVALUE 0#define ASN1_SKIPPED 0#define ASN1_OPTIONAL 1#define ASN1_CHOOSEN 2#define CEIL(X,Y) ((X-1) / Y + 1)#define INVMASK(X,M) (X & (M ^ 0xff))#define MASK(X,M) (X & M)typedef struct {  ErlDrvPort port;} asn1_data;int min_alloc_bytes;static ErlDrvData asn1_drv_start(ErlDrvPort, char *);static void asn1_drv_stop(ErlDrvData);int asn1_drv_control(ErlDrvData, unsigned int, char *, int, char **, int);int complete(ErlDrvBinary **,unsigned char *,unsigned char *, int);int insert_octets(int, unsigned char **, unsigned char **, int *);int insert_octets_except_unused(int, unsigned char **, unsigned char **,				int *, int);int insert_octets_as_bits_exact_len(int, int, unsigned char **,				    unsigned char **, int *);int insert_octets_as_bits(int, unsigned char **, unsigned char **,int *);int pad_bits(int, unsigned char **, int *);int insert_least_sign_bits(int, unsigned char, unsigned char **, int *);int insert_most_sign_bits(int, unsigned char, unsigned char **, int *);int insert_bits_as_bits(int, int, unsigned char **, unsigned char **, int *);int insert_octets_unaligned(int, unsigned char **, unsigned char **, int);int realloc_memory(ErlDrvBinary **,int,unsigned char **,unsigned char **);int decode_begin(ErlDrvBinary **,unsigned char *, int, unsigned int *);int decode(ErlDrvBinary **,int *,unsigned char *,int *, int);int decode_tag(char *,int *,unsigned char *,int,int *);int decode_value(int *,unsigned char *,int *,ErlDrvBinary **,int ,int);/* declaration of functions used for partial decode of a BER encoded   message */int decode_partial(ErlDrvBinary **,unsigned char *, int);int skip_tag(unsigned char *,int *,int);int skip_length_and_value(unsigned char *,int *,int);int get_tag(unsigned char *,int *,int);int get_value(char *,unsigned char *,int *,int);static ErlDrvEntry asn1_drv_entry = {  NULL,              /* init, always NULL for dynamic drivers */  asn1_drv_start,    /* start, called when port is opened */  asn1_drv_stop,     /* stop, called when port is closed */  NULL,              /* output, called when erlang has sent */  NULL,              /* ready_input, called when input descriptor ready */  NULL,              /* ready_output, called when output descriptor ready */  "asn1_erl_drv",    /* char *driver_name, the argument to open_port */  NULL,              /* finish, called when unloaded */  NULL,              /* void * that is not used (BC) */  asn1_drv_control,  /* control, port_control callback */  NULL,              /* timeout, called on timeouts */  NULL               /* outputv, vector output interface */};    DRIVER_INIT(asn1_erl_drv) /* must match name in driver_entry */{  return &asn1_drv_entry;}static ErlDrvData asn1_drv_start(ErlDrvPort port, char *buff){  extern int min_alloc_bytes;  char  *ptr;  asn1_data* d;  d = (asn1_data*)driver_alloc(sizeof(asn1_data));  set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);  d->port = port;    if ((ptr = getenv("ASN1_MIN_BUF_SIZE")) == NULL)    min_alloc_bytes = 1024;  else    min_alloc_bytes = atoi(ptr);  return (ErlDrvData)d;}static void asn1_drv_stop(ErlDrvData handle){  driver_free((char*)handle);}int asn1_drv_control(ErlDrvData   handle, 		     unsigned int command, 		     char        *buf,		     int          buf_len,		     char       **res_buf,		     int          res_buf_len) {  char *complete_buf;  int complete_len, decode_len;  ErlDrvBinary *drv_binary;  ErlDrvBinary **drv_bin_ptr;  asn1_data* a_data;  extern int min_alloc_bytes;  unsigned int err_pos = 0; /* in case of error, return last correct position */  int ret_err; /* return value in case of error in TLV decode, i.e. length of list in res_buf */  /* In case previous call to asn1_drv_control resulted in a change of     return value from binary to integer list */  a_data = (asn1_data *)handle;  set_port_control_flags(a_data->port, PORT_CONTROL_FLAG_BINARY);  if (command == ASN1_COMPLETE)    { /* Do the PER complete encode step */      if ((drv_binary = driver_alloc_binary(buf_len))==NULL) {	/* error handling */	set_port_control_flags(a_data->port, 0);	return ASN1_MEMORY_ERROR;      }      complete_buf = drv_binary->orig_bytes;      if ((complete_len = complete(&drv_binary,complete_buf,buf,buf_len)) == ASN1_ERROR)	{	  /* error handling due to failure in complete */	  /*       printf("error when running complete\n\r"); */	  driver_free_binary(drv_binary);	  set_port_control_flags(a_data->port, 0);	  **res_buf = '1';	  return ASN1_COMPL_ERROR;	}      /* printf("complete_len=%dbuf_len=%d,orig_size=%d\n\r",complete_len,buf_len,drv_binary->orig_size); */      /* now the message is complete packed, return to Erlang */      /*      if (complete_len < buf_len) {*/      if (complete_len < drv_binary->orig_size) {		ErlDrvBinary *tmp;	if ((tmp=driver_realloc_binary(drv_binary,complete_len)) == NULL){	  /*error handling due to memory allocation failure */	  driver_free_binary(drv_binary);	  set_port_control_flags(a_data->port, 0);	  return ASN1_MEMORY_ERROR;	}else	  drv_binary=tmp;      }      *res_buf = (char *)drv_binary;      return complete_len;    } else if (command == ASN1_BER_TLV_DECODE) { /* control == 2 */      /* Do the tlv decode,	 return the resulting term encoded on the Erlang 	 external format *//*       printf("driver: buffer_len = %d, min_alloc_bytes = %d\r\n",buf_len,min_alloc_bytes); */      if ((drv_binary = driver_alloc_binary((buf_len*5)+min_alloc_bytes))==NULL) {	/* error handling */	set_port_control_flags(a_data->port, 0);	return ASN1_MEMORY_ERROR;      }      drv_bin_ptr = &drv_binary;      if ((decode_len = decode_begin(drv_bin_ptr,buf,buf_len,&err_pos)) <= ASN1_ERROR)	{	  /* error handling due to failure in decode  */ 	  char tmp_res_buf[5];	  driver_free_binary(*drv_bin_ptr);	  set_port_control_flags(a_data->port, 0);	  	  if(decode_len==ASN1_ERROR) 	    tmp_res_buf[0]='1';	  else if(decode_len==ASN1_TAG_ERROR) 	    tmp_res_buf[0]='2';	  else if(decode_len==ASN1_LEN_ERROR) 	    tmp_res_buf[0]='3';	  else if(decode_len==ASN1_INDEF_LEN_ERROR) 	    tmp_res_buf[0]='4';	  else if(decode_len==ASN1_VALUE_ERROR)	    tmp_res_buf[0]='5';/* 	  printf("err_pos=%d\r\n",err_pos); *//* 	  printf("decode_len:%d\r\n",decode_len); */	  ret_err = 1;	  while(err_pos>0){	    tmp_res_buf[ret_err] =(char)err_pos;/* c;*/	    err_pos = err_pos >> 8;	    ret_err++;	  } 	  strncpy(*res_buf,tmp_res_buf,ret_err);	  return ret_err;	}/*       printf("decode_len=%d\r\n",decode_len); */      if (decode_len < ((buf_len * 5) + min_alloc_bytes)) {	/* not all memory was used => we have to reallocate */	ErlDrvBinary *tmp;	if ((tmp=driver_realloc_binary(*drv_bin_ptr,decode_len)) == NULL){	  /*error handling due to memory allocation failure */	  driver_free_binary(*drv_bin_ptr);	  set_port_control_flags(a_data->port, 0);	  return ASN1_MEMORY_ERROR;	}else	  *drv_bin_ptr=tmp;      }      *res_buf = (char *)(*drv_bin_ptr);      return decode_len;    } else { /*command == ASN1_BER_TLV_PARTIAL_DECODE */      if ((drv_binary = driver_alloc_binary(buf_len))==NULL) {	/* error handling */	set_port_control_flags(a_data->port, 0);	return ASN1_MEMORY_ERROR;      }      drv_bin_ptr = &drv_binary;      if ((decode_len = decode_partial(drv_bin_ptr,buf,buf_len))	  <= ASN1_ERROR) {	/* error handling due to failure in decode  */	driver_free_binary(*drv_bin_ptr);	set_port_control_flags(a_data->port, 0);	/* 	printf("asn1_drv_control 1: decode_len=%d\r\n",decode_len); */	  	if(decode_len==ASN1_ERROR)	  **res_buf = '1';	return ASN1_DECODE_ERROR;      }      if (decode_len < buf_len) { 	/* not all memory was used => we have to reallocate */	ErlDrvBinary *tmp;/* 	printf("asn1_drv_control 2: decode_len=%d\r\n",decode_len); */	if ((tmp=driver_realloc_binary(*drv_bin_ptr,decode_len)) == NULL){	  /*error handling due to memory allocation failure */	  driver_free_binary(*drv_bin_ptr);	  set_port_control_flags(a_data->port, 0);	  return ASN1_MEMORY_ERROR;	}else	  *drv_bin_ptr=tmp;      }      *res_buf = (char *)(*drv_bin_ptr);      return decode_len;    }}/* *  * This section defines functionality for the complete encode of a * PER encoded message * */int complete(ErlDrvBinary **drv_binary,unsigned char *complete_buf,	     unsigned char *in_buf, int in_buf_len){  int counter = in_buf_len;  /* counter keeps track of number of bytes left in the     input buffer */  int buf_space = in_buf_len;  /* This is the amount of allocated space left of the complete_buf. It     is possible when padding is applied that more space is needed than     was originally allocated. */  int buf_size = in_buf_len;  /* Size of the buffer. May become reallocated and thus other than      in_buf_len */  unsigned char *in_ptr, *ptr;  /* in_ptr points at the next byte in in_buf to be moved to     complete_buf.     ptr points into the new completed buffer, complete_buf, at the     position of the next byte that will be set */  int unused =  8;  /* unused = [1,...,8] indicates how many of the rigthmost bits of      the byte that ptr points at that are unassigned */  int no_bits,no_bytes,in_unused,desired_len,ret, saved_mem, needed, pad_bits;  unsigned char val;    in_ptr = in_buf;  ptr = complete_buf;  *ptr = 0x00;  while(counter > 0) {    counter--;/*     printf("*in_ptr = %d\n\r",*in_ptr); */    switch (*in_ptr) {    case 0:       /* just one zero-bit should be added to the buffer */      if(unused == 1){	unused = 8;	*++ptr = 0x00;	buf_space--;      } else 	unused--;      break;    case 1:      /* one one-bit should be added to the buffer */      if(unused == 1){	*ptr = *ptr | 1;	unused = 8;	*++ptr = 0x00;	buf_space--;      } else {	*ptr = *ptr | (1 << (unused - 1));	unused--;      }      break;    case 2:      /* align buffer to end of byte */      if (unused != 8) {	*++ptr = 0x00;	buf_space--;	unused = 8;      }      break;    case 10:      /* next byte in in_buf tells how many bits in the second next	 byte that will be used */      /* The leftmost unused bits in the value byte are supposed to be	 zero bits */      no_bits =  (int)*(++in_ptr);      val = *(++in_ptr);      counter -= 2;      if ((ret=insert_least_sign_bits(no_bits,val,&ptr,&unused)) == ASN1_ERROR)	return ASN1_ERROR;      buf_space -= ret;      break;    case 20:      /* in this case the next value in_ptr points at holds the number	 of following bytes that holds the value that will be inserted	 in the completed buffer */      no_bytes = (int)*(++in_ptr);      counter -= (no_bytes + 1);      if ((counter<0) || 	  (ret=insert_octets(no_bytes,&in_ptr,&ptr,&unused)) == ASN1_ERROR)	return ASN1_ERROR;      buf_space -= ret;      break;

⌨️ 快捷键说明

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