Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Data Structures | Macros | Functions | Variables
app_confbridge.c File Reference

Conference Bridge application. More...

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include "asterisk/cli.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/bridge.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/audiohook.h"
#include "asterisk/astobj2.h"
#include "confbridge/include/confbridge.h"
#include "asterisk/paths.h"
#include "asterisk/manager.h"
#include "asterisk/test.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/json.h"
#include "asterisk/format_cache.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/stream.h"
#include "asterisk/message.h"
Include dependency graph for app_confbridge.c:

Go to the source code of this file.

Data Structures

struct  async_datastore_data
 
struct  async_delete_name_rec_task_data
 
struct  async_playback_task_data
 
struct  confbridge_hook_data
 
struct  hangup_data
 
struct  playback_task_data
 

Macros

#define CONFERENCE_BRIDGE_BUCKETS   53
 
#define RECORD_FILENAME_INITIAL_SPACE   128
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int action_confbridgekick (struct mansession *s, const struct message *m)
 
static int action_confbridgelist (struct mansession *s, const struct message *m)
 
static int action_confbridgelist_item (struct mansession *s, const char *id_text, struct confbridge_conference *conference, struct confbridge_user *user, int waiting)
 
static int action_confbridgelistrooms (struct mansession *s, const struct message *m)
 
static int action_confbridgelock (struct mansession *s, const struct message *m)
 
static int action_confbridgemute (struct mansession *s, const struct message *m)
 
static int action_confbridgesetsinglevideosrc (struct mansession *s, const struct message *m)
 
static int action_confbridgestartrecord (struct mansession *s, const struct message *m)
 
static int action_confbridgestoprecord (struct mansession *s, const struct message *m)
 
static int action_confbridgeunlock (struct mansession *s, const struct message *m)
 
static int action_confbridgeunmute (struct mansession *s, const struct message *m)
 
static int action_dialplan_exec (struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
 
static int action_kick_last (struct confbridge_conference *conference, struct ast_bridge_channel *bridge_channel, struct confbridge_user *user)
 
static int action_lock_unlock_helper (struct mansession *s, const struct message *m, int lock)
 
static int action_mute_unmute_helper (struct mansession *s, const struct message *m, int mute)
 
static int action_playback (struct ast_bridge_channel *bridge_channel, const char *playback_file)
 
static int action_playback_and_continue (struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel, struct conf_menu *menu, const char *playback_file, const char *cur_dtmf, int *stop_prompts)
 
static int action_toggle_binaural (struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel)
 
static int action_toggle_mute (struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel)
 
static int action_toggle_mute_participants (struct confbridge_conference *conference, struct confbridge_user *user)
 
static int alloc_playback_chan (struct confbridge_conference *conference)
 
static int announce_user_count (struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel)
 Announce number of users in the conference bridge to the caller. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static struct async_datastore_dataasync_datastore_data_alloc (void)
 
static void async_datastore_data_destroy (void *data)
 
static int async_delete_name_rec (struct confbridge_conference *conference, const char *filename)
 
static int async_delete_name_rec_task (void *data)
 Delete user's name file asynchronously. More...
 
static struct async_delete_name_rec_task_dataasync_delete_name_rec_task_data_alloc (struct confbridge_conference *conference, const char *filename)
 
static void async_delete_name_rec_task_data_destroy (struct async_delete_name_rec_task_data *atd)
 
int async_play_sound_file (struct confbridge_conference *conference, const char *filename, struct ast_channel *initiator)
 Play sound file into conference bridge asynchronously. More...
 
static int async_play_sound_helper (struct confbridge_conference *conference, const char *filename, int say_number, struct ast_channel *initiator)
 
void async_play_sound_ready (struct ast_channel *chan)
 Indicate the initiator of an async sound file is ready for it to play. More...
 
static int async_playback_task (void *data)
 Play an announcement into a confbridge asynchronously. More...
 
static struct async_playback_task_dataasync_playback_task_data_alloc (struct confbridge_conference *conference, const char *filename, int say_number, struct ast_channel *initiator)
 
static void async_playback_task_data_destroy (struct async_playback_task_data *aptd)
 
static int cli_mute_unmute_helper (int mute, struct ast_cli_args *a)
 
static char * complete_confbridge_name (const char *line, const char *word, int pos, int state)
 
static char * complete_confbridge_participant (const char *conference_name, const char *line, const char *word, int pos, int state)
 
int conf_add_post_join_action (struct confbridge_user *user, int(*func)(struct confbridge_user *user))
 Queue a function to run with the given conference bridge user as an argument once the state transition is complete. More...
 
void conf_add_user_active (struct confbridge_conference *conference, struct confbridge_user *user)
 Add a conference bridge user as an unmarked active user of the conference. More...
 
void conf_add_user_marked (struct confbridge_conference *conference, struct confbridge_user *user)
 Add a conference bridge user as a marked active user of the conference. More...
 
void conf_add_user_waiting (struct confbridge_conference *conference, struct confbridge_user *user)
 Add a conference bridge user as an waiting user of the conference. More...
 
void conf_ended (struct confbridge_conference *conference)
 Callback to be called when the conference has become empty. More...
 
struct confbridge_conferenceconf_find_bridge (const char *conference_name)
 Find a confbridge by name. More...
 
static int conf_get_pin (struct ast_channel *chan, struct confbridge_user *user)
 
const char * conf_get_sound (enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds)
 Looks to see if sound file is stored in bridge profile sounds, if not default sound is provided. More...
 
int conf_handle_dtmf (struct ast_bridge_channel *bridge_channel, struct confbridge_user *user, struct conf_menu_entry *menu_entry, struct conf_menu *menu)
 Once a DTMF sequence matches a sequence in the user's DTMF menu, this function will get called to perform the menu action. More...
 
void conf_handle_first_join (struct confbridge_conference *conference)
 Callback to execute any time we transition from zero to one active users. More...
 
int conf_handle_inactive_waitmarked (struct confbridge_user *user)
 Handle actions every time a waitmarked user joins w/o a marked user present. More...
 
int conf_handle_only_person (struct confbridge_user *user)
 Handle actions whenever an user joins an empty conference. More...
 
void conf_handle_second_active (struct confbridge_conference *conference)
 Handle when a conference moves to having more than one active participant. More...
 
static int conf_handle_talker_cb (struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking)
 
static int conf_is_recording (struct confbridge_conference *conference)
 
void conf_moh_start (struct confbridge_user *user)
 Start MOH for the conference user. More...
 
void conf_moh_stop (struct confbridge_user *user)
 Stop MOH for the conference user. More...
 
static void conf_moh_suspend (struct confbridge_user *user)
 
static void conf_moh_unsuspend (struct confbridge_user *user)
 
void conf_mute_only_active (struct confbridge_conference *conference)
 Attempt to mute/play MOH to the only user in the conference if they require it. More...
 
static int conf_rec_name (struct confbridge_user *user, const char *conf_name)
 
void conf_remove_user_active (struct confbridge_conference *conference, struct confbridge_user *user)
 Remove a conference bridge user from the unmarked active conference users in the conference. More...
 
void conf_remove_user_marked (struct confbridge_conference *conference, struct confbridge_user *user)
 Remove a conference bridge user from the marked active conference users in the conference. More...
 
void conf_remove_user_waiting (struct confbridge_conference *conference, struct confbridge_user *user)
 Remove a conference bridge user from the waiting conference users in the conference. More...
 
static int conf_start_record (struct confbridge_conference *conference)
 
static int conf_stop_record (struct confbridge_conference *conference)
 
void conf_update_user_mute (struct confbridge_user *user)
 Update the actual mute status of the user and set it on the bridge. More...
 
static int confbridge_exec (struct ast_channel *chan, const char *data)
 The ConfBridge application. More...
 
void confbridge_handle_atxfer (struct ast_attended_transfer_message *msg)
 Create join/leave events for attended transfers. More...
 
static void confbridge_unlock_and_unref (void *obj)
 
static int conference_bridge_cmp_cb (void *obj, void *arg, int flags)
 Comparison function used for conference bridges container. More...
 
static int conference_bridge_hash_cb (const void *obj, const int flags)
 Hashing function used for conference bridges container. More...
 
static int confkick_exec (struct ast_channel *chan, const char *data)
 
static void destroy_conference_bridge (void *obj)
 Destroy a conference bridge. More...
 
static int execute_menu_entry (struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel, struct conf_menu_entry *menu_entry, struct conf_menu *menu)
 
static int func_confbridge_channels (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int func_confbridge_info (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int generic_lock_unlock_helper (int lock, const char *conference_name)
 
static int generic_mute_unmute_helper (int mute, const char *conference_name, const char *chan_name)
 
static void generic_mute_unmute_user (struct confbridge_conference *conference, struct confbridge_user *user, int mute)
 
static char * handle_cli_confbridge_kick (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_confbridge_list (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void handle_cli_confbridge_list_item (struct ast_cli_args *a, struct confbridge_user *user, int waiting)
 
static char * handle_cli_confbridge_lock (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_confbridge_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_confbridge_start_record (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_confbridge_stop_record (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_confbridge_unlock (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_confbridge_unmute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int handle_conf_user_join (struct confbridge_user *user)
 Call the proper join event handler for the user for the conference bridge's current state. More...
 
static int handle_conf_user_leave (struct confbridge_user *user)
 Call the proper leave event handler for the user for the conference bridge's current state. More...
 
static void handle_video_on_exit (struct confbridge_conference *conference, struct ast_channel *chan)
 
static void handle_video_on_join (struct confbridge_conference *conference, struct ast_channel *chan, int marked)
 
static void hangup_data_destroy (struct hangup_data *hangup)
 
static void hangup_data_init (struct hangup_data *hangup, struct confbridge_conference *conference)
 
static int hangup_playback (void *data)
 Hang up the announcer channel. More...
 
static int is_new_rec_file (const char *rec_file, struct ast_str **orig_rec_file)
 
static int join_callback (struct ast_bridge_channel *bridge_channel, void *ignore)
 
static struct confbridge_conferencejoin_conference_bridge (const char *conference_name, struct confbridge_user *user)
 Join a conference bridge. More...
 
static int kick_conference_participant (struct confbridge_conference *conference, const char *channel)
 
static void leave_conference (struct confbridge_user *user)
 Leave a conference. More...
 
static int load_module (void)
 Load the module. More...
 
static int play_file (struct ast_bridge_channel *bridge_channel, struct ast_channel *channel, const char *filename)
 Playback the given filename and monitor for any dtmf interrupts. More...
 
static int play_prompt_to_user (struct confbridge_user *user, const char *filename)
 Play back an audio file to a channel. More...
 
int play_sound_file (struct confbridge_conference *conference, const char *filename)
 Play sound file into conference bridge. More...
 
static int play_sound_helper (struct confbridge_conference *conference, const char *filename, int say_number)
 
static int play_sound_number (struct confbridge_conference *conference, int say_number)
 Play number into the conference bridge. More...
 
static void playback_common (struct confbridge_conference *conference, const char *filename, int say_number)
 
static int playback_task (void *data)
 Play an announcement into a confbridge. More...
 
static void playback_task_data_destroy (struct playback_task_data *ptd)
 
static void playback_task_data_init (struct playback_task_data *ptd, struct confbridge_conference *conference, const char *filename, int say_number)
 
static int push_announcer (struct confbridge_conference *conference)
 Push the announcer channel into the bridge. More...
 
static int register_channel_tech (struct ast_channel_tech *tech)
 
static int reload (void)
 
static void send_conf_end_event (struct confbridge_conference *conference)
 
static void send_conf_start_event (struct confbridge_conference *conference)
 
static void send_conf_stasis (struct confbridge_conference *conference, struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *extras, int channel_topic)
 
static void send_conf_stasis_snapshots (struct confbridge_conference *conference, struct ast_channel_snapshot *chan_snapshot, struct stasis_message_type *type, struct ast_json *extras)
 
static int send_event_hook_callback (struct ast_bridge_channel *bridge_channel, void *data)
 
static void send_join_event (struct confbridge_user *user, struct confbridge_conference *conference)
 
static void send_leave_event (struct confbridge_user *user, struct confbridge_conference *conference)
 
static void send_mute_event (struct confbridge_user *user, struct confbridge_conference *conference)
 
static void send_start_record_event (struct confbridge_conference *conference)
 
static void send_stop_record_event (struct confbridge_conference *conference)
 
static void send_unmute_event (struct confbridge_user *user, struct confbridge_conference *conference)
 
static void set_rec_filename (struct confbridge_conference *conference, struct ast_str **filename, int is_new)
 
static int setup_async_playback_datastore (struct ast_channel *initiator)
 Prepare the async playback datastore. More...
 
static int sound_file_exists (const char *filename)
 
static int unload_module (void)
 Called when module is being unloaded. More...
 
static void unregister_channel_tech (struct ast_channel_tech *tech)
 
static int user_timeout (struct ast_bridge_channel *bridge_channel, void *ignore)
 
static void wait_for_initiator (struct ast_channel *initiator)
 Wait for the initiator of an async playback to be ready. More...
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Conference Bridge Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, .optional_modules = "codec_speex,func_jitterbuffer", }
 
static const char app [] = "ConfBridge"
 
static const char app2 [] = "ConfKick"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_datastore_info async_datastore_info
 Datastore used for timing of async announcement playback. More...
 
static struct ast_cli_entry cli_confbridge []
 
static struct ast_custom_function confbridge_channels_function
 
static struct ast_custom_function confbridge_function
 
static struct ast_custom_function confbridge_info_function
 
struct ao2_containerconference_bridges
 Container to hold all conference bridges in progress. More...
 

Detailed Description

Conference Bridge application.

Author
Joshua Colp <jcolp@digium.com> 
David Vossel <dvossel@digium.com> 

This is a conference bridge application utilizing the bridging core.

Definition in file app_confbridge.c.

Macro Definition Documentation

◆ CONFERENCE_BRIDGE_BUCKETS

#define CONFERENCE_BRIDGE_BUCKETS   53

Number of buckets our conference bridges container can have

Definition at line 598 of file app_confbridge.c.

◆ RECORD_FILENAME_INITIAL_SPACE

#define RECORD_FILENAME_INITIAL_SPACE   128

Initial recording filename space.

Definition at line 601 of file app_confbridge.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4733 of file app_confbridge.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4733 of file app_confbridge.c.

◆ action_confbridgekick()

static int action_confbridgekick ( struct mansession s,
const struct message m 
)
static

Definition at line 4266 of file app_confbridge.c.

4267{
4268 const char *conference_name = astman_get_header(m, "Conference");
4269 const char *channel = astman_get_header(m, "Channel");
4270 struct confbridge_conference *conference;
4271 int found;
4272
4273 if (ast_strlen_zero(conference_name)) {
4274 astman_send_error(s, m, "No Conference name provided.");
4275 return 0;
4276 }
4278 astman_send_error(s, m, "No active conferences.");
4279 return 0;
4280 }
4281
4282 conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
4283 if (!conference) {
4284 astman_send_error(s, m, "No Conference by that name found.");
4285 return 0;
4286 }
4287
4288 found = !kick_conference_participant(conference, channel);
4289 ao2_ref(conference, -1);
4290
4291 if (found) {
4292 astman_send_ack(s, m, !strcmp("all", channel) ? "All participants kicked" : "User kicked");
4293 } else {
4294 astman_send_error(s, m, "No Channel by that name found in Conference.");
4295 }
4296 return 0;
4297}
static int kick_conference_participant(struct confbridge_conference *conference, const char *channel)
struct ao2_container * conference_bridges
Container to hold all conference bridges in progress.
#define OBJ_KEY
Definition: astobj2.h:1151
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1986
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2018
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1647
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
The structure that represents a conference bridge.
Definition: confbridge.h:246

References ao2_container_count(), ao2_find, ao2_ref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), conference_bridges, kick_conference_participant(), and OBJ_KEY.

Referenced by load_module().

◆ action_confbridgelist()

static int action_confbridgelist ( struct mansession s,
const struct message m 
)
static

Definition at line 4098 of file app_confbridge.c.

4099{
4100 const char *actionid = astman_get_header(m, "ActionID");
4101 const char *conference_name = astman_get_header(m, "Conference");
4102 struct confbridge_user *user;
4103 struct confbridge_conference *conference;
4104 char id_text[80];
4105 int total = 0;
4106
4107 id_text[0] = '\0';
4108 if (!ast_strlen_zero(actionid)) {
4109 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
4110 }
4111 if (ast_strlen_zero(conference_name)) {
4112 astman_send_error(s, m, "No Conference name provided.");
4113 return 0;
4114 }
4116 astman_send_error(s, m, "No active conferences.");
4117 return 0;
4118 }
4119 conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
4120 if (!conference) {
4121 astman_send_error(s, m, "No Conference by that name found.");
4122 return 0;
4123 }
4124
4125 astman_send_listack(s, m, "Confbridge user list will follow", "start");
4126
4127 ao2_lock(conference);
4128 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
4129 total += action_confbridgelist_item(s, id_text, conference, user, 0);
4130 }
4131 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
4132 total += action_confbridgelist_item(s, id_text, conference, user, 1);
4133 }
4134 ao2_unlock(conference);
4135 ao2_ref(conference, -1);
4136
4137 astman_send_list_complete_start(s, m, "ConfbridgeListComplete", total);
4139
4140 return 0;
4141}
static int action_confbridgelist_item(struct mansession *s, const char *id_text, struct confbridge_conference *conference, struct confbridge_user *user, int waiting)
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:2028
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:2064
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2072
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
static int total
Definition: res_adsi.c:970
static char user[512]
struct confbridge_conference::@94 active_list
struct confbridge_conference::@95 waiting_list
The structure that represents a conference bridge user.
Definition: confbridge.h:273
structure to hold users read from users.conf

References action_confbridgelist_item(), confbridge_conference::active_list, ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, AST_LIST_TRAVERSE, ast_strlen_zero(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), conference_bridges, OBJ_KEY, total, user, and confbridge_conference::waiting_list.

Referenced by load_module().

◆ action_confbridgelist_item()

static int action_confbridgelist_item ( struct mansession s,
const char *  id_text,
struct confbridge_conference conference,
struct confbridge_user user,
int  waiting 
)
static

Definition at line 4048 of file app_confbridge.c.

4049{
4050 struct ast_channel_snapshot *snapshot;
4051 struct ast_str *snap_str;
4052
4054 if (!snapshot) {
4055 return 0;
4056 }
4057
4058 snap_str = ast_manager_build_channel_state_string(snapshot);
4059 if (!snap_str) {
4060 ao2_ref(snapshot, -1);
4061 return 0;
4062 }
4063
4064 astman_append(s,
4065 "Event: ConfbridgeList\r\n"
4066 "%s"
4067 "Conference: %s\r\n"
4068 "Admin: %s\r\n"
4069 "MarkedUser: %s\r\n"
4070 "WaitMarked: %s\r\n"
4071 "EndMarked: %s\r\n"
4072 "EndMarkedAny: %s\r\n"
4073 "Waiting: %s\r\n"
4074 "Muted: %s\r\n"
4075 "Talking: %s\r\n"
4076 "AnsweredTime: %d\r\n"
4077 "%s"
4078 "\r\n",
4079 id_text,
4080 conference->name,
4086 AST_YESNO(waiting),
4087 AST_YESNO(user->muted),
4088 AST_YESNO(user->talking),
4090 ast_str_buffer(snap_str));
4091
4092 ast_free(snap_str);
4093 ao2_ref(snapshot, -1);
4094
4095 return 1;
4096}
#define ast_free(a)
Definition: astmm.h:180
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_channel_get_up_time(struct ast_channel *chan)
Obtain how long it has been since the channel was answered.
Definition: channel.c:2814
@ USER_OPT_ENDMARKED
Definition: confbridge.h:60
@ USER_OPT_WAITMARKED
Definition: confbridge.h:59
@ USER_OPT_MARKEDUSER
Definition: confbridge.h:54
@ USER_OPT_ENDMARKEDANY
Definition: confbridge.h:74
@ USER_OPT_ADMIN
Definition: confbridge.h:52
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1907
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define AST_YESNO(x)
return Yes or No depending on the argument.
Definition: strings.h:143
Structure representing a snapshot of channel state.
Support for dynamic strings.
Definition: strings.h:623
char name[MAX_CONF_NAME]
Definition: confbridge.h:247
#define ast_test_flag(p, flag)
Definition: utils.h:63

References ao2_ref, ast_channel_get_up_time(), ast_channel_snapshot_get_latest(), ast_channel_uniqueid(), ast_free, ast_manager_build_channel_state_string(), ast_str_buffer(), ast_test_flag, AST_YESNO, astman_append(), confbridge_conference::name, USER_OPT_ADMIN, USER_OPT_ENDMARKED, USER_OPT_ENDMARKEDANY, USER_OPT_MARKEDUSER, and USER_OPT_WAITMARKED.

Referenced by action_confbridgelist().

◆ action_confbridgelistrooms()

static int action_confbridgelistrooms ( struct mansession s,
const struct message m 
)
static

Definition at line 4143 of file app_confbridge.c.

4144{
4145 const char *actionid = astman_get_header(m, "ActionID");
4146 struct confbridge_conference *conference;
4147 struct ao2_iterator iter;
4148 char id_text[512] = "";
4149 int totalitems = 0;
4150
4151 if (!ast_strlen_zero(actionid)) {
4152 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
4153 }
4154
4156 astman_send_error(s, m, "No active conferences.");
4157 return 0;
4158 }
4159
4160 astman_send_listack(s, m, "Confbridge conferences will follow", "start");
4161
4162 /* Traverse the conference list */
4164 while ((conference = ao2_iterator_next(&iter))) {
4165 totalitems++;
4166
4167 ao2_lock(conference);
4168 astman_append(s,
4169 "Event: ConfbridgeListRooms\r\n"
4170 "%s"
4171 "Conference: %s\r\n"
4172 "Parties: %u\r\n"
4173 "Marked: %u\r\n"
4174 "Locked: %s\r\n"
4175 "Muted: %s\r\n"
4176 "\r\n",
4177 id_text,
4178 conference->name,
4179 conference->activeusers + conference->waitingusers,
4180 conference->markedusers,
4181 AST_YESNO(conference->locked),
4182 AST_YESNO(conference->muted));
4183 ao2_unlock(conference);
4184
4185 ao2_ref(conference, -1);
4186 }
4187 ao2_iterator_destroy(&iter);
4188
4189 /* Send final confirmation */
4190 astman_send_list_complete_start(s, m, "ConfbridgeListRoomsComplete", totalitems);
4192 return 0;
4193}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
unsigned int muted
Definition: confbridge.h:255
unsigned int activeusers
Definition: confbridge.h:251
unsigned int waitingusers
Definition: confbridge.h:253
unsigned int markedusers
Definition: confbridge.h:252
unsigned int locked
Definition: confbridge.h:254

References confbridge_conference::activeusers, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_strlen_zero(), AST_YESNO, astman_append(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), conference_bridges, confbridge_conference::locked, confbridge_conference::markedusers, confbridge_conference::muted, confbridge_conference::name, and confbridge_conference::waitingusers.

Referenced by load_module().

◆ action_confbridgelock()

static int action_confbridgelock ( struct mansession s,
const struct message m 
)
static

Definition at line 4261 of file app_confbridge.c.

4262{
4263 return action_lock_unlock_helper(s, m, 1);
4264}
static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock)

References action_lock_unlock_helper().

Referenced by load_module().

◆ action_confbridgemute()

static int action_confbridgemute ( struct mansession s,
const struct message m 
)
static

Definition at line 4232 of file app_confbridge.c.

4233{
4234 return action_mute_unmute_helper(s, m, 1);
4235}
static int action_mute_unmute_helper(struct mansession *s, const struct message *m, int mute)

References action_mute_unmute_helper().

Referenced by load_module().

◆ action_confbridgesetsinglevideosrc()

static int action_confbridgesetsinglevideosrc ( struct mansession s,
const struct message m 
)
static

Definition at line 4378 of file app_confbridge.c.

4379{
4380 const char *conference_name = astman_get_header(m, "Conference");
4381 const char *channel = astman_get_header(m, "Channel");
4382 struct confbridge_user *user;
4383 struct confbridge_conference *conference;
4384
4385 if (ast_strlen_zero(conference_name)) {
4386 astman_send_error(s, m, "No Conference name provided.");
4387 return 0;
4388 }
4389 if (ast_strlen_zero(channel)) {
4390 astman_send_error(s, m, "No channel name provided.");
4391 return 0;
4392 }
4394 astman_send_error(s, m, "No active conferences.");
4395 return 0;
4396 }
4397
4398 conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
4399 if (!conference) {
4400 astman_send_error(s, m, "No Conference by that name found.");
4401 return 0;
4402 }
4403
4404 /* find channel and set as video src. */
4405 ao2_lock(conference);
4406 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
4407 if (!strncmp(channel, ast_channel_name(user->chan), strlen(channel))) {
4409 break;
4410 }
4411 }
4412 ao2_unlock(conference);
4413 ao2_ref(conference, -1);
4414
4415 /* do not access user after conference unlock. We are just
4416 * using this check to see if it was found or not */
4417 if (!user) {
4418 astman_send_error(s, m, "No channel by that name found in conference.");
4419 return 0;
4420 }
4421 astman_send_ack(s, m, "Conference single video source set.");
4422 return 0;
4423}
void ast_bridge_set_single_src_video_mode(struct ast_bridge *bridge, struct ast_channel *video_src_chan)
Set a bridge to feed a single video source to all participants.
Definition: bridge.c:3818
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_bridge * bridge
Definition: confbridge.h:249

References confbridge_conference::active_list, ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_bridge_set_single_src_video_mode(), ast_channel_name(), AST_LIST_TRAVERSE, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), confbridge_conference::bridge, conference_bridges, OBJ_KEY, and user.

Referenced by load_module().

◆ action_confbridgestartrecord()

static int action_confbridgestartrecord ( struct mansession s,
const struct message m 
)
static

Definition at line 4299 of file app_confbridge.c.

4300{
4301 const char *conference_name = astman_get_header(m, "Conference");
4302 const char *recordfile = astman_get_header(m, "RecordFile");
4303 struct confbridge_conference *conference;
4304
4305 if (ast_strlen_zero(conference_name)) {
4306 astman_send_error(s, m, "No Conference name provided.");
4307 return 0;
4308 }
4310 astman_send_error(s, m, "No active conferences.");
4311 return 0;
4312 }
4313
4314 conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
4315 if (!conference) {
4316 astman_send_error(s, m, "No Conference by that name found.");
4317 return 0;
4318 }
4319
4320 ao2_lock(conference);
4321 if (conf_is_recording(conference)) {
4322 astman_send_error(s, m, "Conference is already being recorded.");
4323 ao2_unlock(conference);
4324 ao2_ref(conference, -1);
4325 return 0;
4326 }
4327
4328 if (!ast_strlen_zero(recordfile)) {
4329 ast_copy_string(conference->b_profile.rec_file, recordfile, sizeof(conference->b_profile.rec_file));
4330 }
4331
4332 if (conf_start_record(conference)) {
4333 astman_send_error(s, m, "Internal error starting conference recording.");
4334 ao2_unlock(conference);
4335 ao2_ref(conference, -1);
4336 return 0;
4337 }
4338 ao2_unlock(conference);
4339
4340 ao2_ref(conference, -1);
4341 astman_send_ack(s, m, "Conference Recording Started.");
4342 return 0;
4343}
static int conf_start_record(struct confbridge_conference *conference)
static int conf_is_recording(struct confbridge_conference *conference)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char rec_file[PATH_MAX]
Definition: confbridge.h:230
struct bridge_profile b_profile
Definition: confbridge.h:250

References ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), confbridge_conference::b_profile, conf_is_recording(), conf_start_record(), conference_bridges, OBJ_KEY, and bridge_profile::rec_file.

Referenced by load_module().

◆ action_confbridgestoprecord()

static int action_confbridgestoprecord ( struct mansession s,
const struct message m 
)
static

Definition at line 4344 of file app_confbridge.c.

