Asterisk - The Open Source Telephony Project GIT-master-f36a736
pjsip_transport_events.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2017, Digium Inc.
5 *
6 * Richard Mudgett <rmudgett@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*!
20 * \file
21 * \brief Manages the global transport event notification callbacks.
22 *
23 * \author Richard Mudgett <rmudgett@digium.com>
24 * See Also:
25 *
26 * \arg \ref AstCREDITS
27 */
28
29
30#include "asterisk.h"
31
32#include "asterisk/res_pjsip.h"
36#include "asterisk/vector.h"
37
38/* ------------------------------------------------------------------- */
39
40/*! \brief Number of buckets for monitored active transports */
41#define ACTIVE_TRANSPORTS_BUCKETS 127
42
43/*! Who to notify when transport shuts down. */
45 /*! Who to call when transport shuts down. */
47 /*! ao2 data object to pass to callback. */
48 void *data;
49};
50
51/*! \brief Structure for transport to be monitored */
53 /*! \brief Key <ipaddr>:<port> */
55 /*! \brief The underlying PJSIP transport */
56 pjsip_transport *transport;
57 /*! For debugging purposes, we save the obj_name
58 * in case the transport goes away.
59 */
61 /*! Who is interested in when this transport shuts down. */
63};
64
65/*! \brief Global container of active reliable transports */
66static AO2_GLOBAL_OBJ_STATIC(active_transports);
67
68/*! \brief Existing transport events callback that we need to invoke */
69static pjsip_tp_state_callback tpmgr_state_callback;
70
71/*! List of registered transport state callbacks. */
73
74/*! \brief Hashing function for struct transport_monitor */
76
77/*! \brief Comparison function for struct transport_monitor */
79
80/*! \brief Sort function for struct transport_monitor */
82
83static const char *transport_state2str(pjsip_transport_state state)
84{
85 const char *name;
86
87 switch (state) {
88 case PJSIP_TP_STATE_CONNECTED:
89 name = "CONNECTED";
90 break;
91 case PJSIP_TP_STATE_DISCONNECTED:
92 name = "DISCONNECTED";
93 break;
94 case PJSIP_TP_STATE_SHUTDOWN:
95 name = "SHUTDOWN";
96 break;
97 case PJSIP_TP_STATE_DESTROY:
98 name = "DESTROY";
99 break;
100 default:
101 /*
102 * We have to have a default case because the enum is
103 * defined by a third-party library.
104 */
105 ast_assert(0);
106 name = "<unknown>";
107 break;
108 }
109 return name;
110}
111
112static void transport_monitor_dtor(void *vdoomed)
113{
114 struct transport_monitor *monitored = vdoomed;
115 int idx;
116
117 for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {
118 struct transport_monitor_notifier *notifier;
119
120 notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);
121 ao2_cleanup(notifier->data);
122 }
123 AST_VECTOR_FREE(&monitored->monitors);
124 ast_debug(3, "Transport %s(%s,%s) RefCnt: %ld : state:MONITOR_DESTROYED\n",
125 monitored->key, monitored->transport->obj_name,
126 monitored->transport->type_name,pj_atomic_get(monitored->transport->ref_cnt));
127 ast_free(monitored->transport_obj_name);
128 pjsip_transport_dec_ref(monitored->transport);
129}
130
131/*!
132 * \internal
133 * \brief Do registered callbacks for the transport.
134 * \since 13.21.0
135 *
136 * \param transports Active transports container
137 * \param transport Which transport to do callbacks for.
138 */
139static void transport_state_do_reg_callbacks(struct ao2_container *transports, pjsip_transport *transport)
140{
141 struct ao2_iterator *monitor_iter;
142 struct transport_monitor *monitored;
144 int idx;
145
147
148 monitor_iter = ao2_find(transports, key, OBJ_SEARCH_KEY | OBJ_MULTIPLE);
149 while ((monitored = ao2_iterator_next(monitor_iter))) {
150 if (monitored->transport == transport) {
151 ao2_unlink(transports, monitored);
152 for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {
153 struct transport_monitor_notifier *notifier;
154
155 notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);
156 ast_debug(3, "Transport %s(%s,%s) RefCnt: %ld : running callback %p(%p)\n",
157 monitored->key, monitored->transport->obj_name,
158 monitored->transport->type_name,
159 pj_atomic_get(monitored->transport->ref_cnt), notifier->cb, notifier->data);
160 notifier->cb(notifier->data);
161 }
162 } else {
163 ast_debug(3, "Transport %s(%s,%s) RefCnt: %ld : ignored not matching %s\n",
164 monitored->key, monitored->transport->obj_name,
165 monitored->transport->type_name,
166 pj_atomic_get(monitored->transport->ref_cnt), transport->obj_name);
167 }
168 ao2_ref(monitored, -1);
169 }
170 ao2_iterator_destroy(monitor_iter);
171}
172
173static void verify_log_result(int log_level, const pjsip_transport *transport,
174 pj_uint32_t verify_status)
175{
176 char transport_remote_ipaddr_port[IP6ADDR_COLON_PORT_BUFLEN];
177 const char *status[32];
178 unsigned int count;
179 unsigned int i;
180
181 count = ARRAY_LEN(status);
182
183 if (pj_ssl_cert_get_verify_status_strings(verify_status, status, &count) != PJ_SUCCESS) {
184 ast_log(LOG_ERROR, "Error retrieving certificate verification result(s)\n");
185 return;
186 }
187
188 AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(transport, transport_remote_ipaddr_port);
189 for (i = 0; i < count; ++i) {
190 ast_log(log_level, _A_, "Transport '%s' to remote '%.*s' - %s - %s\n", transport->factory->info,
191 (int)pj_strlen(&transport->remote_name.host), pj_strbuf(&transport->remote_name.host),
192 transport_remote_ipaddr_port,
193 status[i]);
194 }
195}
196
197static int verify_cert_name(const pj_str_t *local, const pj_str_t *remote)
198{
199 const char *p;
200 pj_ssize_t size;
201
202 ast_debug(3, "Verify certificate name: local = %.*s, remote = %.*s\n",
203 (unsigned int)pj_strlen(local), pj_strbuf(local),
204 (unsigned int)pj_strlen(remote), pj_strbuf(remote));
205
206 if (!pj_stricmp(remote, local)) {
207 return 1;
208 }
209
210 if (pj_strnicmp2(remote, "*.", 2)) {
211 return 0;
212 }
213
214 p = pj_strchr(local, '.');
215 if (!p) {
216 return 0;
217 }
218
219 size = pj_strbuf(local) + pj_strlen(local) - ++p;
220
221 return size == pj_strlen(remote) - 2 ?
222 !pj_memcmp(pj_strbuf(remote) + 2, p, size) : 0;
223}
224
225static int verify_cert_names(const pj_str_t *host, const pj_ssl_cert_info *remote)
226{
227 unsigned int i;
228
229 for (i = 0; i < remote->subj_alt_name.cnt; ++i) {
230 /*
231 * DNS is the only type we're matching wildcards against,
232 * so only recheck those.
233 */
234 if (remote->subj_alt_name.entry[i].type == PJ_SSL_CERT_NAME_DNS
235 && verify_cert_name(host, &remote->subj_alt_name.entry[i].name)) {
236 return 1;
237 }
238 }
239
240 return verify_cert_name(host, &remote->subject.cn);
241}
242
243static int transport_tls_verify(const pjsip_transport *transport,
244 const pjsip_tls_state_info *state_info)
245{
246 pj_uint32_t verify_status;
247 const struct ast_sip_transport_state *state;
248
249 if (transport->dir == PJSIP_TP_DIR_INCOMING) {
250 return 1;
251 }
252
253 /* transport_id should always be in factory info (see config_transport) */
254 ast_assert(!ast_strlen_zero(transport->factory->info));
255
257 if (!state) {
258 /*
259 * There should always be an associated state, but if for some
260 * reason there is not then fail verification
261 */
262 ast_log(LOG_ERROR, "Transport state not found for '%s'\n", transport->factory->info);
263 return 0;
264 }
265
266 verify_status = state_info->ssl_sock_info->verify_status;
267
268 /*
269 * By this point pjsip has already completed its verification process. If
270 * there was a name matching error it could be because they disallow wildcards.
271 * If this transport has been configured to allow wildcards then we'll need
272 * to re-check the name(s) for such.
273 */
274 if (state->allow_wildcard_certs &&
275 (verify_status & PJ_SSL_CERT_EIDENTITY_NOT_MATCH)) {
276 if (verify_cert_names(&transport->remote_name.host,
277 state_info->ssl_sock_info->remote_cert_info)) {
278 /* A name matched a wildcard, so clear the error */
279 verify_status &= ~PJ_SSL_CERT_EIDENTITY_NOT_MATCH;
280 }
281 }
282
283 if (state->verify_server && verify_status != PJ_SSL_CERT_ESUCCESS) {
284 verify_log_result(__LOG_ERROR, transport, verify_status);
285 return 0;
286 }
287
289 return 1;
290}
291
292/*! \brief Callback invoked when transport state changes occur */
293static void transport_state_callback(pjsip_transport *transport,
294 pjsip_transport_state state, const pjsip_transport_state_info *info)
295{
296 struct ao2_container *transports;
297 char transport_remote_ipaddr_port[IP6ADDR_COLON_PORT_BUFLEN];
298
299 /* We only care about monitoring reliable transports */
300 if (PJSIP_TRANSPORT_IS_RELIABLE(transport)
301 && (transports = ao2_global_obj_ref(active_transports))) {
302 struct transport_monitor *monitored;
303 AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(transport, transport_remote_ipaddr_port);
304
305 ast_debug(3, "Transport %s(%s,%s): RefCnt: %ld state:%s\n",
306 transport_remote_ipaddr_port, transport->obj_name, transport->type_name,
307 pj_atomic_get(transport->ref_cnt), transport_state2str(state));
308 switch (state) {
309 case PJSIP_TP_STATE_CONNECTED:
310 if (PJSIP_TRANSPORT_IS_SECURE(transport) &&
311 !transport_tls_verify(transport, info->ext_info)) {
312 pjsip_transport_shutdown(transport);
313 return;
314 }
315
316 monitored = ao2_alloc_options(sizeof(*monitored),
318 if (!monitored) {
319 break;
320 }
321 monitored->transport = transport;
322 ast_copy_string(monitored->key, transport_remote_ipaddr_port, sizeof(monitored->key));
323 monitored->transport_obj_name = ast_strdup(transport->obj_name);
324
325 if (AST_VECTOR_INIT(&monitored->monitors, 5)) {
326 ao2_ref(monitored, -1);
327 break;
328 }
329 pjsip_transport_add_ref(monitored->transport);
330 ast_debug(3, "Transport %s(%s,%s): RefCnt: %ld state:MONITOR_CREATED\n",
331 monitored->key, monitored->transport_obj_name,
332 monitored->transport->type_name,
333 pj_atomic_get(monitored->transport->ref_cnt));
334
335 ao2_link(transports, monitored);
336 ao2_ref(monitored, -1);
337 break;
338 case PJSIP_TP_STATE_DISCONNECTED:
339 if (!transport->is_shutdown) {
340 pjsip_transport_shutdown(transport);
341 }
343 break;
344 case PJSIP_TP_STATE_SHUTDOWN:
345 /*
346 * Set shutdown flag early so we can force a new transport to be
347 * created if a monitor callback needs to reestablish a link.
348 * PJPROJECT sets the flag after this routine returns even though
349 * it has already called the transport's shutdown routine.
350 */
351 transport->is_shutdown = PJ_TRUE;
352
354 break;
355 case PJSIP_TP_STATE_DESTROY:
357 break;
358 default:
359 /*
360 * We have to have a default case because the enum is
361 * defined by a third-party library.
362 */
363 ast_assert(0);
364 break;
365 }
366
367 ao2_ref(transports, -1);
368 }
369
370 /* Loop over other transport state callbacks registered with us. */
372 struct ast_sip_tpmgr_state_callback *tpmgr_notifier;
373
375 AST_LIST_TRAVERSE(&transport_state_list, tpmgr_notifier, node) {
376 tpmgr_notifier->cb(transport, state, info);
377 }
379 }
380
381 /* Forward to the old state callback if present */
383 tpmgr_state_callback(transport, state, info);
384 }
385}
386
389 void *data;
391};
392
393static int transport_monitor_unregister_cb(void *obj, void *arg, int flags)
394{
395 struct transport_monitor *monitored = obj;
396 struct callback_data *cb_data = arg;
397 int idx;
398
399 for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {
400 struct transport_monitor_notifier *notifier;
401
402 notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);
403 if (notifier->cb == cb_data->cb && (!cb_data->data
404 || cb_data->matches(cb_data->data, notifier->data))) {
405 ao2_cleanup(notifier->data);
406 AST_VECTOR_REMOVE_UNORDERED(&monitored->monitors, idx);
407 ast_debug(3, "Transport %s(%s,%s) RefCnt: %ld : Unregistered monitor %p(%p)\n",
408 monitored->key, monitored->transport_obj_name,
409 monitored->transport->type_name,
410 pj_atomic_get(monitored->transport->ref_cnt), notifier->cb, notifier->data);
411 }
412 }
413 return 0;
414}
415
416static int ptr_matcher(void *a, void *b)
417{
418 return a == b;
419}
420
423{
424 struct ao2_container *transports;
425 struct callback_data cb_data = {
426 .cb = cb,
427 .data = data,
428 .matches = matches ?: ptr_matcher,
429 };
430
431 ast_assert(cb != NULL);
432
433 transports = ao2_global_obj_ref(active_transports);
434 if (!transports) {
435 return;
436 }
438 ao2_ref(transports, -1);
439}
440
441void ast_sip_transport_monitor_unregister(pjsip_transport *transport,
443{
447}
448
449void ast_sip_transport_monitor_unregister_key(const char *transport_key,
451{
452 struct ao2_container *transports;
453 struct transport_monitor *monitored;
454
455 ast_assert(transport_key != NULL && cb != NULL);
456
457 transports = ao2_global_obj_ref(active_transports);
458 if (!transports) {
459 return;
460 }
461
462 ao2_lock(transports);
463 monitored = ao2_find(transports, transport_key, OBJ_SEARCH_KEY | OBJ_NOLOCK);
464 if (monitored) {
465 struct callback_data cb_data = {
466 .cb = cb,
467 .data = data,
468 .matches = matches ?: ptr_matcher,
469 };
470
471 transport_monitor_unregister_cb(monitored, &cb_data, 0);
472 ao2_ref(monitored, -1);
473 }
474 ao2_unlock(transports);
475 ao2_ref(transports, -1);
476}
477
480{
483
485}
486
489{
490 return ast_sip_transport_monitor_register_replace_key(transport_key, cb, ao2_data, NULL);
491}
492
495{
497
500}
501
504{
505 struct ao2_container *transports;
506 struct transport_monitor *monitored;
508
509 ast_assert(transport_key != NULL && cb != NULL);
510
511 transports = ao2_global_obj_ref(active_transports);
512 if (!transports) {
513 return res;
514 }
515
516 ao2_lock(transports);
517 monitored = ao2_find(transports, transport_key, OBJ_SEARCH_KEY | OBJ_NOLOCK);
518 if (monitored) {
519 struct transport_monitor_notifier new_monitor;
520 struct callback_data cb_data = {
521 .cb = cb,
522 .data = ao2_data,
523 .matches = matches ?: ptr_matcher,
524 };
525
526 transport_monitor_unregister_cb(monitored, &cb_data, 0);
527
528 /* Add new monitor to vector */
529 new_monitor.cb = cb;
530 new_monitor.data = ao2_bump(ao2_data);
531 if (AST_VECTOR_APPEND(&monitored->monitors, new_monitor)) {
532 ao2_cleanup(ao2_data);
534 ast_debug(3, "Transport %s(%s) RefCnt: %ld : Monitor registration failed %p(%p)\n",
535 monitored->key, monitored->transport_obj_name,
536 pj_atomic_get(monitored->transport->ref_cnt), cb, ao2_data);
537 } else {
539 ast_debug(3, "Transport %s(%s,%s) RefCnt: %ld : Registered monitor %p(%p)\n",
540 monitored->key, monitored->transport_obj_name,
541 monitored->transport->type_name,
542 pj_atomic_get(monitored->transport->ref_cnt), cb, ao2_data);
543 }
544
545 ao2_ref(monitored, -1);
546 }
547 ao2_unlock(transports);
548 ao2_ref(transports, -1);
549 return res;
550}
551
553{
557}
558
560{
561 struct ast_sip_tpmgr_state_callback *tpmgr_notifier;
562
564 AST_LIST_TRAVERSE(&transport_state_list, tpmgr_notifier, node) {
565 if (element == tpmgr_notifier) {
566 /* Already registered. */
568 return;
569 }
570 }
573}
574
575static char *cli_show_monitors(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
576{
577 char *cli_rc = CLI_FAILURE;
578 int rc = 0;
579 int using_regex = 0;
580 regex_t regex = { 0, };
581 int container_count;
582 struct ao2_iterator iter;
583 struct ao2_container *sorted_monitors = NULL;
584 struct ao2_container *transports;
585 struct transport_monitor *monitored;
586
587 switch (cmd) {
588 case CLI_INIT:
589 e->command = "pjsip show transport-monitors";
590 e->usage = "Usage: pjsip show transport-monitors [ like <pattern> ]\n"
591 " Show pjsip transport monitors\n";
592 return NULL;
593 case CLI_GENERATE:
594 return NULL;
595 }
596
597 if (a->argc != 3 && a->argc != 5) {
598 return CLI_SHOWUSAGE;
599 }
600
601 if (a->argc == 5) {
602 int regrc;
603 if (strcasecmp(a->argv[3], "like")) {
604 return CLI_SHOWUSAGE;
605 }
606 regrc = regcomp(&regex, a->argv[4], REG_EXTENDED | REG_ICASE | REG_NOSUB);
607 if (regrc) {
608 char err[256];
609 regerror(regrc, &regex, err, 256);
610 ast_cli(a->fd, "PJSIP Transport Monitor: Error: %s\n", err);
611 return CLI_FAILURE;
612 }
613 using_regex = 1;
614 }
615
616 /* Get a sorted snapshot of the scheduled tasks */
618 transport_monitor_sort_fn, NULL);
619 if (!sorted_monitors) {
620 ast_cli(a->fd, "PJSIP Transport Monitor: Unable to allocate temporary container\n");
621 goto error;
622 }
623
624 transports = ao2_global_obj_ref(active_transports);
625 if (!transports) {
626 ast_cli(a->fd, "PJSIP Transport Monitor: Unable to get transports\n");
627 goto error;
628 }
629
630 ao2_lock(transports);
631 rc = ao2_container_dup(sorted_monitors, transports, 0);
632 ao2_unlock(transports);
633 ao2_ref(transports, -1);
634 if (rc != 0) {
635 ast_cli(a->fd, "PJSIP Transport Monitors: Unable to sort temporary container\n");
636 goto error;
637 }
638 container_count = ao2_container_count(sorted_monitors);
639
640 ast_cli(a->fd, "PJSIP Transport Monitors:\n\n");
641
642 ast_cli(a->fd,
643 "<Remote Host...................................> <State.....> <Direction> <RefCnt> <Monitors> <ObjName............>\n");
644
645 iter = ao2_iterator_init(sorted_monitors, AO2_ITERATOR_UNLINK);
646 for (; (monitored = ao2_iterator_next(&iter)); ao2_ref(monitored, -1)) {
647 char *state;
648
649 if (using_regex && regexec(&regex, monitored->key, 0, NULL, 0) == REG_NOMATCH) {
650 continue;
651 }
652
653 if (monitored->transport->is_destroying) {
654 state = "DESTROYING";
655 } else if (monitored->transport->is_shutdown) {
656 state = "SHUTDOWN";
657 } else {
658 state = "ACTIVE";
659 }
660
661 ast_cli(a->fd, " %-46.46s %-10s %-9s %6ld %8zu %s\n",
662 monitored->key, state,
663 monitored->transport->dir == PJSIP_TP_DIR_OUTGOING ? "Outgoing" : "Incoming",
664 pj_atomic_get(monitored->transport->ref_cnt),
665 AST_VECTOR_SIZE(&monitored->monitors), monitored->transport->obj_name);
666 }
668 ast_cli(a->fd, "\nTotal Transport Monitors: %d\n\n", container_count);
669 cli_rc = CLI_SUCCESS;
670error:
671 if (using_regex) {
672 regfree(&regex);
673 }
674 ao2_cleanup(sorted_monitors);
675
676 return cli_rc;
677}
678
679static struct ast_cli_entry cli_commands[] = {
680 AST_CLI_DEFINE(cli_show_monitors, "Show pjsip transport monitors"),
681};
682
684{
685 pjsip_tpmgr *tpmgr;
686
688
689 tpmgr = pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint());
690 if (tpmgr) {
691 pjsip_tpmgr_set_state_cb(tpmgr, tpmgr_state_callback);
692 }
693
694 ao2_global_obj_release(active_transports);
695}
696
698{
699 pjsip_tpmgr *tpmgr;
700 struct ao2_container *transports;
701
702 tpmgr = pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint());
703 if (!tpmgr) {
704 return -1;
705 }
706
708 ACTIVE_TRANSPORTS_BUCKETS, transport_monitor_hash_fn, transport_monitor_sort_fn,
709 transport_monitor_cmp_fn);
710 if (!transports) {
711 return -1;
712 }
713 ao2_global_obj_replace_unref(active_transports, transports);
714 ao2_ref(transports, -1);
715
716 tpmgr_state_callback = pjsip_tpmgr_get_state_cb(tpmgr);
717 pjsip_tpmgr_set_state_cb(tpmgr, &transport_state_callback);
718
720
721
722 return 0;
723}
jack_status_t status
Definition: app_jack.c:146
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_log
Definition: astobj2.c:42
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy all object references in the src container into the dest container.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
Definition: astobj2.h:901
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
@ AO2_ITERATOR_UNLINK
Definition: astobj2.h:1863
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a red-black tree container.
Definition: astobj2.h:1349
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition: astobj2.h:859
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
enum cc_state state
Definition: ccss.c:393
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static const char name[]
Definition: format_mp3.c:68
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
#define _A_
#define __LOG_ERROR
#define ast_debug(level,...)
Log a DEBUG message.
#define __LOG_NOTICE
#define LOG_ERROR
A set of macros to manage forward-linked lists.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define AST_RWLIST_HEAD(name, type)
Defines a structure to be used to hold a read/write list of specified type.
Definition: linkedlists.h:199
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856
def info(msg)
static struct ast_cli_entry cli_commands[]
AO2_STRING_FIELD_SORT_FN(transport_monitor, key)
Sort function for struct transport_monitor.
static struct @455 transport_state_list
static void verify_log_result(int log_level, const pjsip_transport *transport, pj_uint32_t verify_status)
void ast_sip_transport_state_register(struct ast_sip_tpmgr_state_callback *element)
Register a transport state notification callback element.
enum ast_transport_monitor_reg ast_sip_transport_monitor_register_key(const char *transport_key, ast_transport_monitor_shutdown_cb cb, void *ao2_data)
Register a reliable transport shutdown monitor callback.
AO2_STRING_FIELD_HASH_FN(transport_monitor, key)
Hashing function for struct transport_monitor.
enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb, void *ao2_data, ast_transport_monitor_data_matcher matches)
Register a reliable transport shutdown monitor callback replacing any duplicate.
void ast_sip_transport_monitor_unregister(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a reliable transport shutdown monitor.
static int verify_cert_name(const pj_str_t *local, const pj_str_t *remote)
static void transport_state_do_reg_callbacks(struct ao2_container *transports, pjsip_transport *transport)
AO2_STRING_FIELD_CMP_FN(transport_monitor, key)
Comparison function for struct transport_monitor.
void ast_sip_transport_monitor_unregister_all(ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a transport shutdown monitor from all reliable transports.
static int verify_cert_names(const pj_str_t *host, const pj_ssl_cert_info *remote)
enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace_key(const char *transport_key, ast_transport_monitor_shutdown_cb cb, void *ao2_data, ast_transport_monitor_data_matcher matches)
Register a reliable transport shutdown monitor callback replacing any duplicate.
static char * cli_show_monitors(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int ast_sip_initialize_transport_events(void)
enum ast_transport_monitor_reg ast_sip_transport_monitor_register(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb, void *ao2_data)
Register a reliable transport shutdown monitor callback.
void ast_sip_transport_state_unregister(struct ast_sip_tpmgr_state_callback *element)
Unregister a transport state notification callback element.
static void transport_monitor_dtor(void *vdoomed)
static int transport_tls_verify(const pjsip_transport *transport, const pjsip_tls_state_info *state_info)
static void transport_state_callback(pjsip_transport *transport, pjsip_transport_state state, const pjsip_transport_state_info *info)
Callback invoked when transport state changes occur.
static pjsip_tp_state_callback tpmgr_state_callback
Existing transport events callback that we need to invoke.
static int ptr_matcher(void *a, void *b)
static const char * transport_state2str(pjsip_transport_state state)
static int transport_monitor_unregister_cb(void *obj, void *arg, int flags)
static AO2_GLOBAL_OBJ_STATIC(active_transports)
Global container of active reliable transports.
void ast_sip_transport_monitor_unregister_key(const char *transport_key, ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a reliable transport shutdown monitor.
void ast_sip_destroy_transport_events(void)
#define ACTIVE_TRANSPORTS_BUCKETS
Number of buckets for monitored active transports.
int(* ast_transport_monitor_data_matcher)(void *a, void *b)
Transport shutdown monitor data matcher.
Definition: res_pjsip.h:3932
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:520
#define AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(_transport, _dest)
Fill a buffer with a pjsip transport's remote ip address and port.
Definition: res_pjsip.h:90
#define IP6ADDR_COLON_PORT_BUFLEN
Definition: res_pjsip.h:82
ast_transport_monitor_reg
Definition: res_pjsip.h:3934
@ AST_TRANSPORT_MONITOR_REG_NOT_FOUND
Transport not found to monitor.
Definition: res_pjsip.h:3943
@ AST_TRANSPORT_MONITOR_REG_FAILED
Error while registering transport monitor.
Definition: res_pjsip.h:3945
@ AST_TRANSPORT_MONITOR_REG_SUCCESS
Successfully registered the transport monitor.
Definition: res_pjsip.h:3936
void(* ast_transport_monitor_shutdown_cb)(void *data)
Transport shutdown monitor callback.
Definition: res_pjsip.h:3920
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
static int log_level
Log level for history output.
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
pjsip_tp_state_callback cb
Definition: res_pjsip.h:4089
Structure for SIP transport information.
Definition: res_pjsip.h:116
struct pjsip_transport * transport
Transport itself.
Definition: res_pjsip.h:118
ast_transport_monitor_data_matcher matches
ast_transport_monitor_shutdown_cb cb
Definition: test_heap.c:38
ast_transport_monitor_shutdown_cb cb
Structure for transport to be monitored.
pjsip_transport * transport
The underlying PJSIP transport.
char key[IP6ADDR_COLON_PORT_BUFLEN]
Key <ipaddr>:<port>
struct transport_monitor::@456 monitors
static struct test_val b
static struct test_val a
int error(const char *format,...)
Definition: utils/frame.c:999
#define ast_assert(a)
Definition: utils.h:739
#define ARRAY_LEN(a)
Definition: utils.h:666
Vector container support.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_REMOVE_UNORDERED(vec, idx)
Remove an element from an unordered vector by index.
Definition: vector.h:438
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition: vector.h:668