Asterisk - The Open Source Telephony Project  21.4.1
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  <option name="n">
104  <para>Do not automatically answer the channel.</para>
105  </option>
106  </optionlist>
107  </parameter>
108  </syntax>
109  <description>
110  <para>This application places the incoming channel into a holding bridge.
111  The channel will then wait in the holding bridge until some event occurs
112  which removes it from the holding bridge.</para>
113  <note><para>This application will answer calls which haven't already
114  been answered, unless the n option is provided.</para></note>
115  </description>
116  </application>
117  ***/
118 
119 #define APP_NAME "BridgeWait"
120 #define DEFAULT_BRIDGE_NAME "default"
121 
122 static struct ao2_container *wait_bridge_wrappers;
123 
125  struct ast_bridge *bridge; /*!< Bridge being wrapped by this wrapper */
126  char name[0]; /*!< Name of the holding bridge wrapper */
127 };
128 
129 static void wait_bridge_wrapper_destructor(void *obj)
130 {
131  struct wait_bridge_wrapper *wrapper = obj;
132 
133  if (wrapper->bridge) {
134  ast_bridge_destroy(wrapper->bridge, 0);
135  }
136 }
137 
138 static struct wait_bridge_wrapper *wait_bridge_wrapper_find_by_name(const char *bridge_name)
139 {
140  return ao2_find(wait_bridge_wrappers, bridge_name, OBJ_KEY);
141 }
142 
143 static int wait_bridge_hash_fn(const void *obj, const int flags)
144 {
145  const struct wait_bridge_wrapper *entry;
146  const char *key;
147 
148  switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
149  case OBJ_KEY:
150  key = obj;
151  return ast_str_hash(key);
152  case OBJ_POINTER:
153  entry = obj;
154  return ast_str_hash(entry->name);
155  default:
156  /* Hash can only work on something with a full key. */
157  ast_assert(0);
158  return 0;
159  }
160 }
161 
162 static int wait_bridge_sort_fn(const void *obj_left, const void *obj_right, const int flags)
163 {
164  const struct wait_bridge_wrapper *left = obj_left;
165  const struct wait_bridge_wrapper *right = obj_right;
166  const char *right_key = obj_right;
167  int cmp;
168 
169  switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
170  case OBJ_POINTER:
171  right_key = right->name;
172  /* Fall through */
173  case OBJ_KEY:
174  cmp = strcmp(left->name, right_key);
175  break;
176  case OBJ_PARTIAL_KEY:
177  cmp = strncmp(left->name, right_key, strlen(right_key));
178  break;
179  default:
180  /* Sort can only work on something with a full or partial key. */
181  ast_assert(0);
182  cmp = 0;
183  break;
184  }
185  return cmp;
186 }
187 
188 enum bridgewait_flags {
189  MUXFLAG_MOHCLASS = (1 << 0),
190  MUXFLAG_ENTERTAINMENT = (1 << 1),
191  MUXFLAG_TIMEOUT = (1 << 2),
192  MUXFLAG_NOANSWER = (1 << 3),
193 };
194 
195 enum bridgewait_args {
196  OPT_ARG_ENTERTAINMENT,
197  OPT_ARG_MOHCLASS,
198  OPT_ARG_TIMEOUT,
199  OPT_ARG_ARRAY_SIZE, /* Always the last element of the enum */
200 };
201 
202 AST_APP_OPTIONS(bridgewait_opts, {
203  AST_APP_OPTION_ARG('e', MUXFLAG_ENTERTAINMENT, OPT_ARG_ENTERTAINMENT),
204  AST_APP_OPTION_ARG('m', MUXFLAG_MOHCLASS, OPT_ARG_MOHCLASS),
205  AST_APP_OPTION_ARG('S', MUXFLAG_TIMEOUT, OPT_ARG_TIMEOUT),
206  AST_APP_OPTION('n', MUXFLAG_NOANSWER),
207 });
208 
209 static int bridgewait_timeout_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
210 {
211  ast_verb(3, "Channel %s timed out.\n", ast_channel_name(bridge_channel->chan));
213  AST_CAUSE_NORMAL_CLEARING);
214  return -1;
215 }
216 
217 static int apply_option_timeout(struct ast_bridge_features *features, char *duration_arg)
218 {
219  unsigned int duration;
220 
221  if (ast_strlen_zero(duration_arg)) {
222  ast_log(LOG_ERROR, "Timeout option 'S': No value provided.\n");
223  return -1;
224  }
225  if (sscanf(duration_arg, "%u", &duration) != 1 || duration == 0) {
226  ast_log(LOG_ERROR, "Timeout option 'S': Invalid value provided '%s'.\n",
227  duration_arg);
228  return -1;
229  }
230 
231  duration *= 1000;
232  if (ast_bridge_interval_hook(features, 0, duration, bridgewait_timeout_callback,
233  NULL, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
234  ast_log(LOG_ERROR, "Timeout option 'S': Could not create timer.\n");
235  return -1;
236  }
237 
238  return 0;
239 }
240 
241 static int apply_option_moh(struct ast_channel *chan, const char *class_arg)
242 {
243  return ast_channel_set_bridge_role_option(chan, "holding_participant", "moh_class", class_arg);
244 }
245 
246 static int apply_option_entertainment(struct ast_channel *chan, const char *entertainment_arg)
247 {
248  char entertainment = entertainment_arg[0];
249 
250  switch (entertainment) {
251  case 'm':
252  return ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "musiconhold");
253  case 'r':
254  return ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "ringing");
255  case 's':
256  return ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "silence");
257  case 'h':
258  return ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "hold");
259  case 'n':
260  return ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "none");
261  default:
262  ast_log(LOG_ERROR, "Invalid argument for BridgeWait entertainment '%s'\n", entertainment_arg);
263  return -1;
264  }
265 }
266 
267 enum wait_bridge_roles {
268  ROLE_PARTICIPANT = 0,
269  ROLE_ANNOUNCER,
270  ROLE_INVALID,
271 };
272 
273 static int process_options(struct ast_channel *chan, struct ast_flags *flags, char **opts, struct ast_bridge_features *features, enum wait_bridge_roles role)
274 {
275  if (ast_test_flag(flags, MUXFLAG_TIMEOUT)) {
276  if (apply_option_timeout(features, opts[OPT_ARG_TIMEOUT])) {
277  return -1;
278  }
279  }
280 
281  switch (role) {
282  case ROLE_PARTICIPANT:
283  if (ast_channel_add_bridge_role(chan, "holding_participant")) {
284  return -1;
285  }
286 
287  if (ast_test_flag(flags, MUXFLAG_MOHCLASS)) {
288  if (apply_option_moh(chan, opts[OPT_ARG_MOHCLASS])) {
289  return -1;
290  }
291  }
292 
293  if (ast_test_flag(flags, MUXFLAG_ENTERTAINMENT)) {
294  if (apply_option_entertainment(chan, opts[OPT_ARG_ENTERTAINMENT])) {
295  return -1;
296  }
297  }
298 
299  break;
300  case ROLE_ANNOUNCER:
301  if (ast_channel_add_bridge_role(chan, "announcer")) {
302  return -1;
303  }
304  break;
305  case ROLE_INVALID:
306  ast_assert(0);
307  return -1;
308  }
309 
310  return 0;
311 }
312 
313 /*!
314  * \internal
315  * \since 12.0.0
316  * \brief Allocate a new holding bridge wrapper with the given bridge name and bridge ID.
317  *
318  * \param bridge_name name of the bridge wrapper
319  * \param bridge the bridge being wrapped
320  *
321  * \retval Pointer to the newly allocated holding bridge wrapper
322  * \retval NULL if allocation failed. The bridge will be destroyed if this function fails.
323  */
324 static struct wait_bridge_wrapper *wait_bridge_wrapper_alloc(const char *bridge_name, struct ast_bridge *bridge)
325 {
326  struct wait_bridge_wrapper *bridge_wrapper;
327 
328  bridge_wrapper = ao2_alloc_options(sizeof(*bridge_wrapper) + strlen(bridge_name) + 1,
329  wait_bridge_wrapper_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
330  if (!bridge_wrapper) {
331  ast_bridge_destroy(bridge, 0);
332  return NULL;
333  }
334 
335  strcpy(bridge_wrapper->name, bridge_name);
336  bridge_wrapper->bridge = bridge;
337 
338  if (!ao2_link(wait_bridge_wrappers, bridge_wrapper)) {
339  ao2_cleanup(bridge_wrapper);
340  return NULL;
341  }
342 
343  return bridge_wrapper;
344 }
345 
346 static struct wait_bridge_wrapper *get_wait_bridge_wrapper(const char *bridge_name)
347 {
348  struct wait_bridge_wrapper * wrapper;
349  struct ast_bridge *bridge = NULL;
350 
351  SCOPED_AO2LOCK(lock, wait_bridge_wrappers);
352 
353  if ((wrapper = wait_bridge_wrapper_find_by_name(bridge_name))) {
354  return wrapper;
355  }
356 
357  /*
358  * Holding bridges can allow local channel move/swap
359  * optimization to the bridge. However, we cannot allow it for
360  * this holding bridge because the call will lose the channel
361  * roles and dialplan location as a result.
362  */
366  | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED, APP_NAME, bridge_name, NULL);
367 
368  if (!bridge) {
369  return NULL;
370  }
371 
372  /* The bridge reference is unconditionally passed. */
373  return wait_bridge_wrapper_alloc(bridge_name, bridge);
374 }
375 
376 /*!
377  * \internal
378  * \since 12.0.0
379  * \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.
380  *
381  * \param wrapper reference to wait bridge wrapper being checked for list culling - will be cleared on exit
382  */
383 static void wait_wrapper_removal(struct wait_bridge_wrapper *wrapper)
384 {
385  if (!wrapper) {
386  return;
387  }
388 
389  ao2_lock(wait_bridge_wrappers);
390  if (ao2_ref(wrapper, 0) == 2) {
391  /* Either we have the only real reference or else wrapper isn't in the container anyway. */
392  ao2_unlink(wait_bridge_wrappers, wrapper);
393  }
394  ao2_unlock(wait_bridge_wrappers);
395 
396  ao2_cleanup(wrapper);
397 }
398 
399 static enum wait_bridge_roles validate_role(const char *role)
400 {
401  if (!strcmp(role, "participant")) {
402  return ROLE_PARTICIPANT;
403  } else if (!strcmp(role, "announcer")) {
404  return ROLE_ANNOUNCER;
405  } else {
406  return ROLE_INVALID;
407  }
408 }
409 
410 /*!
411  * \internal
412  * \since 12.0.0
413  * \brief Application callback for the bridgewait application
414  *
415  * \param chan channel running the application
416  * \param data Arguments to the application
417  *
418  * \retval 0 Ran successfully and the call didn't hang up
419  * \retval -1 Failed or the call was hung up by the time the channel exited the holding bridge
420  */
421 static int bridgewait_exec(struct ast_channel *chan, const char *data)
422 {
423  char *bridge_name = DEFAULT_BRIDGE_NAME;
424  struct ast_bridge_features chan_features;
425  struct ast_flags flags = { 0 };
426  char *parse;
427  enum wait_bridge_roles role = ROLE_PARTICIPANT;
428  char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
429  struct wait_bridge_wrapper *bridge_wrapper;
430  int res;
431 
433  AST_APP_ARG(name);
434  AST_APP_ARG(role);
435  AST_APP_ARG(options);
436  AST_APP_ARG(other); /* Any remaining unused arguments */
437  );
438 
439  parse = ast_strdupa(data);
440  AST_STANDARD_APP_ARGS(args, parse);
441 
442  if (!ast_strlen_zero(args.name)) {
443  bridge_name = args.name;
444  }
445 
446  if (!ast_strlen_zero(args.role)) {
447  role = validate_role(args.role);
448  if (role == ROLE_INVALID) {
449  ast_log(LOG_ERROR, "Requested waiting bridge role '%s' is invalid.\n", args.role);
450  return -1;
451  }
452  }
453 
454  if (ast_bridge_features_init(&chan_features)) {
455  ast_bridge_features_cleanup(&chan_features);
456  ast_log(LOG_ERROR, "'%s' failed to enter the waiting bridge - could not set up channel features\n",
457  ast_channel_name(chan));
458  return -1;
459  }
460 
461  if (args.options) {
462  ast_app_parse_options(bridgewait_opts, &flags, opts, args.options);
463  }
464 
465  /* Answer the channel if needed */
466  if (ast_channel_state(chan) != AST_STATE_UP && !ast_test_flag(&flags, MUXFLAG_NOANSWER)) {
467  ast_answer(chan);
468  }
469 
470  if (process_options(chan, &flags, opts, &chan_features, role)) {
471  ast_bridge_features_cleanup(&chan_features);
472  return -1;
473  }
474 
475  bridge_wrapper = get_wait_bridge_wrapper(bridge_name);
476  if (!bridge_wrapper) {
477  ast_log(LOG_WARNING, "Failed to find or create waiting bridge '%s' for '%s'.\n", bridge_name, ast_channel_name(chan));
478  ast_bridge_features_cleanup(&chan_features);
479  return -1;
480  }
481 
482  ast_verb(3, "%s is entering waiting bridge %s:%s\n", ast_channel_name(chan), bridge_name, bridge_wrapper->bridge->uniqueid);
483  res = ast_bridge_join(bridge_wrapper->bridge, chan, NULL, &chan_features, NULL, 0);
484  wait_wrapper_removal(bridge_wrapper);
485  ast_bridge_features_cleanup(&chan_features);
486 
487  if (res) {
488  /* For the lifetime of the bridge wrapper the bridge itself will be valid, if an error occurs it is because
489  * of extreme situations.
490  */
491  ast_log(LOG_WARNING, "Failed to join waiting bridge '%s' for '%s'.\n", bridge_name, ast_channel_name(chan));
492  }
493 
494  return (res || ast_check_hangup_locked(chan)) ? -1 : 0;
495 }
496 
497 static int unload_module(void)
498 {
499  ao2_cleanup(wait_bridge_wrappers);
500 
501  return ast_unregister_application(APP_NAME);
502 }
503 
504 static int load_module(void)
505 {
506  wait_bridge_wrappers = ao2_container_alloc_hash(
508  37, wait_bridge_hash_fn, wait_bridge_sort_fn, NULL);
509 
510  if (!wait_bridge_wrappers) {
511  return -1;
512  }
513 
514  return ast_register_application_xml(APP_NAME, bridgewait_exec);
515 }
516 
517 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Place the channel into a holding bridge application");
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:3653
Music on hold handling.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
const ast_string_field uniqueid
Definition: bridge.h:401
Structure that contains features information.
#define OBJ_KEY
Definition: astobj2.h:1151
#define OBJ_POINTER
Definition: astobj2.h:1150
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
int ast_bridge_features_init(struct ast_bridge_features *features)
Initialize bridge features structure.
Definition: bridge.c:3620
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:944
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:313
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1152
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:375
ast_mutex_t lock
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
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:3319
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:934
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:3066
Core PBX routines and definitions.
Structure that contains information about a bridge.
Definition: bridge.h:349
#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
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
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
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
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:1621
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2805
Internal Asterisk hangup causes.
Definition: search.h:40
Reject objects with duplicate keys in container.
Definition: astobj2.h:1188
Generic container type.
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
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's arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
#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:1259
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532