blob: d5fc2c72f0bbf57290d65bf3432857116f61222a [file] [log] [blame]
Miroslav Zagorac70230c62020-12-09 16:54:31 +01001/***
2 * Copyright 2020 HAProxy Technologies
3 *
4 * This file is part of the HAProxy OpenTracing filter.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20#include "include.h"
21
22
23/*
24 * OpenTracing filter id, used to identify OpenTracing filters.
25 * The name of this variable is consistent with the other filter names
26 * declared in include/haproxy/filters.h .
27 */
28const char *ot_flt_id = "the OpenTracing filter";
29
30
31/***
32 * NAME
33 * flt_ot_is_disabled -
34 *
35 * ARGUMENTS
36 * f -
37 * event -
38 *
39 * DESCRIPTION
40 * -
41 *
42 * RETURN VALUE
43 * -
44 */
45bool flt_ot_is_disabled(const struct filter *f FLT_OT_DBG_ARGS(, int event))
46{
47#ifdef DEBUG_OT
48 const struct flt_ot_conf *conf = FLT_OT_CONF(f);
49 const char *msg;
50#endif
51 bool retval;
52
53 retval = FLT_OT_RT_CTX(f->ctx)->flag_disabled ? 1 : 0;
54
55#ifdef DEBUG_OT
56 msg = retval ? " (disabled)" : "";
57
58 if (FLT_OT_IN_RANGE(event, 0, FLT_OT_EVENT_MAX - 1))
59 FLT_OT_DBG(2, "filter '%s', type: %s, event: '%s' %d%s", conf->id, flt_ot_type(f), flt_ot_event_data[event].name, event, msg);
60 else
61 FLT_OT_DBG(2, "filter '%s', type: %s%s", conf->id, flt_ot_type(f), msg);
62#endif
63
64 return retval;
65}
66
67
68/***
69 * NAME
70 * flt_ot_return_int -
71 *
72 * ARGUMENTS
73 * f -
74 * err -
75 * retval -
76 *
77 * DESCRIPTION
78 * -
79 *
80 * RETURN VALUE
81 * -
82 */
83static int flt_ot_return_int(const struct filter *f, char **err, int retval)
84{
85 struct flt_ot_runtime_context *rt_ctx = f->ctx;
86
87 if ((retval == FLT_OT_RET_ERROR) || ((err != NULL) && (*err != NULL))) {
88 if (rt_ctx->flag_harderr) {
89 FLT_OT_DBG(1, "WARNING: filter hard-error (disabled)");
90
91 rt_ctx->flag_disabled = 1;
92
93 _HA_ATOMIC_ADD(FLT_OT_CONF(f)->cnt.disabled + 1, 1);
94 } else {
95 FLT_OT_DBG(1, "WARNING: filter soft-error");
96 }
97
98 retval = FLT_OT_RET_OK;
99 }
100
101 FLT_OT_ERR_FREE(*err);
102
103 return retval;
104}
105
106
107/***
108 * NAME
109 * flt_ot_return_void -
110 *
111 * ARGUMENTS
112 * f -
113 * err -
114 *
115 * DESCRIPTION
116 * -
117 *
118 * RETURN VALUE
119 * This function does not return a value.
120 */
121static void flt_ot_return_void(const struct filter *f, char **err)
122{
123 struct flt_ot_runtime_context *rt_ctx = f->ctx;
124
125 if ((err != NULL) && (*err != NULL)) {
126 if (rt_ctx->flag_harderr) {
127 FLT_OT_DBG(1, "WARNING: filter hard-error (disabled)");
128
129 rt_ctx->flag_disabled = 1;
130
131 _HA_ATOMIC_ADD(FLT_OT_CONF(f)->cnt.disabled + 1, 1);
132 } else {
133 FLT_OT_DBG(1, "WARNING: filter soft-error");
134 }
135 }
136
137 FLT_OT_ERR_FREE(*err);
138}
139
140
141/***
142 * NAME
143 * flt_ot_init - Initialize the filter.
144 *
145 * ARGUMENTS
146 * p -
147 * fconf -
148 *
149 * DESCRIPTION
150 * It initializes the filter for a proxy. You may define this callback
151 * if you need to complete your filter configuration.
152 *
153 * RETURN VALUE
154 * Returns a negative value if an error occurs, any other value otherwise.
155 */
156static int flt_ot_init(struct proxy *p, struct flt_conf *fconf)
157{
158 struct flt_ot_conf *conf = FLT_OT_DEREF(fconf, conf, NULL);
Miroslav Zagoracf2263432021-04-02 04:25:47 +0200159 int retval = FLT_OT_RET_OK;
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100160
161 FLT_OT_FUNC("%p, %p", p, fconf);
162
163 if (conf == NULL)
Miroslav Zagoracf2263432021-04-02 04:25:47 +0200164 FLT_OT_RETURN(FLT_OT_RET_ERROR);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100165
166 flt_ot_cli_init();
167
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100168 FLT_OT_RETURN(retval);
169}
170
171
172/***
173 * NAME
174 * flt_ot_deinit - Free resources allocated by the filter.
175 *
176 * ARGUMENTS
177 * p -
178 * fconf -
179 *
180 * DESCRIPTION
181 * It cleans up what the parsing function and the init callback have done.
182 * This callback is useful to release memory allocated for the filter
183 * configuration.
184 *
185 * RETURN VALUE
186 * This function does not return a value.
187 */
188static void flt_ot_deinit(struct proxy *p, struct flt_conf *fconf)
189{
190 struct flt_ot_conf **conf = (fconf == NULL) ? NULL : (typeof(conf))&(fconf->conf);
191#ifdef DEBUG_OT
192 int i;
193#endif
194
195 FLT_OT_FUNC("%p, %p", p, fconf);
196
197 if (conf == NULL)
198 FLT_OT_RETURN();
199
200 ot_debug();
201 ot_close(&((*conf)->tracer->tracer));
202
203#ifdef DEBUG_OT
204 FLT_OT_DBG(0, "--- used events ----------");
205 for (i = 0; i < FLT_OT_TABLESIZE((*conf)->cnt.event); i++)
206 if ((*conf)->cnt.event[i].flag_used)
207 FLT_OT_DBG(0, " %02d: %" PRIu64 " / %" PRIu64, i, (*conf)->cnt.event[i].htx[0], (*conf)->cnt.event[i].htx[1]);
208#endif
209
210 flt_ot_conf_free(conf);
211
212 FLT_OT_MEMINFO();
213
214 FLT_OT_RETURN();
215}
216
217
218/***
219 * NAME
220 * flt_ot_check - Check configuration of the filter for the specified proxy.
221 *
222 * ARGUMENTS
223 * p -
224 * fconf -
225 *
226 * DESCRIPTION
227 * Optionally, by implementing the flt_ot_check() callback, you add a
228 * step to check the internal configuration of your filter after the
229 * parsing phase, when the HAProxy configuration is fully defined.
230 *
231 * RETURN VALUE
232 * Returns the number of encountered errors.
233 */
234static int flt_ot_check(struct proxy *p, struct flt_conf *fconf)
235{
236 struct proxy *px;
237 struct flt_ot_conf *conf = FLT_OT_DEREF(fconf, conf, NULL);
238 struct flt_ot_conf_group *conf_group;
239 struct flt_ot_conf_scope *conf_scope;
240 struct flt_ot_conf_ph *ph_group, *ph_scope;
241 int retval = 0, scope_unused_cnt = 0, span_root_cnt = 0;
242
243 FLT_OT_FUNC("%p, %p", p, fconf);
244
245 if (conf == NULL)
246 FLT_OT_RETURN(++retval);
247
248 /*
249 * If only the proxy specified with the <p> parameter is checked, then
250 * no duplicate filters can be found that are not defined in the same
251 * configuration sections.
252 */
253 for (px = proxies_list; px != NULL; px = px->next) {
254 struct flt_conf *fconf_tmp;
255
256 FLT_OT_DBG(2, "proxy '%s'", px->id);
257
258 /*
259 * The names of all OT filters (filter ID) should be checked,
260 * they must be unique.
261 */
262 list_for_each_entry(fconf_tmp, &(px->filter_configs), list)
263 if ((fconf_tmp != fconf) && (fconf_tmp->id == ot_flt_id)) {
264 struct flt_ot_conf *conf_tmp = fconf_tmp->conf;
265
266 FLT_OT_DBG(2, " OT filter '%s'", conf_tmp->id);
267
268 if (strcmp(conf_tmp->id, conf->id) == 0) {
269 FLT_OT_ALERT("''%s' : duplicated filter ID'", conf_tmp->id);
270
271 retval++;
272 }
273 }
274 }
275
276 if (FLT_OT_DEREF(conf->tracer, id, NULL) == NULL) {
277 FLT_OT_ALERT("''%s' : no tracer found'", conf->id);
278
279 retval++;
280 }
281
282 /*
283 * Checking that all defined 'ot-group' sections have correctly declared
284 * 'ot-scope' sections (ie whether the declared 'ot-scope' sections have
285 * corresponding definitions).
286 */
287 list_for_each_entry(conf_group, &(conf->groups), list)
288 list_for_each_entry(ph_scope, &(conf_group->ph_scopes), list) {
289 bool flag_found = 0;
290
291 list_for_each_entry(conf_scope, &(conf->scopes), list)
292 if (strcmp(ph_scope->id, conf_scope->id) == 0) {
293 ph_scope->ptr = conf_scope;
294 conf_scope->flag_used = 1;
295 flag_found = 1;
296
297 break;
298 }
299
300 if (!flag_found) {
301 FLT_OT_ALERT("'" FLT_OT_PARSE_SECTION_GROUP_ID " '%s' : try to use undefined " FLT_OT_PARSE_SECTION_SCOPE_ID " '%s''", conf_group->id, ph_scope->id);
302
303 retval++;
304 }
305 }
306
307 if (conf->tracer != NULL) {
308 /*
309 * Checking that all declared 'groups' keywords have correctly
310 * defined 'ot-group' sections.
311 */
312 list_for_each_entry(ph_group, &(conf->tracer->ph_groups), list) {
313 bool flag_found = 0;
314
315 list_for_each_entry(conf_group, &(conf->groups), list)
316 if (strcmp(ph_group->id, conf_group->id) == 0) {
317 ph_group->ptr = conf_group;
318 conf_group->flag_used = 1;
319 flag_found = 1;
320
321 break;
322 }
323
324 if (!flag_found) {
325 FLT_OT_ALERT("'" FLT_OT_PARSE_SECTION_TRACER_ID " '%s' : try to use undefined " FLT_OT_PARSE_SECTION_GROUP_ID " '%s''", conf->tracer->id, ph_group->id);
326
327 retval++;
328 }
329 }
330
331 /*
332 * Checking that all declared 'scopes' keywords have correctly
333 * defined 'ot-scope' sections.
334 */
335 list_for_each_entry(ph_scope, &(conf->tracer->ph_scopes), list) {
336 bool flag_found = 0;
337
338 list_for_each_entry(conf_scope, &(conf->scopes), list)
339 if (strcmp(ph_scope->id, conf_scope->id) == 0) {
340 ph_scope->ptr = conf_scope;
341 conf_scope->flag_used = 1;
342 flag_found = 1;
343
344 break;
345 }
346
347 if (!flag_found) {
348 FLT_OT_ALERT("'" FLT_OT_PARSE_SECTION_TRACER_ID " '%s' : try to use undefined " FLT_OT_PARSE_SECTION_SCOPE_ID " '%s''", conf->tracer->id, ph_scope->id);
349
350 retval++;
351 }
352 }
353 }
354
355 FLT_OT_DBG(3, "--- filter '%s' configuration ----------", conf->id);
356 FLT_OT_DBG(3, "- defined spans ----------");
357
358 list_for_each_entry(conf_scope, &(conf->scopes), list) {
359 if (conf_scope->flag_used) {
360 struct flt_ot_conf_span *conf_span;
361
362 /*
363 * In principle, only one span should be labeled
364 * as a root span.
365 */
366 list_for_each_entry(conf_span, &(conf_scope->spans), list) {
367 FLT_OT_DBG_CONF_SPAN(" ", conf_span);
368
369 span_root_cnt += conf_span->flag_root ? 1 : 0;
370 }
371
372#ifdef DEBUG_OT
373 conf->cnt.event[conf_scope->event].flag_used = 1;
374#endif
375
376 /* Set the flags of the analyzers used. */
377 conf->tracer->analyzers |= flt_ot_event_data[conf_scope->event].an_bit;
378 } else {
379 FLT_OT_ALERT("''%s' : unused " FLT_OT_PARSE_SECTION_SCOPE_ID " '%s''", conf->id, conf_scope->id);
380
381 scope_unused_cnt++;
382 }
383 }
384
385 /*
386 * Unused scopes or a number of root spans other than one do not
387 * necessarily have to be errors, but it is good to print it when
388 * starting HAProxy.
389 */
390 if (scope_unused_cnt > 0)
391 FLT_OT_ALERT("''%s' : %d scope(s) not in use'", conf->id, scope_unused_cnt);
392
393 if (LIST_ISEMPTY(&(conf->scopes)))
394 /* Do nothing. */;
395 else if (span_root_cnt == 0)
396 FLT_OT_ALERT("''%s' : no span is marked as the root span'", conf->id);
397 else if (span_root_cnt > 1)
398 FLT_OT_ALERT("''%s' : multiple spans are marked as the root span'", conf->id);
399
400 FLT_OT_DBG_LIST(conf, group, "", "defined", _group,
401 FLT_OT_DBG_CONF_GROUP(" ", _group);
402 FLT_OT_DBG_LIST(_group, ph_scope, " ", "used", _scope, FLT_OT_DBG_CONF_PH(" ", _scope)));
403 FLT_OT_DBG_LIST(conf, scope, "", "defined", _scope, FLT_OT_DBG_CONF_SCOPE(" ", _scope));
404
405 if (conf->tracer != NULL) {
406 FLT_OT_DBG(3, " --- tracer '%s' configuration ----------", conf->tracer->id);
407 FLT_OT_DBG_LIST(conf->tracer, ph_group, " ", "used", _group, FLT_OT_DBG_CONF_PH(" ", _group));
408 FLT_OT_DBG_LIST(conf->tracer, ph_scope, " ", "used", _scope, FLT_OT_DBG_CONF_PH(" ", _scope));
409 }
410
411 FLT_OT_RETURN(retval);
412}
413
414
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100415/***
416 * NAME
417 * flt_ot_init_per_thread -
418 *
419 * ARGUMENTS
420 * p -
421 * fconf -
422 *
423 * DESCRIPTION
424 * It initializes the filter for each thread. It works the same way than
425 * flt_ot_init() but in the context of a thread. This callback is called
426 * after the thread creation.
427 *
428 * RETURN VALUE
429 * Returns a negative value if an error occurs, any other value otherwise.
430 */
431static int flt_ot_init_per_thread(struct proxy *p, struct flt_conf *fconf)
432{
Miroslav Zagoracf2263432021-04-02 04:25:47 +0200433 struct flt_ot_conf *conf = FLT_OT_DEREF(fconf, conf, NULL);
434 char *err = NULL;
435 int retval = FLT_OT_RET_ERROR;
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100436
437 FLT_OT_FUNC("%p, %p", p, fconf);
438
Miroslav Zagoracf2263432021-04-02 04:25:47 +0200439 if (conf == NULL)
440 FLT_OT_RETURN(retval);
441
442 /*
443 * Initialize the OpenTracing library.
444 * Enable HTX streams filtering.
445 */
446 if (conf->tracer->tracer == NULL) {
447 retval = ot_init(&(conf->tracer->tracer), conf->tracer->config, conf->tracer->plugin, &err);
448 if (retval != FLT_OT_RET_ERROR)
449 fconf->flags |= FLT_CFG_FL_HTX;
450 else if (err != NULL) {
451 FLT_OT_ALERT("%s", err);
452
453 FLT_OT_ERR_FREE(err);
454 }
455 } else {
456 retval = FLT_OT_RET_OK;
457 }
458
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100459 FLT_OT_RETURN(retval);
460}
461
462
Miroslav Zagoracf2263432021-04-02 04:25:47 +0200463#ifdef DEBUG_OT
464
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100465/***
466 * NAME
467 * flt_ot_deinit_per_thread -
468 *
469 * ARGUMENTS
470 * p -
471 * fconf -
472 *
473 * DESCRIPTION
474 * It cleans up what the init_per_thread callback have done. It is called
475 * in the context of a thread, before exiting it.
476 *
477 * RETURN VALUE
478 * This function does not return a value.
479 */
480static void flt_ot_deinit_per_thread(struct proxy *p, struct flt_conf *fconf)
481{
482 FLT_OT_FUNC("%p, %p", p, fconf);
483
484 FLT_OT_RETURN();
485}
486
487#endif /* DEBUG_OT */
488
489
490/***
491 * NAME
492 * flt_ot_attach - Called when a filter instance is created and attach to a stream.
493 *
494 * ARGUMENTS
495 * s -
496 * f -
497 *
498 * DESCRIPTION
499 * It is called after a filter instance creation, when it is attached to a
500 * stream. This happens when the stream is started for filters defined on
501 * the stream's frontend and when the backend is set for filters declared
502 * on the stream's backend. It is possible to ignore the filter, if needed,
503 * by returning 0. This could be useful to have conditional filtering.
504 *
505 * RETURN VALUE
506 * Returns a negative value if an error occurs, 0 to ignore the filter,
507 * any other value otherwise.
508 */
509static int flt_ot_attach(struct stream *s, struct filter *f)
510{
511 const struct flt_ot_conf *conf = FLT_OT_CONF(f);
512 char *err = NULL;
513
514 FLT_OT_FUNC("%p, %p", s, f);
515
516 if (conf->tracer->flag_disabled) {
517 FLT_OT_DBG(2, "filter '%s', type: %s (disabled)", conf->id, flt_ot_type(f));
518
519 FLT_OT_RETURN(FLT_OT_RET_IGNORE);
520 }
521 else if (conf->tracer->rate_limit < FLT_OT_FLOAT_U32(FLT_OT_RATE_LIMIT_MAX, FLT_OT_RATE_LIMIT_MAX)) {
522 uint32_t rnd = ha_random32();
523
524 if (conf->tracer->rate_limit <= rnd) {
525 FLT_OT_DBG(2, "filter '%s', type: %s (ignored: %u <= %u)", conf->id, flt_ot_type(f), conf->tracer->rate_limit, rnd);
526
527 FLT_OT_RETURN(FLT_OT_RET_IGNORE);
528 }
529 }
530
531 FLT_OT_DBG(2, "filter '%s', type: %s (run)", conf->id, flt_ot_type(f));
532
533 f->ctx = flt_ot_runtime_context_init(s, f, &err);
534 FLT_OT_ERR_FREE(err);
535 if (f->ctx == NULL) {
536 FLT_OT_LOG(LOG_EMERG, "failed to create context");
537
538 FLT_OT_RETURN(FLT_OT_RET_IGNORE);
539 }
540
541 /*
542 * AN_REQ_WAIT_HTTP and AN_RES_WAIT_HTTP analyzers can only be used
543 * in the .channel_post_analyze callback function.
544 */
545 f->pre_analyzers |= conf->tracer->analyzers & ((AN_REQ_ALL & ~AN_REQ_WAIT_HTTP & ~AN_REQ_HTTP_TARPIT) | (AN_RES_ALL & ~AN_RES_WAIT_HTTP));
546 f->post_analyzers |= conf->tracer->analyzers & (AN_REQ_WAIT_HTTP | AN_RES_WAIT_HTTP);
547
548 FLT_OT_LOG(LOG_INFO, "%08x %08x", f->pre_analyzers, f->post_analyzers);
549
550 flt_ot_vars_dump(s);
551 flt_ot_http_headers_dump(&(s->req));
552
553 FLT_OT_RETURN(FLT_OT_RET_OK);
554}
555
556
557#ifdef DEBUG_OT
558
559/***
560 * NAME
561 * flt_ot_stream_start - Called when a stream is created.
562 *
563 * ARGUMENTS
564 * s -
565 * f -
566 *
567 * DESCRIPTION
568 * It is called when a stream is started. This callback can fail by
569 * returning a negative value. It will be considered as a critical error
570 * by HAProxy which disabled the listener for a short time.
571 *
572 * RETURN VALUE
573 * Returns a negative value if an error occurs, any other value otherwise.
574 */
575static int flt_ot_stream_start(struct stream *s, struct filter *f)
576{
577 char *err = NULL;
578 int retval = FLT_OT_RET_OK;
579
580 FLT_OT_FUNC("%p, %p", s, f);
581
582 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
583 FLT_OT_RETURN(retval);
584
585 FLT_OT_RETURN(flt_ot_return_int(f, &err, retval));
586}
587
588
589/***
590 * NAME
591 * flt_ot_stream_set_backend - Called when a backend is set for a stream.
592 *
593 * ARGUMENTS
594 * s -
595 * f -
596 * be -
597 *
598 * DESCRIPTION
599 * It is called when a backend is set for a stream. This callbacks will be
600 * called for all filters attached to a stream (frontend and backend). Note
601 * this callback is not called if the frontend and the backend are the same.
602 *
603 * RETURN VALUE
604 * Returns a negative value if an error occurs, any other value otherwise.
605 */
606static int flt_ot_stream_set_backend(struct stream *s, struct filter *f, struct proxy *be)
607{
608 char *err = NULL;
609 int retval = FLT_OT_RET_OK;
610
611 FLT_OT_FUNC("%p, %p, %p", s, f, be);
612
613 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
614 FLT_OT_RETURN(retval);
615
616 FLT_OT_DBG(3, "backend: %s", be->id);
617
618 FLT_OT_RETURN(flt_ot_return_int(f, &err, retval));
619}
620
621
622/***
623 * NAME
624 * flt_ot_stream_stop - Called when a stream is destroyed.
625 *
626 * ARGUMENTS
627 * s -
628 * f -
629 *
630 * DESCRIPTION
631 * It is called when a stream is stopped. This callback always succeed.
632 * Anyway, it is too late to return an error.
633 *
634 * RETURN VALUE
635 * This function does not return a value.
636 */
637static void flt_ot_stream_stop(struct stream *s, struct filter *f)
638{
639 char *err = NULL;
640
641 FLT_OT_FUNC("%p, %p", s, f);
642
643 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
644 FLT_OT_RETURN();
645
646 flt_ot_return_void(f, &err);
647
648 FLT_OT_RETURN();
649}
650
651#endif /* DEBUG_OT */
652
653
654/***
655 * NAME
656 * flt_ot_detach - Called when a filter instance is detach from a stream, just before its destruction.
657 *
658 * ARGUMENTS
659 * s -
660 * f -
661 *
662 * DESCRIPTION
663 * It is called when a filter instance is detached from a stream, before its
664 * destruction. This happens when the stream is stopped for filters defined
665 * on the stream's frontend and when the analyze ends for filters defined on
666 * the stream's backend.
667 *
668 * RETURN VALUE
669 * This function does not return a value.
670 */
671static void flt_ot_detach(struct stream *s, struct filter *f)
672{
673 FLT_OT_FUNC("%p, %p", s, f);
674
675 FLT_OT_DBG(2, "filter '%s', type: %s", FLT_OT_CONF(f)->id, flt_ot_type(f));
676
677 flt_ot_runtime_context_free(f);
678
679 FLT_OT_RETURN();
680}
681
682
683/***
684 * NAME
685 * flt_ot_check_timeouts - Called when a stream is woken up because of an expired timer.
686 *
687 * ARGUMENTS
688 * s -
689 * f -
690 *
691 * DESCRIPTION
692 * -
693 *
694 * RETURN VALUE
695 * This function does not return a value.
696 */
697static void flt_ot_check_timeouts(struct stream *s, struct filter *f)
698{
699 char *err = NULL;
700
701 FLT_OT_FUNC("%p, %p", s, f);
702
703 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
704 FLT_OT_RETURN();
705
706 s->pending_events |= TASK_WOKEN_MSG;
707
708 flt_ot_return_void(f, &err);
709
710 FLT_OT_RETURN();
711}
712
713
714/***
715 * NAME
716 * flt_ot_channel_start_analyze - Called when analyze starts for a given channel.
717 *
718 * ARGUMENTS
719 * s -
720 * f -
721 * chn -
722 *
723 * DESCRIPTION
724 * -
725 *
726 * RETURN VALUE
727 * Returns a negative value if an error occurs, 0 if it needs to wait,
728 * any other value otherwise.
729 */
730static int flt_ot_channel_start_analyze(struct stream *s, struct filter *f, struct channel *chn)
731{
732 char *err = NULL;
733 int retval;
734
735 FLT_OT_FUNC("%p, %p, %p", s, f, chn);
736
737 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, (chn->flags & CF_ISRESP) ? FLT_OT_EVENT_RES_SERVER_SESS_START : FLT_OT_EVENT_REQ_CLIENT_SESS_START)))
738 FLT_OT_RETURN(FLT_OT_RET_OK);
739
740 FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s));
741
742 if (chn->flags & CF_ISRESP) {
743 /* The response channel. */
744 chn->analysers |= f->pre_analyzers & AN_RES_ALL;
745
746 /* The event 'on-server-session-start'. */
747 retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_RES_SERVER_SESS_START, &err);
748 if (retval == FLT_OT_RET_WAIT) {
749 channel_dont_read(chn);
750 channel_dont_close(chn);
751 }
752 } else {
753 /* The request channel. */
754 chn->analysers |= f->pre_analyzers & AN_REQ_ALL;
755
756 /* The event 'on-client-session-start'. */
757 retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_REQ_CLIENT_SESS_START, &err);
758 }
759
760// register_data_filter(s, chn, f);
761
762 FLT_OT_RETURN(flt_ot_return_int(f, &err, retval));
763}
764
765
766/***
767 * NAME
768 * flt_ot_channel_pre_analyze - Called before a processing happens on a given channel.
769 *
770 * ARGUMENTS
771 * s -
772 * f -
773 * chn - the channel on which the analyzing is done
774 * an_bit - the analyzer id
775 *
776 * DESCRIPTION
777 * -
778 *
779 * RETURN VALUE
780 * Returns a negative value if an error occurs, 0 if it needs to wait,
781 * any other value otherwise.
782 */
783static int flt_ot_channel_pre_analyze(struct stream *s, struct filter *f, struct channel *chn, uint an_bit)
784{
785 char *err = NULL;
786 int i, event = -1, retval;
787
788 FLT_OT_FUNC("%p, %p, %p, 0x%08x", s, f, chn, an_bit);
789
790 for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_event_data); i++)
791 if (flt_ot_event_data[i].an_bit == an_bit) {
792 event = i;
793
794 break;
795 }
796
797 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, event)))
798 FLT_OT_RETURN(FLT_OT_RET_OK);
799
800 FLT_OT_DBG(3, "channel: %s, mode: %s (%s), analyzer: %s", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), flt_ot_analyzer(an_bit));
801
802 retval = flt_ot_event_run(s, f, chn, event, &err);
803
804 if ((retval == FLT_OT_RET_WAIT) && (chn->flags & CF_ISRESP)) {
805 channel_dont_read(chn);
806 channel_dont_close(chn);
807 }
808
809 FLT_OT_RETURN(flt_ot_return_int(f, &err, retval));
810}
811
812
813/***
814 * NAME
815 * flt_ot_channel_post_analyze - Called after a processing happens on a given channel.
816 *
817 * ARGUMENTS
818 * s -
819 * f -
820 * chn -
821 * an_bit -
822 *
823 * DESCRIPTION
824 * This function, for its part, is not resumable. It is called when a
825 * filterable analyzer finishes its processing. So it called once for
826 * the same analyzer.
827 *
828 * RETURN VALUE
829 * Returns a negative value if an error occurs, 0 if it needs to wait,
830 * any other value otherwise.
831 */
832static int flt_ot_channel_post_analyze(struct stream *s, struct filter *f, struct channel *chn, uint an_bit)
833{
834 char *err = NULL;
835 int i, event = -1, retval;
836
837 FLT_OT_FUNC("%p, %p, %p, 0x%08x", s, f, chn, an_bit);
838
839 for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_event_data); i++)
840 if (flt_ot_event_data[i].an_bit == an_bit) {
841 event = i;
842
843 break;
844 }
845
846 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, event)))
847 FLT_OT_RETURN(FLT_OT_RET_OK);
848
849 FLT_OT_DBG(3, "channel: %s, mode: %s (%s), analyzer: %s", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), flt_ot_analyzer(an_bit));
850
851 retval = flt_ot_event_run(s, f, chn, event, &err);
852
853 FLT_OT_RETURN(flt_ot_return_int(f, &err, retval));
854}
855
856
857/***
858 * NAME
859 * flt_ot_channel_end_analyze - Called when analyze ends for a given channel.
860 *
861 * ARGUMENTS
862 * s -
863 * f -
864 * chn -
865 *
866 * DESCRIPTION
867 * -
868 *
869 * RETURN VALUE
870 * Returns a negative value if an error occurs, 0 if it needs to wait,
871 * any other value otherwise.
872 */
873static int flt_ot_channel_end_analyze(struct stream *s, struct filter *f, struct channel *chn)
874{
875 char *err = NULL;
876 int rc, retval;
877
878 FLT_OT_FUNC("%p, %p, %p", s, f, chn);
879
880 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, (chn->flags & CF_ISRESP) ? FLT_OT_EVENT_RES_SERVER_SESS_END : FLT_OT_EVENT_REQ_CLIENT_SESS_END)))
881 FLT_OT_RETURN(FLT_OT_RET_OK);
882
883 FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s));
884
885 if (chn->flags & CF_ISRESP) {
886 /* The response channel, event 'on-server-session-end'. */
887 retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_RES_SERVER_SESS_END, &err);
888 } else {
889 /* The request channel, event 'on-client-session-end'. */
890 retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_REQ_CLIENT_SESS_END, &err);
891
892 /*
893 * In case an event using server response is defined and not
894 * executed, event 'on-server-unavailable' is called here.
895 */
896 if ((FLT_OT_CONF(f)->tracer->analyzers & AN_RES_ALL) && !(FLT_OT_RT_CTX(f->ctx)->analyzers & AN_RES_ALL)) {
897 rc = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_REQ_SERVER_UNAVAILABLE, &err);
898 if ((retval == FLT_OT_RET_OK) && (rc != FLT_OT_RET_OK))
899 retval = rc;
900 }
901 }
902
903 FLT_OT_RETURN(flt_ot_return_int(f, &err, retval));
904}
905
906
907#ifdef DEBUG_OT
908
909/***
910 * NAME
911 * flt_ot_http_headers -
912 *
913 * ARGUMENTS
914 * s -
915 * f -
916 * msg -
917 *
918 * DESCRIPTION
919 * -
920 *
921 * RETURN VALUE
922 * Returns a negative value if an error occurs, 0 if it needs to wait,
923 * any other value otherwise.
924 */
925static int flt_ot_http_headers(struct stream *s, struct filter *f, struct http_msg *msg)
926{
927 char *err = NULL;
928 struct htx *htx = htxbuf(&(msg->chn->buf));
929 struct htx_sl *sl = http_get_stline(htx);
930 int retval = FLT_OT_RET_OK;
931
932 FLT_OT_FUNC("%p, %p, %p", s, f, msg);
933
934 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
935 FLT_OT_RETURN(retval);
936
937 FLT_OT_DBG(3, "channel: %s, mode: %s (%s), %.*s %.*s %.*s", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), HTX_SL_P1_LEN(sl), HTX_SL_P1_PTR(sl), HTX_SL_P2_LEN(sl), HTX_SL_P2_PTR(sl), HTX_SL_P3_LEN(sl), HTX_SL_P3_PTR(sl));
938
939 FLT_OT_RETURN(flt_ot_return_int(f, &err, retval));
940}
941
942
943/***
944 * NAME
945 * flt_ot_http_payload -
946 *
947 * ARGUMENTS
948 * s -
949 * f -
950 * msg -
951 * offset -
952 * len -
953 *
954 * DESCRIPTION
955 * -
956 *
957 * RETURN VALUE
958 * Returns a negative value if an error occurs, any other value otherwise.
959 */
960static int flt_ot_http_payload(struct stream *s, struct filter *f, struct http_msg *msg, uint offset, uint len)
961{
962 char *err = NULL;
963 int retval = len;
964
965 FLT_OT_FUNC("%p, %p, %p, %u, %u", s, f, msg, offset, len);
966
967 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
968 FLT_OT_RETURN(len);
969
970 FLT_OT_DBG(3, "channel: %s, mode: %s (%s), offset: %u, len: %u, forward: %d", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), offset, len, retval);
971
972 if (retval != len)
973 task_wakeup(s->task, TASK_WOKEN_MSG);
974
975 FLT_OT_RETURN(flt_ot_return_int(f, &err, retval));
976}
977
978
979/***
980 * NAME
981 * flt_ot_http_end -
982 *
983 * ARGUMENTS
984 * s -
985 * f -
986 * msg -
987 *
988 * DESCRIPTION
989 * -
990 *
991 * RETURN VALUE
992 * Returns a negative value if an error occurs, 0 if it needs to wait,
993 * any other value otherwise.
994 */
995static int flt_ot_http_end(struct stream *s, struct filter *f, struct http_msg *msg)
996{
997 char *err = NULL;
998 int retval = FLT_OT_RET_OK;
999
1000 FLT_OT_FUNC("%p, %p, %p", s, f, msg);
1001
1002 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
1003 FLT_OT_RETURN(retval);
1004
1005 FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s));
1006
1007 FLT_OT_RETURN(flt_ot_return_int(f, &err, retval));
1008}
1009
1010
1011/***
1012 * NAME
1013 * flt_ot_http_reset -
1014 *
1015 * ARGUMENTS
1016 * s -
1017 * f -
1018 * msg -
1019 *
1020 * DESCRIPTION
1021 * -
1022 *
1023 * RETURN VALUE
1024 * This function does not return a value.
1025 */
1026static void flt_ot_http_reset(struct stream *s, struct filter *f, struct http_msg *msg)
1027{
1028 char *err = NULL;
1029
1030 FLT_OT_FUNC("%p, %p, %p", s, f, msg);
1031
1032 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
1033 FLT_OT_RETURN();
1034
1035 FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s));
1036
1037 flt_ot_return_void(f, &err);
1038
1039 FLT_OT_RETURN();
1040}
1041
1042
1043/***
1044 * NAME
1045 * flt_ot_http_reply -
1046 *
1047 * ARGUMENTS
1048 * s -
1049 * f -
1050 * status -
1051 * msg -
1052 *
1053 * DESCRIPTION
1054 * -
1055 *
1056 * RETURN VALUE
1057 * This function does not return a value.
1058 */
1059static void flt_ot_http_reply(struct stream *s, struct filter *f, short status, const struct buffer *msg)
1060{
1061 char *err = NULL;
1062
1063 FLT_OT_FUNC("%p, %p, %hd, %p", s, f, status, msg);
1064
1065 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
1066 FLT_OT_RETURN();
1067
1068 FLT_OT_DBG(3, "channel: -, mode: %s (%s)", flt_ot_pr_mode(s), flt_ot_stream_pos(s));
1069
1070 flt_ot_return_void(f, &err);
1071
1072 FLT_OT_RETURN();
1073}
1074
1075
1076/***
1077 * NAME
1078 * flt_ot_tcp_payload -
1079 *
1080 * ARGUMENTS
1081 * s -
1082 * f -
1083 * chn -
1084 * offset -
1085 * len -
1086 *
1087 * DESCRIPTION
1088 * -
1089 *
1090 * RETURN VALUE
1091 * Returns a negative value if an error occurs, any other value otherwise.
1092 */
1093static int flt_ot_tcp_payload(struct stream *s, struct filter *f, struct channel *chn, uint offset, uint len)
1094{
1095 char *err = NULL;
1096 int retval = len;
1097
1098 FLT_OT_FUNC("%p, %p, %p, %u, %u", s, f, chn, offset, len);
1099
1100 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
1101 FLT_OT_RETURN(len);
1102
1103 FLT_OT_DBG(3, "channel: %s, mode: %s (%s), offset: %u, len: %u, forward: %d", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), offset, len, retval);
1104
1105 if (s->flags & SF_HTX) {
1106 } else {
1107 }
1108
1109 if (retval != len)
1110 task_wakeup(s->task, TASK_WOKEN_MSG);
1111
1112 FLT_OT_RETURN(flt_ot_return_int(f, &err, retval));
1113}
1114
1115#endif /* DEBUG_OT */
1116
1117
1118struct flt_ops flt_ot_ops = {
1119 /* Callbacks to manage the filter lifecycle. */
1120 .init = flt_ot_init,
1121 .deinit = flt_ot_deinit,
1122 .check = flt_ot_check,
Miroslav Zagoracf2263432021-04-02 04:25:47 +02001123 .init_per_thread = flt_ot_init_per_thread,
Miroslav Zagorac70230c62020-12-09 16:54:31 +01001124 .deinit_per_thread = FLT_OT_DBG_IFDEF(flt_ot_deinit_per_thread, NULL),
1125
1126 /* Stream callbacks. */
1127 .attach = flt_ot_attach,
1128 .stream_start = FLT_OT_DBG_IFDEF(flt_ot_stream_start, NULL),
1129 .stream_set_backend = FLT_OT_DBG_IFDEF(flt_ot_stream_set_backend, NULL),
1130 .stream_stop = FLT_OT_DBG_IFDEF(flt_ot_stream_stop, NULL),
1131 .detach = flt_ot_detach,
1132 .check_timeouts = flt_ot_check_timeouts,
1133
1134 /* Channel callbacks. */
1135 .channel_start_analyze = flt_ot_channel_start_analyze,
1136 .channel_pre_analyze = flt_ot_channel_pre_analyze,
1137 .channel_post_analyze = flt_ot_channel_post_analyze,
1138 .channel_end_analyze = flt_ot_channel_end_analyze,
1139
1140 /* HTTP callbacks. */
1141 .http_headers = FLT_OT_DBG_IFDEF(flt_ot_http_headers, NULL),
1142 .http_payload = FLT_OT_DBG_IFDEF(flt_ot_http_payload, NULL),
1143 .http_end = FLT_OT_DBG_IFDEF(flt_ot_http_end, NULL),
1144 .http_reset = FLT_OT_DBG_IFDEF(flt_ot_http_reset, NULL),
1145 .http_reply = FLT_OT_DBG_IFDEF(flt_ot_http_reply, NULL),
1146
1147 /* TCP callbacks. */
1148 .tcp_payload = FLT_OT_DBG_IFDEF(flt_ot_tcp_payload, NULL)
1149};
1150
1151
1152REGISTER_BUILD_OPTS("Built with OpenTracing support.");
1153
1154/*
1155 * Local variables:
1156 * c-indent-level: 8
1157 * c-basic-offset: 8
1158 * End:
1159 *
1160 * vi: noexpandtab shiftwidth=8 tabstop=8
1161 */