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