4345{
4346 const char *conference_name = astman_get_header(m, "Conference");
4347 struct confbridge_conference *conference;
4348
4349 if (ast_strlen_zero(conference_name)) {
4350 astman_send_error(s, m, "No Conference name provided.");
4351 return 0;
4352 }
4354 astman_send_error(s, m, "No active conferences.");
4355 return 0;
4356 }
4357
4358 conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
4359 if (!conference) {
4360 astman_send_error(s, m, "No Conference by that name found.");
4361 return 0;
4362 }
4363
4364 ao2_lock(conference);
4365 if (conf_stop_record(conference)) {
4366 ao2_unlock(conference);
4367 astman_send_error(s, m, "Internal error while stopping recording.");
4368 ao2_ref(conference, -1);
4369 return 0;
4370 }
4371 ao2_unlock(conference);
4372
4373 ao2_ref(conference, -1);
4374 astman_send_ack(s, m, "Conference Recording Stopped.");
4375 return 0;
4376}
static int conf_stop_record(struct confbridge_conference *conference)

References ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), conf_stop_record(), conference_bridges, and OBJ_KEY.

Referenced by load_module().

◆ action_confbridgeunlock()

static int action_confbridgeunlock ( struct mansession s,
const struct message m 
)
static

Definition at line 4257 of file app_confbridge.c.

4258{
4259 return action_lock_unlock_helper(s, m, 0);
4260}

References action_lock_unlock_helper().

Referenced by load_module().

◆ action_confbridgeunmute()

static int action_confbridgeunmute ( struct mansession s,
const struct message m 
)
static

Definition at line 4228 of file app_confbridge.c.

4229{
4230 return action_mute_unmute_helper(s, m, 0);
4231}

References action_mute_unmute_helper().

Referenced by load_module().

◆ action_dialplan_exec()

static int action_dialplan_exec ( struct ast_bridge_channel bridge_channel,
struct conf_menu_action menu_action 
)
static

Definition at line 3202 of file app_confbridge.c.

3203{
3204 struct ast_pbx_args args;
3205 struct ast_pbx *pbx;
3206 char *exten;
3207 char *context;
3208 int priority;
3209 int res;
3210
3211 memset(&args, 0, sizeof(args));
3212 args.no_hangup_chan = 1;
3213
3214 ast_channel_lock(bridge_channel->chan);
3215
3216 /*save off*/
3217 exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
3218 context = ast_strdupa(ast_channel_context(bridge_channel->chan));
3219 priority = ast_channel_priority(bridge_channel->chan);
3220 pbx = ast_channel_pbx(bridge_channel->chan);
3221 ast_channel_pbx_set(bridge_channel->chan, NULL);
3222
3223 /*set new*/
3224 ast_channel_exten_set(bridge_channel->chan, menu_action->data.dialplan_args.exten);
3225 ast_channel_context_set(bridge_channel->chan, menu_action->data.dialplan_args.context);
3226 ast_channel_priority_set(bridge_channel->chan, menu_action->data.dialplan_args.priority);
3227
3228 ast_channel_unlock(bridge_channel->chan);
3229
3230 /*execute*/
3231 res = ast_pbx_run_args(bridge_channel->chan, &args);
3232
3233 /*restore*/
3234 ast_channel_lock(bridge_channel->chan);
3235
3236 ast_channel_exten_set(bridge_channel->chan, exten);
3237 ast_channel_context_set(bridge_channel->chan, context);
3238 ast_channel_priority_set(bridge_channel->chan, priority);
3239 ast_channel_pbx_set(bridge_channel->chan, pbx);
3240
3241 ast_channel_unlock(bridge_channel->chan);
3242
3243 return res;
3244}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
static int priority
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
#define ast_channel_lock(chan)
Definition: channel.h:2972
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
struct ast_pbx * ast_channel_pbx(const 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:2973
void ast_channel_pbx_set(struct ast_channel *chan, struct ast_pbx *value)
enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
Execute the PBX in the current thread.
Definition: pbx.c:4750
#define NULL
Definition: resample.c:96
struct ast_channel * chan
Options for ast_pbx_run()
Definition: pbx.h:408
Definition: pbx.h:215
char exten[AST_MAX_EXTENSION]
Definition: confbridge.h:128
struct conf_menu_action::@88::@90 dialplan_args
char context[AST_MAX_CONTEXT]
Definition: confbridge.h:127
union conf_menu_action::@88 data
const char * args

References args, ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_lock, ast_channel_pbx(), ast_channel_pbx_set(), ast_channel_priority(), ast_channel_priority_set(), ast_channel_unlock, ast_pbx_run_args(), ast_strdupa, ast_bridge_channel::chan, conf_menu_action::context, voicemailpwcheck::context, conf_menu_action::data, conf_menu_action::dialplan_args, conf_menu_action::exten, NULL, conf_menu_action::priority, and priority.

Referenced by execute_menu_entry().

◆ action_kick_last()

static int action_kick_last ( struct confbridge_conference conference,
struct ast_bridge_channel bridge_channel,
struct confbridge_user user 
)
static

Definition at line 3165 of file app_confbridge.c.

3168{
3169 struct confbridge_user *last_user = NULL;
3170 int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
3171
3172 if (!isadmin) {
3173 play_file(bridge_channel, NULL,
3175 ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
3176 ast_channel_name(bridge_channel->chan),
3177 conference->name);
3178 return -1;
3179 }
3180
3182 last_user = AST_LIST_LAST(&conference->active_list);
3183 if (!last_user) {
3185 return 0;
3186 }
3187
3188 if (last_user == user || ast_test_flag(&last_user->u_profile, USER_OPT_ADMIN)) {
3190 play_file(bridge_channel, NULL,
3192 } else if (!last_user->kicked) {
3193 last_user->kicked = 1;
3194 pbx_builtin_setvar_helper(last_user->chan, "CONFBRIDGE_RESULT", "KICKED");
3197 }
3198
3199 return 0;
3200}
const char * conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds)
Looks to see if sound file is stored in bridge profile sounds, if not default sound is provided.
static int play_file(struct ast_bridge_channel *bridge_channel, struct ast_channel *channel, const char *filename)
Playback the given filename and monitor for any dtmf interrupts.
#define ast_log
Definition: astobj2.c:42
int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan)
Remove a channel from a bridge.
Definition: bridge.c:2020
@ CONF_SOUND_ERROR_MENU
Definition: confbridge.h:187
#define LOG_WARNING
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:429
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
struct bridge_profile_sounds * sounds
Definition: confbridge.h:238
unsigned int kicked
Definition: confbridge.h:284
struct confbridge_conference * conference
Definition: confbridge.h:274
struct ast_channel * chan
Definition: confbridge.h:279
struct user_profile u_profile
Definition: confbridge.h:276

References confbridge_conference::active_list, ao2_lock, ao2_unlock, ast_bridge_remove(), ast_channel_name(), AST_LIST_LAST, ast_log, ast_test_flag, confbridge_conference::b_profile, confbridge_conference::bridge, confbridge_user::chan, ast_bridge_channel::chan, conf_get_sound(), CONF_SOUND_ERROR_MENU, confbridge_user::conference, confbridge_user::kicked, LOG_WARNING, confbridge_conference::name, NULL, pbx_builtin_setvar_helper(), play_file(), bridge_profile::sounds, confbridge_user::u_profile, and USER_OPT_ADMIN.

Referenced by execute_menu_entry().

◆ action_lock_unlock_helper()

static int action_lock_unlock_helper ( struct mansession s,
const struct message m,
int  lock 
)
static

Definition at line 4237 of file app_confbridge.c.

4238{
4239 const char *conference_name = astman_get_header(m, "Conference");
4240 int res = 0;
4241
4242 if (ast_strlen_zero(conference_name)) {
4243 astman_send_error(s, m, "No Conference name provided.");
4244 return 0;
4245 }
4247 astman_send_error(s, m, "No active conferences.");
4248 return 0;
4249 }
4250 if ((res = generic_lock_unlock_helper(lock, conference_name))) {
4251 astman_send_error(s, m, "No Conference by that name found.");
4252 return 0;
4253 }
4254 astman_send_ack(s, m, lock ? "Conference locked" : "Conference unlocked");
4255 return 0;
4256}
static int generic_lock_unlock_helper(int lock, const char *conference_name)
ast_mutex_t lock
Definition: app_sla.c:337

References ao2_container_count(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), conference_bridges, generic_lock_unlock_helper(), and lock.

Referenced by action_confbridgelock(), and action_confbridgeunlock().

◆ action_mute_unmute_helper()

static int action_mute_unmute_helper ( struct mansession s,
const struct message m,
int  mute 
)
static

Definition at line 4195 of file app_confbridge.c.

4196{
4197 const char *conference_name = astman_get_header(m, "Conference");
4198 const char *channel_name = astman_get_header(m, "Channel");
4199 int res = 0;
4200
4201 if (ast_strlen_zero(conference_name)) {
4202 astman_send_error(s, m, "No Conference name provided.");
4203 return 0;
4204 }
4205 if (ast_strlen_zero(channel_name)) {
4206 astman_send_error(s, m, "No channel name provided.");
4207 return 0;
4208 }
4210 astman_send_error(s, m, "No active conferences.");
4211 return 0;
4212 }
4213
4214 res = generic_mute_unmute_helper(mute, conference_name, channel_name);
4215
4216 if (res == -1) {
4217 astman_send_error(s, m, "No Conference by that name found.");
4218 return 0;
4219 } else if (res == -2) {
4220 astman_send_error(s, m, "No Channel by that name found in Conference.");
4221 return 0;
4222 }
4223
4224 astman_send_ack(s, m, mute ? "User muted" : "User unmuted");
4225 return 0;
4226}
static int generic_mute_unmute_helper(int mute, const char *conference_name, const char *chan_name)

References ao2_container_count(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), conference_bridges, and generic_mute_unmute_helper().

Referenced by action_confbridgemute(), and action_confbridgeunmute().

◆ action_playback()

static int action_playback ( struct ast_bridge_channel bridge_channel,
const char *  playback_file 
)
static

Definition at line 3080 of file app_confbridge.c.

3081{
3082 char *file_copy = ast_strdupa(playback_file);
3083 char *file = NULL;
3084
3085 while ((file = ast_strsep(&file_copy, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) {
3086 if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
3087 ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
3088 return -1;
3089 }
3090 }
3091 return 0;
3092}
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1886
@ AST_STRSEP_TRIM
Definition: strings.h:256
@ AST_STRSEP_STRIP
Definition: strings.h:255
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition: utils.c:1835

References ast_log, ast_strdupa, ast_stream_and_wait(), ast_strsep(), AST_STRSEP_STRIP, AST_STRSEP_TRIM, ast_bridge_channel::chan, make_ari_stubs::file, LOG_WARNING, and NULL.

Referenced by execute_menu_entry().

◆ action_playback_and_continue()

static int action_playback_and_continue ( struct confbridge_conference conference,
struct confbridge_user user,
struct ast_bridge_channel bridge_channel,
struct conf_menu menu,
const char *  playback_file,
const char *  cur_dtmf,
int *  stop_prompts 
)
static

Definition at line 3094 of file app_confbridge.c.

3101{
3102 int i;
3103 int digit = 0;
3104 char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
3105 struct conf_menu_entry new_menu_entry = { { 0, }, };
3106 char *file_copy = ast_strdupa(playback_file);
3107 char *file = NULL;
3108
3109 while ((file = ast_strsep(&file_copy, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) {
3110 if (ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan))) {
3111 ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
3112 return -1;
3113 }
3114
3115 /* now wait for more digits. */
3116 if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) {
3117 /* streaming finished and no DTMF was entered */
3118 continue;
3119 } else if (digit == -1) {
3120 /* error */
3121 return -1;
3122 } else {
3123 break; /* dtmf was entered */
3124 }
3125 }
3126 if (!digit) {
3127 /* streaming finished on all files and no DTMF was entered */
3128 return -1;
3129 }
3130 ast_stopstream(bridge_channel->chan);
3131
3132 /* If we get here, then DTMF has been entered, This means no
3133 * additional prompts should be played for this menu entry */
3134 *stop_prompts = 1;
3135
3136 /* If a digit was pressed during the payback, update
3137 * the dtmf string and look for a new menu entry in the
3138 * menu structure */
3139 ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf));
3140 for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) {
3141 dtmf[i] = cur_dtmf[i];
3142 if (!dtmf[i]) {
3143 dtmf[i] = (char) digit;
3144 dtmf[i + 1] = '\0';
3145 i = -1;
3146 break;
3147 }
3148 }
3149 /* If i is not -1 then the new dtmf digit was _NOT_ added to the string.
3150 * If this is the case, no new DTMF sequence should be looked for. */
3151 if (i != -1) {
3152 return 0;
3153 }
3154
3155 if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) {
3156 execute_menu_entry(conference,
3157 user,
3158 bridge_channel,
3159 &new_menu_entry, menu);
3160 conf_menu_entry_destroy(&new_menu_entry);
3161 }
3162 return 0;
3163}
char digit
static int execute_menu_entry(struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel, struct conf_menu_entry *menu_entry, struct conf_menu *menu)
#define MAXIMUM_DTMF_FEATURE_STRING
Maximum length of a DTMF feature string.
const char * ast_channel_language(const struct ast_channel *chan)
int conf_find_menu_entry_by_sequence(const char *dtmf_sequence, struct conf_menu *menu, struct conf_menu_entry *result)
Finds a menu_entry in a menu structure matched by DTMF sequence.
void conf_menu_entry_destroy(struct conf_menu_entry *menu_entry)
Destroys and frees all the actions stored in a menu_entry structure.
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:222
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1301
#define AST_DIGIT_ANY
Definition: file.h:48
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1848
Definition: confbridge.h:138
char dtmf[MAXIMUM_DTMF_FEATURE_STRING]
Definition: confbridge.h:140

References ast_channel_language(), ast_copy_string(), AST_DIGIT_ANY, ast_log, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strsep(), AST_STRSEP_STRIP, AST_STRSEP_TRIM, ast_waitstream(), ast_bridge_channel::chan, conf_find_menu_entry_by_sequence(), conf_menu_entry_destroy(), digit, conf_menu_entry::dtmf, execute_menu_entry(), make_ari_stubs::file, LOG_WARNING, MAXIMUM_DTMF_FEATURE_STRING, and NULL.

Referenced by execute_menu_entry().

◆ action_toggle_binaural()

static int action_toggle_binaural ( struct confbridge_conference conference,
struct confbridge_user user,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 3024 of file app_confbridge.c.

3027{
3028 unsigned int binaural;
3029 ast_bridge_channel_lock_bridge(bridge_channel);
3030 binaural = !bridge_channel->binaural_suspended;
3031 bridge_channel->binaural_suspended = binaural;
3032 ast_bridge_unlock(bridge_channel->bridge);
3033 return play_file(bridge_channel, NULL, (binaural ?
3034 conf_get_sound(CONF_SOUND_BINAURAL_OFF, user->b_profile.sounds) :
3035 conf_get_sound(CONF_SOUND_BINAURAL_ON, user->b_profile.sounds))) < 0;
3036}
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:485
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
Lock the bridge associated with the bridge channel.
@ CONF_SOUND_BINAURAL_ON
Definition: confbridge.h:193
@ CONF_SOUND_BINAURAL_OFF
Definition: confbridge.h:194
struct ast_bridge * bridge
Bridge this channel is participating in.
unsigned int binaural_suspended

References ast_bridge_channel_lock_bridge(), ast_bridge_unlock, ast_bridge_channel::binaural_suspended, ast_bridge_channel::bridge, conf_get_sound(), CONF_SOUND_BINAURAL_OFF, CONF_SOUND_BINAURAL_ON, NULL, and play_file().

Referenced by execute_menu_entry().

◆ action_toggle_mute()

static int action_toggle_mute ( struct confbridge_conference conference,
struct confbridge_user user,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 3009 of file app_confbridge.c.

3012{
3013 int mute;
3014
3015 /* Toggle user level mute request. */
3016 mute = !user->muted;
3017 generic_mute_unmute_user(conference, user, mute);
3018
3019 return play_file(bridge_channel, NULL,
3021 conference->b_profile.sounds)) < 0;
3022}
static void generic_mute_unmute_user(struct confbridge_conference *conference, struct confbridge_user *user, int mute)
@ CONF_SOUND_UNMUTED
Definition: confbridge.h:174
@ CONF_SOUND_MUTED
Definition: confbridge.h:173

References confbridge_conference::b_profile, conf_get_sound(), CONF_SOUND_MUTED, CONF_SOUND_UNMUTED, confbridge_hook_data::conference, generic_mute_unmute_user(), NULL, play_file(), and bridge_profile::sounds.

Referenced by execute_menu_entry().

◆ action_toggle_mute_participants()

static int action_toggle_mute_participants ( struct confbridge_conference conference,
struct confbridge_user user 
)
static

Definition at line 3038 of file app_confbridge.c.

3039{
3040 struct confbridge_user *cur_user = NULL;
3041 const char *sound_to_play;
3042 int mute;
3043
3045
3046 /* Toggle bridge level mute request. */
3047 mute = !conference->muted;
3048 conference->muted = mute;
3049
3051 if (!ast_test_flag(&cur_user->u_profile, USER_OPT_ADMIN)) {
3052 /* Set user level to bridge level mute request. */
3053 cur_user->muted = mute;
3054 conf_update_user_mute(cur_user);
3055 }
3056 }
3057
3059
3060 sound_to_play = conf_get_sound(
3063
3064 if (strcmp(conference->b_profile.language, ast_channel_language(user->chan))) {
3065 /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */
3066 ast_stream_and_wait(user->chan, sound_to_play, "");
3067
3068 /* Announce to the group that all participants are muted */
3070 play_sound_file(conference, sound_to_play);
3072 } else {
3073 /* Playing the sound asynchronously lets the sound be heard by everyone at once */
3074 async_play_sound_file(conference, sound_to_play, user->chan);
3075 }
3076
3077 return 0;
3078}
int async_play_sound_file(struct confbridge_conference *conference, const char *filename, struct ast_channel *initiator)
Play sound file into conference bridge asynchronously.
int play_sound_file(struct confbridge_conference *conference, const char *filename)
Play sound file into conference bridge.
void conf_update_user_mute(struct confbridge_user *user)
Update the actual mute status of the user and set it on the bridge.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
@ CONF_SOUND_PARTICIPANTS_UNMUTED
Definition: confbridge.h:191
@ CONF_SOUND_PARTICIPANTS_MUTED
Definition: confbridge.h:190
char language[MAX_LANGUAGE]
Definition: confbridge.h:229
unsigned int muted
Definition: confbridge.h:283
struct confbridge_user::@98 list

References confbridge_conference::active_list, ao2_lock, ao2_unlock, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_language(), AST_LIST_TRAVERSE, ast_stream_and_wait(), ast_test_flag, async_play_sound_file(), confbridge_conference::b_profile, conf_get_sound(), CONF_SOUND_PARTICIPANTS_MUTED, CONF_SOUND_PARTICIPANTS_UNMUTED, conf_update_user_mute(), confbridge_user::conference, bridge_profile::language, confbridge_user::list, confbridge_conference::muted, confbridge_user::muted, NULL, play_sound_file(), bridge_profile::sounds, confbridge_user::u_profile, and USER_OPT_ADMIN.

Referenced by execute_menu_entry().

◆ alloc_playback_chan()

static int alloc_playback_chan ( struct confbridge_conference conference)
static

Definition at line 1630 of file app_confbridge.c.

1631{
1632 struct ast_format_cap *cap;
1633 char taskprocessor_name[AST_TASKPROCESSOR_MAX_NAME + 1];
1634
1636 if (!cap) {
1637 return -1;
1638 }
1640 conference->playback_chan = ast_request("CBAnn", cap, NULL, NULL,
1641 conference->name, NULL);
1642 ao2_ref(cap, -1);
1643 if (!conference->playback_chan) {
1644 return -1;
1645 }
1646
1647 /* To make sure playback_chan has the same language as the bridge */
1648 ast_channel_lock(conference->playback_chan);
1649 ast_channel_language_set(conference->playback_chan, conference->b_profile.language);
1650 ast_channel_unlock(conference->playback_chan);
1651
1652 ast_debug(1, "Created announcer channel '%s' to conference bridge '%s'\n",
1653 ast_channel_name(conference->playback_chan), conference->name);
1654
1655 ast_taskprocessor_build_name(taskprocessor_name, sizeof(taskprocessor_name),
1656 "Confbridge/%s", conference->name);
1657 conference->playback_queue = ast_taskprocessor_get(taskprocessor_name, TPS_REF_DEFAULT);
1658 if (!conference->playback_queue) {
1659 ast_hangup(conference->playback_chan);
1660 conference->playback_chan = NULL;
1661 return -1;
1662 }
1663 return 0;
1664}
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2510
struct ast_channel * ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
Requests a channel.
Definition: channel.c:6313
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
#define ast_debug(level,...)
Log a DEBUG message.
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct ast_channel * playback_chan
Definition: confbridge.h:256
struct ast_taskprocessor * playback_queue
Definition: confbridge.h:262
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary.
@ TPS_REF_DEFAULT
return a reference to a taskprocessor, create one if it does not exist
Definition: taskprocessor.h:76
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
Definition: taskprocessor.h:61

References ao2_ref, ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_slin, ast_hangup(), ast_request(), ast_taskprocessor_build_name(), ast_taskprocessor_get(), AST_TASKPROCESSOR_MAX_NAME, confbridge_conference::b_profile, bridge_profile::language, confbridge_conference::name, NULL, confbridge_conference::playback_chan, confbridge_conference::playback_queue, and TPS_REF_DEFAULT.

Referenced by join_conference_bridge().

◆ announce_user_count()

static int announce_user_count ( struct confbridge_conference conference,
struct confbridge_user user,
struct ast_bridge_channel bridge_channel 
)
static

Announce number of users in the conference bridge to the caller.

Parameters
conferenceConference bridge to peek at
userOptional Caller
bridge_channelThe bridged channel involved
Note
if caller is NULL, the announcement will be sent to all participants in the conference.
Return values
0on success.
-1if the user hung up.

Definition at line 1123 of file app_confbridge.c.

1125{
1126 const char *other_in_party = conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, conference->b_profile.sounds);
1127 const char *only_one = conf_get_sound(CONF_SOUND_ONLY_ONE, conference->b_profile.sounds);
1128 const char *there_are = conf_get_sound(CONF_SOUND_THERE_ARE, conference->b_profile.sounds);
1129
1130 if (conference->activeusers <= 1) {
1131 /* Awww we are the only person in the conference bridge OR we only have waitmarked users */
1132 return 0;
1133 } else if (conference->activeusers == 2) {
1134 if (user) {
1135 /* Eep, there is one other person */
1136 if (play_file(bridge_channel, user->chan, only_one) < 0) {
1137 return -1;
1138 }
1139 } else {
1140 play_sound_file(conference, only_one);
1141 }
1142 } else {
1143 /* Alas multiple others in here */
1144 if (user) {
1145 if (ast_stream_and_wait(user->chan,
1146 there_are,
1147 "")) {
1148 return -1;
1149 }
1150 if (ast_say_number(user->chan, conference->activeusers - 1, "", ast_channel_language(user->chan), NULL)) {
1151 return -1;
1152 }
1153 if (play_file(bridge_channel, user->chan, other_in_party) < 0) {
1154 return -1;
1155 }
1156 } else if (sound_file_exists(there_are) && sound_file_exists(other_in_party)) {
1157 play_sound_file(conference, there_are);
1158 play_sound_number(conference, conference->activeusers - 1);
1159 play_sound_file(conference, other_in_party);
1160 }
1161 }
1162 return 0;
1163}
static int play_sound_number(struct confbridge_conference *conference, int say_number)
Play number into the conference bridge.
static int sound_file_exists(const char *filename)
@ CONF_SOUND_OTHER_IN_PARTY
Definition: confbridge.h:177
@ CONF_SOUND_THERE_ARE
Definition: confbridge.h:176
@ CONF_SOUND_ONLY_ONE
Definition: confbridge.h:175
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8240

References confbridge_conference::activeusers, ast_channel_language(), ast_say_number(), ast_stream_and_wait(), confbridge_conference::b_profile, ast_channel::bridge_channel, conf_get_sound(), CONF_SOUND_ONLY_ONE, CONF_SOUND_OTHER_IN_PARTY, CONF_SOUND_THERE_ARE, NULL, play_file(), play_sound_file(), play_sound_number(), sound_file_exists(), and bridge_profile::sounds.

Referenced by execute_menu_entry(), and join_conference_bridge().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 4733 of file app_confbridge.c.

◆ async_datastore_data_alloc()

static struct async_datastore_data * async_datastore_data_alloc ( void  )
static

Definition at line 2221 of file app_confbridge.c.

2222{
2223 struct async_datastore_data *add;
2224
2225 add = ast_malloc(sizeof(*add));
2226 if (!add) {
2227 return NULL;
2228 }
2229
2230 ast_mutex_init(&add->lock);
2231 ast_cond_init(&add->cond, NULL);
2232 add->wait = 1;
2233
2234 return add;
2235}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_cond_init(cond, attr)
Definition: lock.h:208
#define ast_mutex_init(pmutex)
Definition: lock.h:193

References ast_cond_init, ast_malloc, ast_mutex_init, async_datastore_data::cond, async_datastore_data::lock, NULL, and async_datastore_data::wait.

Referenced by setup_async_playback_datastore().

◆ async_datastore_data_destroy()

static void async_datastore_data_destroy ( void *  data)
static

Definition at line 2189 of file app_confbridge.c.

2190{
2191 struct async_datastore_data *add = data;
2192
2193 ast_mutex_destroy(&add->lock);
2194 ast_cond_destroy(&add->cond);
2195
2196 ast_free(add);
2197}
#define ast_cond_destroy(cond)
Definition: lock.h:209
#define ast_mutex_destroy(a)
Definition: lock.h:195

References ast_cond_destroy, ast_free, ast_mutex_destroy, async_datastore_data::cond, and async_datastore_data::lock.

◆ async_delete_name_rec()

static int async_delete_name_rec ( struct confbridge_conference conference,
const char *  filename 
)
static

Definition at line 2628 of file app_confbridge.c.

2630{
2632
2634 return 0;
2635 } else if (!sound_file_exists(filename)) {
2636 return 0;
2637 }
2638
2640 if (!atd) {
2641 return -1;
2642 }
2643
2645 ast_log(LOG_WARNING, "Conference '%s' was unable to remove user name file '%s'\n",
2648 return -1;
2649 }
2650
2651 return 0;
2652}
static void async_delete_name_rec_task_data_destroy(struct async_delete_name_rec_task_data *atd)
static int async_delete_name_rec_task(void *data)
Delete user's name file asynchronously.
static struct async_delete_name_rec_task_data * async_delete_name_rec_task_data_alloc(struct confbridge_conference *conference, const char *filename)
struct confbridge_conference * conference
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.

References ast_log, ast_strlen_zero(), ast_taskprocessor_push(), async_delete_name_rec_task(), async_delete_name_rec_task_data_alloc(), async_delete_name_rec_task_data_destroy(), async_delete_name_rec_task_data::conference, async_delete_name_rec_task_data::filename, LOG_WARNING, confbridge_conference::name, confbridge_conference::playback_queue, and sound_file_exists().

Referenced by confbridge_exec().

◆ async_delete_name_rec_task()

static int async_delete_name_rec_task ( void *  data)
static

Delete user's name file asynchronously.

This runs in the playback queue taskprocessor. This ensures that sound file is removed after playback is finished and not before.

Parameters
dataAn async_delete_name_rec_task_data
Returns
0

Definition at line 2616 of file app_confbridge.c.

2617{
2618 struct async_delete_name_rec_task_data *atd = data;
2619
2621 ast_log(LOG_DEBUG, "Conference '%s' removed user name file '%s'\n",
2622 atd->conference->name, atd->filename);
2623
2625 return 0;
2626}
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1149
#define LOG_DEBUG

References ast_filedelete(), ast_log, async_delete_name_rec_task_data_destroy(), async_delete_name_rec_task_data::conference, async_delete_name_rec_task_data::filename, LOG_DEBUG, confbridge_conference::name, and NULL.

Referenced by async_delete_name_rec().

◆ async_delete_name_rec_task_data_alloc()

static struct async_delete_name_rec_task_data * async_delete_name_rec_task_data_alloc ( struct confbridge_conference conference,
const char *  filename 
)
static

Definition at line 2585 of file app_confbridge.c.

