ASN.1编解码:asn1c-ORAN-E2AP编解码示例

Posted rtoax

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ASN.1编解码:asn1c-ORAN-E2AP编解码示例相关的知识,希望对你有一定的参考价值。

ASN.1编解码:asn1c-ORAN-E2AP编解码示例


荣涛
2021年9月2日


整体代码: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

RICcontrolRequeste2ap-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编解码示例的主要内容,如果未能解决你的问题,请参考以下文章

ASN.1编解码:ORAN-E2AP分析

ASN.1编解码与编程

ASN.1编解码:asn1c的版本分析-诺基亚

ASN.1编解码:asn1c的基本使用

ASN.1编解码:asn1cenber和unber

C对ASN.1的编解码环境搭建