色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          "); //-->

          博客專欄

          EEPW首頁 > 博客 > ASN.1 -- 使用asn1c完成ASN encode/decode

          ASN.1 -- 使用asn1c完成ASN encode/decode

          發(fā)布人:電子禪石 時間:2022-03-07 來源:工程師 發(fā)布文章

          asn1c官網(wǎng):http://lionet.info/asn1c/blog/

          asn1c源代碼:https://github.com/vlm/asn1c


          一. 下載asn1c并編譯生成可執(zhí)行文件(關(guān)掉交叉編譯)

          下載asn1c (此版本為主線版本asn1c-0.9.29,非release版本)

          git clone https://github.com/vlm/asn1c.git

          1



          進入下載好的代碼asn1c下,執(zhí)行以下命令編譯源代碼(可參考INSTALL.md)

          test -f configure || autoreconf -iv

          sudo ./configure

          sudo make

          make install

          1

          2

          3

          4

          執(zhí)行完以上命令之后,可以使用man asn1c查看命令


          二. 使用asn1c命令將.asn文件生成.c和.h文件

          準備*.asn文件


          新建目錄,將*.asn文件拷貝至./asn下



          在./下創(chuàng)建out文件夾


          v2x@ubuntu:~/ASN/parser$ tree

          .

          ├── asn

          │   ├── MsgFrame.asn

          │   ├── ***.asn

          └── out

          1

          2

          3

          4

          5

          6

          MsgFrame.asn如下所示:


          MessageFrame ::= CHOICE { 

          bsmFrame BasicSafetyMessage,

          mapFrame MapData,

          rsmFrame RoadsideSafetyMessage,

          spatFrame SPAT,

          rsiFrame RoadSideInformation,

          ...

          }

          1

          2

          3

          4

          5

          6

          7

          8

          在./執(zhí)行以下命令,會在out中生成.c和.h文件

          默認生成帶UPER編解碼的版本

          asn1c asn/*.asn -D out/ -gen-autotools -no-gen-example

          1

          如果想要編譯帶例子的版本(正式代碼中不需要,如果想自己測試可以使用)

          asn1c asn/*.asn -D out/ -gen-autotools

          1

          之后會在./生成configure.ac Makefile.am

          生成configuare文件


          sudo autoreconf --force --install

          sudo autoconf -i

          1

          2

          編譯例子


          mkdir build

          sudo ./configure --prefix=$(pwd)/build

          sudo make install

          1

          2

          3

          會在./build下生成可執(zhí)行文件和鏈接庫


          三.生成libasncodec.so(開啟交叉編譯)

          將out/下的*.c 和 *.h 分別拷貝到自己的代碼中,編譯成libasncodec.so



          四.開啟asn1c生成的代碼中的debug log

          在編譯libasncodec.so時,定義“-DEMIT_ASN_DEBUG=1”,CMakeLists.txt示例如下所示:


          源代碼中ASN_DEBUG的定義如下所示:


          五.encode示例

          //asn1c通過MsgFrame.asn自動生成

          /* MessageFrame */

          typedef struct MessageFrame {

          MessageFrame_PR present;

          union MessageFrame_u {

          BasicSafetyMessage_t bsmFrame;

          MapData_t mapFrame;

          RoadsideSafetyMessage_t rsmFrame;

          SPAT_t spatFrame;

          RoadSideInformation_t rsiFrame;

          PrivateMsg_t pmFrame;

          RTCMcorrections_t rtcmFrame;

          /*

          * This type is extensible,

          * possible extensions are below.

          */

          } choice;

          /* Context for parsing across buffer boundaries */

          asn_struct_ctx_t _asn_ctx;

          } MessageFrame_t;


          1

          2

          3

          4

          5

          6

          7

          8

          9

          10

          11

          12

          13

          14

          15

          16

          17

          18

          19

          20

          21

          #define MAX_PAYLOAD_LEN 1300

          asn_enc_rval_t er;

          MessageFrame* msg_frame_;

          msg_frame_ = (MessageFrame *)calloc(1, sizeof(MessageFrame));

          tran_inner_msg_to_asn(msg, msg_frame_);

          char buf_[MAX_PAYLOAD_LEN];

          //ATS_UNALIGNED_BASIC_PER:使用UPER編碼

          //msg_frame_ :asn1c自動生成的根ASN格式

          //buf_ :序列化之后的數(shù)據(jù)

          er = asn_encode_to_buffer(0, ATS_UNALIGNED_BASIC_PER, &asn_DEF_MessageFrame, msg_frame_, buf_, MAX_PAYLOAD_LEN);

          if (er.encoded > 0 && er.encoded <= MAX_PAYLOAD_LEN)

          {

          //success

              len_ = er.encoded;

          }

          else

          {

          //error

          }


          1

          2

          3

          4

          5

          6

          7

          8

          9

          10

          11

          12

          13

          14

          15

          16

          17

          18

          19

          //使用內(nèi)存拷貝的方式將val拷貝到str

          int codec_asn_t::encode_string(const std::string val, OCTET_STRING_t &str)

          {

              if (val.empty())

              {

                  return E_INVAL;

              }


              str.size = val.size();

              str.buf = (uint8_t *)malloc(str.size);

              if (NULL == str.buf)

              {

                  return E_NOMEM;

              }


              memset(str.buf, 0, str.size);

              memcpy(str.buf, val.data(), str.size);


              return E_OK;

          }


          1

          2

          3

          4

          5

          6

          7

          8

          9

          10

          11

          12

          13

          14

          15

          16

          17

          18

          19

          20

          //此例的缺點:此例中傳入的變量val為int型,意味著在32位的機器中最大只能支持SIZE小于等于32個的bitstring

          int codec_asn_t::encode_bitstring(int val, int bit_num, BIT_STRING_t &str)

          {

              int len = (bit_num % 8 == 0) ? (bit_num / 8) : (bit_num / 8) + 1;

              int tmp_val = 0;

          //從源碼中可以看出size為字節(jié)數(shù)

              str.size = bit_num;

              str.buf = (uint8_t *)malloc(len);

              if (NULL == str.buf)

              {

                  return E_NOMEM;

              }

              //str.buf中應該傳入的格式為:若asn中定義的bitstring的SIZE為16,

              //給asn中定義的(0)賦值為1,就將str.buf賦值為0x80(即10000000B);

              //給asn中定義的(1)也賦值為1,就將str.buf賦值為0xC0(即11000000B);

              //以此類推

              memset(str.buf, 0, len);

              tmp_val = 1;

              for (int i = 0; i < bit_num; i++)

              {

                  if (val & tmp_val)

                  {

                      str.buf[i / 8] |= (0x80 >> (i % 8));

                  }

                  tmp_val *= 2;

              }


              return E_OK;

          }


          1

          2

          3

          4

          5

          6

          7

          8

          9

          10

          11

          12

          13

          14

          15

          16

          17

          18

          19

          20

          21

          22

          23

          24

          25

          26

          27

          28

          29

          六.decode示例

          asn_dec_rval_t rval;

          //ATS_UNALIGNED_BASIC_PER:使用UPER編碼

          //msg_frame:接收decode之后的數(shù)據(jù)

          //buf:接收到的decode之前的數(shù)據(jù)

          rval = asn_decode(0, ATS_UNALIGNED_BASIC_PER, &asn_DEF_MessageFrame, (void **)(&msg_frame), (char *)buf, len);

          if (rval.code == RC_OK)

          {

          //success

              msg = tran_asn_to_inner_msg(msg_frame);

              ASN_STRUCT_FREE(asn_DEF_MessageFrame, msg_frame);

          }

          else

          {

          //error

          }

          1

          2

          3

          4

          5

          6

          7

          8

          9

          10

          11

          12

          13

          14

          15

          int codec_asn_t::decode_bitstring(const BIT_STRING_t &str, int &val)

          {

              if ((str.size <= 0) ||

                  (NULL == str.buf))

              {

                  return E_INVAL;

              }


              int tmp_val = 1;


              val = 0;

              for (int i = 0; i < str.size; i++)

              {

                  if (str.buf[i / 8] & (0x80 >> (i % 8)))

                  {

                      val |= tmp_val;

                  }

                  tmp_val *= 2;

              }

              return E_OK;

          }


          1

          2

          3

          4

          5

          6

          7

          8

          9

          10

          11

          12

          13

          14

          15

          16

          17

          18

          19

          20

          21

          七.BIT_STRING.c源碼分析


          由如下源代碼可知,若使用PER、OER編解碼格式,會使用單獨的編解碼函數(shù);若使用其他編解碼格式,編解碼可復用OCTET_STRING

          asn_TYPE_operation_t asn_OP_BIT_STRING = {

          OCTET_STRING_free,         /* Implemented in terms of OCTET STRING */

          BIT_STRING_print,

          BIT_STRING_compare,

          OCTET_STRING_decode_ber,   /* Implemented in terms of OCTET STRING */

          OCTET_STRING_encode_der,   /* Implemented in terms of OCTET STRING */

          OCTET_STRING_decode_xer_binary,

          BIT_STRING_encode_xer,

          #ifdef ASN_DISABLE_OER_SUPPORT

          0,

          0,

          #else

          BIT_STRING_decode_oer,

          BIT_STRING_encode_oer,

          #endif  /* ASN_DISABLE_OER_SUPPORT */

          #ifdef ASN_DISABLE_PER_SUPPORT

          0,

          0,

          #else

          BIT_STRING_decode_uper, /* Unaligned PER decoder */

          BIT_STRING_encode_uper, /* Unaligned PER encoder */

          #endif  /* ASN_DISABLE_PER_SUPPORT */

          BIT_STRING_random_fill,

          0 /* Use generic outmost tag fetcher */

          };


          1

          2

          3

          4

          5

          6

          7

          8

          9

          10

          11

          12

          13

          14

          15

          16

          17

          18

          19

          20

          21

          22

          23

          24

          25

          BIT_STRING_encode_uper函數(shù)下調(diào)用的BIT_STRING__compactify會將bitstring進一步優(yōu)化,將盡可能壓縮發(fā)送的byte,以及進一步填充bits_unused

          /* Figure out the size without the trailing bits */

              st = BIT_STRING__compactify(st, &compact_bstr);

          ————————————————


          原文鏈接:https://blog.csdn.net/mao834099514/article/details/109102770


          *博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。



          關(guān)鍵詞: asn1c

          技術(shù)專區(qū)

          關(guān)閉