ASN.1编解码:asn1c-ORAN-E2AP编解码示例
Posted rtoax
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ASN.1编解码:asn1c-ORAN-E2AP编解码示例相关的知识,希望对你有一定的参考价值。
整体代码:https://gitee.com/rtoax/test/tree/master/ASN.1/asn1c/jt_sran/e2ap
1. 生成的可执行文件
前面文档中已经给出了该测试文件的帮助信息,这里再给出一遍
[rongtao@localhost e2ap]$ ./test -h
Usage: ./test [options] <datafile> ...
Where options are:
-iber Input is in BER (Basic Encoding Rules) or DER
-ioer Input is in OER (Octet Encoding Rules)
-iper Input is in Unaligned PER (Packed Encoding Rules) (DEFAULT)
-iaper Input is in Aligned PER (Packed Encoding Rules)
-ixer Input is in XER (XML Encoding Rules)
-oder Output as DER (Distinguished Encoding Rules)
-ooer Output as Canonical OER (Octet Encoding Rules)
-oper Output as Unaligned PER (Packed Encoding Rules)
-oaper Output as Aligned PER (Packed Encoding Rules)
-oxer Output as XER (XML Encoding Rules) (DEFAULT)
-otext Output as plain semi-structured text
-onull Verify (decode) input, but do not output
-per-nopad Assume PER PDUs are not padded (-iper)
-1 Decode only the first PDU in file
-b <size> Set the i/o buffer size (default is 8192)
-c Check ASN.1 constraints after decoding
-d Enable debugging (-dd is even better)
-n <num> Process files <num> times
-s <size> Set the stack usage limit (default is 30000)
这个可执行文件是比较复杂的,具体怎么使用,后续文档中再做解释,本文先到这。
2. 编译测试例
需要注意一下几点:
- 使用
e2ap-v01.00.00.asn
在CMakeLists.txt中添加宏
-DPDU=RICcontrolRequest
RICcontrolRequest
在e2ap-v01.00.00.asn
中的定义如下,为了更加清晰,这里我使用截图显示:
首先有个枚举值
下面的不知道啥意思
接着是RICcontrolRequest
结构体
当我们采用asn1c对上述的asn编码进行编译后,就可以得到C语言代码。下面一一列举:
数据结构被编译为:
ProtocolIE_Container_1544P7_t
是什么,继续找。在文件ProtocolIE-Container.h
中有:
再看RICcontrolRequest_IEs
结构,在文件ProtocolIE-Field.h
中有:
上面这些数据结构,我们不需要做出修改,我理解,也不用对他理解的太透彻,我们只需要知道如何修改标志性字段即可。
3. 编写编解码C语言代码
为了测试我自己对ASN.1编解码,我选取上一章节中使用的数据结构RICcontrolRequest
。先直接给出测试例总的API
/**
* RICcontrolRequest 测试例代码
*
* 作者 荣涛
* 创建 2021年8月29日
*
*/
#define TEST_RICcontrolRequest
int test_RICcontrolRequest()
{
#ifdef TEST_RICcontrolRequest
FUNC_CALL();
gen_RICcontrolRequest();
load_RICcontrolRequest();
#endif
return 0;
}
使用宏TEST_RICcontrolRequest
控制,接口gen_RICcontrolRequest
会生成ASN.1编码文件,load_RICcontrolRequest
会再次解析使用gen_RICcontrolRequest
生成的文件,验证准确性。
这里,我梳理了我使用的asn1c库函数API,如下图:
起始,也不用做过多的解释,直接上代码吧,解析过程比较简单:
/**
* 测试 RICcontrolRequest_t
*
*
* 作者:荣涛
* 创建时间:2021年8月30日
*
* 修改日志
* 2021年8月30日 创建 xer 编解码
* 2021年8月31日 尝试添加 ber 编解码,
* 2021年9月1日 aper 编解码 完成
* 2021年9月2日 ber、der编解码
*/
#include <stdio.h> /* for stdout */
#include <errno.h> /* for errno */
#include <stdlib.h> /* for malloc() */
#include <assert.h> /* for run-time control */
#include "../RICcontrolRequest.h" /* Include MyTypes definition */
#include "../ProtocolIE-Field.h"
#include "my-test/my_test.h"
#define XER_RICcontrolRequest "RICcontrolRequest.xer"
#define APER_RICcontrolRequest "RICcontrolRequest.aper"
#define OER_RICcontrolRequest "RICcontrolRequest.oer"
#define DER_RICcontrolRequest "RICcontrolRequest.ber"
#define NEW_XER_RICcontrolRequest "RICcontrolRequest-New.xer"
#define NEW_APER_RICcontrolRequest "RICcontrolRequest-New.aper"
#define NEW_OER_RICcontrolRequest "RICcontrolRequest-New.oer"
#define NEW_DER_RICcontrolRequest "RICcontrolRequest-New.ber"
static RICcontrolRequest_IEs_t *alloc_RICcontrolRequest_IEs(ProtocolIE_ID_t id,
RICcontrolRequest_IEs__value_PR choice, void *value)
{
RICcontrolRequest_IEs_t *v = calloc(1, sizeof(RICcontrolRequest_IEs_t));
assert(v && "NULL pointer");
/**
* 我不懂协议,这块不知道应该怎么填写(荣涛 2021年8月31日)
*/
v->id = id;
// v->criticality = id;
v->value.present = choice;
switch(choice) {
default:
case RICcontrolRequest_IEs__value_PR_NOTHING:
{
printf("Nothing to do.\\n");
break;
}
case RICcontrolRequest_IEs__value_PR_RICrequestID:
{
RICrequestID_t *RICrequestID = (RICrequestID_t*)value;
v->value.choice.RICrequestID.ricInstanceID = RICrequestID->ricInstanceID;
v->value.choice.RICrequestID.ricRequestorID = RICrequestID->ricRequestorID;
break;
}
case RICcontrolRequest_IEs__value_PR_RANfunctionID:
{
RANfunctionID_t *RANfunctionID = (RANfunctionID_t*)value;
v->value.choice.RANfunctionID = *RANfunctionID;
break;
}
case RICcontrolRequest_IEs__value_PR_RICcallProcessID:
{
RICcallProcessID_t *RICcallProcessID = (RICcallProcessID_t*)value;
OCTET_STRING_fromBuf(&v->value.choice.RICcallProcessID, (char*)RICcallProcessID->buf, RICcallProcessID->size);
break;
}
case RICcontrolRequest_IEs__value_PR_RICcontrolHeader:
{
RICcontrolHeader_t *RICcontrolHeader = (RICcontrolHeader_t*)value;
OCTET_STRING_fromBuf(&v->value.choice.RICcontrolHeader, (char*)RICcontrolHeader->buf, RICcontrolHeader->size);
break;
}
case RICcontrolRequest_IEs__value_PR_RICcontrolMessage:
{
RICcontrolMessage_t *RICcontrolMessage = (RICcontrolMessage_t*)value;
OCTET_STRING_fromBuf(&v->value.choice.RICcontrolMessage, (char*)RICcontrolMessage->buf, RICcontrolMessage->size);
break;
}
case RICcontrolRequest_IEs__value_PR_RICcontrolAckRequest:
{
RICcontrolAckRequest_t *RICcontrolAckRequest = (RICcontrolAckRequest_t*)value;
v->value.choice.RICcontrolAckRequest = *RICcontrolAckRequest;
break;
}
}
return v;
}
static void fprintf_RICcontrolRequest(FILE* fp, RICcontrolRequest_t *RICcontrolRequest)
{
xer_fprint(fp, &asn_DEF_RICcontrolRequest, RICcontrolRequest);
fprintf(fp, "\\n");
}
static void printf_RICcontrolRequest(RICcontrolRequest_t *RICcontrolRequest)
{
fprintf_RICcontrolRequest(stdout, RICcontrolRequest);
}
static void save_RICcontrolRequest_xer(const char *filename, RICcontrolRequest_t *RICcontrolRequest)
{
FILE *fp = fopen(filename, "w");
fprintf_RICcontrolRequest(fp, RICcontrolRequest);
fclose(fp);
}
static size_t encode_RICcontrolRequest_aper(RICcontrolRequest_t* pdu, void* buffer, size_t buf_size)
{
asn_enc_rval_t encode_result;
encode_result = aper_encode_to_buffer(&asn_DEF_RICcontrolRequest , NULL, pdu, buffer, buf_size);
// ASN_STRUCT_FREE(asn_DEF_RICcontrolRequest , pdu);
if(encode_result.encoded == -1) {
fprintf(stderr, "Cannot encode %s: %s\\n", encode_result.failed_type->name, strerror(errno));
return -1;
} else {
return encode_result.encoded;
}
}
static size_t encode_RICcontrolRequest_oer(RICcontrolRequest_t* pdu, void* buffer, size_t buf_size)
{
asn_enc_rval_t encode_result;
encode_result = oer_encode_to_buffer(&asn_DEF_RICcontrolRequest , NULL, pdu, buffer, buf_size);
// ASN_STRUCT_FREE(asn_DEF_RICcontrolRequest , pdu);
if(encode_result.encoded == -1) {
fprintf(stderr, "Cannot encode %s: %s\\n", encode_result.failed_type->name, strerror(errno));
return -1;
} else {
return encode_result.encoded;
}
}
static size_t encode_RICcontrolRequest_der(RICcontrolRequest_t* pdu, void* buffer, size_t buf_size)
{
asn_enc_rval_t encode_result;
encode_result = der_encode_to_buffer(&asn_DEF_RICcontrolRequest , pdu, buffer, buf_size);
// ASN_STRUCT_FREE(asn_DEF_RICcontrolRequest , pdu);
if(encode_result.encoded == -1) {
fprintf(stderr, "Cannot encode %s: %s\\n", encode_result.failed_type->name, strerror(errno));
return -1;
} else {
return encode_result.encoded;
}
}
static void save_RICcontrolRequest_aper(const char *filename, RICcontrolRequest_t *RICcontrolRequest)
{
char buffer[2048] = {0};
size_t size = encode_RICcontrolRequest_aper(RICcontrolRequest, buffer, 2048);
FILE *fp = fopen(filename, "w");
fwrite(buffer, 1, size, fp);
fclose(fp);
}
static void save_RICcontrolRequest_oer(const char *filename, RICcontrolRequest_t *RICcontrolRequest)
{
char buffer[2048] = {0};
size_t size = encode_RICcontrolRequest_oer(RICcontrolRequest, buffer, 2048);
FILE *fp = fopen(filename, "w");
fwrite(buffer, 1, size, fp);
fclose(fp);
}
static void save_RICcontrolRequest_der(const char *filename, RICcontrolRequest_t *RICcontrolRequest)
{
char buffer[2048] = {0};
size_t size = encode_RICcontrolRequest_der(RICcontrolRequest, buffer, 2048);
FILE *fp = fopen(filename, "w");
fwrite(buffer, 1, size, fp);
fclose(fp);
}
/**
* 生成 RICcontrolRequest 结构体
*/
static int gen_RICcontrolRequest()
{
RICcontrolRequest_t *RICcontrolRequest;
RICcontrolRequest = calloc(1, sizeof(RICcontrolRequest_t));
assert(RICcontrolRequest); /* Assume infinite memory */
/**
*
*/
RICrequestID_t RICrequestID = {
RICrequestID.ricInstanceID = 12,
RICrequestID.ricRequestorID = 13,
};
RICcontrolRequest_IEs_t *RICcontrolRequest_IE =
alloc_RICcontrolRequest_IEs(ProtocolIE_ID_id_RICrequestID,
RICcontrolRequest_IEs__value_PR_RICrequestID, &RICrequestID);
ASN_SEQUENCE_ADD(&RICcontrolRequest->protocolIEs.list, RICcontrolRequest_IE);
/**
*
*/
RANfunctionID_t RANfunctionID = 14;
RICcontrolRequest_IEs_t *RICcontrolRequest_IE2 =
alloc_RICcontrolRequest_IEs(ProtocolIE_ID_id_RANfunctionID,
RICcontrolRequest_IEs__value_PR_RANfunctionID, &RANfunctionID);
ASN_SEQUENCE_ADD(&RICcontrolRequest->protocolIEs.list, RICcontrolRequest_IE2);
/**
*
*/
RICcallProcessID_t RICcallProcessID;
RICcallProcessID.buf = malloc(1);
OCTET_STRING_fromBuf(&RICcallProcessID, "RICcallProcessID", strlen("RICcallProcessID"));
RICcontrolRequest_IEs_t *RICcontrolRequest_IE3 =
alloc_RICcontrolRequest_IEs(ProtocolIE_ID_id_RICcallProcessID,
RICcontrolRequest_IEs__value_PR_RICcallProcessID, &RICcallProcessID);
ASN_SEQUENCE_ADD(&RICcontrolRequest->protocolIEs.list, RICcontrolRequest_IE3);
/**
*
*/
RICcontrolHeader_t RICcontrolHeader;
RICcontrolHeader.buf = malloc(1);
OCTET_STRING_fromBuf(&RICcontrolHeader, "RICcontrolHeader", strlen("RICcontrolHeader"));
RICcontrolRequest_IEs_t *RICcontrolRequest_IE4 =
alloc_RICcontrolRequest_IEs(ProtocolIE_ID_id_RICcontrolHeader,
RICcontrolRequest_IEs__value_PR_RICcontrolHeader, &RICcontrolHeader);
ASN_SEQUENCE_ADD(&RICcontrolRequest->protocolIEs.list, RICcontrolRequest_IE4);
/**
*
*/
RICcontrolMessage_t RICcontrolMessage;
RICcontrolMessage.buf = malloc(1);
OCTET_STRING_fromBuf(&RICcontrolMessage, "RICcontrolMessage", strlen("RICcontrolMessage"));
RICcontrolRequest_IEs_t *RICcontrolRequest_IE5 =
alloc_RICcontrolRequest_IEs(ProtocolIE_ID_id_RICcontrolMessage,
RICcontrolRequest_IEs__value_PR_RICcontrolMessage, &RICcontrolMessage);
ASN_SEQUENCE_ADD(&RICcontrolRequest->protocolIEs.list, RICcontrolRequest_IE5);
/**
*
*/
RICcontrolAckRequest_t RICcontrolAckRequest = RICcontrolAckRequest_nAck;
RICcontrolRequest_IEs_t *RICcontrolRequest_IE6 =
alloc_RICcontrolRequest_IEs(ProtocolIE_ID_id_RICcontrolAckRequest,
RICcontrolRequest_IEs__value_PR_RICcontrolAckRequest, &RICcontrolAckRequest);
ASN_SEQUENCE_ADD(&RICcontrolRequest->protocolIEs.list, RICcontrolRequest_IE6);
/**
* 输出到屏幕
*/
printf("################ Original Struct ##################\\n");
printf_RICcontrolRequest(RICcontrolRequest);
printf("##################################\\n");
/**
* 将其保存为 多种 文件格式
*/
save_RICcontrolRequest_xer(XER_RICcontrolRequest, RICcontrolRequest);
save_RICcontrolRequest_aper(APER_RICcontrolRequest, RICcontrolRequest);
save_RICcontrolRequest_oer(OER_RICcontrolRequest, RICcontrolRequest);
save_RICcontrolRequest_der(DER_RICcontrolRequest, RICcontrolRequest);
return 0;
}
static int decode_RICcontrolRequest_xer()
{
FUNC_CALL();
RICcontrolRequest_t *RICcontrolRequest = NULL;
char buf[2048] = {0};
int size;
asn_dec_rval_t rval;
FILE *fp = fopen(XER_RICcontrolRequest, "r");
size = fread(buf, 1, sizeof buf, fp);
if(size == 0 || size == sizeof buf) {
PRINT_ERROR("%s: Too large input\\n", XER_RICcontrolRequest);
exit(1);
}
fclose(fp);
rval = xer_decode(NULL, &asn_DEF_RICcontrolRequest, (void**)&RICcontrolRequest, buf, size);
if(rval.code != RC_OK) {
ASN_STRUCT_FREE(asn_DEF_RICcontrolRequest, RICcontrolRequest);
return -1;
}
// printf("################ Decode XER file ##################\\n");
// printf_RICcontrolRequest(RICcontrolRequest);
// printf("##################################\\n");
save_RICcontrolRequest_xer(NEW_XER_RICcontrolRequest, RICcontrolRequest);
ASN_STRUCT_FREE(asn_DEF_RICcontrolRequest, RICcontrolRequest);
return 0;
}
static int decode_RICcontrolRequest_aper()
{
FUNC_CALL();
RICcontrolRequest_t *RICcontrolRequest = NULL;
char buf[2048] = {0};
int size;
FILE *fp = fopen(APER_RICcontrolRequest, "r");
size = fread(buf, 1, sizeof buf, fp);
if(size == 0 || size == sizeof buf) {
fprintf(stderr, "%s: Too large input\\n", APER_RICcontrolRequest);
exit(1);
}
fclose(fp);
asn_dec_rval_t decode_result;
decode_result = aper_decode_complete(NULL, &asn_DEF_RICcontrolRequest, (void **)&RICcontrolRequest, buf, size);
if以上是关于ASN.1编解码:asn1c-ORAN-E2AP编解码示例的主要内容,如果未能解决你的问题,请参考以下文章