所谓的编码,就是将数据结构的结构体对象编码为指定协议标准的二进制流,而所谓解码,则是将二进制流解析出对应的结构体对象,有点对象的序列化和反序列化的意思,和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