Asterisk - The Open Source Telephony Project GIT-master-3dae2cf
bridge_after.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2007 - 2009, 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 After Bridge Execution API
22 *
23 * \author Richard Mudgett <rmudgett@digium.com>
24 *
25 * See Also:
26 * \arg \ref AstCREDITS
27 */
28
29/*** MODULEINFO
30 <support_level>core</support_level>
31 ***/
32
33#include "asterisk.h"
34
35#include "asterisk/logger.h"
36#include "asterisk/channel.h"
37#include "asterisk/pbx.h"
39
41 /*! Next list node. */
43 /*! Desired callback function. */
45 /*! After bridge callback will not be called and destroy any resources data may contain. */
47 /*! Extra data to pass to the callback. */
48 void *data;
49 /*! Reason the after bridge callback failed. */
51};
52
54 /*! After bridge callbacks container. */
56};
57
58/*!
59 * \internal
60 * \brief Indicate after bridge callback failed.
61 * \since 12.0.0
62 *
63 * \param node After bridge callback node.
64 */
66{
67 if (node->failed) {
68 node->failed(node->reason, node->data);
69 node->failed = NULL;
70 }
71}
72
73/*!
74 * \internal
75 * \brief Run discarding any after bridge callbacks.
76 * \since 12.0.0
77 *
78 * \param after_bridge After bridge callback container process.
79 * \param reason Why are we doing this.
80 */
82{
84
85 for (;;) {
86 AST_LIST_LOCK(&after_bridge->callbacks);
87 node = AST_LIST_REMOVE_HEAD(&after_bridge->callbacks, list);
88 AST_LIST_UNLOCK(&after_bridge->callbacks);
89 if (!node) {
90 break;
91 }
92 if (!node->reason) {
93 node->reason = reason;
94 }
97 }
98}
99
100/*!
101 * \internal
102 * \brief Destroy the after bridge callback datastore.
103 * \since 12.0.0
104 *
105 * \param data After bridge callback data to destroy.
106 */
108{
109 struct after_bridge_cb_ds *after_bridge = data;
110
112
113 AST_LIST_HEAD_DESTROY(&after_bridge->callbacks);
114 ast_free(after_bridge);
115}
116
117static struct after_bridge_cb_ds *after_bridge_cb_find(struct ast_channel *chan);
118
119/*!
120 * \internal
121 * \brief Fixup the after bridge callback datastore.
122 * \since 12.0.0
123 *
124 * \param data After bridge callback data to fixup.
125 * \param old_chan The datastore is moving from this channel.
126 * \param new_chan The datastore is moving to this channel.
127 */
128static void after_bridge_cb_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
129{
130 struct after_bridge_cb_ds *after_bridge;
132
133 after_bridge = after_bridge_cb_find(new_chan);
134 if (!after_bridge) {
135 return;
136 }
137
138 AST_LIST_LOCK(&after_bridge->callbacks);
139 node = AST_LIST_LAST(&after_bridge->callbacks);
140 if (node && !node->reason) {
142 }
143 AST_LIST_UNLOCK(&after_bridge->callbacks);
144}
145
147 .type = "after-bridge-cb",
148 .destroy = after_bridge_cb_destroy,
149 .chan_fixup = after_bridge_cb_fixup,
150};
151
152/*!
153 * \internal
154 * \brief Find an after bridge callback datastore container.
155 * \since 12.0.0
156 *
157 * \param chan Channel to find the after bridge callback container on.
158 *
159 * \return after_bridge datastore container on success.
160 * \retval NULL on error.
161 */
163{
164 struct ast_datastore *datastore;
166
168 if (!datastore) {
169 return NULL;
170 }
171 return datastore->data;
172}
173
174/*!
175 * \internal
176 * \brief Setup/create an after bridge callback datastore container.
177 * \since 12.0.0
178 *
179 * \param chan Channel to setup/create the after bridge callback container on.
180 *
181 * \return after_bridge datastore container on success.
182 * \retval NULL on error.
183 */
185{
186 struct ast_datastore *datastore;
187 struct after_bridge_cb_ds *after_bridge;
189
191 if (datastore) {
192 return datastore->data;
193 }
194
195 /* Create a new datastore. */
197 if (!datastore) {
198 return NULL;
199 }
200 after_bridge = ast_calloc(1, sizeof(*after_bridge));
201 if (!after_bridge) {
202 ast_datastore_free(datastore);
203 return NULL;
204 }
205 AST_LIST_HEAD_INIT(&after_bridge->callbacks);
206 datastore->data = after_bridge;
207 ast_channel_datastore_add(chan, datastore);
208
209 return datastore->data;
210}
211
213{
214 struct after_bridge_cb_ds *after_bridge;
216
217 after_bridge = after_bridge_cb_find(chan);
218 if (!after_bridge) {
219 return;
220 }
221
222 for (;;) {
223 AST_LIST_LOCK(&after_bridge->callbacks);
224 node = AST_LIST_REMOVE_HEAD(&after_bridge->callbacks, list);
225 AST_LIST_UNLOCK(&after_bridge->callbacks);
226 if (!node) {
227 break;
228 }
229 if (node->reason) {
231 } else {
232 node->failed = NULL;
233 node->callback(chan, node->data);
234 }
235 ast_free(node);
236 }
237}
238
240{
241 struct after_bridge_cb_ds *after_bridge;
242
243 after_bridge = after_bridge_cb_find(chan);
244 if (!after_bridge) {
245 return;
246 }
247
248 after_bridge_cb_run_discard(after_bridge, reason);
249}
250
252{
253 struct after_bridge_cb_ds *after_bridge;
254 struct after_bridge_cb_node *new_node;
255 struct after_bridge_cb_node *last_node;
256
257 /* Sanity checks. */
258 ast_assert(chan != NULL);
259 if (!chan || !callback) {
260 return -1;
261 }
262
263 after_bridge = after_bridge_cb_setup(chan);
264 if (!after_bridge) {
265 return -1;
266 }
267
268 /* Create a new callback node. */
269 new_node = ast_calloc(1, sizeof(*new_node));
270 if (!new_node) {
271 return -1;
272 }
273 new_node->callback = callback;
274 new_node->failed = failed;
275 new_node->data = data;
276
277 /* Put it in the container disabling any previously active one. */
278 AST_LIST_LOCK(&after_bridge->callbacks);
279 last_node = AST_LIST_LAST(&after_bridge->callbacks);
280 if (last_node && !last_node->reason) {
282 }
283 AST_LIST_INSERT_TAIL(&after_bridge->callbacks, new_node, list);
284 AST_LIST_UNLOCK(&after_bridge->callbacks);
285 return 0;
286}
287
289{
290 switch (reason) {
292 return "Channel destroyed (hungup)";
294 return "Callback was replaced";
296 return "Channel masqueraded";
298 return "Channel was departed from bridge";
300 return "Callback was removed";
302 return "Channel failed joining the bridge";
303 }
304 return "Unknown";
305}
306
308 /*! Goto string that can be parsed by ast_parseable_goto(). */
309 const char *parseable_goto;
310 /*! Specific goto context or default context for parseable_goto. */
311 const char *context;
312 /*! Specific goto exten or default exten for parseable_goto. */
313 const char *exten;
314 /*! Specific goto priority or default priority for parseable_goto. */
316 /*! TRUE if the peer should run the h exten. */
317 unsigned int run_h_exten:1;
318 /*! Specific goto location */
319 unsigned int specific:1;
320};
321
322/*!
323 * \internal
324 * \brief Destroy the after bridge goto datastore.
325 * \since 12.0.0
326 *
327 * \param data After bridge goto data to destroy.
328 */
329static void after_bridge_goto_destroy(void *data)
330{
331 struct after_bridge_goto_ds *after_bridge = data;
332
333 ast_free((char *) after_bridge->parseable_goto);
334 ast_free((char *) after_bridge->context);
335 ast_free((char *) after_bridge->exten);
336 ast_free((char *) after_bridge);
337}
338
339/*!
340 * \internal
341 * \brief Fixup the after bridge goto datastore.
342 * \since 12.0.0
343 *
344 * \param data After bridge goto data to fixup.
345 * \param old_chan The datastore is moving from this channel.
346 * \param new_chan The datastore is moving to this channel.
347 */
348static void after_bridge_goto_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
349{
350 /* There can be only one. Discard any already on the new channel. */
352}
353
355 .type = "after-bridge-goto",
356 .destroy = after_bridge_goto_destroy,
357 .chan_fixup = after_bridge_goto_fixup,
358};
359
360/*!
361 * \internal
362 * \brief Remove channel goto location after the bridge and return it.
363 * \since 12.0.0
364 *
365 * \param chan Channel to remove after bridge goto location.
366 *
367 * \return datastore on success.
368 * \retval NULL on error or not found.
369 */
371{
372 struct ast_datastore *datastore;
373
374 ast_channel_lock(chan);
376 if (datastore && ast_channel_datastore_remove(chan, datastore)) {
377 datastore = NULL;
378 }
379 ast_channel_unlock(chan);
380
381 return datastore;
382}
383
385{
386 struct ast_datastore *datastore;
387
388 datastore = after_bridge_goto_remove(chan);
389 if (datastore) {
390 ast_datastore_free(datastore);
391 }
392}
393
394void ast_bridge_read_after_goto(struct ast_channel *chan, char *buffer, size_t buf_size)
395{
396 struct ast_datastore *datastore;
397 struct after_bridge_goto_ds *after_bridge;
398 char *current_pos = buffer;
399 size_t remaining_size = buf_size;
400
402
404 if (!datastore) {
405 buffer[0] = '\0';
406 return;
407 }
408
409 after_bridge = datastore->data;
410
411 if (after_bridge->parseable_goto) {
412 snprintf(buffer, buf_size, "%s", after_bridge->parseable_goto);
413 return;
414 }
415
416 if (!ast_strlen_zero(after_bridge->context)) {
417 snprintf(current_pos, remaining_size, "%s,", after_bridge->context);
418 remaining_size = remaining_size - strlen(current_pos);
419 current_pos += strlen(current_pos);
420 }
421
422 if (after_bridge->run_h_exten) {
423 snprintf(current_pos, remaining_size, "h,");
424 remaining_size = remaining_size - strlen(current_pos);
425 current_pos += strlen(current_pos);
426 } else if (!ast_strlen_zero(after_bridge->exten)) {
427 snprintf(current_pos, remaining_size, "%s,", after_bridge->exten);
428 remaining_size = remaining_size - strlen(current_pos);
429 current_pos += strlen(current_pos);
430 }
431
432 snprintf(current_pos, remaining_size, "%d", after_bridge->priority);
433}
434
436{
437 struct ast_datastore *datastore;
438 struct after_bridge_goto_ds *after_bridge;
439 int goto_failed = -1;
440
441 /* We are going to be leaving the bridging system now;
442 * clear any pending unbridge flags
443 */
445
446 /* Determine if we are going to setup a dialplan location and where. */
448 /* An async goto has already setup a location. */
450 if (!ast_check_hangup(chan)) {
451 goto_failed = 0;
452 }
453 return goto_failed;
454 }
455
456 /* Get after bridge goto datastore. */
457 datastore = after_bridge_goto_remove(chan);
458 if (!datastore) {
459 return goto_failed;
460 }
461
462 after_bridge = datastore->data;
463 if (after_bridge->run_h_exten) {
464 if (ast_exists_extension(chan, after_bridge->context, "h", 1,
465 S_COR(ast_channel_caller(chan)->id.number.valid,
466 ast_channel_caller(chan)->id.number.str, NULL))) {
467 ast_debug(1, "Running after bridge goto h exten %s,h,1\n",
468 ast_channel_context(chan));
469 ast_pbx_h_exten_run(chan, after_bridge->context);
470 }
471 } else if (!ast_check_hangup(chan)) {
472 /* Clear the outgoing flag */
474
475 if (after_bridge->specific) {
476 goto_failed = ast_explicit_goto(chan, after_bridge->context,
477 after_bridge->exten, after_bridge->priority);
478 } else if (!ast_strlen_zero(after_bridge->parseable_goto)) {
479 char *context;
480 char *exten;
481 int priority;
482
483 /* Option F(x) for Bridge(), Dial(), and Queue() */
484
485 /* Save current dialplan location in case of failure. */
489
490 /* Set current dialplan position to default dialplan position */
491 ast_explicit_goto(chan, after_bridge->context, after_bridge->exten,
492 after_bridge->priority);
493
494 /* Then perform the goto */
495 goto_failed = ast_parseable_goto(chan, after_bridge->parseable_goto);
496 if (goto_failed) {
497 /* Restore original dialplan location. */
501 }
502 } else {
503 /* Option F() for Bridge(), Dial(), and Queue() */
504 goto_failed = ast_goto_if_exists(chan, after_bridge->context,
505 after_bridge->exten, after_bridge->priority + 1);
506 }
507 if (!goto_failed) {
510 }
511
512 ast_debug(1, "Setup after bridge goto location to %s,%s,%d.\n",
514 ast_channel_exten(chan),
516 }
517 }
518
519 /* Discard after bridge goto datastore. */
520 ast_datastore_free(datastore);
521
522 return goto_failed;
523}
524
526{
527 int goto_failed;
528
529 goto_failed = ast_bridge_setup_after_goto(chan);
530 if (goto_failed || ast_pbx_run(chan)) {
531 ast_hangup(chan);
532 }
533}
534
535/*!
536 * \internal
537 * \brief Set after bridge goto location of channel.
538 * \since 12.0.0
539 *
540 * \param chan Channel to setup after bridge goto location.
541 * \param run_h_exten TRUE if the h exten should be run.
542 * \param specific TRUE if the context/exten/priority is exactly specified.
543 * \param context Context to goto after bridge.
544 * \param exten Exten to goto after bridge. (Could be NULL if run_h_exten)
545 * \param priority Priority to goto after bridge.
546 * \param parseable_goto User specified goto string. (Could be NULL)
547 *
548 * \details Add a channel datastore to setup the goto location
549 * when the channel leaves the bridge and run a PBX from there.
550 *
551 * If run_h_exten then execute the h exten found in the given context.
552 * Else if specific then goto the given context/exten/priority.
553 * Else if parseable_goto then use the given context/exten/priority
554 * as the relative position for the parseable_goto.
555 * Else goto the given context/exten/priority+1.
556 */
557static void __after_bridge_set_goto(struct ast_channel *chan, int run_h_exten, int specific, const char *context, const char *exten, int priority, const char *parseable_goto)
558{
559 struct ast_datastore *datastore;
560 struct after_bridge_goto_ds *after_bridge;
561
562 /* Sanity checks. */
563 ast_assert(chan != NULL);
564 if (!chan) {
565 return;
566 }
567 if (run_h_exten) {
569 if (!context) {
570 return;
571 }
572 } else {
573 ast_assert(context && exten && 0 < priority);
574 if (!context || !exten || priority < 1) {
575 return;
576 }
577 }
578
579 /* Create a new datastore. */
581 if (!datastore) {
582 return;
583 }
584 after_bridge = ast_calloc(1, sizeof(*after_bridge));
585 if (!after_bridge) {
586 ast_datastore_free(datastore);
587 return;
588 }
589
590 /* Initialize it. */
592 after_bridge->context = ast_strdup(context);
593 after_bridge->exten = ast_strdup(exten);
594 after_bridge->priority = priority;
595 after_bridge->run_h_exten = run_h_exten ? 1 : 0;
596 after_bridge->specific = specific ? 1 : 0;
597 datastore->data = after_bridge;
598 if ((parseable_goto && !after_bridge->parseable_goto)
599 || (context && !after_bridge->context)
600 || (exten && !after_bridge->exten)) {
601 ast_datastore_free(datastore);
602 return;
603 }
604
605 /* Put it on the channel replacing any existing one. */
606 ast_channel_lock(chan);
608 ast_channel_datastore_add(chan, datastore);
609 ast_channel_unlock(chan);
610}
611
612void ast_bridge_set_after_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
613{
615}
616
617void ast_bridge_set_after_h(struct ast_channel *chan, const char *context)
618{
619 __after_bridge_set_goto(chan, 1, 0, context, NULL, 1, NULL);
620}
621
622void ast_bridge_set_after_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto)
623{
624 char *p_goto;
625
627 p_goto = ast_strdupa(parseable_goto);
629 } else {
630 p_goto = NULL;
631 }
632 __after_bridge_set_goto(chan, 0, 0, context, exten, priority, p_goto);
633}
ast_mutex_t lock
Definition: app_sla.c:331
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_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
void ast_bridge_discard_after_callback(struct ast_channel *chan, enum ast_bridge_after_cb_reason reason)
Run discarding any after bridge callbacks.
Definition: bridge_after.c:239
static void __after_bridge_set_goto(struct ast_channel *chan, int run_h_exten, int specific, const char *context, const char *exten, int priority, const char *parseable_goto)
Definition: bridge_after.c:557
void ast_bridge_run_after_goto(struct ast_channel *chan)
Run a PBX on any after bridge goto location.
Definition: bridge_after.c:525
static struct after_bridge_cb_ds * after_bridge_cb_find(struct ast_channel *chan)
Definition: bridge_after.c:162
static void after_bridge_cb_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition: bridge_after.c:128
static void after_bridge_cb_run_discard(struct after_bridge_cb_ds *after_bridge, enum ast_bridge_after_cb_reason reason)
Definition: bridge_after.c:81
static struct ast_datastore * after_bridge_goto_remove(struct ast_channel *chan)
Definition: bridge_after.c:370
static const struct ast_datastore_info after_bridge_cb_info
Definition: bridge_after.c:146
int ast_bridge_setup_after_goto(struct ast_channel *chan)
Setup any after bridge goto location to begin execution.
Definition: bridge_after.c:435
static void after_bridge_cb_destroy(void *data)
Definition: bridge_after.c:107
void ast_bridge_run_after_callback(struct ast_channel *chan)
Run any after bridge callback.
Definition: bridge_after.c:212
void ast_bridge_discard_after_goto(struct ast_channel *chan)
Discard channel after bridge goto location.
Definition: bridge_after.c:384
int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb callback, ast_bridge_after_cb_failed failed, void *data)
Setup an after bridge callback for when the channel leaves the bridging system.
Definition: bridge_after.c:251
void ast_bridge_read_after_goto(struct ast_channel *chan, char *buffer, size_t buf_size)
Read after bridge goto if it exists.
Definition: bridge_after.c:394
static void after_bridge_goto_destroy(void *data)
Definition: bridge_after.c:329
static struct after_bridge_cb_ds * after_bridge_cb_setup(struct ast_channel *chan)
Definition: bridge_after.c:184
void ast_bridge_set_after_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto)
Set channel to go on in the dialplan after the bridge.
Definition: bridge_after.c:622
static void after_bridge_goto_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition: bridge_after.c:348
void ast_bridge_set_after_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set channel to goto specific location after the bridge.
Definition: bridge_after.c:612
void ast_bridge_set_after_h(struct ast_channel *chan, const char *context)
Set channel to run the h exten after the bridge.
Definition: bridge_after.c:617
static const struct ast_datastore_info after_bridge_goto_info
Definition: bridge_after.c:354
const char * ast_bridge_after_cb_reason_string(enum ast_bridge_after_cb_reason reason)
Get a string representation of an after bridge callback reason.
Definition: bridge_after.c:288
static void after_bridge_cb_failed(struct after_bridge_cb_node *node)
Definition: bridge_after.c:65
After Bridge Execution API.
ast_bridge_after_cb_reason
Definition: bridge_after.h:37
@ AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED
Definition: bridge_after.h:49
@ AST_BRIDGE_AFTER_CB_REASON_REMOVED
Definition: bridge_after.h:47
@ AST_BRIDGE_AFTER_CB_REASON_DEPART
Definition: bridge_after.h:45
@ AST_BRIDGE_AFTER_CB_REASON_MASQUERADE
Definition: bridge_after.h:43
@ AST_BRIDGE_AFTER_CB_REASON_DESTROY
Definition: bridge_after.h:39
@ AST_BRIDGE_AFTER_CB_REASON_REPLACED
Definition: bridge_after.h:41
void(* ast_bridge_after_cb)(struct ast_channel *chan, void *data)
After bridge callback function.
Definition: bridge_after.h:194
void(* ast_bridge_after_cb_failed)(enum ast_bridge_after_cb_reason reason, void *data)
After bridge callback failed.
Definition: bridge_after.h:185
static int priority
General Asterisk PBX channel definitions.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
void ast_channel_clear_flag(struct ast_channel *chan, unsigned int flag)
Clear a flag on a channel.
Definition: channel.c:11056
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2404
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2413
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2451
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2560
#define ast_channel_lock(chan)
Definition: channel.h:2968
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
void ast_channel_set_unbridged(struct ast_channel *chan, int value)
Sets the unbridged flag and queues a NULL frame on the channel to trigger a check by bridge_channel_w...
@ AST_SOFTHANGUP_ASYNCGOTO
Definition: channel.h:1146
void ast_channel_context_set(struct ast_channel *chan, const char *value)
@ AST_FLAG_OUTGOING
Definition: channel.h:1019
@ AST_FLAG_IN_AUTOLOOP
Definition: channel.h:1017
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_priority_set(struct ast_channel *chan, int value)
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2969
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2418
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:429
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:653
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:626
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:173
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:619
Core PBX routines and definitions.
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4755
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8781
void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
Run the h exten from the given context.
Definition: pbx.c:4205
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6945
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:8866
#define NULL
Definition: resample.c:96
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
struct after_bridge_cb_ds::@311 callbacks
enum ast_bridge_after_cb_reason reason
Definition: bridge_after.c:50
struct after_bridge_cb_node::@310 list
ast_bridge_after_cb_failed failed
Definition: bridge_after.c:46
ast_bridge_after_cb callback
Definition: bridge_after.c:44
unsigned int run_h_exten
Definition: bridge_after.c:317
const char * exten
Definition: bridge_after.c:313
unsigned int specific
Definition: bridge_after.c:319
const char * context
Definition: bridge_after.c:311
const char * parseable_goto
Definition: bridge_after.c:309
Main Channel structure associated with a channel.
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
Definition: test_heap.c:38
Number structure.
Definition: app_followme.c:154
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_assert(a)
Definition: utils.h:739
void ast_replace_subargument_delimiter(char *s)
Replace '^' in a string with ','.
Definition: utils.c:2343