所谓的编码,就是将数据结构的结构体对象编码为指定协议标准的二进制流,而所谓解码,则是将二进制流解析出对应的结构体对象,有点对象的序列化和反序列化的意思,和RPC实现的基本原理倒是相通的;
比方RTP包一直都长的一样,所以一个数据结构就能定义了;如果需要同一套协议,承载不同结构的payload的情况,KMIP的实现提供了一套通用的代码框架,值得参考和学习;
KMIP的对象,就是一个包括了编码缓冲区的一个ctx上下文对象,所有编码的数据都会存储到buffer中,每个数据对象的编码操作,都是向buffer写数据的过程,编码完成后则可以将ctx->buffer的数据通过网络或者其他方式发送出去;
数据结构很关键:
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); }
编码命令的通用方法:
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的通用方法:
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命令的编码方法
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); }
解码命令的通用方法:
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的通用方法:
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使用例子:
/* 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
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com