Coverage Report

Created: 2026-05-16 07:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fluent-bit/plugins/in_opentelemetry/opentelemetry_utils.c
Line
Count
Source
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  Fluent Bit
4
 *  ==========
5
 *  Copyright (C) 2015-2026 The Fluent Bit Authors
6
 *
7
 *  Licensed under the Apache License, Version 2.0 (the "License");
8
 *  you may not use this file except in compliance with the License.
9
 *  You may obtain a copy of the License at
10
 *
11
 *      http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 *  Unless required by applicable law or agreed to in writing, software
14
 *  distributed under the License is distributed on an "AS IS" BASIS,
15
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 *  See the License for the specific language governing permissions and
17
 *  limitations under the License.
18
 */
19
20
#include <fluent-bit/flb_input_plugin.h>
21
#include <ctype.h>
22
23
int find_map_entry_by_key(msgpack_object_map *map,
24
                          char *key,
25
                          size_t match_index,
26
                          int case_insensitive)
27
0
{
28
0
    int     result;
29
0
    int     index;
30
0
    int key_len;
31
0
    size_t  match_count;
32
33
0
    if (!key) {
34
0
        return -1;
35
0
    }
36
37
0
    key_len = strlen(key);
38
0
    match_count = 0;
39
40
0
    for (index = 0 ; index < (int) map->size ; index++) {
41
0
        if (key_len != map->ptr[index].key.via.str.size) {
42
0
            continue;
43
0
        }
44
45
0
        if (map->ptr[index].key.type == MSGPACK_OBJECT_STR) {
46
0
            if (case_insensitive) {
47
0
                result = strncasecmp(map->ptr[index].key.via.str.ptr,
48
0
                                     key,
49
0
                                     map->ptr[index].key.via.str.size);
50
0
            }
51
0
            else {
52
0
                result = strncmp(map->ptr[index].key.via.str.ptr,
53
0
                                 key,
54
0
                                 map->ptr[index].key.via.str.size);
55
0
            }
56
57
0
            if (result == 0) {
58
0
                if (match_count == match_index) {
59
0
                    return index;
60
0
                }
61
62
0
                match_count++;
63
0
            }
64
0
        }
65
0
    }
66
67
0
    return -1;
68
0
}
69
70
int json_payload_get_wrapped_value(msgpack_object *wrapper,
71
                                   msgpack_object **value,
72
                                   int            *type)
