从KMIP编解码库libkmip的代码学到的编解码代码框架

2023-05-02 15:28:28 浏览数 (2)

所谓的编码,就是将数据结构的结构体对象编码为指定协议标准的二进制流,而所谓解码,则是将二进制流解析出对应的结构体对象,有点对象的序列化和反序列化的意思,和RPC实现的基本原理倒是相通的;

比方RTP包一直都长的一样,所以一个数据结构就能定义了;如果需要同一套协议,承载不同结构的payload的情况,KMIP的实现提供了一套通用的代码框架,值得参考和学习;

KMIP的对象,就是一个包括了编码缓冲区的一个ctx上下文对象,所有编码的数据都会存储到buffer中,每个数据对象的编码操作,都是向buffer写数据的过程,编码完成后则可以将ctx->buffer的数据通过网络或者其他方式发送出去;

数据结构很关键:

代码语言:javascript复制
typedef struct kmip
{
    /* Encoding buffer */
    uint8 *buffer;
    uint8 *index;
    size_t size;
 } KMIP;


/*
Encoding Functions
*/

int
kmip_encode_int8_be(KMIP *ctx, int8 value)
{
    CHECK_BUFFER_FULL(ctx, sizeof(int8));

    uint8 v = *(uint8 *)((void *)(&value));

    *ctx->index   = v;
    
    return(KMIP_OK);
}

int
kmip_encode_int32_be(KMIP *ctx, int32 value)
{
    CHECK_BUFFER_FULL(ctx, sizeof(int32));

    uint32 v = *(uint32 *)((void *)(&value));

    *ctx->index   = (uint8)((v & 0xFF000000) >> 24);
    *ctx->index   = (uint8)((v & 0x00FF0000) >> 16);
    *ctx->index   = (uint8)((v & 0x0000FF00) >> 8);
    *ctx->index   = (uint8)((v & 0x000000FF) >> 0);

    return(KMIP_OK);
}


/*
Decoding Functions
*/

int
kmip_decode_int8_be(KMIP *ctx, void *value)
{
    CHECK_BUFFER_FULL(ctx, sizeof(int8));
    
    int8 *i = (int8*)value;
    
    *i = 0;
    *i = *ctx->index  ;
    
    return(KMIP_OK);
}

int
kmip_decode_int32_be(KMIP *ctx, void *value)
{
    CHECK_BUFFER_FULL(ctx, sizeof(int32));
    
    int32 *i = (int32*)value;
    
    *i = 0;
    *i |= ((int32)*ctx->index   << 24);
    *i |= ((int32)*ctx->index   << 16);
    *i |= ((int32)*ctx->index   << 8);
    *i |= ((int32)*ctx->index   << 0);
    
    return(KMIP_OK);
}

编码命令的通用方法:

代码语言:javascript复制
int
kmip_encode_request_message(KMIP *ctx, const RequestMessage *value)
{
    int result = 0;
    result = kmip_encode_int32_be(ctx, TAG_TYPE(KMIP_TAG_REQUEST_MESSAGE, KMIP_TYPE_STRUCTURE));
    CHECK_RESULT(ctx, result);
    
    uint8 *length_index = ctx->index;
    uint8 *value_index = ctx->index  = 4;
    
    result = kmip_encode_request_header(ctx, value->request_header);
    CHECK_RESULT(ctx, result);
    
    for(size_t i = 0; i < value->batch_count; i  )
    {
        result = kmip_encode_request_batch_item(ctx, &value->batch_items[i]);
        CHECK_RESULT(ctx, result);
    }
    
    uint8 *curr_index = ctx->index;
    ctx->index = length_index;
    
    result = kmip_encode_length(ctx, curr_index - value_index);
    CHECK_RESULT(ctx, result);

    ctx->index = curr_index;
    
    return(KMIP_OK);
}


int
kmip_encode_request_header(KMIP *ctx, const RequestHeader *value)
{
    int result = 0;
    result = kmip_encode_int32_be(ctx, TAG_TYPE(KMIP_TAG_REQUEST_HEADER, KMIP_TYPE_STRUCTURE));
    CHECK_RESULT(ctx, result);
    
    uint8 *length_index = ctx->index;
    uint8 *value_index = ctx->index  = 4;
    
    result = kmip_encode_protocol_version(ctx, value->protocol_version);
    CHECK_RESULT(ctx, result);
   
    /*header info start. */
 
    /*header info end.*/
    
    uint8 *curr_index = ctx->index;
    ctx->index = length_index;

    result = kmip_encode_length(ctx, curr_index - value_index);
    CHECK_RESULT(ctx, result);

    ctx->index = curr_index;
    
    return(KMIP_OK);
}

编码payload的通用方法:

代码语言:javascript复制
int
kmip_encode_request_batch_item(KMIP *ctx, const RequestBatchItem *value)
{
    CHECK_ENCODE_ARGS(ctx, value);

    int result = 0;
    result = kmip_encode_int32_be(ctx, TAG_TYPE(KMIP_TAG_BATCH_ITEM, KMIP_TYPE_STRUCTURE));
    CHECK_RESULT(ctx, result);
    
    uint8 *length_index = ctx->index;
    uint8 *value_index = ctx->index  = 4;
    
    result = kmip_encode_enum(ctx, KMIP_TAG_OPERATION, value->operation);
    CHECK_RESULT(ctx, result);

    if(ctx->version >= KMIP_2_0)
    {
        if(value->ephemeral != KMIP_UNSET)
        {
            result=kmip_encode_bool(ctx, KMIP_TAG_EPHEMERAL, value->ephemeral);
            CHECK_RESULT(ctx, result);
        }
    }

    if(value->unique_batch_item_id != NULL)
    {
        result = kmip_encode_byte_string(ctx, KMIP_TAG_UNIQUE_BATCH_ITEM_ID, value->unique_batch_item_id);
        CHECK_RESULT(ctx, result);
    }
     
    switch(value->operation)
    {
        //3.2.5 创建主密钥
        case KMIP_OP_CREATE:
        result = kmip_encode_create_request_payload(ctx, (CreateRequestPayload*)value->request_payload);
        break;
       
       // other command.
  
        default:
        kmip_push_error_frame(ctx, __func__, __LINE__);
        return(KMIP_NOT_IMPLEMENTED);
        break;
    };
    CHECK_RESULT(ctx, result);
    
    uint8 *curr_index = ctx->index;
    ctx->index = length_index;
    
    result = kmip_encode_length(ctx, curr_index - value_index);
    CHECK_RESULT(ctx, result);

    ctx->index = curr_index;
    
    return(KMIP_OK);
}

//sample命令的编码方法

代码语言:javascript复制
int
kmip_encode_sample_request_payload(KMIP *ctx, const SampleRequestPayload *value){

    CHECK_ENCODE_ARGS(ctx, value);

    int result = 0;
    result = kmip_encode_int32_be(ctx, TAG_TYPE(KMIP_TAG_REQUEST_PAYLOAD, KMIP_TYPE_STRUCTURE));
    CHECK_RESULT(ctx, result);
    
    uint8 *length_index = ctx->index;
    uint8 *value_index = ctx->index  = 4;
     

    
    /*....code START...*/


    /*....code END...*/


    uint8 *curr_index = ctx->index;
    ctx->index = length_index;
    
    result = kmip_encode_length(ctx, curr_index - value_index);
    CHECK_RESULT(ctx, result);

    ctx->index = curr_index;
    
    return(KMIP_OK);
}

解码命令的通用方法:

代码语言:javascript复制
int
kmip_decode_response_message(KMIP *ctx, ResponseMessage *value)
{
    CHECK_BUFFER_FULL(ctx, 8);
    
    int result = 0;
    int32 tag_type = 0;
    uint32 length = 0;
    
    kmip_decode_int32_be(ctx, &tag_type);
    CHECK_TAG_TYPE(ctx, tag_type, KMIP_TAG_RESPONSE_MESSAGE, KMIP_TYPE_STRUCTURE);
    
    kmip_decode_length(ctx, &length);
    CHECK_BUFFER_FULL(ctx, length);
    
    value->response_header = ctx->calloc_func(ctx->state, 1, sizeof(ResponseHeader));
    CHECK_NEW_MEMORY(ctx, value->response_header, sizeof(ResponseHeader), "ResponseHeader structure");
    
    result = kmip_decode_response_header(ctx, value->response_header);
    CHECK_RESULT(ctx, result);
    
    value->batch_count = kmip_get_num_items_next(ctx, KMIP_TAG_BATCH_ITEM);
    if(value->batch_count > 0)
    {
        value->batch_items = ctx->calloc_func(ctx->state, value->batch_count, sizeof(ResponseBatchItem));
        CHECK_NEW_MEMORY(ctx, value->batch_items, value->batch_count * sizeof(ResponseBatchItem), "sequence of ResponseBatchItem structures");
        
        for(size_t i = 0; i < value->batch_count; i  )
        {
            result = kmip_decode_response_batch_item(ctx, &value->batch_items[i]);
            CHECK_RESULT(ctx, result);
        }
    }
    
    return(KMIP_OK);
}