2587{
2589
2590 atd = ast_malloc(sizeof(*atd) + strlen(filename) + 1);
2591 if (!atd) {
2592 return NULL;
2593 }
2594
2595 /* Safe */
2596 strcpy(atd->filename, filename);
2597 atd->conference = conference;
2598
2599 return atd;
2600}

References ast_malloc, async_delete_name_rec_task_data::conference, async_delete_name_rec_task_data::filename, and NULL.

Referenced by async_delete_name_rec().

◆ async_delete_name_rec_task_data_destroy()

static void async_delete_name_rec_task_data_destroy ( struct async_delete_name_rec_task_data atd)
static

Definition at line 2602 of file app_confbridge.c.

2603{
2604 ast_free(atd);
2605}

References ast_free.

Referenced by async_delete_name_rec(), and async_delete_name_rec_task().

◆ async_play_sound_file()

int async_play_sound_file ( struct confbridge_conference conference,
const char *  filename,
struct ast_channel initiator 
)

Play sound file into conference bridge asynchronously.

If the initiator parameter is non-NULL, then the playback will wait for that initiator channel to get back in the bridge before playing the sound file. This way, the initiator has no danger of hearing a "clipped" file.

Parameters
conferenceThe conference bridge to play sound file into
filenameSound file to play
initiatorChannel that initiated playback.
Return values
0success
-1failure

Definition at line 2418 of file app_confbridge.c.

2420{
2421 return async_play_sound_helper(conference, filename, -1, initiator);
2422}
static int async_play_sound_helper(struct confbridge_conference *conference, const char *filename, int say_number, struct ast_channel *initiator)

References async_play_sound_helper(), async_playback_task_data::conference, async_playback_task_data::filename, and async_playback_task_data::initiator.

Referenced by action_toggle_mute_participants(), confbridge_exec(), and leave_marked().

◆ async_play_sound_helper()

static int async_play_sound_helper ( struct confbridge_conference conference,
const char *  filename,
int  say_number,
struct ast_channel initiator 
)
static

Definition at line 2384 of file app_confbridge.c.

2386{
2387 struct async_playback_task_data *aptd;
2388
2389 /* Do not waste resources trying to play files that do not exist */
2391 if (say_number < 0) {
2392 return 0;
2393 }
2394 } else if (!sound_file_exists(filename)) {
2395 return 0;
2396 }
2397
2399 if (!aptd) {
2400 return -1;
2401 }
2402
2404 if (!ast_strlen_zero(filename)) {
2405 ast_log(LOG_WARNING, "Unable to play file '%s' to conference '%s'\n",
2407 } else {
2408 ast_log(LOG_WARNING, "Unable to say number '%d' to conference '%s'\n",
2410 }
2412 return -1;
2413 }
2414
2415 return 0;
2416}
static void async_playback_task_data_destroy(struct async_playback_task_data *aptd)
static struct async_playback_task_data * async_playback_task_data_alloc(struct confbridge_conference *conference, const char *filename, int say_number, struct ast_channel *initiator)
static int async_playback_task(void *data)
Play an announcement into a confbridge asynchronously.
struct confbridge_conference * conference
struct ast_channel * initiator

References ast_log, ast_strlen_zero(), ast_taskprocessor_push(), async_playback_task(), async_playback_task_data_alloc(), async_playback_task_data_destroy(), async_playback_task_data::conference, async_playback_task_data::filename, async_playback_task_data::initiator, LOG_WARNING, confbridge_conference::name, confbridge_conference::playback_queue, async_playback_task_data::say_number, and sound_file_exists().

Referenced by async_play_sound_file().

◆ async_play_sound_ready()

void async_play_sound_ready ( struct ast_channel chan)

Indicate the initiator of an async sound file is ready for it to play.

When playing an async sound file, the initiator is typically either out of the bridge or not in a position to hear the queued announcement. This function lets the announcement thread know that the initiator is now ready for the sound to play.

If an async announcement was queued and no initiator channel was provided, then this is a no-op

Parameters
chanThe channel that initiated the async announcement

Definition at line 2424 of file app_confbridge.c.

2425{
2426 struct ast_datastore *async_datastore;
2427 struct async_datastore_data *add;
2428
2429 ast_channel_lock(chan);
2430 async_datastore = ast_channel_datastore_find(chan, &async_datastore_info, NULL);
2431 ast_channel_unlock(chan);
2432 if (!async_datastore) {
2433 return;
2434 }
2435
2436 add = async_datastore->data;
2437
2438 ast_mutex_lock(&add->lock);
2439 add->wait = 0;
2440 ast_cond_signal(&add->cond);
2441 ast_mutex_unlock(&add->lock);
2442}
static struct ast_datastore_info async_datastore_info
Datastore used for timing of async announcement playback.
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:2368
#define ast_mutex_unlock(a)
Definition: lock.h:197
#define ast_mutex_lock(a)
Definition: lock.h:196
#define ast_cond_signal(cond)
Definition: lock.h:210
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, async_datastore_info, async_datastore_data::cond, ast_datastore::data, async_datastore_data::lock, NULL, and async_datastore_data::wait.

Referenced by conf_handle_dtmf(), confbridge_exec(), and join_callback().

◆ async_playback_task()

static int async_playback_task ( void *  data)
static

Play an announcement into a confbridge asynchronously.

This runs in the playback queue taskprocessor. This ensures that all playbacks are handled in sequence and do not play over top one another.

Parameters
dataAn async_playback_task_data
Returns
0

Definition at line 2369 of file app_confbridge.c.

2370{
2371 struct async_playback_task_data *aptd = data;
2372
2373 /* Wait for the initiator to get back in the bridge or be hung up */
2374 if (aptd->initiator) {
2376 }
2377
2378 playback_common(aptd->conference, aptd->filename, aptd->say_number);
2379
2381 return 0;
2382}
static void playback_common(struct confbridge_conference *conference, const char *filename, int say_number)
static void wait_for_initiator(struct ast_channel *initiator)
Wait for the initiator of an async playback to be ready.

References async_playback_task_data_destroy(), async_playback_task_data::conference, async_playback_task_data::filename, async_playback_task_data::initiator, playback_common(), async_playback_task_data::say_number, and wait_for_initiator().

Referenced by async_play_sound_helper().

◆ async_playback_task_data_alloc()

static struct async_playback_task_data * async_playback_task_data_alloc ( struct confbridge_conference conference,
const char *  filename,
int  say_number,
struct ast_channel initiator 
)
static

Definition at line 2277 of file app_confbridge.c.

2280{
2281 struct async_playback_task_data *aptd;
2282
2283 aptd = ast_malloc(sizeof(*aptd) + strlen(filename) + 1);
2284 if (!aptd) {
2285 return NULL;
2286 }
2287
2288 /* Safe */
2289 strcpy(aptd->filename, filename);
2290 aptd->say_number = say_number;
2291
2292 /* You may think that we need to bump the conference refcount since we are pushing
2293 * this task to the taskprocessor.
2294 *
2295 * In this case, that actually causes a problem. The destructor for the conference
2296 * pushes a hangup task into the taskprocessor and waits for it to complete before
2297 * continuing. If the destructor gets called from a taskprocessor task, we're
2298 * deadlocked.
2299 *
2300 * So is there a risk of the conference being freed out from under us? No. Since
2301 * the destructor pushes a task into the taskprocessor and waits for it to complete,
2302 * the destructor cannot free the conference out from under us. No further tasks
2303 * can be queued onto the taskprocessor after the hangup since no channels are referencing
2304 * the conference at that point any more.
2305 */
2306 aptd->conference = conference;
2307
2308 aptd->initiator = initiator;
2309 if (initiator) {
2312 /* We don't really care if this fails. If the datastore fails to get set up
2313 * we'll still play the announcement. It's possible that the sound will be
2314 * clipped for the initiator, but that's not the end of the world.
2315 */
2318 }
2319
2320 return aptd;
2321}
static int setup_async_playback_datastore(struct ast_channel *initiator)
Prepare the async playback datastore.
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997

References ast_channel_lock, ast_channel_ref, ast_channel_unlock, ast_malloc, async_playback_task_data::conference, async_playback_task_data::filename, async_playback_task_data::initiator, NULL, async_playback_task_data::say_number, and setup_async_playback_datastore().

Referenced by async_play_sound_helper().

◆ async_playback_task_data_destroy()

static void async_playback_task_data_destroy ( struct async_playback_task_data aptd)
static

Definition at line 2323 of file app_confbridge.c.

2324{
2326 ast_free(aptd);
2327}
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3019

References ast_channel_cleanup, ast_free, and async_playback_task_data::initiator.

Referenced by async_play_sound_helper(), and async_playback_task().

◆ cli_mute_unmute_helper()

static int cli_mute_unmute_helper ( int  mute,
struct ast_cli_args a 
)
static

Definition at line 3717 of file app_confbridge.c.

3718{
3719 int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]);
3720
3721 if (res == -1) {
3722 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
3723 return -1;
3724 } else if (res == -2) {
3725 if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
3726 ast_cli(a->fd, "No participants found in conference %s\n", a->argv[2]);
3727 } else {
3728 ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
3729 }
3730 return -1;
3731 }
3732 ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
3733 return 0;
3734}
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static struct test_val a

References a, ast_cli(), and generic_mute_unmute_helper().

Referenced by handle_cli_confbridge_mute(), and handle_cli_confbridge_unmute().

◆ complete_confbridge_name()

static char * complete_confbridge_name ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 3423 of file app_confbridge.c.

3424{
3425 int which = 0;
3426 struct confbridge_conference *conference;
3427 char *res = NULL;
3428 int wordlen = strlen(word);
3429 struct ao2_iterator iter;
3430
3432 while ((conference = ao2_iterator_next(&iter))) {
3433 if (!strncasecmp(conference->name, word, wordlen) && ++which > state) {
3434 res = ast_strdup(conference->name);
3435 ao2_ref(conference, -1);
3436 break;
3437 }
3438 ao2_ref(conference, -1);
3439 }
3440 ao2_iterator_destroy(&iter);
3441
3442 return res;
3443}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
short word

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_strdup, conference_bridges, confbridge_conference::name, and NULL.

Referenced by handle_cli_confbridge_kick(), handle_cli_confbridge_list(), handle_cli_confbridge_lock(), handle_cli_confbridge_mute(), handle_cli_confbridge_start_record(), handle_cli_confbridge_stop_record(), handle_cli_confbridge_unlock(), and handle_cli_confbridge_unmute().

◆ complete_confbridge_participant()

static char * complete_confbridge_participant ( const char *  conference_name,
const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 3445 of file app_confbridge.c.

3446{
3447 int which = 0;
3448 RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
3449 struct confbridge_user *user;
3450 char *res = NULL;
3451 int wordlen = strlen(word);
3452
3453 conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3454 if (!conference) {
3455 return NULL;
3456 }
3457
3458 if (!strncasecmp("all", word, wordlen) && ++which > state) {
3459 return ast_strdup("all");
3460 }
3461
3462 if (!strncasecmp("participants", word, wordlen) && ++which > state) {
3463 return ast_strdup("participants");
3464 }
3465
3466 {
3467 SCOPED_AO2LOCK(bridge_lock, conference);
3469 if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
3470 res = ast_strdup(ast_channel_name(user->chan));
3471 return res;
3472 }
3473 }
3475 if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
3476 res = ast_strdup(ast_channel_name(user->chan));
3477 return res;
3478 }
3479 }
3480 }
3481
3482 return NULL;
3483}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:611
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References confbridge_conference::active_list, ao2_cleanup, ao2_find, ast_channel_name(), AST_LIST_TRAVERSE, ast_strdup, confbridge_user::conference, conference_bridges, confbridge_user::list, NULL, OBJ_KEY, RAII_VAR, SCOPED_AO2LOCK, user, and confbridge_conference::waiting_list.

Referenced by handle_cli_confbridge_kick(), handle_cli_confbridge_mute(), and handle_cli_confbridge_unmute().

◆ conf_add_post_join_action()

int conf_add_post_join_action ( struct confbridge_user user,
int(*)(struct confbridge_user *user func 
)

Queue a function to run with the given conference bridge user as an argument once the state transition is complete.

Parameters
userThe conference bridge user to pass to the function
funcThe function to queue
Return values
0success
non-zerofailure

Definition at line 1579 of file app_confbridge.c.

1580{
1581 struct post_join_action *action;
1582 if (!(action = ast_calloc(1, sizeof(*action)))) {
1583 return -1;
1584 }
1585 action->func = func;
1586 AST_LIST_INSERT_TAIL(&user->post_join_list, action, list);
1587 return 0;
1588}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
int(* func)(struct confbridge_user *user)
Definition: confbridge.h:268
struct post_join_action::@96 list

References ast_calloc, AST_LIST_INSERT_TAIL, post_join_action::func, and post_join_action::list.

Referenced by conf_default_join_waitmarked(), join_marked(), join_unmarked(), and transition_to_marked().

◆ conf_add_user_active()

void conf_add_user_active ( struct confbridge_conference conference,
struct confbridge_user user 
)

Add a conference bridge user as an unmarked active user of the conference.

Parameters
conferenceThe conference bridge to add the user to
userThe conference bridge user to add to the conference

Definition at line 4532 of file app_confbridge.c.

4533{
4534 AST_LIST_INSERT_TAIL(&conference->active_list, user, list);
4535 conference->activeusers++;
4536}

References confbridge_conference::active_list, confbridge_conference::activeusers, and AST_LIST_INSERT_TAIL.

Referenced by join_active(), and join_unmarked().

◆ conf_add_user_marked()

void conf_add_user_marked ( struct confbridge_conference conference,
struct confbridge_user user 
)

Add a conference bridge user as a marked active user of the conference.

Parameters
conferenceThe conference bridge to add the user to
userThe conference bridge user to add to the conference

Definition at line 4538 of file app_confbridge.c.

4539{
4540 AST_LIST_INSERT_TAIL(&conference->active_list, user, list);
4541 conference->activeusers++;
4542 conference->markedusers++;
4543}

References confbridge_conference::active_list, confbridge_conference::activeusers, AST_LIST_INSERT_TAIL, and confbridge_conference::markedusers.

Referenced by join_marked().

◆ conf_add_user_waiting()

void conf_add_user_waiting ( struct confbridge_conference conference,
struct confbridge_user user 
)

Add a conference bridge user as an waiting user of the conference.

Parameters
conferenceThe conference bridge to add the user to
userThe conference bridge user to add to the conference

Definition at line 4545 of file app_confbridge.c.

4546{
4547 AST_LIST_INSERT_TAIL(&conference->waiting_list, user, list);
4548 conference->waitingusers++;
4549}

References AST_LIST_INSERT_TAIL, confbridge_conference::waiting_list, and confbridge_conference::waitingusers.

Referenced by conf_default_join_waitmarked().

◆ conf_ended()

void conf_ended ( struct confbridge_conference conference)

Callback to be called when the conference has become empty.

Parameters
conferenceThe conference bridge

Definition at line 1607 of file app_confbridge.c.

1608{
1609 struct pbx_find_info q = { .stacklen = 0 };
1610
1611 /* Called with a reference to conference */
1612 ao2_unlink(conference_bridges, conference);
1613 send_conf_end_event(conference);
1614 if (!ast_strlen_zero(conference->b_profile.regcontext) &&
1616 conference->name, 1, NULL, "", E_MATCH)) {
1618 conference->name, 1, NULL);
1619 }
1620 ao2_lock(conference);
1621 conf_stop_record(conference);
1622 ao2_unlock(conference);
1623}
static void send_conf_end_event(struct confbridge_conference *conference)
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
@ E_MATCH
Definition: extconf.h:217
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
Definition: pbx.c:4963
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: ael_main.c:152
char regcontext[AST_MAX_CONTEXT]
Definition: confbridge.h:239
int stacklen
Definition: extconf.h:237

References ao2_lock, ao2_unlink, ao2_unlock, ast_context_remove_extension(), ast_strlen_zero(), confbridge_conference::b_profile, conf_stop_record(), conference_bridges, E_MATCH, confbridge_conference::name, NULL, pbx_find_extension(), bridge_profile::regcontext, send_conf_end_event(), and pbx_find_info::stacklen.

Referenced by transition_to_empty().

◆ conf_find_bridge()

struct confbridge_conference * conf_find_bridge ( const char *  conference_name)

Find a confbridge by name.

Since
13.22.0
15.5.0
Parameters
conference_nameThe name to search for
Returns
ConfBridge (which must be unreffed) or NULL.

Definition at line 922 of file app_confbridge.c.

923{
924 return ao2_find(conference_bridges, conference_name, OBJ_KEY);
925}

References ao2_find, conference_bridges, and OBJ_KEY.

Referenced by confbridge_publish_manager_event().

◆ conf_get_pin()

static int conf_get_pin ( struct ast_channel chan,
struct confbridge_user user 
)
static

Definition at line 2486 of file app_confbridge.c.

2487{
2488 char pin_guess[MAX_PIN+1] = { 0, };
2489 const char *pin = user->u_profile.pin;
2490 char *tmp = pin_guess;
2491 int i, res;
2492 unsigned int len = MAX_PIN;
2493
2494 /*
2495 * NOTE: We have not joined a conference yet so we have to use
2496 * the bridge profile requested by the user.
2497 */
2498
2499 /* give them three tries to get the pin right */
2500 for (i = 0; i < 3; i++) {
2501 if (ast_app_getdata(chan,
2502 conf_get_sound(CONF_SOUND_GET_PIN, user->b_profile.sounds),
2503 tmp, len, 0) >= 0) {
2504 if (!strcasecmp(pin, pin_guess)) {
2505 return 0;
2506 }
2507 }
2508 ast_streamfile(chan,
2509 conf_get_sound(CONF_SOUND_INVALID_PIN, user->b_profile.sounds),
2510 ast_channel_language(chan));
2511 res = ast_waitstream(chan, AST_DIGIT_ANY);
2512 if (res > 0) {
2513 /* Account for digit already read during ivalid pin playback
2514 * resetting pin buf. */
2515 pin_guess[0] = res;
2516 pin_guess[1] = '\0';
2517 tmp = pin_guess + 1;
2518 len = MAX_PIN - 1;
2519 } else {
2520 /* reset pin buf as empty buffer. */
2521 tmp = pin_guess;
2522 len = MAX_PIN;
2523 }
2524 }
2525 return -1;
2526}
#define MAX_PIN
Definition: app_meetme.c:882
@ CONF_SOUND_INVALID_PIN
Definition: confbridge.h:182
@ CONF_SOUND_GET_PIN
Definition: confbridge.h:181
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
enum ast_getdata_result ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
Plays a stream and gets DTMF data from a channel.
Definition: main/app.c:188

References ast_app_getdata(), ast_channel_language(), AST_DIGIT_ANY, ast_streamfile(), ast_waitstream(), conf_get_sound(), CONF_SOUND_GET_PIN, CONF_SOUND_INVALID_PIN, len(), and MAX_PIN.

Referenced by confbridge_exec().

◆ conf_get_sound()

const char * conf_get_sound ( enum conf_sounds  sound,
struct bridge_profile_sounds custom_sounds 
)

Looks to see if sound file is stored in bridge profile sounds, if not default sound is provided.

Definition at line 661 of file app_confbridge.c.

662{
663 switch (sound) {
665 return S_OR(custom_sounds->hasjoin, "conf-hasjoin");
667 return S_OR(custom_sounds->hasleft, "conf-hasleft");
669 return S_OR(custom_sounds->kicked, "conf-kicked");
670 case CONF_SOUND_MUTED:
671 return S_OR(custom_sounds->muted, "conf-muted");
673 return S_OR(custom_sounds->unmuted, "conf-unmuted");
675 return S_OR(custom_sounds->binauralon, "confbridge-binaural-on");
677 return S_OR(custom_sounds->binauraloff, "confbridge-binaural-off");
679 return S_OR(custom_sounds->onlyone, "conf-onlyone");
681 return S_OR(custom_sounds->thereare, "conf-thereare");
683 return S_OR(custom_sounds->otherinparty, "conf-otherinparty");
685 return S_OR(custom_sounds->placeintoconf, "conf-placeintoconf");
687 return S_OR(custom_sounds->waitforleader, "conf-waitforleader");
689 return S_OR(custom_sounds->leaderhasleft, "conf-leaderhasleft");
691 return S_OR(custom_sounds->getpin, "conf-getpin");
693 return S_OR(custom_sounds->invalidpin, "conf-invalidpin");
695 return S_OR(custom_sounds->onlyperson, "conf-onlyperson");
697 return S_OR(custom_sounds->locked, "conf-locked");
699 return S_OR(custom_sounds->lockednow, "conf-lockednow");
701 return S_OR(custom_sounds->unlockednow, "conf-unlockednow");
703 return S_OR(custom_sounds->errormenu, "conf-errormenu");
704 case CONF_SOUND_JOIN:
705 return S_OR(custom_sounds->join, "confbridge-join");
706 case CONF_SOUND_LEAVE:
707 return S_OR(custom_sounds->leave, "confbridge-leave");
709 return S_OR(custom_sounds->participantsmuted, "conf-now-muted");
711 return S_OR(custom_sounds->participantsunmuted, "conf-now-unmuted");
712 case CONF_SOUND_BEGIN:
713 return S_OR(custom_sounds->begin, "confbridge-conf-begin");
714 }
715
716 return "";
717}
@ CONF_SOUND_JOIN
Definition: confbridge.h:188
@ CONF_SOUND_LOCKED_NOW
Definition: confbridge.h:185
@ CONF_SOUND_ONLY_PERSON
Definition: confbridge.h:183
@ CONF_SOUND_BEGIN
Definition: confbridge.h:192
@ CONF_SOUND_WAIT_FOR_LEADER
Definition: confbridge.h:179
@ CONF_SOUND_HAS_LEFT
Definition: confbridge.h:171
@ CONF_SOUND_LEAVE
Definition: confbridge.h:189
@ CONF_SOUND_LEADER_HAS_LEFT
Definition: confbridge.h:180
@ CONF_SOUND_PLACE_IN_CONF
Definition: confbridge.h:178
@ CONF_SOUND_HAS_JOINED
Definition: confbridge.h:170
@ CONF_SOUND_UNLOCKED_NOW
Definition: confbridge.h:186
@ CONF_SOUND_LOCKED
Definition: confbridge.h:184
@ CONF_SOUND_KICKED
Definition: confbridge.h:172
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
const ast_string_field waitforleader
Definition: confbridge.h:224
const ast_string_field invalidpin
Definition: confbridge.h:224
const ast_string_field placeintoconf
Definition: confbridge.h:224
const ast_string_field onlyone
Definition: confbridge.h:224
const ast_string_field otherinparty
Definition: confbridge.h:224
const ast_string_field unlockednow
Definition: confbridge.h:224
const ast_string_field binauralon
Definition: confbridge.h:224
const ast_string_field getpin
Definition: confbridge.h:224
const ast_string_field errormenu
Definition: confbridge.h:224
const ast_string_field participantsunmuted
Definition: confbridge.h:224
const ast_string_field participantsmuted
Definition: confbridge.h:224
const ast_string_field leave
Definition: confbridge.h:224
const ast_string_field locked
Definition: confbridge.h:224
const ast_string_field join
Definition: confbridge.h:224
const ast_string_field kicked
Definition: confbridge.h:224
const ast_string_field hasleft
Definition: confbridge.h:224
const ast_string_field unmuted
Definition: confbridge.h:224
const ast_string_field leaderhasleft
Definition: confbridge.h:224
const ast_string_field lockednow
Definition: confbridge.h:224
const ast_string_field hasjoin
Definition: confbridge.h:224
const ast_string_field binauraloff
Definition: confbridge.h:224
const ast_string_field onlyperson
Definition: confbridge.h:224
const ast_string_field thereare
Definition: confbridge.h:224
const ast_string_field muted
Definition: confbridge.h:224
const ast_string_field begin
Definition: confbridge.h:224

References bridge_profile_sounds::begin, bridge_profile_sounds::binauraloff, bridge_profile_sounds::binauralon, CONF_SOUND_BEGIN, CONF_SOUND_BINAURAL_OFF, CONF_SOUND_BINAURAL_ON, CONF_SOUND_ERROR_MENU, CONF_SOUND_GET_PIN, CONF_SOUND_HAS_JOINED, CONF_SOUND_HAS_LEFT, CONF_SOUND_INVALID_PIN, CONF_SOUND_JOIN, CONF_SOUND_KICKED, CONF_SOUND_LEADER_HAS_LEFT, CONF_SOUND_LEAVE, CONF_SOUND_LOCKED, CONF_SOUND_LOCKED_NOW, CONF_SOUND_MUTED, CONF_SOUND_ONLY_ONE, CONF_SOUND_ONLY_PERSON, CONF_SOUND_OTHER_IN_PARTY, CONF_SOUND_PARTICIPANTS_MUTED, CONF_SOUND_PARTICIPANTS_UNMUTED, CONF_SOUND_PLACE_IN_CONF, CONF_SOUND_THERE_ARE, CONF_SOUND_UNLOCKED_NOW, CONF_SOUND_UNMUTED, CONF_SOUND_WAIT_FOR_LEADER, bridge_profile_sounds::errormenu, bridge_profile_sounds::getpin, bridge_profile_sounds::hasjoin, bridge_profile_sounds::hasleft, bridge_profile_sounds::invalidpin, bridge_profile_sounds::join, bridge_profile_sounds::kicked, bridge_profile_sounds::leaderhasleft, bridge_profile_sounds::leave, bridge_profile_sounds::locked, bridge_profile_sounds::lockednow, bridge_profile_sounds::muted, bridge_profile_sounds::onlyone, bridge_profile_sounds::onlyperson, bridge_profile_sounds::otherinparty, bridge_profile_sounds::participantsmuted, bridge_profile_sounds::participantsunmuted, bridge_profile_sounds::placeintoconf, S_OR, bridge_profile_sounds::thereare, bridge_profile_sounds::unlockednow, bridge_profile_sounds::unmuted, and bridge_profile_sounds::waitforleader.

Referenced by action_kick_last(), action_toggle_binaural(), action_toggle_mute(), action_toggle_mute_participants(), announce_user_count(), conf_get_pin(), conf_handle_inactive_waitmarked(), conf_handle_only_person(), confbridge_exec(), execute_menu_entry(), handle_cli_confbridge_show_bridge_profile(), join_conference_bridge(), leave_marked(), and post_join_play_begin().

◆ conf_handle_dtmf()

int conf_handle_dtmf ( struct ast_bridge_channel bridge_channel,
struct confbridge_user user,
struct conf_menu_entry menu_entry,
struct conf_menu menu 
)

Once a DTMF sequence matches a sequence in the user's DTMF menu, this function will get called to perform the menu action.

Parameters
bridge_channelBridged channel this is involving
userthe conference user to perform the action on.
menu_entrythe menu entry that invoked this callback to occur.
menuan AO2 referenced pointer to the entire menu structure the menu_entry derived from.
Note
The menu_entry is a deep copy of the entry found in the menu structure. This allows for the menu_entry to be accessed without requiring the menu lock. If the menu must be accessed, the menu lock must be held. Reference counting of the menu structure is handled outside of the scope of this function.
Return values
0success
-1failure

Definition at line 3357 of file app_confbridge.c.

3361{
3362 /* See if music on hold is playing */
3364
3365 /* execute the list of actions associated with this menu entry */
3366 execute_menu_entry(user->conference, user, bridge_channel, menu_entry, menu);
3367
3368 /* See if music on hold needs to be started back up again */
3370
3371 async_play_sound_ready(bridge_channel->chan);
3372
3373 return 0;
3374}
static void conf_moh_unsuspend(struct confbridge_user *user)
static void conf_moh_suspend(struct confbridge_user *user)
void async_play_sound_ready(struct ast_channel *chan)
Indicate the initiator of an async sound file is ready for it to play.

References async_play_sound_ready(), ast_bridge_channel::chan, conf_moh_suspend(), conf_moh_unsuspend(), and execute_menu_entry().

Referenced by menu_hook_callback().

◆ conf_handle_first_join()

void conf_handle_first_join ( struct confbridge_conference conference)

Callback to execute any time we transition from zero to one active users.

Parameters
conferenceThe conference bridge with a single active user joined

Definition at line 1591 of file app_confbridge.c.

