新闻  |   论坛  |   博客  |   在线研讨会
ASN.1 -- 使用asn1c完成ASN encode/decode
电子禅石 | 2022-03-07 09:49:12    阅读:10696   发布文章

asn1c官网:http://lionet.info/asn1c/blog/

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


一. 下载asn1c并编译生成可执行文件(关掉交叉编译)

下载asn1c (此版本为主线版本asn1c-0.9.29,非release版本)

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

1



进入下载好的代码asn1c下,执行以下命令编译源代码(可参考INSTALL.md)

test -f configure || autoreconf -iv

sudo ./configure

sudo make

make install

1

2

3

4

执行完以上命令之后,可以使用man asn1c查看命令


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

准备*.asn文件


新建目录,将*.asn文件拷贝至./asn下



在./下创建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

在./执行以下命令,会在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下生成可执行文件和链接库


三.生成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_ :序列化之后的数据

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

//使用内存拷贝的方式将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为字节数

    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之后的数据

//buf:接收到的decode之前的数据

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编解码格式,会使用单独的编解码函数;若使用其他编解码格式,编解码可复用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函数下调用的BIT_STRING__compactify会将bitstring进一步优化,将尽可能压缩发送的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


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
属于自己的技术积累分享,成为嵌入式系统研发高手。
推荐文章
最近访客