编解码库使用
- 编解码库libhiasn1.so,位于“/usr/local/ksl/lib”下。用户可以在编译源码时链接此库,提供用于将用户数据编码成码流,或将码流解码成用户数据的接口。
- 编解码接口定义头文件,位于“/usr/local/ksl/include/hiasn1/”下,KSL_ASN1相关数据结构和接口定义位于此目录下。
本章节将演示如何使用编译工具使用中解析asn1文件生成的C代码文件,通过调用KSL_ASN1的编解码库接口,实现将已有数据编码成流,及如何将流解码为数据的方法。
- 在“test_demo”目录下新建一个codec_test.c文件。
1
vim codec_test.c
- 按“i”进入编辑模式,填写编解码样例代码。
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
#include <stdio.h> #include <stdbool.h> #include <string.h> #include <assert.h> #include "asn_codec.h" #include "exports/test/codec_index.h" #include "exports/test/codec_interfaces.h" // 缓冲区大小 #define BUF_SIZE 64 // 缓冲区 uint8_t g_buffer[BUF_SIZE]; // 编码测试 bool EncodeTest(const AsnDesc *desc, AsnCtx *ctx) { // 准备待编码数据 OctStrType octStrArr[3] = { { .len = 2, .item = "\x12\x23" }, { .len = 2, .item = "\x45\x56" }, { .len = 2, .item = "\x78\x89" }, }; uint32_t oid[3] = {0, 1, 2}; MyType userData = { .boolType = false, .intType = 10, .enumType = MY_TYPE_ENUM_TYPE_A, .bitStrType = { .item = "\x01\x02\x03" }, .seqOfType = { .cnt = 3, .item = octStrArr }, .choiceType = { .choice = MY_TYPE_CHOICE_TYPE_B, .u = { .b = true, } }, .oidType = { .cnt = 3, .item = oid }, }; // 编码 ssize_t ret = AsnEncode(desc, &userData, ctx); if (ret < 0) { printf("failed to encode, ret: %zd\n", -ret); return false; } size_t encodedBytes = (size_t)(ret + 7) >> 3; printf("successfully encoded into %zu bytes data\n", encodedBytes); // 打印编码结果 printf("encoded: "); for (size_t i = 0; i < encodedBytes; ++i) { printf("%02X ", g_buffer[i]); } printf("\n"); // 比较编码结果 uint8_t expected[] = "\x05\x00\x01\x02\x03\x03\x80\x12\x23\x80\x45\x56\x80\x78\x89\xC0\x02\x01\x02"; size_t expectedBytes = sizeof(expected) - 1; if (encodedBytes != expectedBytes || memcmp(g_buffer, expected, expectedBytes) != 0) { printf("expected: "); for (size_t j = 0; j < expectedBytes; ++j) { printf("%02X ", expected[j]); } printf("\n"); printf("encoded bytes unexpected\n"); return false; } return true; } // 解码测试 void DecodeTest(const AsnDesc *desc, AsnCtx *ctx) { // 解码 MyType decoded = {0}; ssize_t ret = AsnDecode(desc, &decoded, ctx); if (ret < 0) { printf("failed to decode, ret: %zd\n", -ret); return; } printf("successfully decoded\n"); // 校验解码结果 assert(decoded.boolType == false); assert(decoded.intType == 10); assert(decoded.enumType == MY_TYPE_ENUM_TYPE_A); assert(decoded.bitStrType.item[0] == 0x01); assert(decoded.bitStrType.item[1] == 0x02); assert(decoded.bitStrType.item[2] == 0x03); assert(decoded.seqOfType.cnt == 3); assert(decoded.seqOfType.item[0].len == 2); assert(decoded.seqOfType.item[0].item[0] == 0x12); assert(decoded.seqOfType.item[0].item[1] == 0x23); assert(decoded.seqOfType.item[1].len == 2); assert(decoded.seqOfType.item[1].item[0] == 0x45); assert(decoded.seqOfType.item[1].item[1] == 0x56); assert(decoded.seqOfType.item[2].len == 2); assert(decoded.seqOfType.item[2].item[0] == 0x78); assert(decoded.seqOfType.item[2].item[1] == 0x89); assert(decoded.choiceType.choice == MY_TYPE_CHOICE_TYPE_B); assert(decoded.choiceType.u.b == true); assert(decoded.oidType.cnt == 3); assert(decoded.oidType.item[0] == 0); assert(decoded.oidType.item[1] == 1); assert(decoded.oidType.item[2] == 2); } int main() { // 获取结构对应的描述符 const AsnDesc *desc = CODEC_GET_TEST_DESC(CODEC_IDX_TEST_MY_TYPE); // 获取上下文结构体 AsnCtx *ctx = CODEC_GET_TEST_CTX(); AsnBuf buf; // 缓冲区结构体 buf.buf = g_buffer; // 设置缓冲区 buf.bufLen = BUF_SIZE; // 设置缓冲区大小 // 初始化,传入上下文结构体、缓冲区结构体指针 if (!AsnInit(ctx, &buf)) { printf("failed to init\n"); return 1; } // 编码测试 if (!EncodeTest(desc, ctx)) { return 1; } // 解码测试 DecodeTest(desc, ctx); // 释放所有内部申请内存 AsnFree(ctx); return 0; }
- AsnBuf结构体的缓冲区和缓冲区大小的合法性由用户保证。
- AsnCtx结构体需先清零,再对buf和method字段赋值。
- 使用统一的编解码接口AsnEncode、AsnDecode,接口内部通过ctx.method判断编码模式。
- 编解码接口返回值是ssize_t类型的:
- 当返回值大于等于0时,表示编码成功,返回已编码字节数或比特数。
- 当返回值小于0时,表示编码失败,错误码为返回值的绝对值,可在asn_codec_errors.h中找到对应的错误信息。
- 按“Esc”键,输入:wq,按“Enter”保存并退出编辑。
- 编译运行。
1 2
gcc codec_test.c exports/test/*.c -I/usr/local/ksl/include/hiasn1/ -L/usr/local/ksl/lib/ -Wl,-rpath=/usr/local/ksl/lib/ -lhiasn1 -o codec_test ./codec_test
父主题: 使用说明