1592{
1593 ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "confbridge:%s", conference->name);
1594}
@ AST_DEVSTATE_CACHABLE
Definition: devicestate.h:70
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:513
@ AST_DEVICE_INUSE
Definition: devicestate.h:55

References AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), and confbridge_conference::name.

Referenced by join_marked(), join_unmarked(), and join_waitmarked().

◆ conf_handle_inactive_waitmarked()

int conf_handle_inactive_waitmarked ( struct confbridge_user user)

Handle actions every time a waitmarked user joins w/o a marked user present.

Parameters
userThe waitmarked user
Return values
0success
-1failure

Definition at line 1555 of file app_confbridge.c.

1556{
1557 /* If we have not been quieted play back that they are waiting for the leader */
1559 conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, user->conference->b_profile.sounds))) {
1560 /* user hungup while the sound was playing */
1561 return -1;
1562 }
1563 return 0;
1564}
static int play_prompt_to_user(struct confbridge_user *user, const char *filename)
Play back an audio file to a channel.
@ USER_OPT_QUIET
Definition: confbridge.h:57

References ast_test_flag, conf_get_sound(), CONF_SOUND_WAIT_FOR_LEADER, play_prompt_to_user(), and USER_OPT_QUIET.

Referenced by conf_default_join_waitmarked().

◆ conf_handle_only_person()

int conf_handle_only_person ( struct confbridge_user user)

Handle actions whenever an user joins an empty conference.

Parameters
userThe user

Definition at line 1566 of file app_confbridge.c.

1567{
1568 /* If audio prompts have not been quieted or this prompt quieted play it on out */
1571 conf_get_sound(CONF_SOUND_ONLY_PERSON, user->conference->b_profile.sounds))) {
1572 /* user hungup while the sound was playing */
1573 return -1;
1574 }
1575 }
1576 return 0;
1577}
@ USER_OPT_NOONLYPERSON
Definition: confbridge.h:53

References ast_test_flag, conf_get_sound(), CONF_SOUND_ONLY_PERSON, play_prompt_to_user(), USER_OPT_NOONLYPERSON, and USER_OPT_QUIET.

Referenced by join_marked(), and join_unmarked().

◆ conf_handle_second_active()

void conf_handle_second_active ( struct confbridge_conference conference)

Handle when a conference moves to having more than one active participant.

Parameters
conferenceThe conference bridge with more than one active participant

Definition at line 1596 of file app_confbridge.c.

1597{
1598 /* If we are the second participant we may need to stop music on hold on the first */
1599 struct confbridge_user *first_user = AST_LIST_FIRST(&conference->active_list);
1600
1601 if (ast_test_flag(&first_user->u_profile, USER_OPT_MUSICONHOLD)) {
1602 conf_moh_stop(first_user);
1603 }
1604 conf_update_user_mute(first_user);
1605}
void conf_moh_stop(struct confbridge_user *user)
Stop MOH for the conference user.
@ USER_OPT_MUSICONHOLD
Definition: confbridge.h:56
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421

References confbridge_conference::active_list, AST_LIST_FIRST, ast_test_flag, conf_moh_stop(), conf_update_user_mute(), confbridge_user::conference, confbridge_user::u_profile, and USER_OPT_MUSICONHOLD.

Referenced by join_active(), join_marked(), and join_unmarked().

◆ conf_handle_talker_cb()

static int conf_handle_talker_cb ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt,
int  talking 
)
static

Definition at line 2458 of file app_confbridge.c.

2459{
2460 struct confbridge_user *user = hook_pvt;
2462 struct ast_json *talking_extras;
2463
2464 conference = ao2_find(conference_bridges, user->conference->name, OBJ_KEY);
2465 if (!conference) {
2466 /* Remove the hook since the conference does not exist. */
2467 return -1;
2468 }
2469
2470 ao2_lock(conference);
2471 user->talking = talking;
2472 ao2_unlock(conference);
2473
2474 talking_extras = ast_json_pack("{s: s, s: b}",
2475 "talking_status", talking ? "on" : "off",
2476 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN));
2477 if (!talking_extras) {
2478 return 0;
2479 }
2480
2481 send_conf_stasis(conference, bridge_channel->chan, confbridge_talking_type(), talking_extras, 0);
2482 ast_json_unref(talking_extras);
2483 return 0;
2484}
static void send_conf_stasis(struct confbridge_conference *conference, struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *extras, int channel_topic)
struct stasis_message_type * confbridge_talking_type(void)
get the confbridge talking stasis message type
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
Abstract JSON element (object, array, string, int, ...).

References ao2_cleanup, ao2_find, ao2_lock, ao2_unlock, ast_json_pack(), ast_json_unref(), ast_test_flag, ast_bridge_channel::chan, confbridge_talking_type(), confbridge_user::conference, conference_bridges, NULL, OBJ_KEY, RAII_VAR, send_conf_stasis(), and USER_OPT_ADMIN.

Referenced by confbridge_exec().

◆ conf_is_recording()

static int conf_is_recording ( struct confbridge_conference conference)
static

Definition at line 938 of file app_confbridge.c.

939{
940 return conference->record_chan != NULL;
941}
struct ast_channel * record_chan
Definition: confbridge.h:257

References NULL, and confbridge_conference::record_chan.

Referenced by action_confbridgestartrecord(), conf_start_record(), conf_stop_record(), and handle_cli_confbridge_start_record().

◆ conf_moh_start()

void conf_moh_start ( struct confbridge_user user)

Start MOH for the conference user.

Parameters
userConference user to start MOH on.

Definition at line 1498 of file app_confbridge.c.

1499{
1500 user->playing_moh = 1;
1501 if (!user->suspended_moh) {
1502 int in_bridge;
1503
1504 /*
1505 * Locking the ast_bridge here is the only way to hold off the
1506 * call to ast_bridge_join() in confbridge_exec() from
1507 * interfering with the bridge and MOH operations here.
1508 */
1509 ast_bridge_lock(user->conference->bridge);
1510
1511 /*
1512 * Temporarily suspend the user from the bridge so we have
1513 * control to start MOH if needed.
1514 */
1515 in_bridge = !ast_bridge_suspend(user->conference->bridge, user->chan);
1516 ast_moh_start(user->chan, user->u_profile.moh_class, NULL);
1517 if (in_bridge) {
1518 ast_bridge_unsuspend(user->conference->bridge, user->chan);
1519 }
1520
1521 ast_bridge_unlock(user->conference->bridge);
1522 }
1523}
int ast_bridge_suspend(struct ast_bridge *bridge, struct ast_channel *chan)
Suspend a channel temporarily from a bridge.
Definition: bridge.c:3076
int ast_bridge_unsuspend(struct ast_bridge *bridge, struct ast_channel *chan)
Unsuspend a channel from a bridge.
Definition: bridge.c:3097
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:474
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7739

References ast_bridge_lock, ast_bridge_suspend(), ast_bridge_unlock, ast_bridge_unsuspend(), ast_moh_start(), and NULL.

Referenced by conf_mute_moh_inactive_waitmarked(), conf_mute_only_active(), and leave_marked().

◆ conf_moh_stop()

void conf_moh_stop ( struct confbridge_user user)

Stop MOH for the conference user.

Parameters
userConference user to stop MOH on.

Definition at line 1471 of file app_confbridge.c.

1472{
1473 user->playing_moh = 0;
1474 if (!user->suspended_moh) {
1475 int in_bridge;
1476
1477 /*
1478 * Locking the ast_bridge here is the only way to hold off the
1479 * call to ast_bridge_join() in confbridge_exec() from
1480 * interfering with the bridge and MOH operations here.
1481 */
1482 ast_bridge_lock(user->conference->bridge);
1483
1484 /*
1485 * Temporarily suspend the user from the bridge so we have
1486 * control to stop MOH if needed.
1487 */
1488 in_bridge = !ast_bridge_suspend(user->conference->bridge, user->chan);
1489 ast_moh_stop(user->chan);
1490 if (in_bridge) {
1491 ast_bridge_unsuspend(user->conference->bridge, user->chan);
1492 }
1493
1494 ast_bridge_unlock(user->conference->bridge);
1495 }
1496}
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7749

References ast_bridge_lock, ast_bridge_suspend(), ast_bridge_unlock, ast_bridge_unsuspend(), and ast_moh_stop().

Referenced by conf_default_leave_waitmarked(), conf_handle_second_active(), leave_marked(), leave_unmarked(), and transition_to_marked().

◆ conf_moh_suspend()

static void conf_moh_suspend ( struct confbridge_user user)
static

Definition at line 1546 of file app_confbridge.c.

1547{
1548 ao2_lock(user->conference);
1549 if (user->suspended_moh++ == 0 && user->playing_moh) {
1550 ast_moh_stop(user->chan);
1551 }
1552 ao2_unlock(user->conference);
1553}

References ao2_lock, ao2_unlock, and ast_moh_stop().

Referenced by conf_handle_dtmf().

◆ conf_moh_unsuspend()

static void conf_moh_unsuspend ( struct confbridge_user user)
static

Definition at line 1531 of file app_confbridge.c.

1532{
1533 ao2_lock(user->conference);
1534 if (--user->suspended_moh == 0 && user->playing_moh) {
1535 ast_moh_start(user->chan, user->u_profile.moh_class, NULL);
1536 }
1537 ao2_unlock(user->conference);
1538}

References ao2_lock, ao2_unlock, ast_moh_start(), and NULL.

Referenced by conf_handle_dtmf(), and confbridge_exec().

◆ conf_mute_only_active()

void conf_mute_only_active ( struct confbridge_conference conference)

Attempt to mute/play MOH to the only user in the conference if they require it.

Parameters
conferenceA conference bridge containing a single user

Definition at line 4564 of file app_confbridge.c.

4565{
4567
4568 /* Turn on MOH if the single participant is set up for it */
4569 if (ast_test_flag(&only_user->u_profile, USER_OPT_MUSICONHOLD)) {
4570 conf_moh_start(only_user);
4571 }
4572 conf_update_user_mute(only_user);
4573}
void conf_moh_start(struct confbridge_user *user)
Start MOH for the conference user.

References confbridge_conference::active_list, AST_LIST_FIRST, ast_test_flag, conf_moh_start(), conf_update_user_mute(), confbridge_user::conference, confbridge_user::u_profile, and USER_OPT_MUSICONHOLD.

Referenced by transition_to_single(), and transition_to_single_marked().

◆ conf_rec_name()

static int conf_rec_name ( struct confbridge_user user,
const char *  conf_name 
)
static

Definition at line 2535 of file app_confbridge.c.

2536{
2537 char destdir[PATH_MAX];
2538 int res;
2539 int duration = 20;
2540
2541 snprintf(destdir, sizeof(destdir), "%s/confbridge", ast_config_AST_SPOOL_DIR);
2542
2543 if (ast_mkdir(destdir, 0777) != 0) {
2544 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno));
2545 return -1;
2546 }
2547 snprintf(user->name_rec_location, sizeof(user->name_rec_location),
2548 "%s/confbridge-name-%s-%s", destdir,
2549 conf_name, ast_channel_uniqueid(user->chan));
2550
2552 res = ast_play_and_record(user->chan,
2553 "vm-rec-name",
2554 user->name_rec_location,
2555 10,
2556 "sln",
2557 &duration,
2558 NULL,
2560 0,
2561 NULL);
2562 } else {
2563 res = ast_record_review(user->chan,
2564 "vm-rec-name",
2565 user->name_rec_location,
2566 10,
2567 "sln",
2568 &duration,
2569 NULL);
2570 }
2571
2572 if (res == -1) {
2573 ast_filedelete(user->name_rec_location, NULL);
2574 user->name_rec_location[0] = '\0';
2575 return -1;
2576 }
2577 return 0;
2578}
#define PATH_MAX
Definition: asterisk.h:40
@ USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW
Definition: confbridge.h:68
@ THRESHOLD_SILENCE
Definition: dsp.h:73
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:2009
int ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime_sec, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence_ms, const char *path)
Record a file based on input from a channel. Use default accept and cancel DTMF. This function will p...
Definition: main/app.c:2154
int ast_record_review(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path)
Allow to record message and have a review option.
Definition: main/app.c:2646
int errno
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:155
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2479

References ast_channel_uniqueid(), ast_config_AST_SPOOL_DIR, ast_dsp_get_threshold_from_settings(), ast_filedelete(), ast_log, ast_mkdir(), ast_play_and_record(), ast_record_review(), ast_test_flag, errno, LOG_WARNING, NULL, PATH_MAX, THRESHOLD_SILENCE, and USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW.

Referenced by confbridge_exec().

◆ conf_remove_user_active()

void conf_remove_user_active ( struct confbridge_conference conference,
struct confbridge_user user 
)

Remove a conference bridge user from the unmarked active conference users in the conference.

Parameters
conferenceThe conference bridge to remove the user from
userThe conference bridge user to remove from the conference

Definition at line 4551 of file app_confbridge.c.

4552{
4553 AST_LIST_REMOVE(&conference->active_list, user, list);
4554 conference->activeusers--;
4555}
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856

References confbridge_conference::active_list, confbridge_conference::activeusers, and AST_LIST_REMOVE.

Referenced by leave_active(), and leave_unmarked().

◆ conf_remove_user_marked()

void conf_remove_user_marked ( struct confbridge_conference conference,
struct confbridge_user user 
)

Remove a conference bridge user from the marked active conference users in the conference.

Parameters
conferenceThe conference bridge to remove the user from
userThe conference bridge user to remove from the conference

Definition at line 4557 of file app_confbridge.c.

4558{
4559 AST_LIST_REMOVE(&conference->active_list, user, list);
4560 conference->activeusers--;
4561 conference->markedusers--;
4562}

References confbridge_conference::active_list, confbridge_conference::activeusers, AST_LIST_REMOVE, and confbridge_conference::markedusers.

Referenced by leave_marked().

◆ conf_remove_user_waiting()

void conf_remove_user_waiting ( struct confbridge_conference conference,
struct confbridge_user user 
)

Remove a conference bridge user from the waiting conference users in the conference.

Parameters
conferenceThe conference bridge to remove the user from
userThe conference bridge user to remove from the conference

Definition at line 4575 of file app_confbridge.c.

4576{
4577 AST_LIST_REMOVE(&conference->waiting_list, user, list);
4578 conference->waitingusers--;
4579}

References AST_LIST_REMOVE, confbridge_user::conference, confbridge_user::list, confbridge_conference::waiting_list, and confbridge_conference::waitingusers.

Referenced by conf_default_leave_waitmarked().

◆ conf_start_record()

static int conf_start_record ( struct confbridge_conference conference)
static

Definition at line 986 of file app_confbridge.c.