73
0
{
74
0
    int                 internal_type;
75
0
    msgpack_object     *kv_value;
76
0
    msgpack_object_str *kv_key;
77
0
    msgpack_object_map *map;
78
79
0
    if (wrapper->type != MSGPACK_OBJECT_MAP) {
80
0
        return -1;
81
0
    }
82
83
0
    map = &wrapper->via.map;
84
0
    kv_value = NULL;
85
0
    internal_type = -1;
86
87
0
    if (map->size == 1) {
88
0
        if (map->ptr[0].key.type == MSGPACK_OBJECT_STR) {
89
0
            kv_value = &map->ptr[0].val;
90
0
            kv_key = &map->ptr[0].key.via.str;
91
92
0
            if (strncasecmp(kv_key->ptr, "stringValue",  kv_key->size) == 0 ||
93
0
                strncasecmp(kv_key->ptr, "string_value", kv_key->size) == 0) {
94
0
                internal_type = MSGPACK_OBJECT_STR;
95
0
            }
96
0
            else if (strncasecmp(kv_key->ptr, "boolValue",  kv_key->size) == 0 ||
97
0
                     strncasecmp(kv_key->ptr, "bool_value", kv_key->size) == 0) {
98
0
                internal_type = MSGPACK_OBJECT_BOOLEAN;
99
0
            }
100
0
            else if (strncasecmp(kv_key->ptr, "intValue",  kv_key->size) == 0 ||
101
0
                     strncasecmp(kv_key->ptr, "int_value", kv_key->size) == 0) {
102
0
                internal_type = MSGPACK_OBJECT_POSITIVE_INTEGER;
103
0
            }
104
0
            else if (strncasecmp(kv_key->ptr, "doubleValue",  kv_key->size) == 0 ||
105
0
                     strncasecmp(kv_key->ptr, "double_value", kv_key->size) == 0) {
106
0
                internal_type = MSGPACK_OBJECT_FLOAT;
107
0
            }
108
0
            else if (strncasecmp(kv_key->ptr, "bytesValue",  kv_key->size) == 0 ||
109
0
                     strncasecmp(kv_key->ptr, "bytes_value", kv_key->size) == 0) {
110
0
                internal_type = MSGPACK_OBJECT_BIN;
111
0
            }
112
0
            else if (strncasecmp(kv_key->ptr, "arrayValue",  kv_key->size) == 0 ||
113
0
                     strncasecmp(kv_key->ptr, "array_value", kv_key->size) == 0) {
114
0
                internal_type = MSGPACK_OBJECT_ARRAY;
115
0
            }
116
0
            else if (strncasecmp(kv_key->ptr, "kvlistValue",  kv_key->size) == 0 ||
117
0
                     strncasecmp(kv_key->ptr, "kvlist_value", kv_key->size) == 0) {
118
0
                internal_type = MSGPACK_OBJECT_MAP;
119
0
            }
120
0
        }
121
0
    }
122
123
0
    if (internal_type != -1) {
124
0
        if (type != NULL) {
125
0
            *type  = internal_type;
126
0
        }
127
128
0
        if (value != NULL) {
129
0
            *value = kv_value;
130
0
        }
131
132
0
        if (kv_value->type == MSGPACK_OBJECT_MAP) {
133
0
            map = &kv_value->via.map;
134
135
0
            if (map->size == 1) {
136
0
                kv_value = &map->ptr[0].val;
137
0
                kv_key = &map->ptr[0].key.via.str;
138
139
0
                if (strncasecmp(kv_key->ptr, "values", kv_key->size) == 0) {
140
0
                    if (value != NULL) {
141
0
                        *value = kv_value;
142
0
                    }
143
0
                }
144
0
                else {
145
0
                    return -3;
146
0
                }
147
0
            }
148
0
        }
149
0
    }
150
0
    else {
151
0
        return -2;
152
0
    }
153
154
0
    return 0;
155
0
}
156
157
static int opentelemetry_content_type_matches(const char *content_type,
158
                                              const char *expected_content_type)
159
0
{
160
0
    size_t content_length;
161
0
    size_t expected_length;
162
0
    char trailing_character;
163
164
0
    if (content_type == NULL || expected_content_type == NULL) {
165
0
        return FLB_FALSE;
166
0
    }
167
168
0
    expected_length = strlen(expected_content_type);
169
0
    content_length = strlen(content_type);
170
171
0
    if (content_length < expected_length) {
172
0
        return FLB_FALSE;
173
0
    }
174
175
0
    if (strncasecmp(content_type, expected_content_type, expected_length) != 0) {
176
0
        return FLB_FALSE;
177
0
    }
178
179
0
    trailing_character = content_type[expected_length];
180
181
0
    if (trailing_character == '\0' ||
182
0
        trailing_character == ';' ||
183
0
        trailing_character == ' ' ||
184
0
        trailing_character == '\t') {
185
0
        return FLB_TRUE;
186
0
    }
187
188
0
    return FLB_FALSE;
189
0
}
190
191
int opentelemetry_is_grpc_content_type(const char *content_type)
192
0
{
193
0
    size_t content_length;
194
195
0
    if (content_type == NULL) {
196
0
        return FLB_FALSE;
197
0
    }
198
199
0
    content_length = strlen(content_type);
200
0
    if (content_length < 16) {
201
0
        return FLB_FALSE;
202
0
    }
203
204
0
    if (strncasecmp(content_type, "application/grpc", 16) != 0) {
205
0
        return FLB_FALSE;
206
0
    }
207
208
0
    if (content_type[16] == '\0' ||
209
0
        content_type[16] == '+' ||
210
0
        content_type[16] == ';' ||
211
0
        content_type[16] == ' ' ||
212
0
        content_type[16] == '\t') {
213
0
        return FLB_TRUE;
214
0
    }
215
216
0
    return FLB_FALSE;
217
0
}
218
219
int opentelemetry_is_json_content_type(const char *content_type)
220
0
{
221
0
    return opentelemetry_content_type_matches(content_type, "application/json");
222
0
}
223
224
int opentelemetry_is_protobuf_content_type(const char *content_type)
225
0
{
226
0
    if (opentelemetry_content_type_matches(content_type, "application/protobuf") ==
227
0
        FLB_TRUE) {
228
0
        return FLB_TRUE;
229
0
    }
230
231
0
    if (opentelemetry_content_type_matches(content_type,
232
0
                                           "application/x-protobuf") == FLB_TRUE) {
233
0
        return FLB_TRUE;
234
0
    }
235
236
0
    if (opentelemetry_is_grpc_content_type(content_type) == FLB_TRUE) {
237
0
        return FLB_TRUE;
238
0
    }
239
240
0
    return FLB_FALSE;
241
0
}
242
243
int opentelemetry_payload_starts_with_json_object(const void *payload,
244
                                                  size_t payload_size)
