diff --git a/include/ctraces/ctr_id.h b/include/ctraces/ctr_id.h index 8cd391f..91e27e9 100644 --- a/include/ctraces/ctr_id.h +++ b/include/ctraces/ctr_id.h @@ -39,5 +39,6 @@ int ctr_id_cmp(struct ctrace_id *cid1, struct ctrace_id *cid2); size_t ctr_id_get_len(struct ctrace_id *cid); void *ctr_id_get_buf(struct ctrace_id *cid); cfl_sds_t ctr_id_to_lower_base16(struct ctrace_id *cid); +struct ctrace_id *ctr_id_from_base16(cfl_sds_t id); #endif diff --git a/src/ctr_decode_msgpack.c b/src/ctr_decode_msgpack.c index 56cb444..f1df5c3 100644 --- a/src/ctr_decode_msgpack.c +++ b/src/ctr_decode_msgpack.c @@ -236,10 +236,14 @@ static int unpack_link_trace_id(mpack_reader_t *reader, size_t index, void *ctx) int result; cfl_sds_t value; - result = ctr_mpack_consume_binary_tag(reader, &value); + result = ctr_mpack_consume_string_or_nil_tag(reader, &value); - if (result == CTR_MPACK_SUCCESS) { - context->link->trace_id = ctr_id_create(value, cfl_sds_len(value)); + if (result == CTR_MPACK_SUCCESS && value != NULL) { + context->link->trace_id = ctr_id_from_base16(value); + + if (context->link->trace_id == NULL) { + result = CTR_MPACK_CORRUPT_INPUT_DATA_ERROR; + } cfl_sds_destroy(value); } @@ -253,11 +257,14 @@ static int unpack_link_span_id(mpack_reader_t *reader, size_t index, void *ctx) int result; cfl_sds_t value; - result = ctr_mpack_consume_binary_or_nil_tag(reader, &value); + result = ctr_mpack_consume_string_or_nil_tag(reader, &value); - if (result == CTR_MPACK_SUCCESS && - value != NULL) { - context->link->span_id = ctr_id_create(value, cfl_sds_len(value)); + if (result == CTR_MPACK_SUCCESS && value != NULL) { + context->link->span_id = ctr_id_from_base16(value); + + if (context->link->span_id == NULL) { + result = CTR_MPACK_CORRUPT_INPUT_DATA_ERROR; + } cfl_sds_destroy(value); } @@ -339,13 +346,23 @@ static int unpack_link(mpack_reader_t *reader, size_t index, void *ctx) static int unpack_span_trace_id(mpack_reader_t *reader, size_t index, void *ctx) { struct ctr_msgpack_decode_context *context = ctx; + struct ctrace_id *decoded_id; int result; cfl_sds_t value; - result = ctr_mpack_consume_binary_or_nil_tag(reader, &value); + result = ctr_mpack_consume_string_or_nil_tag(reader, &value); if (result == CTR_MPACK_SUCCESS && value != NULL) { - ctr_span_set_trace_id(context->span, value, cfl_sds_len(value)); + decoded_id = ctr_id_from_base16(value); + + if (decoded_id != NULL) { + ctr_span_set_trace_id_with_cid(context->span, decoded_id); + + ctr_id_destroy(decoded_id); + } + else { + result = CTR_MPACK_CORRUPT_INPUT_DATA_ERROR; + } cfl_sds_destroy(value); } @@ -356,13 +373,23 @@ static int unpack_span_trace_id(mpack_reader_t *reader, size_t index, void *ctx) static int unpack_span_span_id(mpack_reader_t *reader, size_t index, void *ctx) { struct ctr_msgpack_decode_context *context = ctx; + struct ctrace_id *decoded_id; int result; cfl_sds_t value; - result = ctr_mpack_consume_binary_or_nil_tag(reader, &value); + result = ctr_mpack_consume_string_or_nil_tag(reader, &value); if (result == CTR_MPACK_SUCCESS && value != NULL) { - ctr_span_set_span_id(context->span, value, cfl_sds_len(value)); + decoded_id = ctr_id_from_base16(value); + + if (decoded_id != NULL) { + ctr_span_set_span_id_with_cid(context->span, decoded_id); + + ctr_id_destroy(decoded_id); + } + else { + result = CTR_MPACK_CORRUPT_INPUT_DATA_ERROR; + } cfl_sds_destroy(value); } @@ -373,13 +400,23 @@ static int unpack_span_span_id(mpack_reader_t *reader, size_t index, void *ctx) static int unpack_span_parent_span_id(mpack_reader_t *reader, size_t index, void *ctx) { struct ctr_msgpack_decode_context *context = ctx; + struct ctrace_id *decoded_id; int result; cfl_sds_t value; - result = ctr_mpack_consume_binary_or_nil_tag(reader, &value); + result = ctr_mpack_consume_string_or_nil_tag(reader, &value); if (result == CTR_MPACK_SUCCESS && value != NULL) { - ctr_span_set_parent_span_id(context->span, value, cfl_sds_len(value)); + decoded_id = ctr_id_from_base16(value); + + if (decoded_id != NULL) { + ctr_span_set_parent_span_id_with_cid(context->span, decoded_id); + + ctr_id_destroy(decoded_id); + } + else { + result = CTR_MPACK_CORRUPT_INPUT_DATA_ERROR; + } cfl_sds_destroy(value); } diff --git a/src/ctr_encode_msgpack.c b/src/ctr_encode_msgpack.c index 2494f89..bd3d187 100644 --- a/src/ctr_encode_msgpack.c +++ b/src/ctr_encode_msgpack.c @@ -175,8 +175,24 @@ static void pack_instrumentation_scope(mpack_writer_t *writer, struct ctrace_ins static void pack_id(mpack_writer_t *writer, struct ctrace_id *id) { + cfl_sds_t encoded_id; + + if (id) { - mpack_write_bin(writer, id->buf, cfl_sds_len(id->buf)); + encoded_id = ctr_id_to_lower_base16(id); + + if (encoded_id != NULL) { + mpack_write_cstr(writer, encoded_id); + + cfl_sds_destroy(encoded_id); + } + else { + /* we should be able to report this but at the moment + * we are not. + */ + + mpack_write_nil(writer); + } } else { mpack_write_nil(writer); diff --git a/src/ctr_id.c b/src/ctr_id.c index cd299a2..e91a894 100644 --- a/src/ctr_id.c +++ b/src/ctr_id.c @@ -151,3 +151,104 @@ cfl_sds_t ctr_id_to_lower_base16(struct ctrace_id *cid) return out; } + +/* This function returns CFL_TRUE on success and CFL_FALSE on + * failure. + */ +static int decode_hex_digit(char *digit) +{ + if (*digit >= '0' && *digit <= '9') { + *digit -= '0'; + } + else if (*digit >= 'a' && *digit <= 'f') { + *digit -= 'a'; + *digit += 10; + } + else if (*digit >= 'A' && *digit <= 'F') { + *digit -= 'A'; + *digit += 10; + } + else { + return CFL_FALSE; + } + + return CFL_TRUE; +} + +struct ctrace_id *ctr_id_from_base16(cfl_sds_t id) +{ + size_t output_index; + size_t input_index; + cfl_sds_t decoded_id; + struct ctrace_id *result_id; + int result; + size_t length; + char digit; + char value; + + if (id == NULL) { + return NULL; + } + + length = cfl_sds_len(id); + + if (length < 2) { + return NULL; + } + + if ((length % 2) != 0) { + return NULL; + } + + decoded_id = cfl_sds_create_size(length / 2); + + if (decoded_id == NULL) { + return NULL; + } + + output_index = 0; + input_index = 0; + value = 0; + + /* This loop consumes one character per iteration, + * on each iteration it verifies that the character + * corresponds to the base16 charset and then + * it subtracts the correct base to get a number + * ranging from 0 to 16. + * Then the accumulator is left shifted 4 bits and + * the current value is bitwise ORed to its value. + * If the character index is odd then the accumulator + * value is appended to the decoded id buffer and + * reinitialized to be used on the next iteration. + */ + + while (input_index < length) { + digit = id[input_index]; + result = decode_hex_digit(&digit); + + if (!result) { + break; + } + + digit &= 0xF; + value <<= 4; + value |= digit; + + if ((input_index % 2) == 1) { + decoded_id[output_index++] = value; + value = 0; + } + + input_index++; + } + + if (!result) { + return NULL; + } + + result_id = ctr_id_create(decoded_id, length / 2); + + cfl_sds_destroy(decoded_id); + + return result_id; +}