987{
988 struct ast_app *mixmonapp;
989 struct ast_channel *chan;
990 struct ast_format_cap *cap;
991 struct ast_bridge_features *features;
992
993 if (conf_is_recording(conference)) {
994 return -1;
995 }
996
997 mixmonapp = pbx_findapp("MixMonitor");
998 if (!mixmonapp) {
999 ast_log(LOG_WARNING, "Cannot record ConfBridge, MixMonitor app is not installed\n");
1000 return -1;
1001 }
1002
1003 features = ast_bridge_features_new();
1004 if (!features) {
1005 return -1;
1006 }
1008
1010 if (!cap) {
1012 return -1;
1013 }
1015
1016 /* Create the recording channel. */
1017 chan = ast_request("CBRec", cap, NULL, NULL, conference->name, NULL);
1018 ao2_ref(cap, -1);
1019 if (!chan) {
1021 return -1;
1022 }
1023
1024 /* Start recording. */
1025 set_rec_filename(conference, &conference->record_filename,
1026 is_new_rec_file(conference->b_profile.rec_file, &conference->orig_rec_file));
1027 ast_answer(chan);
1028 pbx_exec(chan, mixmonapp, ast_str_buffer(conference->record_filename));
1029
1030 /* Put the channel into the conference bridge. */
1031 ast_channel_ref(chan);
1032 conference->record_chan = chan;
1033 if (ast_bridge_impart(conference->bridge, chan, NULL, features,
1035 ast_hangup(chan);
1036 ast_channel_unref(chan);
1037 conference->record_chan = NULL;
1038 return -1;
1039 }
1040
1041 ast_test_suite_event_notify("CONF_START_RECORD", "Message: started conference recording channel\r\nConference: %s", conference->b_profile.name);
1042 send_start_record_event(conference);
1043
1044 return 0;
1045}
static int is_new_rec_file(const char *rec_file, struct ast_str **orig_rec_file)
static void set_rec_filename(struct confbridge_conference *conference, struct ast_str **filename, int is_new)
static void send_start_record_event(struct confbridge_conference *conference)
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
Definition: bridge.c:1947
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition: bridge.h:594
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3752
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition: bridge.c:3743
@ AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2774
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
ast_app: A registered application
Definition: pbx_app.c:45
Structure that contains features information.
struct ast_flags feature_flags
Main Channel structure associated with a channel.
char name[MAX_PROFILE_NAME]
Definition: confbridge.h:228
struct ast_str * orig_rec_file
Definition: confbridge.h:259
struct ast_str * record_filename
Definition: confbridge.h:258
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:189
#define ast_set_flag(p, flag)
Definition: utils.h:70

References ao2_ref, ast_answer(), AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE, ast_bridge_features_destroy(), ast_bridge_features_new(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_channel_ref, ast_channel_unref, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_slin, ast_hangup(), ast_log, ast_request(), ast_set_flag, ast_str_buffer(), ast_test_suite_event_notify, confbridge_conference::b_profile, confbridge_conference::bridge, conf_is_recording(), ast_bridge_features::feature_flags, is_new_rec_file(), LOG_WARNING, confbridge_conference::name, bridge_profile::name, NULL, confbridge_conference::orig_rec_file, pbx_exec(), pbx_findapp(), bridge_profile::rec_file, confbridge_conference::record_chan, confbridge_conference::record_filename, send_start_record_event(), and set_rec_filename().

Referenced by action_confbridgestartrecord(), handle_cli_confbridge_start_record(), and join_conference_bridge().

◆ conf_stop_record()

static int conf_stop_record ( struct confbridge_conference conference)
static

Definition at line 954 of file app_confbridge.c.

955{
956 struct ast_channel *chan;
957 struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
958
959 if (!conf_is_recording(conference)) {
960 return -1;
961 }
962
963 /* Remove the recording channel from the conference bridge. */
964 chan = conference->record_chan;
965 conference->record_chan = NULL;
966 ast_queue_frame(chan, &f);
967 ast_channel_unref(chan);
968
969 ast_test_suite_event_notify("CONF_STOP_RECORD", "Message: stopped conference recording channel\r\nConference: %s", conference->b_profile.name);
970 send_stop_record_event(conference);
971
972 return 0;
973}
static void send_stop_record_event(struct confbridge_conference *conference)
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1169
@ AST_FRAME_CONTROL
@ AST_CONTROL_HANGUP
Data structure associated with a single frame of data.

References ast_channel_unref, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, ast_queue_frame(), ast_test_suite_event_notify, confbridge_conference::b_profile, conf_is_recording(), bridge_profile::name, NULL, confbridge_conference::record_chan, and send_stop_record_event().

Referenced by action_confbridgestoprecord(), conf_ended(), and handle_cli_confbridge_stop_record().

◆ conf_update_user_mute()

void conf_update_user_mute ( struct confbridge_user user)

Update the actual mute status of the user and set it on the bridge.

Parameters
userUser to update the mute status.

Definition at line 1413 of file app_confbridge.c.

1414{
1415 int mute_user;
1416 int mute_system;
1417 int mute_effective;
1418
1419 /* User level mute request. */
1420 mute_user = user->muted;
1421
1422 /* System level mute request. */
1423 mute_system = user->playing_moh
1424 /*
1425 * Do not allow waitmarked users to talk to anyone unless there
1426 * is a marked user present.
1427 */
1428 || (!user->conference->markedusers
1429 && ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED));
1430
1431 mute_effective = mute_user || mute_system;
1432
1433 ast_debug(1, "User %s is %s: user:%d system:%d.\n",
1434 ast_channel_name(user->chan), mute_effective ? "muted" : "unmuted",
1435 mute_user, mute_system);
1436 user->features.mute = mute_effective;
1437 ast_test_suite_event_notify("CONF_MUTE_UPDATE",
1438 "Mode: %s\r\n"
1439 "Conference: %s\r\n"
1440 "Channel: %s",
1441 mute_effective ? "muted" : "unmuted",
1442 user->conference->b_profile.name,
1443 ast_channel_name(user->chan));
1444}

References ast_channel_name(), ast_debug, ast_test_flag, ast_test_suite_event_notify, and USER_OPT_WAITMARKED.

Referenced by action_toggle_mute_participants(), conf_handle_second_active(), conf_mute_moh_inactive_waitmarked(), conf_mute_only_active(), generic_mute_unmute_user(), join_active(), join_marked(), join_unmarked(), leave_marked(), and transition_to_marked().

◆ confbridge_exec()

static int confbridge_exec ( struct ast_channel chan,
const char *  data 
)
static

The ConfBridge application.

Definition at line 2680 of file app_confbridge.c.

2681{
2682 int res = 0, volume_adjustments[2];
2683 int quiet = 0;
2684 int async_delete_task_pushed = 0;
2685 char *parse;
2686 const char *b_profile_name = NULL;
2687 const char *u_profile_name = NULL;
2688 const char *menu_profile_name = NULL;
2689 struct confbridge_conference *conference = NULL;
2690 struct confbridge_user user = {
2691 .chan = chan,
2692 .tech_args.talking_threshold = DEFAULT_TALKING_THRESHOLD,
2693 .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD,
2694 .tech_args.drop_silence = 0,
2695 };
2696 struct confbridge_hook_data *join_hook_data;
2697 struct confbridge_hook_data *leave_hook_data;
2698
2700 AST_APP_ARG(conf_name);
2701 AST_APP_ARG(b_profile_name);
2702 AST_APP_ARG(u_profile_name);
2703 AST_APP_ARG(menu_profile_name);
2704 );
2705
2706 if (ast_bridge_features_init(&user.features)) {
2707 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2708 res = -1;
2709 goto confbridge_cleanup;
2710 }
2711
2712 /* We need to make a copy of the input string if we are going to modify it! */
2713 parse = ast_strdupa(data);
2714
2716
2717 if (ast_strlen_zero(args.conf_name)) {
2718 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2719 ast_log(LOG_WARNING, "%s requires an argument (conference name[,options])\n", app);
2720 res = -1;
2721 goto confbridge_cleanup;
2722 }
2723
2724 if (strlen(args.conf_name) >= MAX_CONF_NAME) {
2725 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2726 ast_log(LOG_WARNING, "%s does not accept conference names longer than %d\n", app, MAX_CONF_NAME - 1);
2727 res = -1;
2728 goto confbridge_cleanup;
2729 }
2730
2731 /* bridge profile name */
2732 if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) {
2733 b_profile_name = args.b_profile_name;
2734 }
2735 if (!conf_find_bridge_profile(chan, b_profile_name, &user.b_profile)) {
2736 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2737 ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name ?
2738 b_profile_name : DEFAULT_BRIDGE_PROFILE);
2739 res = -1;
2740 goto confbridge_cleanup;
2741 }
2742
2743 /* user profile name */
2744 if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) {
2745 u_profile_name = args.u_profile_name;
2746 }
2747 if (!conf_find_user_profile(chan, u_profile_name, &user.u_profile)) {
2748 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2749 ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name ?
2750 u_profile_name : DEFAULT_USER_PROFILE);
2751 res = -1;
2752 goto confbridge_cleanup;
2753 }
2754
2755 /* If channel hasn't been answered already, answer it, unless we're explicitly not supposed to */
2756 if ((ast_channel_state(chan) != AST_STATE_UP) && (ast_test_flag(&user.u_profile, USER_OPT_ANSWER_CHANNEL))) {
2757 ast_answer(chan);
2758 }
2759
2760 quiet = ast_test_flag(&user.u_profile, USER_OPT_QUIET);
2761
2762 /* ask for a PIN immediately after finding user profile. This has to be
2763 * prompted for requardless of quiet setting. */
2764 if (!ast_strlen_zero(user.u_profile.pin)) {
2765 if (conf_get_pin(chan, &user)) {
2766 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2767 res = -1; /* invalid PIN */
2768 goto confbridge_cleanup;
2769 }
2770 }
2771
2772 /* See if we need them to record a intro name */
2773 if (!quiet &&
2776 if (conf_rec_name(&user, args.conf_name)) {
2777 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2778 res = -1; /* Hangup during name recording */
2779 goto confbridge_cleanup;
2780 }
2781 }
2782
2783 /* menu name */
2784 if (args.argc > 3 && !ast_strlen_zero(args.menu_profile_name)) {
2785 menu_profile_name = args.menu_profile_name;
2786 }
2787
2788 if (conf_set_menu_to_user(chan, &user, menu_profile_name)) {
2789 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2790 ast_log(LOG_WARNING, "Conference menu profile %s does not exist\n", menu_profile_name ?
2791 menu_profile_name : DEFAULT_MENU_PROFILE);
2792 res = -1;
2793 goto confbridge_cleanup;
2794 }
2795
2796 /* Set if DTMF should pass through for this user or not */
2797 if (ast_test_flag(&user.u_profile, USER_OPT_DTMF_PASS)) {
2798 user.features.dtmf_passthrough = 1;
2799 } else {
2800 user.features.dtmf_passthrough = 0;
2801 }
2802
2803 /* Set if text messaging is enabled for this user or not */
2804 if (ast_test_flag(&user.u_profile, USER_OPT_TEXT_MESSAGING)) {
2805 user.features.text_messaging = 1;
2806 } else {
2807 user.features.text_messaging = 0;
2808 }
2809
2810 /* Set dsp threshold values if present */
2811 if (user.u_profile.talking_threshold) {
2812 user.tech_args.talking_threshold = user.u_profile.talking_threshold;
2813 }
2814 if (user.u_profile.silence_threshold) {
2815 user.tech_args.silence_threshold = user.u_profile.silence_threshold;
2816 }
2817
2818 /* Set a talker indicate call back if talking detection is requested */
2819 if (ast_test_flag(&user.u_profile, USER_OPT_TALKER_DETECT)) {
2822 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2823 res = -1;
2824 goto confbridge_cleanup;
2825 }
2826 }
2827
2828 /* Look for a conference bridge matching the provided name */
2829 if (!(conference = join_conference_bridge(args.conf_name, &user))) {
2830 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2831 res = -1;
2832 goto confbridge_cleanup;
2833 }
2834
2835 /* Keep a copy of volume adjustments so we can restore them later if need be */
2836 volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
2837 volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
2838
2839 if (ast_test_flag(&user.u_profile, USER_OPT_DROP_SILENCE)) {
2840 user.tech_args.drop_silence = 1;
2841 }
2842
2843 if (ast_test_flag(&user.u_profile, USER_OPT_JITTERBUFFER)) {
2844 ast_func_write(chan, "JITTERBUFFER(adaptive)", "default");
2845 }
2846
2847 if (ast_test_flag(&user.u_profile, USER_OPT_DENOISE)) {
2848 ast_func_write(chan, "DENOISE(rx)", "on");
2849 }
2850
2851 /* if this user has a intro, play it before entering */
2852 if (!ast_strlen_zero(user.name_rec_location)) {
2854 play_sound_file(conference, user.name_rec_location);
2858 }
2859
2860 if (!quiet) {
2861 const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference->b_profile.sounds);
2862
2863 /* if hear_own_join_sound is enabled play the Join sound to everyone */
2865 if (strcmp(conference->b_profile.language, ast_channel_language(chan))) {
2866 ast_stream_and_wait(chan, join_sound, "");
2868 play_sound_file(conference, join_sound);
2870 } else {
2871 async_play_sound_file(conference, join_sound, chan);
2872 }
2873 /* if hear_own_join_sound is disabled only play the Join sound to just the conference */
2874 } else {
2876 play_sound_file(conference, join_sound);
2878 }
2879 }
2880
2881 if (user.u_profile.timeout) {
2883 0,
2884 user.u_profile.timeout * 1000,
2886 NULL,
2887 NULL,
2889 }
2890
2891 /* See if we need to automatically set this user as a video source or not */
2893
2895
2896 join_hook_data = ast_malloc(sizeof(*join_hook_data));
2897 if (!join_hook_data) {
2898 res = -1;
2899 goto confbridge_cleanup;
2900 }
2901 join_hook_data->user = &user;
2902 join_hook_data->conference = conference;
2903 join_hook_data->hook_type = AST_BRIDGE_HOOK_TYPE_JOIN;
2905 join_hook_data, ast_free_ptr, 0);
2906 if (res) {
2907 ast_free(join_hook_data);
2908 ast_log(LOG_ERROR, "Couldn't add bridge join hook for channel '%s'\n", ast_channel_name(chan));
2909 goto confbridge_cleanup;
2910 }
2911
2912 leave_hook_data = ast_malloc(sizeof(*leave_hook_data));
2913 if (!leave_hook_data) {
2914 /* join_hook_data is cleaned up by ast_bridge_features_cleanup via the goto */
2915 res = -1;
2916 goto confbridge_cleanup;
2917 }
2918 leave_hook_data->user = &user;
2919 leave_hook_data->conference = conference;
2920 leave_hook_data->hook_type = AST_BRIDGE_HOOK_TYPE_LEAVE;
2922 leave_hook_data, ast_free_ptr, 0);
2923 if (res) {
2924 /* join_hook_data is cleaned up by ast_bridge_features_cleanup via the goto */
2925 ast_free(leave_hook_data);
2926 ast_log(LOG_ERROR, "Couldn't add bridge leave hook for channel '%s'\n", ast_channel_name(chan));
2927 goto confbridge_cleanup;
2928 }
2929
2930 if (ast_bridge_join_hook(&user.features, join_callback, NULL, NULL, 0)) {
2932 }
2933
2935 chan,
2936 NULL,
2937 &user.features,
2938 &user.tech_args,
2939 0);
2940
2941 /* This is a catch-all in case joining the bridge failed or for some reason
2942 * an async announcement got queued up and hasn't been told to play yet
2943 */
2945
2946 if (!user.kicked && ast_check_hangup(chan)) {
2947 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "HANGUP");
2948 }
2949
2950 /* if we're shutting down, don't attempt to do further processing */
2951 if (ast_shutting_down()) {
2952 /*
2953 * Not taking any new calls at this time. We cannot create
2954 * the announcer channel if this is the first channel into
2955 * the conference and we certainly cannot create any
2956 * recording channel.
2957 */
2959 conference = NULL;
2960 goto confbridge_cleanup;
2961 }
2962
2963 /* If this user was a video source, we need to clean up and possibly pick a new source. */
2965
2966 /* if this user has a intro, play it when leaving */
2967 if (!quiet && !ast_strlen_zero(user.name_rec_location)) {
2968 async_play_sound_file(conference, user.name_rec_location, NULL);
2971 async_delete_name_rec(conference, user.name_rec_location);
2972 async_delete_task_pushed = 1;
2973 }
2974
2975 /* play the leave sound */
2976 if (!quiet) {
2977 const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, conference->b_profile.sounds);
2978 async_play_sound_file(conference, leave_sound, NULL);
2979 }
2980
2981 /* If the user was kicked from the conference play back the audio prompt for it */
2982 if (!quiet && user.kicked) {
2983 res = ast_stream_and_wait(chan,
2985 "");
2986 }
2987
2988 /* Easy as pie, depart this channel from the conference bridge */
2990 conference = NULL;
2991
2992 /* Restore volume adjustments to previous values in case they were changed */
2993 if (volume_adjustments[0]) {
2994 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
2995 }
2996 if (volume_adjustments[1]) {
2997 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
2998 }
2999
3000confbridge_cleanup:
3001 if (!async_delete_task_pushed && !ast_strlen_zero(user.name_rec_location)) {
3002 ast_filedelete(user.name_rec_location, NULL);
3003 }
3006 return res;
3007}
static int quiet
Definition: ael_main.c:123
static int send_event_hook_callback(struct ast_bridge_channel *bridge_channel, void *data)
static int join_callback(struct ast_bridge_channel *bridge_channel, void *ignore)
static const char app[]
static void leave_conference(struct confbridge_user *user)
Leave a conference.
static int conf_get_pin(struct ast_channel *chan, struct confbridge_user *user)
static int conf_rec_name(struct confbridge_user *user, const char *conf_name)
static void handle_video_on_join(struct confbridge_conference *conference, struct ast_channel *chan, int marked)
static struct confbridge_conference * join_conference_bridge(const char *conference_name, struct confbridge_user *user)
Join a conference bridge.
static int async_delete_name_rec(struct confbridge_conference *conference, const char *filename)
static int user_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
static int conf_handle_talker_cb(struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking)
static void handle_video_on_exit(struct confbridge_conference *conference, struct ast_channel *chan)
int ast_shutting_down(void)
Definition: asterisk.c:1886
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
@ AST_AUDIOHOOK_DIRECTION_READ
Definition: audiohook.h:49
@ AST_AUDIOHOOK_DIRECTION_WRITE
Definition: audiohook.h:50
int ast_audiohook_volume_get(struct ast_channel *chan, enum ast_audiohook_direction direction)
Retrieve the volume adjustment value on frames read from or written to a channel.
Definition: audiohook.c:1346
int ast_audiohook_volume_set(struct ast_channel *chan, enum ast_audiohook_direction direction, int volume)
Adjust the volume on frames read from or written to a channel.
Definition: audiohook.c:1321
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:1690
@ AST_BRIDGE_HOOK_TYPE_JOIN
@ AST_BRIDGE_HOOK_TYPE_LEAVE
int ast_bridge_features_init(struct ast_bridge_features *features)
Initialize bridge features structure.
Definition: bridge.c:3689
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:3388
@ AST_BRIDGE_HOOK_REMOVE_ON_PULL
int ast_bridge_talk_detector_hook(struct ast_bridge_features *features, ast_bridge_talking_indicate_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a bridge channel talk detection hook to a bridge features structure.
Definition: bridge.c:3364
int ast_bridge_join_hook(struct ast_bridge_features *features, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a bridge channel join hook to a bridge features structure.
Definition: bridge.c:3344
int ast_bridge_leave_hook(struct ast_bridge_features *features, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a bridge channel leave hook to a bridge features structure.
Definition: bridge.c:3354
void ast_bridge_features_cleanup(struct ast_bridge_features *features)
Clean up the contents of a bridge features structure.
Definition: bridge.c:3722
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:444
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
void conf_bridge_profile_destroy(struct bridge_profile *b_profile)
Destroy a bridge profile found by 'conf_find_bridge_profile'.
const struct bridge_profile * conf_find_bridge_profile(struct ast_channel *chan, const char *bridge_profile_name, struct bridge_profile *result)
Find a bridge profile given a bridge profile's name and store that profile in result structure.
int conf_set_menu_to_user(struct ast_channel *chan, struct confbridge_user *user, const char *menu_profile_name)
find a menu profile given a menu profile's name and apply the menu in DTMF hooks.
const struct user_profile * conf_find_user_profile(struct ast_channel *chan, const char *user_profile_name, struct user_profile *result)
find a user profile given a user profile's name and store that profile in result structure.
#define DEFAULT_SILENCE_THRESHOLD
Definition: confbridge.h:49
@ USER_OPT_HEAR_OWN_JOIN_SOUND
Definition: confbridge.h:73
@ USER_OPT_TEXT_MESSAGING
Definition: confbridge.h:71
@ USER_OPT_DENOISE
Definition: confbridge.h:61
@ USER_OPT_DTMF_PASS
Definition: confbridge.h:65
@ USER_OPT_TALKER_DETECT
Definition: confbridge.h:63
@ USER_OPT_DROP_SILENCE
Definition: confbridge.h:64
@ USER_OPT_ANSWER_CHANNEL
Definition: confbridge.h:72
@ USER_OPT_JITTERBUFFER
Definition: confbridge.h:67
@ USER_OPT_ANNOUNCE_JOIN_LEAVE
Definition: confbridge.h:62
#define DEFAULT_TALKING_THRESHOLD
Definition: confbridge.h:46
#define DEFAULT_MENU_PROFILE
Definition: confbridge.h:43
#define DEFAULT_BRIDGE_PROFILE
Definition: confbridge.h:42
#define DEFAULT_USER_PROFILE
Definition: confbridge.h:41
#define MAX_CONF_NAME
Definition: confbridge.h:35
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define LOG_ERROR
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function
struct confbridge_conference * conference
struct confbridge_user * user
enum ast_bridge_hook_type hook_type

References app, args, ast_answer(), AST_APP_ARG, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, ast_audiohook_volume_get(), ast_audiohook_volume_set(), ast_autoservice_start(), ast_autoservice_stop(), ast_bridge_features_cleanup(), ast_bridge_features_init(), AST_BRIDGE_HOOK_REMOVE_ON_PULL, AST_BRIDGE_HOOK_TYPE_JOIN, AST_BRIDGE_HOOK_TYPE_LEAVE, ast_bridge_interval_hook(), ast_bridge_join(), ast_bridge_join_hook(), ast_bridge_leave_hook(), ast_bridge_talk_detector_hook(), ast_channel_language(), ast_channel_name(), ast_check_hangup(), AST_DECLARE_APP_ARGS, ast_filedelete(), ast_free, ast_free_ptr(), ast_func_write(), ast_log, ast_malloc, ast_shutting_down(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, async_delete_name_rec(), async_play_sound_file(), async_play_sound_ready(), confbridge_conference::b_profile, confbridge_conference::bridge, confbridge_user::chan, conf_bridge_profile_destroy(), conf_find_bridge_profile(), conf_find_user_profile(), conf_get_pin(), conf_get_sound(), conf_handle_talker_cb(), conf_moh_unsuspend(), conf_rec_name(), conf_set_menu_to_user(), CONF_SOUND_HAS_JOINED, CONF_SOUND_HAS_LEFT, CONF_SOUND_JOIN, CONF_SOUND_KICKED, CONF_SOUND_LEAVE, confbridge_hook_data::conference, DEFAULT_BRIDGE_PROFILE, DEFAULT_MENU_PROFILE, DEFAULT_SILENCE_THRESHOLD, DEFAULT_TALKING_THRESHOLD, DEFAULT_USER_PROFILE, handle_video_on_exit(), handle_video_on_join(), confbridge_hook_data::hook_type, join_callback(), join_conference_bridge(), bridge_profile::language, leave_conference(), LOG_ERROR, LOG_WARNING, MAX_CONF_NAME, NULL, pbx_builtin_setvar_helper(), play_sound_file(), quiet, send_event_hook_callback(), bridge_profile::sounds, confbridge_hook_data::user, user, USER_OPT_ANNOUNCE_JOIN_LEAVE, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW, USER_OPT_ANSWER_CHANNEL, USER_OPT_DENOISE, USER_OPT_DROP_SILENCE, USER_OPT_DTMF_PASS, USER_OPT_HEAR_OWN_JOIN_SOUND, USER_OPT_JITTERBUFFER, USER_OPT_MARKEDUSER, USER_OPT_QUIET, USER_OPT_TALKER_DETECT, USER_OPT_TEXT_MESSAGING, and user_timeout().

Referenced by load_module().

◆ confbridge_handle_atxfer()

void confbridge_handle_atxfer ( struct ast_attended_transfer_message msg)

Create join/leave events for attended transfers.

Since
13.28
16.5
Parameters
msgThe attended transfer stasis message

Definition at line 1696 of file app_confbridge.c.

1697{
1698 struct ast_channel_snapshot *old_snapshot;
1699 struct ast_channel_snapshot *new_snapshot;
1700 char *confbr_name = NULL;
1701 char *comma;
1703 struct confbridge_user *user = NULL;
1704 int found_user = 0;
1705 struct ast_json *json_object;
1706
1708 && strcmp(msg->to_transferee.channel_snapshot->dialplan->appl, "ConfBridge") == 0
1709 && msg->target) {
1710 /* We're transferring a bridge to an extension */
1711 old_snapshot = msg->to_transferee.channel_snapshot;
1712 new_snapshot = msg->target;
1713 } else if (msg->to_transfer_target.channel_snapshot
1714 && strcmp(msg->to_transfer_target.channel_snapshot->dialplan->appl, "ConfBridge") == 0
1715 && msg->transferee) {
1716 /* We're transferring a call to a bridge */
1717 old_snapshot = msg->to_transfer_target.channel_snapshot;
1718 new_snapshot = msg->transferee;
1719 } else {
1720 ast_log(LOG_ERROR, "Could not determine proper channels\n");
1721 return;
1722 }
1723
1724 /*
1725 * old_snapshot->data should have the original parameters passed to
1726 * the ConfBridge app:
1727 * conference[,bridge_profile[,user_profile[,menu]]]
1728 * We'll use "conference" to look up the bridge.
1729 *
1730 * We _could_ use old_snapshot->bridgeid to get the bridge but
1731 * that would involve locking the conference_bridges container
1732 * and iterating over it looking for a matching bridge.
1733 */
1734 if (ast_strlen_zero(old_snapshot->dialplan->data)) {
1735 ast_log(LOG_ERROR, "Channel '%s' didn't have app data set\n", old_snapshot->base->name);
1736 return;
1737 }
1738 confbr_name = ast_strdupa(old_snapshot->dialplan->data);
1739 comma = strchr(confbr_name, ',');
1740 if (comma) {
1741 *comma = '\0';
1742 }
1743
1744 ast_debug(1, "Confbr: %s Leaving: %s Joining: %s\n", confbr_name, old_snapshot->base->name, new_snapshot->base->name);
1745
1746 conference = ao2_find(conference_bridges, confbr_name, OBJ_SEARCH_KEY);
1747 if (!conference) {
1748 ast_log(LOG_ERROR, "Conference bridge '%s' not found\n", confbr_name);
1749 return;
1750 }
1751 ao2_lock(conference);
1752
1753 /*
1754 * We need to grab the user profile for the departing user in order to
1755 * properly format the join/leave messages.
1756 */
1757 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
1758 if (strcasecmp(ast_channel_name(user->chan), old_snapshot->base->name) == 0) {
1759 found_user = 1;
1760 break;
1761 }
1762 }
1763
1764 /*
1765 * If we didn't find the user in the active list, try the waiting list.
1766 */
1767 if (!found_user && conference->waitingusers) {
1768 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
1769 if (strcasecmp(ast_channel_name(user->chan), old_snapshot->base->name) == 0) {
1770 found_user = 1;
1771 break;
1772 }
1773 }
1774 }
1775
1776 if (!found_user) {
1777 ast_log(LOG_ERROR, "Unable to find user profile for channel '%s' in bridge '%s'\n",
1778 old_snapshot->base->name, confbr_name);
1779 return;
1780 }
1781
1782 /*
1783 * We're going to use the existing user profile to create the messages.
1784 */
1785 json_object = ast_json_pack("{s: b}",
1786 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
1787 );
1788 if (!json_object) {
1789 return;
1790 }
1791
1792 send_conf_stasis_snapshots(conference, old_snapshot, confbridge_leave_type(), json_object);
1793 ast_json_unref(json_object);
1794
1795 json_object = ast_json_pack("{s: b, s: b}",
1796 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN),
1797 "muted", user->muted);
1798 if (!json_object) {
1799 return;
1800 }
1801 send_conf_stasis_snapshots(conference, new_snapshot, confbridge_join_type(), json_object);
1802 ast_json_unref(json_object);
1803}
static void send_conf_stasis_snapshots(struct confbridge_conference *conference, struct ast_channel_snapshot *chan_snapshot, struct stasis_message_type *type, struct ast_json *extras)
static void confbridge_unlock_and_unref(void *obj)
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
struct stasis_message_type * confbridge_join_type(void)
get the confbridge join stasis message type
struct stasis_message_type * confbridge_leave_type(void)
get the confbridge leave stasis message type
struct ast_bridge_channel_snapshot_pair to_transfer_target
struct ast_channel_snapshot * transferee
struct ast_bridge_channel_snapshot_pair to_transferee
struct ast_channel_snapshot * target
struct ast_channel_snapshot * channel_snapshot
const ast_string_field name
const ast_string_field data
const ast_string_field appl
struct ast_channel_snapshot_dialplan * dialplan
struct ast_channel_snapshot_base * base

References ao2_find, ao2_lock, ast_channel_snapshot_dialplan::appl, ast_channel_name(), ast_debug, ast_json_pack(), ast_json_unref(), AST_LIST_TRAVERSE, ast_log, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel_snapshot::base, ast_bridge_channel_snapshot_pair::channel_snapshot, confbridge_join_type(), confbridge_leave_type(), confbridge_unlock_and_unref(), conference_bridges, ast_channel_snapshot_dialplan::data, ast_channel_snapshot::dialplan, LOG_ERROR, ast_channel_snapshot_base::name, NULL, OBJ_SEARCH_KEY, RAII_VAR, send_conf_stasis_snapshots(), ast_attended_transfer_message::target, ast_attended_transfer_message::to_transfer_target, ast_attended_transfer_message::to_transferee, ast_attended_transfer_message::transferee, and USER_OPT_ADMIN.

Referenced by confbridge_atxfer_cb().

◆ confbridge_unlock_and_unref()

static void confbridge_unlock_and_unref ( void *  obj)
static

Definition at line 1685 of file app_confbridge.c.

1686{
1687 struct confbridge_conference *conference = obj;
1688
1689 if (!obj) {
1690 return;
1691 }
1692 ao2_unlock(conference);
1693 ao2_ref(conference, -1);
1694}

References ao2_ref, and ao2_unlock.

Referenced by confbridge_handle_atxfer().

◆ conference_bridge_cmp_cb()

static int conference_bridge_cmp_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Comparison function used for conference bridges container.

Definition at line 639 of file app_confbridge.c.

640{
641 const struct confbridge_conference *left = obj;
642 const struct confbridge_conference *right = arg;
643 const char *right_name = arg;
644 int cmp;
645
646 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
647 default:
648 case OBJ_POINTER:
649 right_name = right->name;
650 /* Fall through */
651 case OBJ_KEY:
652 cmp = strcasecmp(left->name, right_name);
653 break;
654 case OBJ_PARTIAL_KEY:
655 cmp = strncasecmp(left->name, right_name, strlen(right_name));
656 break;
657 }
658 return cmp ? 0 : CMP_MATCH;
659}
@ CMP_MATCH
Definition: astobj2.h:1027
#define OBJ_POINTER
Definition: astobj2.h:1150
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1152

References CMP_MATCH, confbridge_conference::name, OBJ_KEY, OBJ_PARTIAL_KEY, and OBJ_POINTER.

Referenced by load_module().

◆ conference_bridge_hash_cb()

static int conference_bridge_hash_cb ( const void *  obj,
const int  flags 
)
static

Hashing function used for conference bridges container.

Definition at line 615 of file app_confbridge.c.

616{
617 const struct confbridge_conference *conference = obj;
618 const char *name = obj;
619 int hash;
620
621 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
622 default:
623 case OBJ_POINTER:
624 name = conference->name;
625 /* Fall through */
626 case OBJ_KEY:
627 hash = ast_str_case_hash(name);
628 break;
629 case OBJ_PARTIAL_KEY:
630 /* Should never happen in hash callback. */
631 ast_assert(0);
632 hash = 0;
633 break;
634 }
635 return hash;
636}
static const char name[]
Definition: format_mp3.c:68
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1303
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_str_case_hash(), name, confbridge_conference::name, OBJ_KEY, OBJ_PARTIAL_KEY, and OBJ_POINTER.

Referenced by load_module().

◆ confkick_exec()

static int confkick_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 4485 of file app_confbridge.c.

4486{
4487 char *parse;
4488 struct confbridge_conference *conference;
4489 int not_found;
4490
4492 AST_APP_ARG(confbridge);
4493 AST_APP_ARG(channel);
4494 );
4495
4496 if (ast_strlen_zero(data)) {
4497 ast_log(LOG_WARNING, "No conference bridge specified.\n");
4498 pbx_builtin_setvar_helper(chan, "CONFKICKSTATUS", "FAILURE");
4499 return 0;
4500 }
4501
4502 parse = ast_strdupa(data);
4504
4505 conference = ao2_find(conference_bridges, args.confbridge, OBJ_KEY);
4506 if (!conference) {
4507 ast_log(LOG_WARNING, "No conference bridge named '%s' found!\n", args.confbridge);
4508 pbx_builtin_setvar_helper(chan, "CONFKICKSTATUS", "FAILURE");
4509 return 0;
4510 }
4511 if (ast_strlen_zero(args.channel)) {
4512 not_found = kick_conference_participant(conference, "all");
4513 } else {
4514 not_found = kick_conference_participant(conference, args.channel);
4515 }
4516
4517 ao2_ref(conference, -1);
4518 if (not_found) {
4519 if (ast_strlen_zero(args.channel) || !strcasecmp("all", args.channel) || !strcasecmp("participants", args.channel)) {
4520 ast_log(LOG_WARNING, "No participants found in conference bridge '%s'!\n", args.confbridge);
4521 } else {
4522 ast_log(LOG_WARNING, "No participant named '%s' found in conference bridge '%s'!\n", args.channel, args.confbridge);
4523 }
4524 pbx_builtin_setvar_helper(chan, "CONFKICKSTATUS", "FAILURE");
4525 return 0;
4526 }
4527 ast_debug(1, "Kicked '%s' out of conference '%s'\n", args.channel, args.confbridge);
4528 pbx_builtin_setvar_helper(chan, "CONFKICKSTATUS", "SUCCESS");
4529 return 0;
4530}

References ao2_find, ao2_ref, args, AST_APP_ARG, ast_debug, AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), conference_bridges, kick_conference_participant(), LOG_WARNING, OBJ_KEY, and pbx_builtin_setvar_helper().

Referenced by load_module().

◆ destroy_conference_bridge()

static void destroy_conference_bridge ( void *  obj)
static

Destroy a conference bridge.

Parameters
objThe conference bridge object

Definition at line 1311 of file app_confbridge.c.

1312{
1313 struct confbridge_conference *conference = obj;
1314
1315 ast_debug(1, "Destroying conference bridge '%s'\n", conference->name);
1316
1317 if (conference->playback_chan) {
1318 if (conference->playback_queue) {
1319 struct hangup_data hangup;
1321
1323 ast_mutex_lock(&hangup.lock);
1324 while (!hangup.hungup) {
1325 ast_cond_wait(&hangup.cond, &hangup.lock);
1326 }
1327 ast_mutex_unlock(&hangup.lock);
1328 }
1329
1331 } else {
1332 /* Playback queue is not yet allocated. Just hang up the channel straight */
1335 }
1336 }
1337
1338 /* Destroying a conference bridge is simple, all we have to do is destroy the bridging object */
1339 if (conference->bridge) {
1342 }
1343
1347
1350}
static void hangup_data_init(struct hangup_data *hangup, struct confbridge_conference *conference)
static void hangup_data_destroy(struct hangup_data *hangup)
static int hangup_playback(void *data)
Hang up the announcer channel.
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:1009
static int hangup(void *data)
Definition: chan_pjsip.c:2520
#define ast_cond_wait(cond, mutex)
Definition: lock.h:212
struct confbridge_conference * conference
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.

References ast_bridge_destroy(), ast_channel_cleanup, ast_cond_wait, ast_debug, ast_free, ast_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_taskprocessor_push(), ast_taskprocessor_unreference(), confbridge_conference::b_profile, confbridge_conference::bridge, conf_bridge_profile_destroy(), hangup_data::conference, hangup(), hangup_data_destroy(), hangup_data_init(), hangup_playback(), confbridge_conference::name, NULL, confbridge_conference::orig_rec_file, confbridge_conference::playback_chan, confbridge_conference::playback_queue, confbridge_conference::record_chan, and confbridge_conference::record_filename.

Referenced by join_conference_bridge().

◆ execute_menu_entry()

static int execute_menu_entry ( struct confbridge_conference conference,
struct confbridge_user user,
struct ast_bridge_channel bridge_channel,
struct conf_menu_entry menu_entry,
struct conf_menu menu 
)
static

Definition at line 3246 of file app_confbridge.c.

