Branch data Line data Source code
1 : : #include <hpactor/tracing/trace_context_parser.hpp>
2 : :
3 : : #include <array>
4 : : #include <cstring>
5 : :
6 : : namespace hpactor::tracing {
7 : :
8 : : namespace {
9 : :
10 : 230 : int hex_value(char c) noexcept {
11 : 230 : if (c >= '0' && c <= '9')
12 : 164 : return c - '0';
13 : 66 : if (c >= 'a' && c <= 'f')
14 : 48 : return c - 'a' + 10;
15 : 18 : if (c >= 'A' && c <= 'F')
16 : 18 : return c - 'A' + 10;
17 : 0 : return -1;
18 : : }
19 : :
20 : : template <size_t N>
21 : 12 : bool parse_hex_bytes(std::string_view text, std::array<uint8_t, N>& out) noexcept {
22 : 12 : if (text.size() != N * 2)
23 : 0 : return false;
24 : 127 : for (size_t i = 0; i < N; ++i) {
25 : 115 : int hi = hex_value(text[i * 2]);
26 : 115 : int lo = hex_value(text[i * 2 + 1]);
27 : 115 : if (hi < 0 || lo < 0)
28 : 0 : return false;
29 : 115 : out[i] = static_cast<uint8_t>((hi << 4) | lo);
30 : : }
31 : 12 : return true;
32 : : }
33 : :
34 : 150 : void append_hex_byte(std::string& out, uint8_t b) {
35 : 150 : constexpr char kHex[] = "0123456789abcdef";
36 : 150 : out.push_back(kHex[(b >> 4) & 0x0F]);
37 : 150 : out.push_back(kHex[b & 0x0F]);
38 : 150 : }
39 : :
40 : : } // namespace
41 : :
42 : 7 : TraceParseResult parse_w3c_trace_context(std::string_view traceparent,
43 : : std::string_view tracestate,
44 : : uint16_t max_tracestate_len) noexcept {
45 : 7 : TraceParseResult result;
46 : 7 : if (traceparent.empty()) {
47 : 1 : result.status_value = TraceParseStatus::kMissing;
48 : 1 : return result;
49 : : }
50 : 11 : if (traceparent.size() != 55 || traceparent[2] != '-' ||
51 : 11 : traceparent[35] != '-' || traceparent[52] != '-') {
52 : 1 : result.status_value = TraceParseStatus::kMalformed;
53 : 1 : return result;
54 : : }
55 : 5 : if (!traceparent.starts_with("00")) {
56 : 0 : result.status_value = TraceParseStatus::kUnsupportedVersion;
57 : 0 : return result;
58 : : }
59 : :
60 : 5 : TraceContext ctx;
61 : 10 : if (!parse_hex_bytes(traceparent.substr(3, 32), ctx.trace_id.bytes) ||
62 : 5 : !ctx.trace_id.valid()) {
63 : 1 : result.status_value = TraceParseStatus::kInvalidTraceId;
64 : 1 : return result;
65 : : }
66 : 8 : if (!parse_hex_bytes(traceparent.substr(36, 16), ctx.span_id.bytes) ||
67 : 4 : !ctx.span_id.valid()) {
68 : 1 : result.status_value = TraceParseStatus::kInvalidSpanId;
69 : 1 : return result;
70 : : }
71 : :
72 : 3 : std::array<uint8_t, 1> flags{};
73 : 3 : if (!parse_hex_bytes(traceparent.substr(53, 2), flags)) {
74 : 0 : result.status_value = TraceParseStatus::kMalformed;
75 : 0 : return result;
76 : : }
77 : 3 : ctx.flags.value = flags[0];
78 : :
79 : 5 : if (tracestate.size() > max_tracestate_len ||
80 : 4 : tracestate.size() > ctx.tracestate.size()) {
81 : 1 : result.status_value = TraceParseStatus::kTracestateTooLarge;
82 : 1 : return result;
83 : : }
84 : 2 : if (!tracestate.empty()) {
85 : 1 : std::memcpy(ctx.tracestate.data(), tracestate.data(), tracestate.size());
86 : 1 : ctx.tracestate_len = static_cast<uint16_t>(tracestate.size());
87 : : }
88 : :
89 : 2 : result.status_value = TraceParseStatus::kOk;
90 : 2 : result.context = ctx;
91 : 2 : return result;
92 : : }
93 : :
94 : 6 : std::string format_traceparent(const TraceContext& context) {
95 : 6 : std::string out;
96 : 6 : out.reserve(55);
97 : 6 : out += "00-";
98 : 102 : for (uint8_t b : context.trace_id.bytes)
99 : 96 : append_hex_byte(out, b);
100 : 6 : out.push_back('-');
101 : 54 : for (uint8_t b : context.span_id.bytes)
102 : 48 : append_hex_byte(out, b);
103 : 6 : out.push_back('-');
104 : 6 : append_hex_byte(out, context.flags.value);
105 : 6 : return out;
106 : : }
107 : :
108 : 1 : std::string format_tracestate(const TraceContext& context) {
109 : 1 : return std::string(context.tracestate_view());
110 : : }
111 : :
112 : : } // namespace hpactor::tracing
|