Asterisk - The Open Source Telephony Project  GIT-master-44aef04
app_bridgewait.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * Author: Jonathan Rose <jrose@digium.com>
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  * This program is free software, distributed under the terms of
17  * the GNU General Public License Version 2. See the LICENSE file
18  * at the top of the source tree.
19  */
20 
21 /*! \file
22  *
23  * \brief Application to place the channel into a holding Bridge
24  *
25  * \author Jonathan Rose <jrose@digium.com>
26  *
27  * \ingroup applications
28  */
29 
30 /*** MODULEINFO
31  <depend>bridge_holding</depend>
32  <support_level>core</support_level>
33  ***/
34 
35 #include "asterisk.h"
36 
37 #include "asterisk/file.h"
38 #include "asterisk/channel.h"
39 #include "asterisk/pbx.h"
40 #include "asterisk/module.h"
41 #include "asterisk/features.h"
42 #include "asterisk/say.h"
43 #include "asterisk/lock.h"
44 #include "asterisk/utils.h"
45 #include "asterisk/app.h"
46 #include "asterisk/bridge.h"
47 #include "asterisk/musiconhold.h"
48 #include "asterisk/astobj2.h"
49 #include "asterisk/causes.h"
50 
51 /*** DOCUMENTATION
52  <application name="BridgeWait" language="en_US">
53  <synopsis>
54  Put a call into the holding bridge.
55  </synopsis>
56  <syntax>
57  <parameter name="name">
58  <para>Name of the holding bridge to join. This is a handle for <literal>BridgeWait</literal>
59  only and does not affect the actual bridges that are created. If not provided,
60  the reserved name <literal>default</literal> will be used.
61  </para>
62  </parameter>
63  <parameter name="role" required="false">
64  <para>Defines the channel's purpose for entering the holding bridge. Values are case sensitive.
65  </para>
66  <enumlist>
67  <enum name="participant">
68  <para>The channel will enter the holding bridge to be placed on hold
69  until it is removed from the bridge for some reason. (default)</para>
70  </enum>
71  <enum name="announcer">
72  <para>The channel will enter the holding bridge to make announcements
73  to channels that are currently in the holding bridge. While an
74  announcer is present, holding for the participants will be
75  suspended.</para>
76  </enum>
77  </enumlist>
78  </parameter>
79  <parameter name="options">
80  <optionlist>
81  <option name="m">
82  <argument name="class" required="true" />
83  <para>The specified MOH class will be used/suggested for
84  music on hold operations. This option will only be useful for
85  entertainment modes that use it (m and h).</para>
86  </option>
87  <option name="e">
88  <para>Which entertainment mechanism should be used while on hold
89  in the holding bridge. Only the first letter is read.</para>
90  <enumlist>
91  <enum name="m"><para>Play music on hold (default)</para></enum>
92  <enum name="r"><para>Ring without pause</para></enum>
93  <enum name="s"><para>Generate silent audio</para></enum>
94  <enum name="h"><para>Put the channel on hold</para></enum>
95  <enum name="n"><para>No entertainment</para></enum>
96  </enumlist>
97  </option>
98  <option name="S">
99  <argument name="duration" required="true" />
100  <para>Automatically exit the bridge and return to the PBX after
101  <emphasis>duration</emphasis> seconds.</para>
102  </option>
103  </optionlist>
104  </parameter>
105  </syntax>
106  <description>
107  <para>This application places the incoming channel into a holding bridge.
108  The channel will then wait in the holding bridge until some event occurs
109  which removes it from the holding bridge.</para>
110  <note><para>This application will answer calls which haven't already
111  been answered.</para></note>
112  </description>
113  </application>
114  ***/
115 
116 #define APP_NAME "BridgeWait"
117 #define DEFAULT_BRIDGE_NAME "default"
118 
120 
122  struct ast_bridge *bridge; /*!< Bridge being wrapped by this wrapper */
123  char name[0]; /*!< Name of the holding bridge wrapper */
124 };
125 
126 static void wait_bridge_wrapper_destructor(void *obj)
127 {
128  struct wait_bridge_wrapper *wrapper = obj;
129 
130  if (wrapper->bridge) {
131  ast_bridge_destroy(wrapper->bridge, 0);
132  }
133 }
134 
135 static struct wait_bridge_wrapper *wait_bridge_wrapper_find_by_name(const char *bridge_name)
136 {
137  return ao2_find(wait_bridge_wrappers, bridge_name, OBJ_KEY);
138 }
139 
140 static int wait_bridge_hash_fn(const void *obj, const int flags)
141 {
142  const struct wait_bridge_wrapper *entry;
143  const char *key;
144 
145  switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
146  case OBJ_KEY:
147  key = obj;
148  return ast_str_hash(key);
149  case OBJ_POINTER:
150  entry = obj;
151  return ast_str_hash(entry->name);
152  default:
153  /* Hash can only work on something with a full key. */
154  ast_assert(0);
155  return 0;
156  }
157 }
158 
159 static int wait_bridge_sort_fn(const void *obj_left, const void *obj_right, const int flags)
160 {
161  const struct wait_bridge_wrapper *left = obj_left;
162  const struct wait_bridge_wrapper *right = obj_right;
163  const char *right_key = obj_right;
164  int cmp;
165 
166  switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
167  case OBJ_POINTER:
168  right_key = right->name;
169  /* Fall through */
170  case OBJ_KEY:
171  cmp = strcmp(left->name, right_key);
172  break;
173  case OBJ_PARTIAL_KEY:
174  cmp = strncmp(left->name, right_key, strlen(right_key));
175  break;
176  default:
177  /* Sort can only work on something with a full or partial key. */
178  ast_assert(0);
179  cmp = 0;
180  break;
181  }
182  return cmp;
183 }
184 
186  MUXFLAG_MOHCLASS = (1 << 0),
188  MUXFLAG_TIMEOUT = (1 << 2),
189 };
190 
195  OPT_ARG_ARRAY_SIZE, /* Always the last element of the enum */
196 };
197 
202 });
203 
204 static int bridgewait_timeout_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
205 {
206  ast_verb(3, "Channel %s timed out.\n", ast_channel_name(bridge_channel->chan));
209  return -1;
210 }
211 
212 static int apply_option_timeout(struct ast_bridge_features *features, char *duration_arg)
213 {
214  unsigned int duration;
215 
216  if (ast_strlen_zero(duration_arg)) {
217  ast_log(LOG_ERROR, "Timeout option 'S': No value provided.\n");
218  return -1;
219  }
220  if (sscanf(duration_arg, "%u", &duration) != 1 || duration == 0) {
221  ast_log(LOG_ERROR, "Timeout option 'S': Invalid value provided '%s'.\n",
222  duration_arg);
223  return -1;
224  }
225 
226  duration *= 1000;
227  if (ast_bridge_interval_hook(features, 0, duration, bridgewait_timeout_callback,
229  ast_log(LOG_ERROR, "Timeout option 'S': Could not create timer.\n");
230  return -1;
231  }
232 
233  return 0;
234 }
235 
236 static int apply_option_moh(struct ast_channel *chan, const char *class_arg)
237 {
238  return ast_channel_set_bridge_role_option(chan, "holding_participant", "moh_class", class_arg);
239 }
240 
241 static int apply_option_entertainment(struct ast_channel *chan, const char *entertainment_arg)
242 {
243  char entertainment = entertainment_arg[0];
244 
245  switch (entertainment) {
246  case 'm':
247  return ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "musiconhold");
248  case 'r':
249  return ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "ringing");
250  case 's':
251  return ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "silence");
252  case 'h':
253  return ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "hold");
254  case 'n':
255  return ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "none");
256  default:
257  ast_log(LOG_ERROR, "Invalid argument for BridgeWait entertainment '%s'\n", entertainment_arg);
258  return -1;
259  }
260 }
261 
266 };
267 
268 static int process_options(struct ast_channel *chan, struct ast_flags *flags, char **opts, struct ast_bridge_features *features, enum wait_bridge_roles role)
269 {
270  if (ast_test_flag(flags, MUXFLAG_TIMEOUT)) {
271  if (apply_option_timeout(features, opts[OPT_ARG_TIMEOUT])) {
272  return -1;
273  }
274  }
275 
276  switch (role) {
277  case ROLE_PARTICIPANT:
278  if (ast_channel_add_bridge_role(chan, "holding_participant")) {
279  return -1;
280  }
281 
282  if (ast_test_flag(flags, MUXFLAG_MOHCLASS)) {
283  if (apply_option_moh(chan, opts[OPT_ARG_MOHCLASS])) {
284  return -1;
285  }
286  }
287 
288  if (ast_test_flag(flags, MUXFLAG_ENTERTAINMENT)) {
290  return -1;
291  }
292  }
293 
294  break;
295  case ROLE_ANNOUNCER:
296  if (ast_channel_add_bridge_role(chan, "announcer")) {
297  return -1;
298  }
299  break;
300  case ROLE_INVALID:
301  ast_assert(0);
302  return -1;
303  }
304 
305  return 0;
306 }
307 
308 /*!
309  * \internal
310  * \since 12.0.0
311  * \brief Allocate a new holding bridge wrapper with the given bridge name and bridge ID.
312  *
313  * \param bridge_name name of the bridge wrapper
314  * \param bridge the bridge being wrapped
315  *
316  * \retval Pointer to the newly allocated holding bridge wrapper
317  * \retval NULL if allocation failed. The bridge will be destroyed if this function fails.
318  */
319 static struct wait_bridge_wrapper *wait_bridge_wrapper_alloc(const char *bridge_name, struct ast_bridge *bridge)
320 {
321  struct wait_bridge_wrapper *bridge_wrapper;
322 
323  bridge_wrapper = ao2_alloc_options(sizeof(*bridge_wrapper) + strlen(bridge_name) + 1,
325  if (!bridge_wrapper) {
326  ast_bridge_destroy(bridge, 0);
327  return NULL;
328  }
329 
330  strcpy(bridge_wrapper->name, bridge_name);
331  bridge_wrapper->bridge = bridge;
332 
333  if (!ao2_link(wait_bridge_wrappers, bridge_wrapper)) {
334  ao2_cleanup(bridge_wrapper);
335  return NULL;
336  }
337 
338  return bridge_wrapper;
339 }
340 
341 static struct wait_bridge_wrapper *get_wait_bridge_wrapper(const char *bridge_name)
342 {
343  struct wait_bridge_wrapper * wrapper;
344  struct ast_bridge *bridge = NULL;
345 
346  SCOPED_AO2LOCK(lock, wait_bridge_wrappers);
347 
348  if ((wrapper = wait_bridge_wrapper_find_by_name(bridge_name))) {
349  return wrapper;
350  }
351 
352  /*
353  * Holding bridges can allow local channel move/swap
354  * optimization to the bridge. However, we cannot allow it for
355  * this holding bridge because the call will lose the channel
356  * roles and dialplan location as a result.
357  */
362 
363  if (!bridge) {
364  return NULL;
365  }
366 
367  /* The bridge reference is unconditionally passed. */
368  return wait_bridge_wrapper_alloc(bridge_name, bridge);
369 }
370 
371 /*!
372  * \internal
373  * \since 12.0.0
374  * \brief If we are down to the last reference of a wrapper and it's still contained within the list, remove it from the list.
375  *
376  * \param wrapper reference to wait bridge wrapper being checked for list culling - will be cleared on exit
377  */
378 static void wait_wrapper_removal(struct wait_bridge_wrapper *wrapper)
379 {
380  if (!wrapper) {
381  return;
382  }
383 
384  ao2_lock(wait_bridge_wrappers);
385  if (ao2_ref(wrapper, 0) == 2) {
386  /* Either we have the only real reference or else wrapper isn't in the container anyway. */
387  ao2_unlink(wait_bridge_wrappers, wrapper);
388  }
389  ao2_unlock(wait_bridge_wrappers);
390 
391  ao2_cleanup(wrapper);
392 }
393 
394 /*!
395  * \internal
396  * \since 12.0.0
397  * \brief Application callback for the bridgewait application
398  *
399  * \param chan channel running the application
400  * \param data Arguments to the application
401  *
402  * \retval 0 Ran successfully and the call didn't hang up
403  * \retval -1 Failed or the call was hung up by the time the channel exited the holding bridge
404  */
405 static enum wait_bridge_roles validate_role(const char *role)
406 {
407  if (!strcmp(role, "participant")) {
408  return ROLE_PARTICIPANT;
409  } else if (!strcmp(role, "announcer")) {
410  return ROLE_ANNOUNCER;
411  } else {
412  return ROLE_INVALID;
413  }
414 }
415 
416 static int bridgewait_exec(struct ast_channel *chan, const char *data)
417 {
418  char *bridge_name = DEFAULT_BRIDGE_NAME;
419  struct ast_bridge_features chan_features;
420  struct ast_flags flags = { 0 };
421  char *parse;
423  char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
424  struct wait_bridge_wrapper *bridge_wrapper;
425  int res;
426 
428  AST_APP_ARG(name);
429  AST_APP_ARG(role);
431  AST_APP_ARG(other); /* Any remaining unused arguments */
432  );
433 
434  parse = ast_strdupa(data);
435  AST_STANDARD_APP_ARGS(args, parse);
436 
437  if (!ast_strlen_zero(args.name)) {
438  bridge_name = args.name;
439  }
440 
441  if (!ast_strlen_zero(args.role)) {
442  role = validate_role(args.role);
443  if (role == ROLE_INVALID) {
444  ast_log(LOG_ERROR, "Requested waiting bridge role '%s' is invalid.\n", args.role);
445  return -1;
446  }
447  }
448 
449  if (ast_bridge_features_init(&chan_features)) {
450  ast_bridge_features_cleanup(&chan_features);
451  ast_log(LOG_ERROR, "'%s' failed to enter the waiting bridge - could not set up channel features\n",
452  ast_channel_name(chan));
453  return -1;
454  }
455 
456  if (args.options) {
457  ast_app_parse_options(bridgewait_opts, &flags, opts, args.options);
458  }
459 
460  /* Answer the channel if needed */
461  if (ast_channel_state(chan) != AST_STATE_UP) {
462  ast_answer(chan);
463  }
464 
465  if (process_options(chan, &flags, opts, &chan_features, role)) {
466  ast_bridge_features_cleanup(&chan_features);
467  return -1;
468  }
469 
470  bridge_wrapper = get_wait_bridge_wrapper(bridge_name);
471  if (!bridge_wrapper) {
472  ast_log(LOG_WARNING, "Failed to find or create waiting bridge '%s' for '%s'.\n", bridge_name, ast_channel_name(chan));
473  ast_bridge_features_cleanup(&chan_features);
474  return -1;
475  }
476 
477  ast_verb(3, "%s is entering waiting bridge %s:%s\n", ast_channel_name(chan), bridge_name, bridge_wrapper->bridge->uniqueid);
478  res = ast_bridge_join(bridge_wrapper->bridge, chan, NULL, &chan_features, NULL, 0);
479  wait_wrapper_removal(bridge_wrapper);
480  ast_bridge_features_cleanup(&chan_features);
481 
482  if (res) {
483  /* For the lifetime of the bridge wrapper the bridge itself will be valid, if an error occurs it is because
484  * of extreme situations.
485  */
486  ast_log(LOG_WARNING, "Failed to join waiting bridge '%s' for '%s'.\n", bridge_name, ast_channel_name(chan));
487  }
488 
489  return (res || ast_check_hangup_locked(chan)) ? -1 : 0;
490 }
491 
492 static int unload_module(void)
493 {
494  ao2_cleanup(wait_bridge_wrappers);
495 
497 }
498 
499 static int load_module(void)
500 {
501  wait_bridge_wrappers = ao2_container_alloc_hash(
504 
505  if (!wait_bridge_wrappers) {
506  return -1;
507  }
508 
510 }
511 
512 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Place the channel into a holding bridge application");
static int apply_option_entertainment(struct ast_channel *chan, const char *entertainment_arg)
Main Channel structure associated with a channel.
void ast_bridge_features_cleanup(struct ast_bridge_features *features)
Clean up the contents of a bridge features structure.
Definition: bridge.c:3720
Music on hold handling.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
const ast_string_field uniqueid
Definition: bridge.h:409
bridgewait_flags
Structure that contains features information.
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define APP_NAME
#define OBJ_KEY
Definition: astobj2.h:1155
static const struct ast_app_option bridgewait_opts[128]
static int apply_option_timeout(struct ast_bridge_features *features, char *duration_arg)
#define OBJ_POINTER
Definition: astobj2.h:1154
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
int ast_check_hangup_locked(struct ast_channel *chan)
Definition: channel.c:455
#define LOG_WARNING
Definition: logger.h:274
int ast_bridge_features_init(struct ast_bridge_features *features)
Initialize bridge features structure.
Definition: bridge.c:3687
static int wait_bridge_sort_fn(const void *obj_left, const void *obj_right, const int flags)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
wait_bridge_roles
static struct wait_bridge_wrapper * wait_bridge_wrapper_find_by_name(const char *bridge_name)
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_assert(a)
Definition: utils.h:650
#define ao2_unlock(a)
Definition: astobj2.h:730
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_channel_add_bridge_role(struct ast_channel *chan, const char *role_name)
Adds a bridge role to a channel.
Definition: bridge_roles.c:317
const char * args
#define NULL
Definition: resample.c:96
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static int unload_module(void)
#define ast_verb(level,...)
Definition: logger.h:455
static struct wait_bridge_wrapper * get_wait_bridge_wrapper(const char *bridge_name)
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1156
Utility functions.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
int ast_channel_set_bridge_role_option(struct ast_channel *channel, const char *role_name, const char *option, const char *value)
Set a role option on a channel.
Definition: bridge_roles.c:379
static struct wait_bridge_wrapper * wait_bridge_wrapper_alloc(const char *bridge_name, struct ast_bridge *bridge)
#define ast_log
Definition: astobj2.c:42
General Asterisk PBX channel definitions.
static void wait_wrapper_removal(struct wait_bridge_wrapper *wrapper)
ast_mutex_t lock
Definition: app_meetme.c:1091
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_bridge_interval_hook(struct ast_bridge_features *features, enum ast_bridge_hook_timer_option flags, unsigned int interval, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach an interval hook to a bridge features structure.
Definition: bridge.c:3382
static int wait_bridge_hash_fn(const void *obj, const int flags)
static int bridgewait_timeout_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
struct ast_bridge * ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
Create a new base class bridge.
Definition: bridge.c:960
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2829
Core PBX routines and definitions.
Structure that contains information about a bridge.
Definition: bridge.h:357
#define LOG_ERROR
Definition: logger.h:285
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
static int bridgewait_exec(struct ast_channel *chan, const char *data)
#define DEFAULT_BRIDGE_NAME
static int load_module(void)
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
struct ast_bridge * bridge
static void wait_bridge_wrapper_destructor(void *obj)
static enum wait_bridge_roles validate_role(const char *role)
#define ast_strlen_zero(a)
Definition: muted.c:73
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
Structure used to handle boolean flags.
Definition: utils.h:199
int ast_bridge_join(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, struct ast_bridge_tech_optimizations *tech_args, enum ast_bridge_join_flags flags)
Join a channel to a bridge (blocking)
Definition: bridge.c:1667
static int process_options(struct ast_channel *chan, struct ast_flags *flags, char **opts, struct ast_bridge_features *features, enum wait_bridge_roles role)
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
bridgewait_args
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int apply_option_moh(struct ast_channel *chan, const char *class_arg)
const char * ast_channel_name(const struct ast_channel *chan)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2800
Internal Asterisk hangup causes.
Definition: search.h:40
Reject objects with duplicate keys in container.
Definition: astobj2.h:1192
Generic container type.
static struct test_options options
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
Say numbers and dates (maybe words one day too)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Bridging API.
Asterisk module definitions.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static struct ao2_container * wait_bridge_wrappers
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
#define AST_APP_ARG(name)
Define an application argument.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206
#define ao2_link(container, obj)
Definition: astobj2.h:1549