3251{
3252 struct conf_menu_action *menu_action;
3253 int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
3254 int stop_prompts = 0;
3255 int res = 0;
3256
3257 AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
3258 switch (menu_action->id) {
3260 res |= action_toggle_mute(conference, user, bridge_channel);
3261 break;
3263 action_toggle_binaural(conference, user, bridge_channel);
3264 break;
3266 if (!isadmin) {
3267 break;
3268 }
3270 break;
3272 announce_user_count(conference, user, bridge_channel);
3273 break;
3275 if (!stop_prompts) {
3276 res |= action_playback(bridge_channel, menu_action->data.playback_file);
3277 ast_test_suite_event_notify("CONF_MENU_PLAYBACK",
3278 "Message: %s\r\nChannel: %s",
3279 menu_action->data.playback_file, ast_channel_name(bridge_channel->chan));
3280 }
3281 break;
3284 break;
3287 break;
3291 break;
3295 break;
3299 break;
3303 break;
3305 if (!(stop_prompts)) {
3306 res |= action_playback_and_continue(conference,
3307 user,
3308 bridge_channel,
3309 menu,
3310 menu_action->data.playback_file,
3311 menu_entry->dtmf,
3312 &stop_prompts);
3313 }
3314 break;
3316 res |= action_dialplan_exec(bridge_channel, menu_action);
3317 break;
3319 if (!isadmin) {
3320 break;
3321 }
3322 conference->locked = (!conference->locked ? 1 : 0);
3323 res |= play_file(bridge_channel, NULL,
3326 conference->b_profile.sounds)) < 0;
3327 break;
3329 res |= action_kick_last(conference, bridge_channel, user);
3330 break;
3331 case MENU_ACTION_LEAVE:
3332 pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "DTMF");
3333 ao2_lock(conference);
3334 ast_bridge_remove(conference->bridge, bridge_channel->chan);
3335 ast_test_suite_event_notify("CONF_MENU_LEAVE",
3336 "Channel: %s",
3337 ast_channel_name(bridge_channel->chan));
3338 ao2_unlock(conference);
3339 break;
3340 case MENU_ACTION_NOOP:
3341 break;
3343 ao2_lock(conference);
3344 if (!ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_SFU)) {
3345 ast_bridge_set_single_src_video_mode(conference->bridge, bridge_channel->chan);
3346 }
3347 ao2_unlock(conference);
3348 break;
3350 handle_video_on_exit(conference, bridge_channel->chan);
3351 break;
3352 }
3353 }
3354 return res;
3355}
static int action_dialplan_exec(struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
static int action_playback_and_continue(struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel, struct conf_menu *menu, const char *playback_file, const char *cur_dtmf, int *stop_prompts)
static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
static int action_toggle_mute(struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel)
static int action_toggle_mute_participants(struct confbridge_conference *conference, struct confbridge_user *user)
static int announce_user_count(struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel)
Announce number of users in the conference bridge to the caller.
static int action_kick_last(struct confbridge_conference *conference, struct ast_bridge_channel *bridge_channel, struct confbridge_user *user)
static int action_toggle_binaural(struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel)
int ast_audiohook_volume_adjust(struct ast_channel *chan, enum ast_audiohook_direction direction, int volume)
Adjust the volume on frames read from or written to a channel.
Definition: audiohook.c:1371
@ BRIDGE_OPT_VIDEO_SRC_SFU
Definition: confbridge.h:85
@ MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC
Definition: confbridge.h:112
@ MENU_ACTION_SET_SINGLE_VIDEO_SRC
Definition: confbridge.h:111
@ MENU_ACTION_ADMIN_KICK_LAST
Definition: confbridge.h:108
@ MENU_ACTION_TOGGLE_BINAURAL
Definition: confbridge.h:115
@ MENU_ACTION_PLAYBACK
Definition: confbridge.h:98
@ MENU_ACTION_LEAVE
Definition: confbridge.h:109
@ MENU_ACTION_RESET_LISTENING
Definition: confbridge.h:102
@ MENU_ACTION_INCREASE_TALKING
Definition: confbridge.h:104
@ MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS
Definition: confbridge.h:114
@ MENU_ACTION_INCREASE_LISTENING
Definition: confbridge.h:100
@ MENU_ACTION_DIALPLAN_EXEC
Definition: confbridge.h:106
@ MENU_ACTION_DECREASE_LISTENING
Definition: confbridge.h:101
@ MENU_ACTION_PLAYBACK_AND_CONTINUE
Definition: confbridge.h:99
@ MENU_ACTION_ADMIN_TOGGLE_LOCK
Definition: confbridge.h:107
@ MENU_ACTION_DECREASE_TALKING
Definition: confbridge.h:105
@ MENU_ACTION_PARTICIPANT_COUNT
Definition: confbridge.h:113
@ MENU_ACTION_TOGGLE_MUTE
Definition: confbridge.h:97
@ MENU_ACTION_NOOP
Definition: confbridge.h:110
@ MENU_ACTION_RESET_TALKING
Definition: confbridge.h:103
enum conf_menu_action_id id
Definition: confbridge.h:123
struct conf_menu_action::@89 action
char playback_file[PATH_MAX]
Definition: confbridge.h:125
struct conf_menu_entry::@91 actions

References conf_menu_action::action, action_dialplan_exec(), action_kick_last(), action_playback(), action_playback_and_continue(), action_toggle_binaural(), action_toggle_mute(), action_toggle_mute_participants(), conf_menu_entry::actions, announce_user_count(), ao2_lock, ao2_unlock, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, ast_audiohook_volume_adjust(), ast_audiohook_volume_set(), ast_bridge_remove(), ast_bridge_set_single_src_video_mode(), ast_channel_name(), AST_LIST_TRAVERSE, ast_test_flag, ast_test_suite_event_notify, confbridge_conference::b_profile, confbridge_conference::bridge, BRIDGE_OPT_VIDEO_SRC_SFU, ast_bridge_channel::chan, conf_get_sound(), CONF_SOUND_LOCKED_NOW, CONF_SOUND_UNLOCKED_NOW, conf_menu_action::data, conf_menu_entry::dtmf, handle_video_on_exit(), conf_menu_action::id, confbridge_conference::locked, MENU_ACTION_ADMIN_KICK_LAST, MENU_ACTION_ADMIN_TOGGLE_LOCK, MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS, MENU_ACTION_DECREASE_LISTENING, MENU_ACTION_DECREASE_TALKING, MENU_ACTION_DIALPLAN_EXEC, MENU_ACTION_INCREASE_LISTENING, MENU_ACTION_INCREASE_TALKING, MENU_ACTION_LEAVE, MENU_ACTION_NOOP, MENU_ACTION_PARTICIPANT_COUNT, MENU_ACTION_PLAYBACK, MENU_ACTION_PLAYBACK_AND_CONTINUE, MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC, MENU_ACTION_RESET_LISTENING, MENU_ACTION_RESET_TALKING, MENU_ACTION_SET_SINGLE_VIDEO_SRC, MENU_ACTION_TOGGLE_BINAURAL, MENU_ACTION_TOGGLE_MUTE, NULL, pbx_builtin_setvar_helper(), play_file(), conf_menu_action::playback_file, bridge_profile::sounds, and USER_OPT_ADMIN.

Referenced by action_playback_and_continue(), and conf_handle_dtmf().

◆ func_confbridge_channels()

static int func_confbridge_channels ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 3964 of file app_confbridge.c.

3965{
3966 char *parse, *outbuf;
3967 struct confbridge_conference *conference;
3968 struct confbridge_user *user;
3969 int bytes, count = 0;
3970 size_t outlen;
3973 AST_APP_ARG(confno);
3974 );
3975
3976 /* parse all the required arguments and make sure they exist. */
3977 if (ast_strlen_zero(data)) {
3978 return -1;
3979 }
3980 parse = ast_strdupa(data);
3982 if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) {
3983 ast_log(LOG_WARNING, "Usage: %s(category,confno)", cmd);
3984 return -1;
3985 }
3987 if (!conference) {
3988 ast_debug(1, "No such conference: %s\n", args.confno);
3989 return -1;
3990 }
3991
3992 outbuf = buf;
3993 outlen = len;
3994
3996 if (!strcasecmp(args.type, "parties")) {
3998 bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
3999 outbuf += bytes;
4000 outlen -= bytes;
4001 }
4003 bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
4004 outbuf += bytes;
4005 outlen -= bytes;
4006 }
4007 } else if (!strcasecmp(args.type, "active")) {
4009 bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
4010 outbuf += bytes;
4011 outlen -= bytes;
4012 }
4013 } else if (!strcasecmp(args.type, "waiting")) {
4015 bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
4016 outbuf += bytes;
4017 outlen -= bytes;
4018 }
4019 } else if (!strcasecmp(args.type, "admins")) {
4021 if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
4022 bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
4023 outbuf += bytes;
4024 outlen -= bytes;
4025 }
4026 }
4027 } else if (!strcasecmp(args.type, "marked")) {
4029 if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
4030 bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
4031 outbuf += bytes;
4032 outlen -= bytes;
4033 }
4034 }
4035 } else {
4036 ast_log(LOG_ERROR, "Invalid keyword '%s' passed to %s.\n", args.type, cmd);
4037 }
4039 ao2_ref(conference, -1);
4040 return 0;
4041}
static const char type[]
Definition: chan_ooh323.c:109
char buf[BUFSIZE]
Definition: eagi_proxy.c:66

References confbridge_conference::active_list, ao2_find, ao2_lock, ao2_ref, ao2_unlock, args, AST_APP_ARG, ast_channel_name(), ast_debug, AST_DECLARE_APP_ARGS, AST_LIST_TRAVERSE, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, buf, confbridge_user::conference, conference_bridges, len(), confbridge_user::list, LOG_ERROR, LOG_WARNING, OBJ_KEY, type, user, USER_OPT_ADMIN, USER_OPT_MARKEDUSER, and confbridge_conference::waiting_list.

◆ func_confbridge_info()

static int func_confbridge_info ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 4425 of file app_confbridge.c.

4426{
4427 char *parse;
4428 struct confbridge_conference *conference;
4429 struct confbridge_user *user;
4430 int count = 0;
4433 AST_APP_ARG(confno);
4434 );
4435
4436 /* parse all the required arguments and make sure they exist. */
4437 if (ast_strlen_zero(data)) {
4438 return -1;
4439 }
4440 parse = ast_strdupa(data);
4442 if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) {
4443 return -1;
4444 }
4446 if (!conference) {
4447 snprintf(buf, len, "0");
4448 return 0;
4449 }
4450
4451 /* get the correct count for the type requested */
4453 if (!strcasecmp(args.type, "parties")) {
4455 count++;
4456 }
4458 count++;
4459 }
4460 } else if (!strcasecmp(args.type, "admins")) {
4462 if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
4463 count++;
4464 }
4465 }
4466 } else if (!strcasecmp(args.type, "marked")) {
4468 if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
4469 count++;
4470 }
4471 }
4472 } else if (!strcasecmp(args.type, "locked")) {
4473 count = conference->locked;
4474 } else if (!strcasecmp(args.type, "muted")) {
4475 count = conference->muted;
4476 } else {
4477 ast_log(LOG_ERROR, "Invalid keyword '%s' passed to CONFBRIDGE_INFO.\n", args.type);
4478 }
4479 snprintf(buf, len, "%d", count);
4481 ao2_ref(conference, -1);
4482 return 0;
4483}

References confbridge_conference::active_list, ao2_find, ao2_lock, ao2_ref, ao2_unlock, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_LIST_TRAVERSE, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, buf, confbridge_user::conference, conference_bridges, len(), confbridge_user::list, confbridge_conference::locked, LOG_ERROR, confbridge_conference::muted, OBJ_KEY, type, user, USER_OPT_ADMIN, USER_OPT_MARKEDUSER, and confbridge_conference::waiting_list.

◆ generic_lock_unlock_helper()

static int generic_lock_unlock_helper ( int  lock,
const char *  conference_name 
)
static

Definition at line 3646 of file app_confbridge.c.

3647{
3648 struct confbridge_conference *conference;
3649 int res = 0;
3650
3651 conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3652 if (!conference) {
3653 return -1;
3654 }
3655 ao2_lock(conference);
3656 conference->locked = lock;
3657 ast_test_suite_event_notify("CONF_LOCK", "Message: conference %s\r\nConference: %s", conference->locked ? "locked" : "unlocked", conference->b_profile.name);
3658 ao2_unlock(conference);
3659 ao2_ref(conference, -1);
3660
3661 return res;
3662}

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_test_suite_event_notify, confbridge_conference::b_profile, conference_bridges, lock, confbridge_conference::locked, bridge_profile::name, and OBJ_KEY.

Referenced by action_lock_unlock_helper(), handle_cli_confbridge_lock(), and handle_cli_confbridge_unlock().

◆ generic_mute_unmute_helper()

static int generic_mute_unmute_helper ( int  mute,
const char *  conference_name,
const char *  chan_name 
)
static

Definition at line 3671 of file app_confbridge.c.

3673{
3674 RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
3675 struct confbridge_user *user;
3676 int all = !strcasecmp("all", chan_name);
3677 int participants = !strcasecmp("participants", chan_name);
3678 int res = -2;
3679
3680 conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3681 if (!conference) {
3682 return -1;
3683 }
3684
3685 {
3686 SCOPED_AO2LOCK(bridge_lock, conference);
3688 int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
3689 strlen(chan_name));
3690 if (match || all
3691 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
3693 res = 0;
3694 if (match) {
3695 return res;
3696 }
3697 }
3698 }
3699
3701 int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
3702 strlen(chan_name));
3703 if (match || all
3704 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
3706 res = 0;
3707 if (match) {
3708 return res;
3709 }
3710 }
3711 }
3712 }
3713
3714 return res;
3715}
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2388

References confbridge_conference::active_list, ao2_cleanup, ao2_find, ast_channel_name(), AST_LIST_TRAVERSE, ast_test_flag, confbridge_user::conference, conference_bridges, generic_mute_unmute_user(), confbridge_user::list, match(), NULL, OBJ_KEY, RAII_VAR, SCOPED_AO2LOCK, user, USER_OPT_ADMIN, and confbridge_conference::waiting_list.

Referenced by action_mute_unmute_helper(), and cli_mute_unmute_helper().

◆ generic_mute_unmute_user()

static void generic_mute_unmute_user ( struct confbridge_conference conference,
struct confbridge_user user,
int  mute 
)
static

Definition at line 1450 of file app_confbridge.c.

1451{
1452 /* Set user level mute request. */
1453 user->muted = mute ? 1 : 0;
1454
1456 ast_test_suite_event_notify("CONF_MUTE",
1457 "Message: participant %s %s\r\n"
1458 "Conference: %s\r\n"
1459 "Channel: %s",
1460 ast_channel_name(user->chan),
1461 mute ? "muted" : "unmuted",
1462 conference->b_profile.name,
1463 ast_channel_name(user->chan));
1464 if (mute) {
1465 send_mute_event(user, conference);
1466 } else {
1467 send_unmute_event(user, conference);
1468 }
1469}
static void send_mute_event(struct confbridge_user *user, struct confbridge_conference *conference)
static void send_unmute_event(struct confbridge_user *user, struct confbridge_conference *conference)

References ast_channel_name(), ast_test_suite_event_notify, confbridge_conference::b_profile, conf_update_user_mute(), hangup_data::conference, bridge_profile::name, send_mute_event(), and send_unmute_event().

Referenced by action_toggle_mute(), and generic_mute_unmute_helper().

◆ handle_cli_confbridge_kick()

static char * handle_cli_confbridge_kick ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3485 of file app_confbridge.c.

3486{
3487 struct confbridge_conference *conference;
3488 int not_found;
3489
3490 switch (cmd) {
3491 case CLI_INIT:
3492 e->command = "confbridge kick";
3493 e->usage =
3494 "Usage: confbridge kick <conference> <channel>\n"
3495 " Kicks a channel out of the conference bridge.\n"
3496 " (all to kick everyone, participants to kick non-admins).\n";
3497 return NULL;
3498 case CLI_GENERATE:
3499 if (a->pos == 2) {
3500 return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3501 }
3502 if (a->pos == 3) {
3503 return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
3504 }
3505 return NULL;
3506 }
3507
3508 if (a->argc != 4) {
3509 return CLI_SHOWUSAGE;
3510 }
3511
3512 conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
3513 if (!conference) {
3514 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
3515 return CLI_SUCCESS;
3516 }
3517 not_found = kick_conference_participant(conference, a->argv[3]);
3518 ao2_ref(conference, -1);
3519 if (not_found) {
3520 if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
3521 ast_cli(a->fd, "No participants found!\n");
3522 } else {
3523 ast_cli(a->fd, "No participant named '%s' found!\n", a->argv[3]);
3524 }
3525 return CLI_SUCCESS;
3526 }
3527 ast_cli(a->fd, "Kicked '%s' out of conference '%s'\n", a->argv[3], a->argv[2]);
3528 return CLI_SUCCESS;
3529}
static char * complete_confbridge_participant(const char *conference_name, const char *line, const char *word, int pos, int state)
static char * complete_confbridge_name(const char *line, const char *word, int pos, int state)
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177

References a, ao2_find, ao2_ref, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), complete_confbridge_participant(), conference_bridges, kick_conference_participant(), NULL, OBJ_KEY, and ast_cli_entry::usage.

◆ handle_cli_confbridge_list()

static char * handle_cli_confbridge_list ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3567 of file app_confbridge.c.

3568{
3569 struct confbridge_conference *conference;
3570
3571 switch (cmd) {
3572 case CLI_INIT:
3573 e->command = "confbridge list";
3574 e->usage =
3575 "Usage: confbridge list [<name>]\n"
3576 " Lists all currently active conference bridges or a specific conference bridge.\n"
3577 "\n"
3578 " When a conference bridge name is provided, flags may be shown for users. Below\n"
3579 " are the flags and what they represent.\n"
3580 "\n"
3581 " Flags:\n"
3582 " A - The user is an admin\n"
3583 " M - The user is a marked user\n"
3584 " W - The user must wait for a marked user to join\n"
3585 " E - The user will be kicked after the last marked user leaves the conference\n"
3586 " m - The user is muted\n"
3587 " w - The user is waiting for a marked user to join\n";
3588 return NULL;
3589 case CLI_GENERATE:
3590 if (a->pos == 2) {
3591 return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3592 }
3593 return NULL;
3594 }
3595
3596 if (a->argc == 2) {
3597 struct ao2_iterator iter;
3598
3599 ast_cli(a->fd, "Conference Bridge Name Users Marked Locked Muted\n");
3600 ast_cli(a->fd, "================================ ====== ====== ====== =====\n");
3602 while ((conference = ao2_iterator_next(&iter))) {
3603 ast_cli(a->fd, "%-32s %6u %6u %-6s %s\n",
3604 conference->name,
3605 conference->activeusers + conference->waitingusers,
3606 conference->markedusers,
3607 AST_CLI_YESNO(conference->locked),
3608 AST_CLI_YESNO(conference->muted));
3609 ao2_ref(conference, -1);
3610 }
3611 ao2_iterator_destroy(&iter);
3612 return CLI_SUCCESS;
3613 }
3614
3615 if (a->argc == 3) {
3616 struct confbridge_user *user;
3617
3619 if (!conference) {
3620 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
3621 return CLI_SUCCESS;
3622 }
3623 ast_cli(a->fd, "Channel Flags User Profile Bridge Profile Menu CallerID\n");
3624 ast_cli(a->fd, "============================== ====== ================ ================ ================ ================\n");
3628 }
3631 }
3633 ao2_ref(conference, -1);
3634 return CLI_SUCCESS;
3635 }
3636
3637 return CLI_SHOWUSAGE;
3638}
static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct confbridge_user *user, int waiting)
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
Definition: cli.h:71

References a, confbridge_conference::active_list, confbridge_conference::activeusers, ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), AST_CLI_YESNO, AST_LIST_TRAVERSE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), confbridge_user::conference, conference_bridges, handle_cli_confbridge_list_item(), confbridge_user::list, confbridge_conference::locked, confbridge_conference::markedusers, confbridge_conference::muted, confbridge_conference::name, NULL, OBJ_KEY, ast_cli_entry::usage, user, confbridge_conference::waiting_list, and confbridge_conference::waitingusers.

◆ handle_cli_confbridge_list_item()

static void handle_cli_confbridge_list_item ( struct ast_cli_args a,
struct confbridge_user user,
int  waiting 
)
static

Definition at line 3531 of file app_confbridge.c.

3532{
3533 char flag_str[6 + 1];/* Max flags + terminator */
3534 int pos = 0;
3535
3536 /* Build flags column string. */
3537 if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
3538 flag_str[pos++] = 'A';
3539 }
3540 if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
3541 flag_str[pos++] = 'M';
3542 }
3543 if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
3544 flag_str[pos++] = 'W';
3545 }
3546 if (ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED)) {
3547 flag_str[pos++] = 'E';
3548 }
3549 if (user->muted) {
3550 flag_str[pos++] = 'm';
3551 }
3552 if (waiting) {
3553 flag_str[pos++] = 'w';
3554 }
3555 flag_str[pos] = '\0';
3556
3557 ast_cli(a->fd, "%-30s %-6s %-16s %-16s %-16s %s\n",
3558 ast_channel_name(user->chan),
3559 flag_str,
3560 user->u_profile.name,
3561 user->conference->b_profile.name,
3562 user->menu_name,
3564 ast_channel_caller(user->chan)->id.number.str, "<unknown>"));
3565}
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
#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
struct ast_party_id id
Caller party ID.
Definition: channel.h:422
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:344
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:299
char * str
Subscriber phone number (Malloced)
Definition: channel.h:293

References a, ast_channel_caller(), ast_channel_name(), ast_cli(), ast_test_flag, ast_party_caller::id, ast_party_id::number, S_COR, ast_party_number::str, USER_OPT_ADMIN, USER_OPT_ENDMARKED, USER_OPT_MARKEDUSER, USER_OPT_WAITMARKED, and ast_party_number::valid.

Referenced by handle_cli_confbridge_list().

◆ handle_cli_confbridge_lock()

static char * handle_cli_confbridge_lock ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3798 of file app_confbridge.c.

3799{
3800 switch (cmd) {
3801 case CLI_INIT:
3802 e->command = "confbridge lock";
3803 e->usage =
3804 "Usage: confbridge lock <conference>\n"
3805 " Lock a conference. While locked, no new non-admins\n"
3806 " may join the conference.\n";
3807 return NULL;
3808 case CLI_GENERATE:
3809 if (a->pos == 2) {
3810 return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3811 }
3812 return NULL;
3813 }
3814 if (a->argc != 3) {
3815 return CLI_SHOWUSAGE;
3816 }
3817 if (generic_lock_unlock_helper(1, a->argv[2])) {
3818 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
3819 } else {
3820 ast_cli(a->fd, "Conference %s is locked.\n", a->argv[2]);
3821 }
3822 return CLI_SUCCESS;
3823}

References a, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), generic_lock_unlock_helper(), NULL, and ast_cli_entry::usage.

◆ handle_cli_confbridge_mute()

static char * handle_cli_confbridge_mute ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3736 of file app_confbridge.c.

3737{
3738 switch (cmd) {
3739 case CLI_INIT:
3740 e->command = "confbridge mute";
3741 e->usage =
3742 "Usage: confbridge mute <conference> <channel>\n"
3743 " Mute a channel in a conference.\n"
3744 " (all to mute everyone, participants to mute non-admins)\n"
3745 " If the specified channel is a prefix,\n"
3746 " the action will be taken on the first\n"
3747 " matching channel.\n";
3748 return NULL;
3749 case CLI_GENERATE:
3750 if (a->pos == 2) {
3751 return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3752 }
3753 if (a->pos == 3) {
3754 return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
3755 }
3756 return NULL;
3757 }
3758 if (a->argc != 4) {
3759 return CLI_SHOWUSAGE;
3760 }
3761
3763
3764 return CLI_SUCCESS;
3765}
static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)

References a, CLI_GENERATE, CLI_INIT, cli_mute_unmute_helper(), CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), complete_confbridge_participant(), NULL, and ast_cli_entry::usage.

◆ handle_cli_confbridge_start_record()

static char * handle_cli_confbridge_start_record ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3851 of file app_confbridge.c.

3852{
3853 const char *rec_file = NULL;
3854 struct confbridge_conference *conference;
3855
3856 switch (cmd) {
3857 case CLI_INIT:
3858 e->command = "confbridge record start";
3859 e->usage =
3860 "Usage: confbridge record start <conference> <file>\n"
3861 " <file> is optional, Otherwise the bridge profile\n"
3862 " record file will be used. If the bridge profile\n"
3863 " has no record file specified, a file will automatically\n"
3864 " be generated in the monitor directory\n";
3865 return NULL;
3866 case CLI_GENERATE:
3867 if (a->pos == 3) {
3868 return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3869 }
3870 return NULL;
3871 }
3872 if (a->argc < 4) {
3873 return CLI_SHOWUSAGE;
3874 }
3875 if (a->argc == 5) {
3876 rec_file = a->argv[4];
3877 }
3878
3879 conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
3880 if (!conference) {
3881 ast_cli(a->fd, "Conference not found.\n");
3882 return CLI_FAILURE;
3883 }
3884 ao2_lock(conference);
3885 if (conf_is_recording(conference)) {
3886 ast_cli(a->fd, "Conference is already being recorded.\n");
3887 ao2_unlock(conference);
3888 ao2_ref(conference, -1);
3889 return CLI_SUCCESS;
3890 }
3891 if (!ast_strlen_zero(rec_file)) {
3892 ast_copy_string(conference->b_profile.rec_file, rec_file, sizeof(conference->b_profile.rec_file));
3893 }
3894
3895 if (conf_start_record(conference)) {
3896 ast_cli(a->fd, "Could not start recording due to internal error.\n");
3897 ao2_unlock(conference);
3898 ao2_ref(conference, -1);
3899 return CLI_FAILURE;
3900 }
3901 ao2_unlock(conference);
3902
3903 ast_cli(a->fd, "Recording started\n");
3904 ao2_ref(conference, -1);
3905 return CLI_SUCCESS;
3906}
#define CLI_FAILURE
Definition: cli.h:46

References a, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_copy_string(), ast_strlen_zero(), confbridge_conference::b_profile, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), conf_is_recording(), conf_start_record(), conference_bridges, NULL, OBJ_KEY, bridge_profile::rec_file, and ast_cli_entry::usage.

◆ handle_cli_confbridge_stop_record()

static char * handle_cli_confbridge_stop_record ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3908 of file app_confbridge.c.

3909{
3910 struct confbridge_conference *conference;
3911 int ret;
3912
3913 switch (cmd) {
3914 case CLI_INIT:
3915 e->command = "confbridge record stop";
3916 e->usage =
3917 "Usage: confbridge record stop <conference>\n"
3918 " Stop a previously started recording.\n";
3919 return NULL;
3920 case CLI_GENERATE:
3921 if (a->pos == 3) {
3922 return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3923 }
3924 return NULL;
3925 }
3926 if (a->argc != 4) {
3927 return CLI_SHOWUSAGE;
3928 }
3929
3930 conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
3931 if (!conference) {
3932 ast_cli(a->fd, "Conference not found.\n");
3933 return CLI_SUCCESS;
3934 }
3935 ao2_lock(conference);
3936 ret = conf_stop_record(conference);
3937 ao2_unlock(conference);
3938 ast_cli(a->fd, "Recording %sstopped.\n", ret ? "could not be " : "");
3939 ao2_ref(conference, -1);
3940 return CLI_SUCCESS;
3941}

References a, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), conf_stop_record(), conference_bridges, NULL, OBJ_KEY, and ast_cli_entry::usage.

◆ handle_cli_confbridge_unlock()

static char * handle_cli_confbridge_unlock ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3825 of file app_confbridge.c.

3826{
3827 switch (cmd) {
3828 case CLI_INIT:
3829 e->command = "confbridge unlock";
3830 e->usage =
3831 "Usage: confbridge unlock <conference>\n"
3832 " Unlock a previously locked conference.\n";
3833 return NULL;
3834 case CLI_GENERATE:
3835 if (a->pos == 2) {
3836 return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3837 }
3838 return NULL;
3839 }
3840 if (a->argc != 3) {
3841 return CLI_SHOWUSAGE;
3842 }
3843 if (generic_lock_unlock_helper(0, a->argv[2])) {
3844 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
3845 } else {
3846 ast_cli(a->fd, "Conference %s is unlocked.\n", a->argv[2]);
3847 }
3848 return CLI_SUCCESS;
3849}

References a, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), generic_lock_unlock_helper(), NULL, and ast_cli_entry::usage.

◆ handle_cli_confbridge_unmute()

static char * handle_cli_confbridge_unmute ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3767 of file app_confbridge.c.

3768{
3769 switch (cmd) {
3770 case CLI_INIT:
3771 e->command = "confbridge unmute";
3772 e->usage =
3773 "Usage: confbridge unmute <conference> <channel>\n"
3774 " Unmute a channel in a conference.\n"
3775 " (all to unmute everyone, participants to unmute non-admins)\n"
3776 " If the specified channel is a prefix,\n"
3777 " the action will be taken on the first\n"
3778 " matching channel.\n";
3779 return NULL;
3780 case CLI_GENERATE:
3781 if (a->pos == 2) {
3782 return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3783 }
3784 if (a->pos == 3) {
3785 return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
3786 }
3787 return NULL;
3788 }
3789 if (a->argc != 4) {
3790 return CLI_SHOWUSAGE;
3791 }
3792
3794
3795 return CLI_SUCCESS;
3796}

References a, CLI_GENERATE, CLI_INIT, cli_mute_unmute_helper(), CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), complete_confbridge_participant(), NULL, and ast_cli_entry::usage.

◆ handle_conf_user_join()

static int handle_conf_user_join ( struct confbridge_user user)
static

Call the proper join event handler for the user for the conference bridge's current state.

Definition at line 1358 of file app_confbridge.c.

1359{
1361 if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
1362 handler = user->conference->state->join_marked;
1363 } else if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
1364 handler = user->conference->state->join_waitmarked;
1365 } else {
1366 handler = user->conference->state->join_unmarked;
1367 }
1368
1370
1371 if (!handler) {
1373 return -1;
1374 }
1375
1376 handler(user);
1377
1378 return 0;
1379}
void conf_invalid_event_fn(struct confbridge_user *user)
A handler for join/leave events that are invalid in a particular state.
Definition: conf_state.c:42
void(* conference_event_fn)(struct confbridge_user *user)
Definition: conf_state.h:40
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition: test_ari.c:59

References ast_assert, ast_test_flag, conf_invalid_event_fn(), handler(), NULL, USER_OPT_MARKEDUSER, and USER_OPT_WAITMARKED.

Referenced by join_conference_bridge().

◆ handle_conf_user_leave()

static int handle_conf_user_leave ( struct confbridge_user user)
static

Call the proper leave event handler for the user for the conference bridge's current state.

Definition at line 1387 of file app_confbridge.c.

1388{
1390 if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
1391 handler = user->conference->state->leave_marked;
1392 } else if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
1393 handler = user->conference->state->leave_waitmarked;
1394 } else {
1395 handler = user->conference->state->leave_unmarked;
1396 }
1397
1399
1400 if (!handler) {
1401 /* This should never happen. If it does, though, it is bad. The user will not have been removed
1402 * from the appropriate list, so counts will be off and stuff. The conference won't be torn down, etc.
1403 * Shouldn't happen, though. */
1405 return -1;
1406 }
1407
1408 handler(user);
1409
1410 return 0;
1411}

References ast_assert, ast_test_flag, conf_invalid_event_fn(), handler(), NULL, USER_OPT_MARKEDUSER, and USER_OPT_WAITMARKED.

Referenced by leave_conference().

◆ handle_video_on_exit()

static void handle_video_on_exit ( struct confbridge_conference conference,
struct ast_channel chan 
)
static

Definition at line 1215 of file app_confbridge.c.

1216{
1217 struct confbridge_user *user = NULL;
1218
1219 /* if this isn't a video source, nothing to update */
1221 return;
1222 }
1223
1225
1226 /* If in follow talker mode, make sure to restore this mode on the
1227 * bridge when a source is removed. It is possible this channel was
1228 * only set temporarily as a video source by an AMI or DTMF action. */
1231 }
1232
1233 /* if the video_mode isn't set to automatically pick the video source, do nothing on exit. */
1236 return;
1237 }
1238
1239 /* Make the next available marked user the video src. */
1242 if (user->chan == chan) {
1243 continue;
1244 }
1245 if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
1247 break;
1248 }
1249 }
1251}
void ast_bridge_set_talker_src_video_mode(struct ast_bridge *bridge)
Set the bridge to pick the strongest talker supporting video as the single source video feed.
Definition: bridge.c:3835
void ast_bridge_remove_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
remove a channel as a source of video for the bridge.
Definition: bridge.c:3986
int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
Determine if a channel is a video src for the bridge.
Definition: bridge.c:3960
@ BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER
Definition: confbridge.h:81
@ BRIDGE_OPT_VIDEO_SRC_LAST_MARKED
Definition: confbridge.h:79
@ BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
Definition: confbridge.h:80

