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