119 #define APP_NAME "BridgeWait"
120 #define DEFAULT_BRIDGE_NAME "default"
129 static void wait_bridge_wrapper_destructor(
void *obj)
138 static struct wait_bridge_wrapper *wait_bridge_wrapper_find_by_name(
const char *bridge_name)
140 return ao2_find(wait_bridge_wrappers, bridge_name,
OBJ_KEY);
143 static int wait_bridge_hash_fn(
const void *obj,
const int flags)
162 static int wait_bridge_sort_fn(
const void *obj_left,
const void *obj_right,
const int flags)
166 const char *right_key = obj_right;
171 right_key = right->
name;
174 cmp = strcmp(left->
name, right_key);
177 cmp = strncmp(left->
name, right_key, strlen(right_key));
188 enum bridgewait_flags {
189 MUXFLAG_MOHCLASS = (1 << 0),
190 MUXFLAG_ENTERTAINMENT = (1 << 1),
191 MUXFLAG_TIMEOUT = (1 << 2),
192 MUXFLAG_NOANSWER = (1 << 3),
195 enum bridgewait_args {
196 OPT_ARG_ENTERTAINMENT,
209 static int bridgewait_timeout_callback(
struct ast_bridge_channel *bridge_channel,
void *hook_pvt)
211 ast_verb(3,
"Channel %s timed out.\n", ast_channel_name(bridge_channel->
chan));
213 AST_CAUSE_NORMAL_CLEARING);
219 unsigned int duration;
221 if (ast_strlen_zero(duration_arg)) {
222 ast_log(LOG_ERROR,
"Timeout option 'S': No value provided.\n");
225 if (sscanf(duration_arg,
"%u", &duration) != 1 || duration == 0) {
226 ast_log(LOG_ERROR,
"Timeout option 'S': Invalid value provided '%s'.\n",
234 ast_log(LOG_ERROR,
"Timeout option 'S': Could not create timer.\n");
241 static int apply_option_moh(
struct ast_channel *chan,
const char *class_arg)
246 static int apply_option_entertainment(
struct ast_channel *chan,
const char *entertainment_arg)
248 char entertainment = entertainment_arg[0];
250 switch (entertainment) {
262 ast_log(LOG_ERROR,
"Invalid argument for BridgeWait entertainment '%s'\n", entertainment_arg);
267 enum wait_bridge_roles {
268 ROLE_PARTICIPANT = 0,
275 if (ast_test_flag(flags, MUXFLAG_TIMEOUT)) {
276 if (apply_option_timeout(features, opts[OPT_ARG_TIMEOUT])) {
282 case ROLE_PARTICIPANT:
287 if (ast_test_flag(flags, MUXFLAG_MOHCLASS)) {
288 if (apply_option_moh(chan, opts[OPT_ARG_MOHCLASS])) {
293 if (ast_test_flag(flags, MUXFLAG_ENTERTAINMENT)) {
294 if (apply_option_entertainment(chan, opts[OPT_ARG_ENTERTAINMENT])) {
328 bridge_wrapper = ao2_alloc_options(
sizeof(*bridge_wrapper) + strlen(bridge_name) + 1,
330 if (!bridge_wrapper) {
335 strcpy(bridge_wrapper->
name, bridge_name);
338 if (!
ao2_link(wait_bridge_wrappers, bridge_wrapper)) {
339 ao2_cleanup(bridge_wrapper);
343 return bridge_wrapper;
353 if ((wrapper = wait_bridge_wrapper_find_by_name(bridge_name))) {
373 return wait_bridge_wrapper_alloc(bridge_name, bridge);
389 ao2_lock(wait_bridge_wrappers);
390 if (
ao2_ref(wrapper, 0) == 2) {
394 ao2_unlock(wait_bridge_wrappers);
396 ao2_cleanup(wrapper);
399 static enum wait_bridge_roles validate_role(
const char *role)
401 if (!strcmp(role,
"participant")) {
402 return ROLE_PARTICIPANT;
403 }
else if (!strcmp(role,
"announcer")) {
404 return ROLE_ANNOUNCER;
421 static int bridgewait_exec(
struct ast_channel *chan,
const char *data)
423 char *bridge_name = DEFAULT_BRIDGE_NAME;
427 enum wait_bridge_roles role = ROLE_PARTICIPANT;
428 char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
442 if (!ast_strlen_zero(args.name)) {
443 bridge_name = args.name;
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);
456 ast_log(LOG_ERROR,
"'%s' failed to enter the waiting bridge - could not set up channel features\n",
457 ast_channel_name(chan));
470 if (process_options(chan, &flags, opts, &chan_features, role)) {
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));
482 ast_verb(3,
"%s is entering waiting bridge %s:%s\n", ast_channel_name(chan), bridge_name, bridge_wrapper->
bridge->
uniqueid);
484 wait_wrapper_removal(bridge_wrapper);
491 ast_log(LOG_WARNING,
"Failed to join waiting bridge '%s' for '%s'.\n", bridge_name, ast_channel_name(chan));
494 return (res || ast_check_hangup_locked(chan)) ? -1 : 0;
497 static int unload_module(
void)
499 ao2_cleanup(wait_bridge_wrappers);
504 static int load_module(
void)
508 37, wait_bridge_hash_fn, wait_bridge_sort_fn, NULL);
510 if (!wait_bridge_wrappers) {
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.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
const ast_string_field uniqueid
Structure that contains features information.
#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.
ast_channel_state
ast_channel states
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
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.
int ast_unregister_application(const char *app)
Unregister an application.
#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.
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
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.
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.
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.
Core PBX routines and definitions.
Structure that contains information about a bridge.
#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.
#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.
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.
Structure used to handle boolean flags.
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)
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
int ast_answer(struct ast_channel *chan)
Answer a channel.
Internal Asterisk hangup causes.
Reject objects with duplicate keys in container.
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.
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.
#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.
#define ao2_link(container, obj)
Add an object to a container.