References confbridge_conference::active_list, ao2_lock, ao2_unlock, ast_bridge_is_video_src(), ast_bridge_remove_video_src(), ast_bridge_set_single_src_video_mode(), ast_bridge_set_talker_src_video_mode(), AST_LIST_TRAVERSE, ast_test_flag, confbridge_conference::b_profile, confbridge_conference::bridge, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED, confbridge_user::chan, confbridge_user::conference, confbridge_user::list, NULL, and USER_OPT_MARKEDUSER.

Referenced by confbridge_exec(), and execute_menu_entry().

◆ handle_video_on_join()

static void handle_video_on_join ( struct confbridge_conference conference,
struct ast_channel chan,
int  marked 
)
static

Definition at line 1183 of file app_confbridge.c.

1184{
1185 /* Right now, only marked users are automatically set as the single src of video.*/
1186 if (!marked) {
1187 return;
1188 }
1189
1191 int set = 1;
1192 struct confbridge_user *user = NULL;
1193
1195 /* see if anyone is already the video src */
1197 if (user->chan == chan) {
1198 continue;
1199 }
1201 set = 0;
1202 break;
1203 }
1204 }
1206 if (set) {
1208 }
1210 /* we joined and are video capable, we override anyone else that may have already been the video feed */
1212 }
1213}
static int set(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:266

References confbridge_conference::active_list, ao2_lock, ao2_unlock, ast_bridge_is_video_src(), ast_bridge_set_single_src_video_mode(), AST_LIST_TRAVERSE, ast_test_flag, confbridge_conference::b_profile, confbridge_conference::bridge, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED, confbridge_user::chan, confbridge_user::conference, confbridge_user::list, NULL, and set().

Referenced by confbridge_exec().

◆ hangup_data_destroy()

static void hangup_data_destroy ( struct hangup_data hangup)
static

Definition at line 1300 of file app_confbridge.c.

1301{
1302 ast_mutex_destroy(&hangup->lock);
1303 ast_cond_destroy(&hangup->cond);
1304}

References ast_cond_destroy, ast_mutex_destroy, and hangup().

Referenced by destroy_conference_bridge().

◆ hangup_data_init()

static void hangup_data_init ( struct hangup_data hangup,
struct confbridge_conference conference 
)
static

Definition at line 1291 of file app_confbridge.c.

1292{
1293 ast_mutex_init(&hangup->lock);
1294 ast_cond_init(&hangup->cond, NULL);
1295
1296 hangup->conference = conference;
1297 hangup->hungup = 0;
1298}

References ast_cond_init, ast_mutex_init, hangup_data::conference, hangup(), and NULL.

Referenced by destroy_conference_bridge().

◆ hangup_playback()

static int hangup_playback ( void *  data)
static

Hang up the announcer channel.

This hangs up the announcer channel in the conference. This runs in the playback queue taskprocessor since we do not want to hang up the channel while it's trying to play an announcement.

This task is performed synchronously, so there is no need to perform any cleanup on the passed-in data.

Parameters
dataA hangup_data structure
Returns
0

Definition at line 1274 of file app_confbridge.c.

1275{
1276 struct hangup_data *hangup = data;
1277
1278 ast_autoservice_stop(hangup->conference->playback_chan);
1279
1280 ast_hangup(hangup->conference->playback_chan);
1281 hangup->conference->playback_chan = NULL;
1282
1283 ast_mutex_lock(&hangup->lock);
1284 hangup->hungup = 1;
1285 ast_cond_signal(&hangup->cond);
1286 ast_mutex_unlock(&hangup->lock);
1287
1288 return 0;
1289}

References ast_autoservice_stop(), ast_cond_signal, ast_hangup(), ast_mutex_lock, ast_mutex_unlock, hangup(), and NULL.

Referenced by destroy_conference_bridge().

◆ is_new_rec_file()

static int is_new_rec_file ( const char *  rec_file,
struct ast_str **  orig_rec_file 
)
static

Definition at line 906 of file app_confbridge.c.

907{
908 if (!ast_strlen_zero(rec_file)) {
909 if (!*orig_rec_file) {
911 }
912
913 if (*orig_rec_file
914 && strcmp(ast_str_buffer(*orig_rec_file), rec_file)) {
915 ast_str_set(orig_rec_file, 0, "%s", rec_file);
916 return 1;
917 }
918 }
919 return 0;
920}
#define RECORD_FILENAME_INITIAL_SPACE
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113

References ast_str_buffer(), ast_str_create, ast_str_set(), ast_strlen_zero(), and RECORD_FILENAME_INITIAL_SPACE.

Referenced by conf_start_record().

◆ join_callback()

static int join_callback ( struct ast_bridge_channel bridge_channel,
void *  ignore 
)
static

Definition at line 2654 of file app_confbridge.c.

2655{
2656 async_play_sound_ready(bridge_channel->chan);
2657 return 0;
2658}

References async_play_sound_ready(), and ast_bridge_channel::chan.

Referenced by confbridge_exec().

◆ join_conference_bridge()

static struct confbridge_conference * join_conference_bridge ( const char *  conference_name,
struct confbridge_user user 
)
static

Join a conference bridge.

Parameters
conference_nameThe conference name
userConference bridge user structure
Returns
A pointer to the conference bridge struct, or NULL if the conference room wasn't found.

Definition at line 1813 of file app_confbridge.c.

1814{
1815 struct confbridge_conference *conference;
1816 struct post_join_action *action;
1817 int max_members_reached = 0;
1818
1819 /* We explicitly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same time */
1821
1822 ast_debug(1, "Trying to find conference bridge '%s'\n", conference_name);
1823
1824 /* Attempt to find an existing conference bridge */
1825 conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
1826 if (conference && conference->b_profile.max_members) {
1827 max_members_reached = conference->b_profile.max_members > conference->activeusers ? 0 : 1;
1828 }
1829
1830 /* When finding a conference bridge that already exists make sure that it is not locked, and if so that we are not an admin */
1831 if (conference && (max_members_reached || conference->locked) && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
1833 ast_debug(1, "Conference '%s' is locked and caller is not an admin\n", conference_name);
1836 "");
1837 ao2_ref(conference, -1);
1838 return NULL;
1839 }
1840
1841 /* If no conference bridge was found see if we can create one */
1842 if (!conference) {
1843 /* Try to allocate memory for a new conference bridge, if we fail... this won't end well. */
1844 if (!(conference = ao2_alloc(sizeof(*conference), destroy_conference_bridge))) {
1846 ast_log(LOG_ERROR, "Conference '%s' could not be created.\n", conference_name);
1847 return NULL;
1848 }
1849
1850 /* Setup for the record channel */
1852 if (!conference->record_filename) {
1853 ao2_ref(conference, -1);
1855 return NULL;
1856 }
1857
1858 /* Setup conference bridge parameters */
1859 ast_copy_string(conference->name, conference_name, sizeof(conference->name));
1860 conf_bridge_profile_copy(&conference->b_profile, &user->b_profile);
1861
1862 /* Create an actual bridge that will do the audio mixing */
1865 app, conference_name, NULL);
1866 if (!conference->bridge) {
1867 ao2_ref(conference, -1);
1869 ast_log(LOG_ERROR, "Conference '%s' mixing bridge could not be created.\n", conference_name);
1870 return NULL;
1871 }
1872
1873 /* Set the internal sample rate on the bridge from the bridge profile */
1875 /* Set the maximum sample rate on the bridge from the bridge profile */
1877 /* Set the internal mixing interval on the bridge from the bridge profile */
1880
1883 } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_SFU)) {
1888 } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_REMB_BEHAVIOR_LOWEST)) {
1890 } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST)) {
1898 } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_REMB_BEHAVIOR_FORCE)) {
1901 }
1902 }
1903
1904 /* Always set the minimum interval between video updates, to avoid infinite video updates. */
1906
1908 ast_bridge_set_send_sdp_label(conference->bridge, 1);
1909 }
1910
1911 /* Link it into the conference bridges container */
1912 if (!ao2_link(conference_bridges, conference)) {
1913 ao2_ref(conference, -1);
1916 "Conference '%s' could not be added to the conferences list.\n", conference_name);
1917 return NULL;
1918 }
1919
1920 /* Set the initial state to EMPTY */
1921 conference->state = CONF_STATE_EMPTY;
1922
1923 if (alloc_playback_chan(conference)) {
1924 ao2_unlink(conference_bridges, conference);
1925 ao2_ref(conference, -1);
1927 ast_log(LOG_ERROR, "Could not allocate announcer channel for conference '%s'\n", conference_name);
1928 return NULL;
1929 }
1930
1931 if (push_announcer(conference)) {
1932 ao2_unlink(conference_bridges, conference);
1933 ao2_ref(conference, -1);
1935 ast_log(LOG_ERROR, "Could not add announcer channel for conference '%s' bridge\n", conference_name);
1936 return NULL;
1937 }
1938
1940 ao2_lock(conference);
1941 conf_start_record(conference);
1942 ao2_unlock(conference);
1943 }
1944
1945 send_conf_start_event(conference);
1946
1947 if (!ast_strlen_zero(conference->b_profile.regcontext)) {
1948 if (!ast_exists_extension(NULL, conference->b_profile.regcontext, conference->name, 1, NULL)) {
1949 ast_add_extension(conference->b_profile.regcontext, 1, conference->name, 1, NULL, NULL, "Noop", NULL, NULL, "ConfBridge");
1950 }
1951 }
1952
1953 ast_debug(1, "Created conference '%s' and linked to container.\n", conference_name);
1954 }
1955
1957
1958 /* Setup conference bridge user parameters */
1959 user->conference = conference;
1960
1961 ao2_lock(conference);
1962
1963 /* Determine if the new user should join the conference muted. */
1964 if (ast_test_flag(&user->u_profile, USER_OPT_STARTMUTED)
1965 || (!ast_test_flag(&user->u_profile, USER_OPT_ADMIN) && conference->muted)) {
1966 /* Set user level mute request. */
1967 user->muted = 1;
1968 }
1969
1970 /*
1971 * Suspend any MOH until the user actually joins the bridge of
1972 * the conference. This way any pre-join file playback does not
1973 * need to worry about MOH.
1974 */
1975 user->suspended_moh = 1;
1976
1978 /* Invalid event, nothing was done, so we don't want to process a leave. */
1979 ao2_unlock(conference);
1980 ao2_ref(conference, -1);
1981 user->conference = NULL;
1982 return NULL;
1983 }
1984
1985 if (ast_check_hangup(user->chan)) {
1986 ao2_unlock(conference);
1988 return NULL;
1989 }
1990
1991 ao2_unlock(conference);
1992
1993 /* If an announcement is to be played play it */
1994 if (!ast_strlen_zero(user->u_profile.announcement)) {
1996 user->u_profile.announcement)) {
1998 return NULL;
1999 }
2000 }
2001
2002 /* Announce number of users if need be */
2003 if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) {
2004 if (announce_user_count(conference, user, NULL)) {
2006 return NULL;
2007 }
2008 }
2009
2011 (conference->activeusers > user->u_profile.announce_user_count_all_after)) {
2012 int user_count_res;
2013
2014 /*
2015 * We have to autoservice the new user because he has not quite
2016 * joined the conference yet.
2017 */
2019 user_count_res = announce_user_count(conference, NULL, NULL);
2021 if (user_count_res) {
2023 return NULL;
2024 }
2025 }
2026
2027 /* Handle post-join actions */
2028 while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
2029 action->func(user);
2030 ast_free(action);
2031 }
2032
2033 return conference;
2034}
static int push_announcer(struct confbridge_conference *conference)
Push the announcer channel into the bridge.
static void send_conf_start_event(struct confbridge_conference *conference)
static void destroy_conference_bridge(void *obj)
Destroy a conference bridge.
static int handle_conf_user_join(struct confbridge_user *user)
Call the proper join event handler for the user for the conference bridge's current state.
static int alloc_playback_chan(struct confbridge_conference *conference)
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
void ast_bridge_set_remb_estimated_bitrate(struct ast_bridge *bridge, float estimated_bitrate)
Force the REMB report estimated bitrate to a specific max value.
Definition: bridge.c:3876
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:999
void ast_bridge_set_binaural_active(struct ast_bridge *bridge, unsigned int binaural_active)
Activates the use of binaural signals in a conference bridge.
Definition: bridge.c:3774
@ AST_BRIDGE_VIDEO_SFU_REMB_LOWEST
Definition: bridge.h:139
@ AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST_ALL
Definition: bridge.h:147
@ AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE
Definition: bridge.h:137
@ AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST
Definition: bridge.h:141
@ AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE_ALL
Definition: bridge.h:143
@ AST_BRIDGE_VIDEO_SFU_REMB_FORCE
Definition: bridge.h:149
@ AST_BRIDGE_VIDEO_SFU_REMB_LOWEST_ALL
Definition: bridge.h:145
void ast_bridge_set_sfu_video_mode(struct ast_bridge *bridge)
Set the bridge to be a selective forwarding unit.
Definition: bridge.c:3843
void ast_bridge_set_maximum_sample_rate(struct ast_bridge *bridge, unsigned int sample_rate)
Adjust the maximum mixing sample rate of a bridge used during multimix mode.
Definition: bridge.c:3788
void ast_bridge_set_video_update_discard(struct ast_bridge *bridge, unsigned int video_update_discard)
Set the amount of time to discard subsequent video updates after a video update has been sent.
Definition: bridge.c:3851
void ast_brige_set_remb_behavior(struct ast_bridge *bridge, enum ast_bridge_video_sfu_remb_behavior behavior)
Set the REMB report generation behavior on a bridge.
Definition: bridge.c:3867
@ AST_BRIDGE_CAPABILITY_MULTIMIX
Definition: bridge.h:98
void ast_bridge_set_mixing_interval(struct ast_bridge *bridge, unsigned int mixing_interval)
Adjust the internal mixing interval of a bridge used during multimix mode.
Definition: bridge.c:3767
void ast_bridge_set_send_sdp_label(struct ast_bridge *bridge, unsigned int send_sdp_label)
Controls whether to send a "label" attribute in each stream in an SDP.
Definition: bridge.c:4035
void ast_bridge_set_remb_send_interval(struct ast_bridge *bridge, unsigned int remb_send_interval)
Set the interval at which a combined REMB frame will be sent to video sources.
Definition: bridge.c:3858
void ast_bridge_set_internal_sample_rate(struct ast_bridge *bridge, unsigned int sample_rate)
Adjust the internal mixing sample rate of a bridge used during multimix mode.
Definition: bridge.c:3781
@ AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY
@ AST_BRIDGE_FLAG_MASQUERADE_ONLY
void conf_bridge_profile_copy(struct bridge_profile *dst, struct bridge_profile *src)
copies a bridge profile
struct confbridge_state * CONF_STATE_EMPTY
Conference state with no active or waiting users.
@ USER_OPT_ANNOUNCEUSERCOUNTALL
Definition: confbridge.h:66
@ USER_OPT_ANNOUNCEUSERCOUNT
Definition: confbridge.h:58
@ USER_OPT_STARTMUTED
Definition: confbridge.h:55
@ BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE
Definition: confbridge.h:86
@ BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST_ALL
Definition: confbridge.h:92
@ BRIDGE_OPT_REMB_BEHAVIOR_LOWEST
Definition: confbridge.h:87
@ BRIDGE_OPT_BINAURAL_ACTIVE
Definition: confbridge.h:84
@ BRIDGE_OPT_RECORD_CONFERENCE
Definition: confbridge.h:78
@ BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL
Definition: confbridge.h:91
@ BRIDGE_OPT_ENABLE_EVENTS
Definition: confbridge.h:89
@ BRIDGE_OPT_REMB_BEHAVIOR_FORCE
Definition: confbridge.h:93
@ BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL
Definition: confbridge.h:90
@ BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST
Definition: confbridge.h:88
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:6943
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:4190
unsigned int remb_send_interval
Definition: confbridge.h:241
unsigned int maximum_sample_rate
Definition: confbridge.h:236
unsigned int remb_estimated_bitrate
Definition: confbridge.h:242
unsigned int mix_interval
Definition: confbridge.h:237
unsigned int video_update_discard
Definition: confbridge.h:240
unsigned int internal_sample_rate
Definition: confbridge.h:235
unsigned int max_members
Definition: confbridge.h:234
struct confbridge_state * state
Definition: confbridge.h:248

References confbridge_conference::activeusers, alloc_playback_chan(), announce_user_count(), ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, app, ast_add_extension(), ast_autoservice_start(), ast_autoservice_stop(), ast_bridge_base_new(), AST_BRIDGE_CAPABILITY_MULTIMIX, AST_BRIDGE_FLAG_MASQUERADE_ONLY, AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY, ast_bridge_set_binaural_active(), ast_bridge_set_internal_sample_rate(), ast_bridge_set_maximum_sample_rate(), ast_bridge_set_mixing_interval(), ast_bridge_set_remb_estimated_bitrate(), ast_bridge_set_remb_send_interval(), ast_bridge_set_send_sdp_label(), ast_bridge_set_sfu_video_mode(), ast_bridge_set_talker_src_video_mode(), ast_bridge_set_video_update_discard(), AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE, AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE_ALL, AST_BRIDGE_VIDEO_SFU_REMB_FORCE, AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST, AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST_ALL, AST_BRIDGE_VIDEO_SFU_REMB_LOWEST, AST_BRIDGE_VIDEO_SFU_REMB_LOWEST_ALL, ast_brige_set_remb_behavior(), ast_check_hangup(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_free, AST_LIST_REMOVE_HEAD, ast_log, ast_str_create, ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, confbridge_conference::b_profile, confbridge_conference::bridge, BRIDGE_OPT_BINAURAL_ACTIVE, BRIDGE_OPT_ENABLE_EVENTS, BRIDGE_OPT_RECORD_CONFERENCE, BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE, BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL, BRIDGE_OPT_REMB_BEHAVIOR_FORCE, BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST, BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST_ALL, BRIDGE_OPT_REMB_BEHAVIOR_LOWEST, BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER, BRIDGE_OPT_VIDEO_SRC_SFU, conf_bridge_profile_copy(), conf_get_sound(), CONF_SOUND_LOCKED, conf_start_record(), CONF_STATE_EMPTY, conference_bridges, destroy_conference_bridge(), post_join_action::func, handle_conf_user_join(), bridge_profile::internal_sample_rate, leave_conference(), post_join_action::list, confbridge_conference::locked, LOG_ERROR, bridge_profile::max_members, bridge_profile::maximum_sample_rate, bridge_profile::mix_interval, confbridge_conference::muted, confbridge_conference::name, NULL, OBJ_KEY, play_prompt_to_user(), push_announcer(), confbridge_conference::record_filename, RECORD_FILENAME_INITIAL_SPACE, bridge_profile::regcontext, bridge_profile::remb_estimated_bitrate, bridge_profile::remb_send_interval, send_conf_start_event(), bridge_profile::sounds, confbridge_conference::state, USER_OPT_ADMIN, USER_OPT_ANNOUNCEUSERCOUNT, USER_OPT_ANNOUNCEUSERCOUNTALL, USER_OPT_STARTMUTED, and bridge_profile::video_update_discard.

Referenced by confbridge_exec().

◆ kick_conference_participant()

static int kick_conference_participant ( struct confbridge_conference conference,
const char *  channel 
)
static

Definition at line 3376 of file app_confbridge.c.

3378{
3379 int res = -1;
3380 int match;
3381 struct confbridge_user *user = NULL;
3382 int all = !strcasecmp("all", channel);
3383 int participants = !strcasecmp("participants", channel);
3384
3385 SCOPED_AO2LOCK(bridge_lock, conference);
3386
3388 if (user->kicked) {
3389 continue;
3390 }
3391 match = !strcasecmp(channel, ast_channel_name(user->chan));
3392 if (match || all
3393 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
3394 user->kicked = 1;
3395 pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
3397 res = 0;
3398 if (match) {
3399 return res;
3400 }
3401 }
3402 }
3404 if (user->kicked) {
3405 continue;
3406 }
3407 match = !strcasecmp(channel, ast_channel_name(user->chan));
3408 if (match || all
3409 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
3410 user->kicked = 1;
3411 pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
3413 res = 0;
3414 if (match) {
3415 return res;
3416 }
3417 }
3418 }
3419
3420 return res;
3421}

References confbridge_conference::active_list, ast_bridge_remove(), ast_channel_name(), AST_LIST_TRAVERSE, ast_test_flag, confbridge_conference::bridge, confbridge_user::conference, confbridge_user::list, match(), NULL, pbx_builtin_setvar_helper(), SCOPED_AO2LOCK, USER_OPT_ADMIN, and confbridge_conference::waiting_list.

Referenced by action_confbridgekick(), confkick_exec(), and handle_cli_confbridge_kick().

◆ leave_conference()

static void leave_conference ( struct confbridge_user user)
static

Leave a conference.

Parameters
userThe conference user

Definition at line 2041 of file app_confbridge.c.

2042{
2043 struct post_join_action *action;
2044
2045 ao2_lock(user->conference);
2047 ao2_unlock(user->conference);
2048
2049 /* Discard any post-join actions */
2050 while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
2051 ast_free(action);
2052 }
2053
2054 /* Done mucking with the conference, huzzah */
2055 ao2_ref(user->conference, -1);
2056 user->conference = NULL;
2057}
static int handle_conf_user_leave(struct confbridge_user *user)
Call the proper leave event handler for the user for the conference bridge's current state.

References ao2_lock, ao2_ref, ao2_unlock, ast_free, AST_LIST_REMOVE_HEAD, handle_conf_user_leave(), post_join_action::list, and NULL.

Referenced by confbridge_exec(), and join_conference_bridge().

◆ load_module()

static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 4667 of file app_confbridge.c.

4668{
4669 int res = 0;
4670
4671 if (conf_load_config()) {
4672 ast_log(LOG_ERROR, "Unable to load config. Not loading module.\n");
4674 }
4675
4678 unload_module();
4680 }
4681
4682 /* Create a container to hold the conference bridges */
4686 if (!conference_bridges) {
4687 unload_module();
4689 }
4690
4691 /* Setup manager stasis subscriptions */
4692 res |= manager_confbridge_init();
4693
4696
4700
4702
4712 res |= ast_manager_register_xml("ConfbridgeSetSingleVideoSrc", EVENT_FLAG_CALL, action_confbridgesetsinglevideosrc);
4713 if (res) {
4714 unload_module();
4716 }
4717
4719}
static int action_confbridgemute(struct mansession *s, const struct message *m)
static int action_confbridgeunlock(struct mansession *s, const struct message *m)
static int action_confbridgekick(struct mansession *s, const struct message *m)
static int register_channel_tech(struct ast_channel_tech *tech)
static int action_confbridgesetsinglevideosrc(struct mansession *s, const struct message *m)
static int action_confbridgeunmute(struct mansession *s, const struct message *m)
static int action_confbridgestoprecord(struct mansession *s, const struct message *m)
static struct ast_custom_function confbridge_function
#define CONFERENCE_BRIDGE_BUCKETS
static int action_confbridgelist(struct mansession *s, const struct message *m)
static const char app2[]
static int conference_bridge_cmp_cb(void *obj, void *arg, int flags)
Comparison function used for conference bridges container.
static struct ast_custom_function confbridge_info_function
static int confbridge_exec(struct ast_channel *chan, const char *data)
The ConfBridge application.
static int action_confbridgestartrecord(struct mansession *s, const struct message *m)
static int conference_bridge_hash_cb(const void *obj, const int flags)
Hashing function used for conference bridges container.
static int action_confbridgelistrooms(struct mansession *s, const struct message *m)
static int unload_module(void)
Called when module is being unloaded.
static int action_confbridgelock(struct mansession *s, const struct message *m)
static struct ast_custom_function confbridge_channels_function
static struct ast_cli_entry cli_confbridge[]
static int confkick_exec(struct ast_channel *chan, const char *data)
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#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_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
struct ast_channel_tech * conf_announce_get_tech(void)
Get ConfBridge announce channel technology struct.
struct ast_channel_tech * conf_record_get_tech(void)
Get ConfBridge record channel technology struct.
int conf_load_config(void)
load confbridge.conf file
int manager_confbridge_init(void)
register stasis message routers to handle manager events for confbridge messages
#define EVENT_FLAG_REPORTING
Definition: manager.h:84
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:192
#define EVENT_FLAG_CALL
Definition: manager.h:76
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
#define ast_custom_function_register_escalating(acf, escalation)
Register a custom function which requires escalated privileges.
Definition: pbx.h:1568
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1559
@ AST_CFE_WRITE
Definition: pbx.h:1552
#define ARRAY_LEN(a)
Definition: utils.h:666

References action_confbridgekick(), action_confbridgelist(), action_confbridgelistrooms(), action_confbridgelock(), action_confbridgemute(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_confbridgeunlock(), action_confbridgeunmute(), AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, app, app2, ARRAY_LEN, AST_CFE_WRITE, ast_cli_register_multiple, ast_custom_function_register, ast_custom_function_register_escalating, ast_log, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, cli_confbridge, conf_announce_get_tech(), conf_load_config(), conf_record_get_tech(), confbridge_channels_function, confbridge_exec(), confbridge_function, confbridge_info_function, CONFERENCE_BRIDGE_BUCKETS, conference_bridge_cmp_cb(), conference_bridge_hash_cb(), conference_bridges, confkick_exec(), EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, LOG_ERROR, manager_confbridge_init(), NULL, register_channel_tech(), and unload_module().

◆ play_file()

static int play_file ( struct ast_bridge_channel bridge_channel,
struct ast_channel channel,
const char *  filename 
)
static

Playback the given filename and monitor for any dtmf interrupts.

This function is used to playback sound files on a given channel and optionally allow dtmf interrupts to occur.

If the optional bridge_channel parameter is given then sound file playback is played on that channel and dtmf interruptions are allowed. However, if bridge_channel is not set then the channel parameter is expected to be set instead and non interruptible playback is played on that channel.

Parameters
bridge_channelBridge channel to play file on
channelOptional channel to play file on if bridge_channel not given
filenameThe file name to playback
Return values
-1failure during playback.
0on file was fully played.
1on dtmf interrupt.

Definition at line 1065 of file app_confbridge.c.

1067{
1068 struct ast_channel *chan;
1069 const char *stop_digits;
1070 int digit;
1071
1072 if (bridge_channel) {
1073 chan = bridge_channel->chan;
1074 stop_digits = AST_DIGIT_ANY;
1075 } else {
1076 chan = channel;
1077 stop_digits = AST_DIGIT_NONE;
1078 }
1079
1080 digit = ast_stream_and_wait(chan, filename, stop_digits);
1081 if (digit < 0) {
1082 ast_log(LOG_WARNING, "Failed to playback file '%s' to channel\n", filename);
1083 return -1;
1084 }
1085
1086 if (digit > 0) {
1089 return 1;
1090 }
1091
1092 return 0;
1093}
void ast_bridge_channel_feature_digit_add(struct ast_bridge_channel *bridge_channel, int digit)
Add a DTMF digit to the collected digits.
#define AST_DIGIT_NONE
Definition: file.h:47
struct ast_bridge_channel * bridge_channel

References ast_bridge_channel_feature_digit_add(), AST_DIGIT_ANY, AST_DIGIT_NONE, ast_log, ast_stopstream(), ast_stream_and_wait(), ast_channel::bridge_channel, ast_bridge_channel::chan, digit, and LOG_WARNING.

Referenced by action_kick_last(), action_toggle_binaural(), action_toggle_mute(), announce_user_count(), check_bridge_play_sound(), and execute_menu_entry().

◆ play_prompt_to_user()

static int play_prompt_to_user ( struct confbridge_user user,
const char *  filename 
)
static

Play back an audio file to a channel.

Parameters
userUser to play audio prompt to
filenamePrompt to play
Return values
0on success.
-1if the user hung up.
Note
Generally this should be called when the conference is unlocked to avoid blocking the entire conference while the sound is played. But don't unlock the conference bridge in the middle of a state transition.

Definition at line 1178 of file app_confbridge.c.

1179{
1180 return ast_stream_and_wait(user->chan, filename, "");
1181}

References ast_stream_and_wait().

Referenced by conf_handle_inactive_waitmarked(), conf_handle_only_person(), and join_conference_bridge().

◆ play_sound_file()

int play_sound_file ( struct confbridge_conference conference,
const char *  filename 
)

Play sound file into conference bridge.

Parameters
conferenceThe conference bridge to play sound file into
filenameSound file to play
Return values
0success
-1failure

Definition at line 2171 of file app_confbridge.c.

2172{
2173 return play_sound_helper(conference, filename, -1);
2174}
static int play_sound_helper(struct confbridge_conference *conference, const char *filename, int say_number)

References playback_task_data::conference, playback_task_data::filename, and play_sound_helper().

Referenced by action_toggle_mute_participants(), announce_user_count(), confbridge_exec(), and post_join_play_begin().

◆ play_sound_helper()

static int play_sound_helper ( struct confbridge_conference conference,
const char *  filename,
int  say_number 
)
static

Definition at line 2133 of file app_confbridge.c.

2134{
2135 struct playback_task_data ptd;
2136
2137 /* Do not waste resources trying to play files that do not exist */
2139 if (say_number < 0) {
2140 return 0;
2141 }
2142 } else if (!sound_file_exists(filename)) {
2143 return 0;
2144 }
2145
2148 if (!ast_strlen_zero(filename)) {
2149 ast_log(LOG_WARNING, "Unable to play file '%s' to conference %s\n",
2151 } else {
2152 ast_log(LOG_WARNING, "Unable to say number '%d' to conference %s\n",
2154 }
2156 return -1;
2157 }
2158
2159 /* Wait for the playback to complete */
2160 ast_mutex_lock(&ptd.lock);
2161 while (!ptd.playback_finished) {
2162 ast_cond_wait(&ptd.cond, &ptd.lock);
2163 }
2164 ast_mutex_unlock(&ptd.lock);
2165
2167
2168 return 0;
2169}
static void playback_task_data_init(struct playback_task_data *ptd, struct confbridge_conference *conference, const char *filename, int say_number)
static void playback_task_data_destroy(struct playback_task_data *ptd)
static int playback_task(void *data)
Play an announcement into a confbridge.
struct confbridge_conference * conference
const char * filename

References ast_cond_wait, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), ast_taskprocessor_push(), playback_task_data::cond, playback_task_data::conference, playback_task_data::filename, playback_task_data::lock, LOG_WARNING, confbridge_conference::name, playback_task_data::playback_finished, confbridge_conference::playback_queue, playback_task(), playback_task_data_destroy(), playback_task_data_init(), playback_task_data::say_number, and sound_file_exists().