245
0
{
246
0
    size_t index;
247
0
    const unsigned char *buffer;
248
249
0
    if (payload == NULL || payload_size == 0) {
250
0
        return FLB_FALSE;
251
0
    }
252
253
0
    buffer = (const unsigned char *) payload;
254
255
0
    for (index = 0; index < payload_size; index++) {
256
0
        if (isspace(buffer[index])) {
257
0
            continue;
258
0
        }
259
260
0
        if (buffer[index] == '{') {
261
0
            return FLB_TRUE;
262
0
        }
263
264
0
        return FLB_FALSE;
265
0
    }
266
267
0
    return FLB_FALSE;
268
0
}
269
270
static int hex_to_int(char ch)
271
0
{
272
0
    if (ch >= '0' && ch <= '9') {
273
0
        return ch - '0';
274
0
    }
275
276
0
    if (ch >= 'a' && ch <= 'f') {
277
0
        return ch - 'a' + 10;
278
0
    }
279
280
0
    if (ch >= 'A' && ch <= 'F') {
281
0
        return ch - 'A' + 10;
282
0
    }
283
284
0
    return -1;
285
0
}
286
287
/* convert an hex string to the expected id (16 bytes) */
288
int hex_to_id(char *str, int len, unsigned char *out_buf, int out_size)
289
0
{
290
0
    int i;
291
0
    int high;
292
0
    int low;
293
294
0
    if (len % 2 != 0) {
295
0
        return -1;
296
0
    }
297
298
0
    for (i = 0; i < len; i += 2) {
299
0
        if (!isxdigit(str[i]) || !isxdigit(str[i + 1])) {
300
0
            return -1;
301
0
        }
302
303
0
        high = hex_to_int(str[i]);
304
0
        low = hex_to_int(str[i + 1]);
305
306
0
        if (high == -1 || low == -1) {
307
0
            return -1;
308
0
        }
309
310
0
        out_buf[i / 2] = (high << 4) | low;
311
0
    }
312
313
0
    return 0;
314
0
}
315
316
uint64_t convert_string_number_to_u64(char *str, size_t len)
317
0
{
318
0
    uint64_t val;
319
0
    size_t i;
320
0
    char tmp[32];
321
322
0
    if (len > sizeof(tmp) - 1) {
323
0
        return 0;
324
0
    }
325
326
0
    for (i = 0; i < len; i++) {
327
0
        if (!isdigit((unsigned char) str[i])) {
328
0
            return 0;
329
0
        }
330
0
    }
331
332
0
    memcpy(tmp, str, len);
333
0
    tmp[len] = '\0';
334
335
    val = strtoull(tmp, NULL, 10);
336
0
    return val;
337
0
}