int
kmip_decode_response_header(KMIP *ctx, ResponseHeader *value)
{
    CHECK_BUFFER_FULL(ctx, 8);
    
    int result = 0;
    int32 tag_type = 0;
    uint32 length = 0;
    
    kmip_decode_int32_be(ctx, &tag_type);
    CHECK_TAG_TYPE(ctx, tag_type, KMIP_TAG_RESPONSE_HEADER, KMIP_TYPE_STRUCTURE);
    
    kmip_decode_length(ctx, &length);
    CHECK_BUFFER_FULL(ctx, length);
    
    value->protocol_version = ctx->calloc_func(ctx->state, 1, sizeof(ProtocolVersion));
    CHECK_NEW_MEMORY(ctx, value->protocol_version, sizeof(ProtocolVersion), "ProtocolVersion structure");
    
    result = kmip_decode_protocol_version(ctx, value->protocol_version);
    CHECK_RESULT(ctx, result);
    
    result = kmip_decode_date_time(ctx, KMIP_TAG_TIME_STAMP, &value->time_stamp);
    CHECK_RESULT(ctx, result);
     
    //other header….

    result = kmip_decode_integer(ctx, KMIP_TAG_BATCH_COUNT, &value->batch_count);
    CHECK_RESULT(ctx, result);
    
    return(KMIP_OK);
}

解码payload的通用方法:

代码语言:javascript复制
int
kmip_decode_sample_response_payload(KMIP *ctx, SampleResponsePayload *value){

    CHECK_DECODE_ARGS(ctx, value);
    CHECK_BUFFER_FULL(ctx, 8);

    int result = 0;
    int32 tag_type = 0;
    uint32 length = 0;

    kmip_decode_int32_be(ctx, &tag_type);
    CHECK_TAG_TYPE(ctx, tag_type, KMIP_TAG_RESPONSE_PAYLOAD, KMIP_TYPE_STRUCTURE);
    
    kmip_decode_length(ctx, &length);
    CHECK_BUFFER_FULL(ctx, length);
     
    /*....code START...*/


    /*....code END...*/
}

Demo使用例子:

代码语言:javascript复制
    /* Build the request message. */
    ProtocolVersion pv = {0};
    kmip_init_protocol_version(&pv, ctx->version);
    
    RequestHeader rh = {0};
    kmip_init_request_header(&rh);
    
    rh.protocol_version = &pv;
    rh.maximum_response_size = ctx->max_message_size;
    rh.time_stamp = time(NULL);
    rh.batch_count = 1;
        
    TextString id = {0};
    id.value = uuid;
    id.size = uuid_size;
 
    GetKeyAttributesRequestPayload  crp = {0};  
    crp.unique_identifier  = &id; 

    RequestBatchItem rbi = {0};
    kmip_init_request_batch_item(&rbi);
    rbi.operation = KMIP_OP_GetAttributes;//
    rbi.request_payload = &crp;
    
    RequestMessage rm = {0};
    rm.request_header = &rh;
    rm.batch_items = &rbi;
    rm.batch_count = 1;
     
    int encode_result = kmip_encode_request_message(ctx, rm);

    //send
    int sent = BIO_write(bio, ctx->buffer, ctx->index - ctx->buffer);


   //收包、解码
    int recv = BIO_read(bio, encoding, buffer_total_size);
    if((size_t)recv != buffer_total_size)
    {
        kmip_free_buffer(ctx, encoding, buffer_total_size);
        encoding = NULL;
        kmip_set_buffer(ctx, NULL, 0);
        return(KMIP_IO_FAILURE);
    }
    
    kmip_set_buffer(ctx, encoding, buffer_total_size);
    ctx->index  = 4;
    int length = 0;
    
    kmip_decode_int32_be(ctx, &length);
    kmip_rewind(ctx);
    if(length > ctx->max_message_size)
    {
        kmip_free_buffer(ctx, encoding, buffer_total_size);
        encoding = NULL;
        kmip_set_buffer(ctx, NULL, 0);
        return(KMIP_EXCEED_MAX_MESSAGE_SIZE);
    }
    
    kmip_set_buffer(ctx, NULL, 0);
    uint8 *extended = ctx->realloc_func(ctx->state, encoding, buffer_total_size   length);
    if(encoding != extended)
    {
        encoding = extended;
    }
    ctx->memset_func(encoding   buffer_total_size, 0, length);
    
    buffer_block_size  = length;
    buffer_total_size = buffer_blocks * buffer_block_size;
    
    recv = BIO_read(bio, encoding   8, length);
    if(recv != length)
    {
        kmip_free_buffer(ctx, encoding, buffer_total_size);
        encoding = NULL;
        kmip_set_buffer(ctx, NULL, 0);
        return(KMIP_IO_FAILURE);
    }
    
    kmip_set_buffer(ctx, encoding, buffer_block_size);
    
    int decode_result = kmip_decode_response_message(ctx, resp_m);
    
    kmip_set_buffer(ctx, NULL, 0);

KMIP协议库地址:https://github.com/OpenKMIP/libkmip

0 人点赞