Referenced by play_sound_file(), and play_sound_number().

◆ play_sound_number()

static int play_sound_number ( struct confbridge_conference conference,
int  say_number 
)
static

Play number into the conference bridge.

Parameters
conferenceThe conference bridge to say the number into
say_numbernumber to say
Return values
0success
-1failure

Definition at line 2453 of file app_confbridge.c.

2454{
2455 return play_sound_helper(conference, NULL, say_number);
2456}

References NULL, and play_sound_helper().

Referenced by announce_user_count().

◆ playback_common()

static void playback_common ( struct confbridge_conference conference,
const char *  filename,
int  say_number 
)
static

Definition at line 2059 of file app_confbridge.c.

2060{
2061 /* Don't try to play if the playback channel has been hung up */
2062 if (!conference->playback_chan) {
2063 return;
2064 }
2065
2067
2068 /* The channel is all under our control, in goes the prompt */
2069 if (!ast_strlen_zero(filename)) {
2070 ast_stream_and_wait(conference->playback_chan, filename, "");
2071 } else if (say_number >= 0) {
2072 ast_say_number(conference->playback_chan, say_number, "",
2074 }
2075
2077}

References ast_autoservice_start(), ast_autoservice_stop(), ast_channel_language(), ast_say_number(), ast_stream_and_wait(), ast_strlen_zero(), NULL, and confbridge_conference::playback_chan.

Referenced by async_playback_task(), and playback_task().

◆ playback_task()

static int playback_task ( void *  data)
static

Play an announcement into a confbridge.

This runs in the playback queue taskprocessor. This ensures that all playbacks are handled in sequence and do not play over top one another.

This task runs synchronously so there is no need for performing any sort of cleanup on the input parameter.

Parameters
dataA playback_task_data
Returns
0

Definition at line 2101 of file app_confbridge.c.

2102{
2103 struct playback_task_data *ptd = data;
2104
2106
2107 ast_mutex_lock(&ptd->lock);
2108 ptd->playback_finished = 1;
2109 ast_cond_signal(&ptd->cond);
2110 ast_mutex_unlock(&ptd->lock);
2111
2112 return 0;
2113}

References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, playback_task_data::cond, playback_task_data::conference, playback_task_data::filename, playback_task_data::lock, playback_common(), playback_task_data::playback_finished, and playback_task_data::say_number.

Referenced by play_sound_helper().

◆ playback_task_data_destroy()

static void playback_task_data_destroy ( struct playback_task_data ptd)
static

Definition at line 2127 of file app_confbridge.c.

2128{
2129 ast_mutex_destroy(&ptd->lock);
2130 ast_cond_destroy(&ptd->cond);
2131}

References ast_cond_destroy, ast_mutex_destroy, playback_task_data::cond, and playback_task_data::lock.

Referenced by play_sound_helper().

◆ playback_task_data_init()

static void playback_task_data_init ( struct playback_task_data ptd,
struct confbridge_conference conference,
const char *  filename,
int  say_number 
)
static

Definition at line 2115 of file app_confbridge.c.

2117{
2118 ast_mutex_init(&ptd->lock);
2119 ast_cond_init(&ptd->cond, NULL);
2120
2121 ptd->filename = filename;
2122 ptd->say_number = say_number;
2123 ptd->conference = conference;
2124 ptd->playback_finished = 0;
2125}

References ast_cond_init, ast_mutex_init, playback_task_data::cond, playback_task_data::conference, playback_task_data::filename, playback_task_data::lock, NULL, playback_task_data::playback_finished, and playback_task_data::say_number.

Referenced by play_sound_helper().

◆ push_announcer()

static int push_announcer ( struct confbridge_conference conference)
static

Push the announcer channel into the bridge.

Parameters
conferenceConference bridge to push the announcer to
Return values
0Success
-1Failed to push the channel to the bridge

Definition at line 1673 of file app_confbridge.c.

1674{
1675 if (conf_announce_channel_push(conference->playback_chan)) {
1676 ast_hangup(conference->playback_chan);
1677 conference->playback_chan = NULL;
1678 return -1;
1679 }
1680
1682 return 0;
1683}
int conf_announce_channel_push(struct ast_channel *ast)
Push the announcer channel into the conference.

References ast_autoservice_start(), ast_hangup(), conf_announce_channel_push(), NULL, and confbridge_conference::playback_chan.

Referenced by join_conference_bridge().

◆ register_channel_tech()

static int register_channel_tech ( struct ast_channel_tech tech)
static

Definition at line 4604 of file app_confbridge.c.

4605{
4607 if (!tech->capabilities) {
4608 return -1;
4609 }
4611 if (ast_channel_register(tech)) {
4612 ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n",
4613 tech->type, tech->description);
4614 return -1;
4615 }
4616 return 0;
4617}
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:538
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Add all codecs Asterisk knows about for a specific type to the capabilities structure.
Definition: format_cap.c:216
struct ast_format_cap * capabilities
Definition: channel.h:652
const char *const type
Definition: channel.h:649
const char *const description
Definition: channel.h:650

References ast_channel_register(), ast_format_cap_alloc, ast_format_cap_append_by_type(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_log, AST_MEDIA_TYPE_UNKNOWN, ast_channel_tech::capabilities, ast_channel_tech::description, LOG_ERROR, and ast_channel_tech::type.

Referenced by load_module().

◆ reload()

static int reload ( void  )
static

Definition at line 4721 of file app_confbridge.c.

4722{
4723 return conf_reload_config();
4724}
int conf_reload_config(void)
reload confbridge.conf file

References conf_reload_config().

◆ send_conf_end_event()

static void send_conf_end_event ( struct confbridge_conference conference)
static

Definition at line 799 of file app_confbridge.c.

800{
801 send_conf_stasis(conference, NULL, confbridge_end_type(), NULL, 0);
802}
struct stasis_message_type * confbridge_end_type(void)
get the confbridge end stasis message type

References confbridge_end_type(), NULL, and send_conf_stasis().

Referenced by conf_ended().

◆ send_conf_start_event()

static void send_conf_start_event ( struct confbridge_conference conference)
static

Definition at line 794 of file app_confbridge.c.

795{
797}
struct stasis_message_type * confbridge_start_type(void)
get the confbridge start stasis message type

References confbridge_start_type(), NULL, and send_conf_stasis().

Referenced by join_conference_bridge().

◆ send_conf_stasis()

static void send_conf_stasis ( struct confbridge_conference conference,
struct ast_channel chan,
struct stasis_message_type type,
struct ast_json extras,
int  channel_topic 
)
static

Definition at line 720 of file app_confbridge.c.

722{
723 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
724 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
725
726 json_object = ast_json_pack("{s: s}",
727 "conference", conference->name);
728 if (!json_object) {
729 return;
730 }
731
732 if (extras) {
733 ast_json_object_update(json_object, extras);
734 }
735
736 ast_bridge_lock(conference->bridge);
738 conference->bridge,
739 chan,
740 json_object);
741 ast_bridge_unlock(conference->bridge);
742 if (!msg) {
743 return;
744 }
745
747 conf_send_event_to_participants(conference, chan, msg);
748 }
749
750 if (channel_topic) {
752 } else {
753 stasis_publish(ast_bridge_topic(conference->bridge), msg);
754 }
755}
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
void conf_send_event_to_participants(struct confbridge_conference *conference, struct ast_channel *chan, struct stasis_message *msg)
Send events to bridge participants.
int ast_json_object_update(struct ast_json *object, struct ast_json *other)
Update object with all of the fields of other.
Definition: json.c:426
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1538
struct stasis_message * ast_bridge_blob_create(struct stasis_message_type *type, struct ast_bridge *bridge, struct ast_channel *chan, struct ast_json *blob)
Creates a ast_bridge_blob message.
struct stasis_topic * ast_bridge_topic(struct ast_bridge *bridge)
A topic which publishes the events for a particular bridge.

References ao2_cleanup, ast_bridge_blob_create(), ast_bridge_lock, ast_bridge_topic(), ast_bridge_unlock, ast_channel_topic(), ast_json_object_update(), ast_json_pack(), ast_json_unref(), ast_test_flag, confbridge_conference::b_profile, confbridge_conference::bridge, BRIDGE_OPT_ENABLE_EVENTS, conf_send_event_to_participants(), confbridge_conference::name, NULL, RAII_VAR, stasis_publish(), and type.

Referenced by conf_handle_talker_cb(), send_conf_end_event(), send_conf_start_event(), send_join_event(), send_leave_event(), send_mute_event(), send_start_record_event(), send_stop_record_event(), and send_unmute_event().

◆ send_conf_stasis_snapshots()

static void send_conf_stasis_snapshots ( struct confbridge_conference conference,
struct ast_channel_snapshot chan_snapshot,
struct stasis_message_type type,
struct ast_json extras 
)
static

Definition at line 757 of file app_confbridge.c.

760{
761 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
762 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
763 RAII_VAR(struct ast_bridge_snapshot *, bridge_snapshot, NULL, ao2_cleanup);
764
765 json_object = ast_json_pack("{s: s}",
766 "conference", conference->name);
767 if (!json_object) {
768 return;
769 }
770
771 if (extras) {
772 ast_json_object_update(json_object, extras);
773 }
774
775 ast_bridge_lock(conference->bridge);
776 bridge_snapshot = ast_bridge_snapshot_create(conference->bridge);
777 ast_bridge_unlock(conference->bridge);
778 if (!bridge_snapshot) {
779 return;
780 }
781
783 bridge_snapshot,
784 chan_snapshot,
785 json_object);
786 if (!msg) {
787 return;
788 }
789
790 stasis_publish(ast_bridge_topic(conference->bridge), msg);
791}
struct ast_bridge_snapshot * ast_bridge_snapshot_create(struct ast_bridge *bridge)
Generate a snapshot of the bridge state. This is an ao2 object, so ao2_cleanup() to deallocate.
struct stasis_message * ast_bridge_blob_create_from_snapshots(struct stasis_message_type *type, struct ast_bridge_snapshot *bridge_snapshot, struct ast_channel_snapshot *chan_snapshot, struct ast_json *blob)
Creates a ast_bridge_blob message from snapshots.
Structure that contains a snapshot of information about a bridge.
Definition: bridge.h:318

References ao2_cleanup, ast_bridge_blob_create_from_snapshots(), ast_bridge_lock, ast_bridge_snapshot_create(), ast_bridge_topic(), ast_bridge_unlock, ast_json_object_update(), ast_json_pack(), ast_json_unref(), confbridge_conference::bridge, confbridge_conference::name, NULL, RAII_VAR, stasis_publish(), and type.

Referenced by confbridge_handle_atxfer().

◆ send_event_hook_callback()

static int send_event_hook_callback ( struct ast_bridge_channel bridge_channel,
void *  data 
)
static

Definition at line 2666 of file app_confbridge.c.

2667{
2668 struct confbridge_hook_data *hook_data = data;
2669
2670 if (hook_data->hook_type == AST_BRIDGE_HOOK_TYPE_JOIN) {
2671 send_join_event(hook_data->user, hook_data->conference);
2672 } else {
2673 send_leave_event(hook_data->user, hook_data->conference);
2674 }
2675
2676 return 0;
2677}
static void send_join_event(struct confbridge_user *user, struct confbridge_conference *conference)
static void send_leave_event(struct confbridge_user *user, struct confbridge_conference *conference)

References AST_BRIDGE_HOOK_TYPE_JOIN, confbridge_hook_data::conference, confbridge_hook_data::hook_type, send_join_event(), send_leave_event(), and confbridge_hook_data::user.

Referenced by confbridge_exec().

◆ send_join_event()

static void send_join_event ( struct confbridge_user user,
struct confbridge_conference conference 
)
static

Definition at line 804 of file app_confbridge.c.

805{
806 struct ast_json *json_object;
807
808 json_object = ast_json_pack("{s: b, s: b}",
809 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN),
810 "muted", user->muted);
811 if (!json_object) {
812 return;
813 }
814 send_conf_stasis(conference, user->chan, confbridge_join_type(), json_object, 0);
815 ast_json_unref(json_object);
816}

References ast_json_pack(), ast_json_unref(), ast_test_flag, confbridge_join_type(), send_conf_stasis(), and USER_OPT_ADMIN.

Referenced by send_event_hook_callback().

◆ send_leave_event()

static void send_leave_event ( struct confbridge_user user,
struct confbridge_conference conference 
)
static

Definition at line 818 of file app_confbridge.c.

819{
820 struct ast_json *json_object;
821
822 json_object = ast_json_pack("{s: b}",
823 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
824 );
825 if (!json_object) {
826 return;
827 }
828 send_conf_stasis(conference, user->chan, confbridge_leave_type(), json_object, 0);
829 ast_json_unref(json_object);
830}

References ast_json_pack(), ast_json_unref(), ast_test_flag, confbridge_leave_type(), send_conf_stasis(), and USER_OPT_ADMIN.

Referenced by send_event_hook_callback().

◆ send_mute_event()

static void send_mute_event ( struct confbridge_user user,
struct confbridge_conference conference 
)
static

Definition at line 842 of file app_confbridge.c.

843{
844 struct ast_json *json_object;
845
846 json_object = ast_json_pack("{s: b}",
847 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
848 );
849 if (!json_object) {
850 return;
851 }
852 send_conf_stasis(conference, user->chan, confbridge_mute_type(), json_object, 1);
853 ast_json_unref(json_object);
854}
struct stasis_message_type * confbridge_mute_type(void)
get the confbridge mute stasis message type

References ast_json_pack(), ast_json_unref(), ast_test_flag, confbridge_mute_type(), send_conf_stasis(), and USER_OPT_ADMIN.

Referenced by generic_mute_unmute_user().

◆ send_start_record_event()

static void send_start_record_event ( struct confbridge_conference conference)
static

Definition at line 832 of file app_confbridge.c.

833{
835}
struct stasis_message_type * confbridge_start_record_type(void)
get the confbridge start_record stasis message type

References confbridge_start_record_type(), NULL, and send_conf_stasis().

Referenced by conf_start_record().

◆ send_stop_record_event()

static void send_stop_record_event ( struct confbridge_conference conference)
static

Definition at line 837 of file app_confbridge.c.

838{
840}
struct stasis_message_type * confbridge_stop_record_type(void)
get the confbridge stop_record stasis message type

References confbridge_stop_record_type(), NULL, and send_conf_stasis().

Referenced by conf_stop_record().

◆ send_unmute_event()

static void send_unmute_event ( struct confbridge_user user,
struct confbridge_conference conference 
)
static

Definition at line 856 of file app_confbridge.c.

857{
858 struct ast_json *json_object;
859
860 json_object = ast_json_pack("{s: b}",
861 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
862 );
863 if (!json_object) {
864 return;
865 }
866 send_conf_stasis(conference, user->chan, confbridge_unmute_type(), json_object, 1);
867 ast_json_unref(json_object);
868}
struct stasis_message_type * confbridge_unmute_type(void)
get the confbridge unmute stasis message type

References ast_json_pack(), ast_json_unref(), ast_test_flag, confbridge_unmute_type(), send_conf_stasis(), and USER_OPT_ADMIN.

Referenced by generic_mute_unmute_user().

◆ set_rec_filename()

static void set_rec_filename ( struct confbridge_conference conference,
struct ast_str **  filename,
int  is_new 
)
static

Definition at line 870 of file app_confbridge.c.

871{
872 char *rec_file = conference->b_profile.rec_file;
873 char *ext;
874 time_t now;
875
876 if (ast_str_strlen(*filename)
878 && !is_new) {
879 return;
880 }
881
882 time(&now);
883
884 ast_str_reset(*filename);
885 if (ast_strlen_zero(rec_file)) {
886 ast_str_set(filename, 0, "confbridge-%s-%u.wav", conference->name,
887 (unsigned int) now);
888 } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_TIMESTAMP)) {
889 /* insert time before file extension */
890 ext = strrchr(rec_file, '.');
891 if (ext) {
892 ast_str_set_substr(filename, 0, rec_file, ext - rec_file);
893 ast_str_append(filename, 0, "-%u%s", (unsigned int) now, ext);
894 } else {
895 ast_str_set(filename, 0, "%s-%u", rec_file, (unsigned int) now);
896 }
897 } else {
898 ast_str_set(filename, 0, "%s", rec_file);
899 }
900 ast_str_append(filename, 0, ",%s%s,%s",
901 ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_APPEND) ? "a" : "",
902 conference->b_profile.rec_options,
903 conference->b_profile.rec_command);
904}
@ BRIDGE_OPT_RECORD_FILE_TIMESTAMP
Definition: confbridge.h:83
@ BRIDGE_OPT_RECORD_FILE_APPEND
Definition: confbridge.h:82
const char * ext
Definition: http.c:150
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
char * ast_str_set_substr(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Set a dynamic string to a non-NULL terminated substring.
Definition: strings.h:1055
char rec_options[128]
Definition: confbridge.h:231
char rec_command[128]
Definition: confbridge.h:232

References ast_str_append(), ast_str_reset(), ast_str_set(), ast_str_set_substr(), ast_str_strlen(), ast_strlen_zero(), ast_test_flag, confbridge_conference::b_profile, BRIDGE_OPT_RECORD_FILE_APPEND, BRIDGE_OPT_RECORD_FILE_TIMESTAMP, ext, confbridge_conference::name, bridge_profile::rec_command, bridge_profile::rec_file, and bridge_profile::rec_options.

Referenced by conf_start_record().

◆ setup_async_playback_datastore()

static int setup_async_playback_datastore ( struct ast_channel initiator)
static

Prepare the async playback datastore.

This is done prior to queuing an async announcement. If the datastore has not yet been created, it is allocated and initialized. If it already exists, we set it to be in "waiting" mode.

Parameters
initiatorThe channel that is queuing the async playback
Return values
0Success
-1Failure :(

Definition at line 2248 of file app_confbridge.c.

2249{
2250 struct ast_datastore *async_datastore;
2251
2252 async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
2253 if (async_datastore) {
2254 struct async_datastore_data *add;
2255
2256 add = async_datastore->data;
2257 add->wait = 1;
2258
2259 return 0;
2260 }
2261
2262 async_datastore = ast_datastore_alloc(&async_datastore_info, NULL);
2263 if (!async_datastore) {
2264 return -1;
2265 }
2266
2267 async_datastore->data = async_datastore_data_alloc();
2268 if (!async_datastore->data) {
2269 ast_datastore_free(async_datastore);
2270 return -1;
2271 }
2272
2273 ast_channel_datastore_add(initiator, async_datastore);
2274 return 0;
2275}
static struct async_datastore_data * async_datastore_data_alloc(void)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2354
#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

References ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), async_datastore_data_alloc(), async_datastore_info, ast_datastore::data, NULL, and async_datastore_data::wait.

Referenced by async_playback_task_data_alloc().

◆ sound_file_exists()

static int sound_file_exists ( const char *  filename)
static

Definition at line 1103 of file app_confbridge.c.

1104{
1105 if (ast_fileexists(filename, NULL, NULL)) {
1106 return -1;
1107 }
1108 ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
1109 return 0;
1110}
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1137

References ast_fileexists(), ast_log, LOG_WARNING, and NULL.

Referenced by announce_user_count(), async_delete_name_rec(), async_play_sound_helper(), and play_sound_helper().

◆ unload_module()

static int unload_module ( void  )
static

Called when module is being unloaded.

Definition at line 4620 of file app_confbridge.c.

4621{
4624
4628
4630
4631 ast_manager_unregister("ConfbridgeList");
4632 ast_manager_unregister("ConfbridgeListRooms");
4633 ast_manager_unregister("ConfbridgeMute");
4634 ast_manager_unregister("ConfbridgeUnmute");
4635 ast_manager_unregister("ConfbridgeKick");
4636 ast_manager_unregister("ConfbridgeUnlock");
4637 ast_manager_unregister("ConfbridgeLock");
4638 ast_manager_unregister("ConfbridgeStartRecord");
4639 ast_manager_unregister("ConfbridgeStopRecord");
4640 ast_manager_unregister("ConfbridgeSetSingleVideoSrc");
4641
4642 /* Unsubscribe from stasis confbridge message type and clean it up. */
4644
4645 /* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */
4648
4650
4653
4654 return 0;
4655}
static void unregister_channel_tech(struct ast_channel_tech *tech)
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void conf_destroy_config(void)
destroy the information loaded from the confbridge.conf file
void manager_confbridge_shutdown(void)
unregister stasis message routers to handle manager events for confbridge messages
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7697
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.

References ao2_cleanup, app, app2, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_manager_unregister(), ast_unregister_application(), cli_confbridge, conf_announce_get_tech(), conf_destroy_config(), conf_record_get_tech(), confbridge_channels_function, confbridge_function, confbridge_info_function, conference_bridges, manager_confbridge_shutdown(), NULL, and unregister_channel_tech().

Referenced by load_module().

◆ unregister_channel_tech()

static void unregister_channel_tech ( struct ast_channel_tech tech)
static

Definition at line 4588 of file app_confbridge.c.

4589{
4592}
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:569

References ao2_cleanup, ast_channel_unregister(), and ast_channel_tech::capabilities.

Referenced by unload_module().

◆ user_timeout()

static int user_timeout ( struct ast_bridge_channel bridge_channel,
void *  ignore 
)
static

Definition at line 2528 of file app_confbridge.c.

2529{
2531 pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "TIMEOUT");
2532 return -1;
2533}
@ BRIDGE_CHANNEL_STATE_END
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).

References ast_bridge_channel_leave_bridge(), BRIDGE_CHANNEL_STATE_END, ast_bridge_channel::chan, and pbx_builtin_setvar_helper().

Referenced by confbridge_exec().

◆ wait_for_initiator()

static void wait_for_initiator ( struct ast_channel initiator)
static

Wait for the initiator of an async playback to be ready.

See the description on the async_datastore_info structure for more information about what this is about.

Parameters
initiatorThe channel that queued the async announcement

Definition at line 2337 of file app_confbridge.c.

2338{
2339 struct ast_datastore *async_datastore;
2340 struct async_datastore_data *add;
2341
2342 ast_channel_lock(initiator);
2343 async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
2344 ast_channel_unlock(initiator);
2345
2346 if (!async_datastore) {
2347 return;
2348 }
2349
2350 add = async_datastore->data;
2351
2352 ast_mutex_lock(&add->lock);
2353 while (add->wait) {
2354 ast_cond_wait(&add->cond, &add->lock);
2355 }
2356 ast_mutex_unlock(&add->lock);
2357}

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_cond_wait, ast_mutex_lock, ast_mutex_unlock, async_datastore_info, async_datastore_data::cond, ast_datastore::data, async_datastore_data::lock, NULL, and async_datastore_data::wait.

Referenced by async_playback_task().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Conference Bridge Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, .optional_modules = "codec_speex,func_jitterbuffer", }
static

Definition at line 4733 of file app_confbridge.c.

◆ app

const char app[] = "ConfBridge"
static
Playing back a file to a channel in a conference
You might notice in this application that while playing a sound file to a channel the actual conference bridge lock is not held. This is done so that other channels are not blocked from interacting with the conference bridge. Unfortunately because of this it is possible for things to change after the sound file is done being played. Data must therefore be checked after reacquiring the conference bridge lock if it is important.

Definition at line 594 of file app_confbridge.c.

Referenced by confbridge_exec(), join_conference_bridge(), load_module(), and unload_module().

◆ app2

const char app2[] = "ConfKick"
static

Definition at line 595 of file app_confbridge.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4733 of file app_confbridge.c.

◆ async_datastore_info

struct ast_datastore_info async_datastore_info
static
Initial value:
= {
.type = "Confbridge async playback",
}
static void async_datastore_data_destroy(void *data)

Datastore used for timing of async announcement playback.

Announcements that are played to the entire conference can be played asynchronously (i.e. The channel that queues the playback does not wait for the playback to complete before continuing)

The thing about async announcements is that the channel that queues the announcement is either not in the bridge or is in some other way "occupied" at the time the announcement is queued. Because of that, the initiator of the announcement may enter after the announcement has already started, resulting in the sound being "clipped".

This datastore makes it so that the channel that queues the async announcement can say "I'm ready now". This way the announcement does not start until the initiator of the announcement is ready to hear the sound.

Definition at line 2216 of file app_confbridge.c.

Referenced by async_play_sound_ready(), setup_async_playback_datastore(), and wait_for_initiator().

◆ cli_confbridge

struct ast_cli_entry cli_confbridge[]
static

Definition at line 3943 of file app_confbridge.c.

Referenced by load_module(), and unload_module().

◆ confbridge_channels_function

struct ast_custom_function confbridge_channels_function
static
Initial value:
= {
.name = "CONFBRIDGE_CHANNELS",
}
static int func_confbridge_channels(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)

Definition at line 4043 of file app_confbridge.c.

Referenced by load_module(), and unload_module().

◆ confbridge_function

struct ast_custom_function confbridge_function
static
Initial value:
= {
.name = "CONFBRIDGE",
}
int func_confbridge_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value)

Definition at line 3953 of file app_confbridge.c.

Referenced by load_module(), and unload_module().

◆ confbridge_info_function

struct ast_custom_function confbridge_info_function
static
Initial value:
= {
.name = "CONFBRIDGE_INFO",
}
static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)

Definition at line 3959 of file app_confbridge.c.

Referenced by load_module(), and unload_module().

◆ conference_bridges

struct ao2_container* conference_bridges