app_confbridge / bridge_softmix: Add ability to configure REMB interval.
[asterisk/asterisk.git] / apps / app_confbridge.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007-2008, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  * David Vossel <dvossel@digium.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20 /*! \file
21  *
22  * \brief Conference Bridge application
23  *
24  * \author\verbatim Joshua Colp <jcolp@digium.com> \endverbatim
25  * \author\verbatim David Vossel <dvossel@digium.com> \endverbatim
26  *
27  * This is a conference bridge application utilizing the bridging core.
28  * \ingroup applications
29  */
30
31 /*! \li \ref app_confbridge.c uses the configuration file \ref confbridge.conf
32  * \addtogroup configuration_file Configuration Files
33  */
34
35 /*!
36  * \page confbridge.conf confbridge.conf
37  * \verbinclude confbridge.conf.sample
38  */
39
40 /*** MODULEINFO
41         <support_level>core</support_level>
42  ***/
43
44 #include "asterisk.h"
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <string.h>
50 #include <signal.h>
51
52 #include "asterisk/cli.h"
53 #include "asterisk/file.h"
54 #include "asterisk/channel.h"
55 #include "asterisk/pbx.h"
56 #include "asterisk/pbx.h"
57 #include "asterisk/module.h"
58 #include "asterisk/lock.h"
59 #include "asterisk/bridge.h"
60 #include "asterisk/musiconhold.h"
61 #include "asterisk/say.h"
62 #include "asterisk/audiohook.h"
63 #include "asterisk/astobj2.h"
64 #include "confbridge/include/confbridge.h"
65 #include "asterisk/paths.h"
66 #include "asterisk/manager.h"
67 #include "asterisk/test.h"
68 #include "asterisk/stasis.h"
69 #include "asterisk/stasis_bridges.h"
70 #include "asterisk/stasis_channels.h"
71 #include "asterisk/json.h"
72 #include "asterisk/format_cache.h"
73 #include "asterisk/taskprocessor.h"
74
75 /*** DOCUMENTATION
76         <application name="ConfBridge" language="en_US">
77                 <synopsis>
78                         Conference bridge application.
79                 </synopsis>
80                 <syntax>
81                         <parameter name="conference" required="true">
82                                 <para>Name of the conference bridge.  You are not limited to just
83                                 numbers.</para>
84                         </parameter>
85                         <parameter name="bridge_profile">
86                                 <para>The bridge profile name from confbridge.conf.  When left blank,
87                                 a dynamically built bridge profile created by the CONFBRIDGE dialplan
88                                 function is searched for on the channel and used.  If no dynamic
89                                 profile is present, the 'default_bridge' profile found in
90                                 confbridge.conf is used. </para>
91                                 <para>It is important to note that while user profiles may be unique
92                                 for each participant, mixing bridge profiles on a single conference
93                                 is _NOT_ recommended and will produce undefined results.</para>
94                         </parameter>
95                         <parameter name="user_profile">
96                                 <para>The user profile name from confbridge.conf.  When left blank,
97                                 a dynamically built user profile created by the CONFBRIDGE dialplan
98                                 function is searched for on the channel and used.  If no dynamic
99                                 profile is present, the 'default_user' profile found in
100                                 confbridge.conf is used.</para>
101                         </parameter>
102                         <parameter name="menu">
103                                 <para>The name of the DTMF menu in confbridge.conf to be applied to
104                                 this channel.  When left blank, a dynamically built menu profile
105                                 created by the CONFBRIDGE dialplan function is searched for on
106                                 the channel and used. If no dynamic profile is present, the
107                                 'default_menu' profile found in confbridge.conf is used.</para>
108                         </parameter>
109                 </syntax>
110                 <description>
111                         <para>Enters the user into a specified conference bridge.  The user can
112                         exit the conference by hangup or DTMF menu option.</para>
113                         <para>This application sets the following channel variable upon completion:</para>
114                         <variablelist>
115                                 <variable name="CONFBRIDGE_RESULT">
116                                         <value name="FAILED">The channel encountered an error and could not enter the conference.</value>
117                                         <value name="HANGUP">The channel exited the conference by hanging up.</value>
118                                         <value name="KICKED">The channel was kicked from the conference.</value>
119                                         <value name="ENDMARKED">The channel left the conference as a result of the last marked user leaving.</value>
120                                         <value name="DTMF">The channel pressed a DTMF sequence to exit the conference.</value>
121                                         <value name="TIMEOUT">The channel reached its configured timeout.</value>
122                                 </variable>
123                         </variablelist>
124                 </description>
125                 <see-also>
126                         <ref type="application">ConfBridge</ref>
127                         <ref type="function">CONFBRIDGE</ref>
128                         <ref type="function">CONFBRIDGE_INFO</ref>
129                 </see-also>
130         </application>
131         <function name="CONFBRIDGE" language="en_US">
132                 <synopsis>
133                         Set a custom dynamic bridge, user, or menu profile on a channel for the
134                         ConfBridge application using the same options available in confbridge.conf.
135                 </synopsis>
136                 <syntax>
137                         <parameter name="type" required="true">
138                                 <para>To what type of conference profile the option applies.</para>
139                                 <enumlist>
140                                         <enum name="bridge"></enum>
141                                         <enum name="menu"></enum>
142                                         <enum name="user"></enum>
143                                 </enumlist>
144                         </parameter>
145                         <parameter name="option" required="true">
146                                 <para>Option refers to a <filename>confbridge.conf</filename> option
147                                 that is being set dynamically on this channel, or <literal>clear</literal>
148                                 to remove already applied profile options from the channel.</para>
149                         </parameter>
150                 </syntax>
151                 <description>
152                         <para>A custom profile uses the default profile type settings defined in
153                         <filename>confbridge.conf</filename> as defaults if the profile template
154                         is not explicitly specified first.</para>
155                         <para>For <literal>bridge</literal> profiles the default template is <literal>default_bridge</literal>.</para>
156                         <para>For <literal>menu</literal> profiles the default template is <literal>default_menu</literal>.</para>
157                         <para>For <literal>user</literal> profiles the default template is <literal>default_user</literal>.</para>
158                         <para>---- Example 1 ----</para>
159                         <para>In this example the custom user profile set on the channel will
160                         automatically be used by the ConfBridge application.</para>
161                         <para>exten => 1,1,Answer()</para>
162                         <para>; In this example the effect of the following line is</para>
163                         <para>; implied:</para>
164                         <para>; same => n,Set(CONFBRIDGE(user,template)=default_user)</para>
165                         <para>same => n,Set(CONFBRIDGE(user,announce_join_leave)=yes)</para>
166                         <para>same => n,Set(CONFBRIDGE(user,startmuted)=yes)</para>
167                         <para>same => n,ConfBridge(1) </para>
168                         <para>---- Example 2 ----</para>
169                         <para>This example shows how to use a predefined user profile in
170                         <filename>confbridge.conf</filename> as a template for a dynamic profile.
171                         Here we make an admin/marked user out of the <literal>my_user</literal>
172                         profile that you define in <filename>confbridge.conf</filename>.</para>
173                         <para>exten => 1,1,Answer()</para>
174                         <para>same => n,Set(CONFBRIDGE(user,template)=my_user)</para>
175                         <para>same => n,Set(CONFBRIDGE(user,admin)=yes)</para>
176                         <para>same => n,Set(CONFBRIDGE(user,marked)=yes)</para>
177                         <para>same => n,ConfBridge(1)</para>
178                 </description>
179         </function>
180         <function name="CONFBRIDGE_INFO" language="en_US">
181                 <synopsis>
182                         Get information about a ConfBridge conference.
183                 </synopsis>
184                 <syntax>
185                         <parameter name="type" required="true">
186                                 <para>What conference information is requested.</para>
187                                 <enumlist>
188                                         <enum name="admins">
189                                                 <para>Get the number of admin users in the conference.</para>
190                                         </enum>
191                                         <enum name="locked">
192                                                 <para>Determine if the conference is locked. (0 or 1)</para>
193                                         </enum>
194                                         <enum name="marked">
195                                                 <para>Get the number of marked users in the conference.</para>
196                                         </enum>
197                                         <enum name="muted">
198                                                 <para>Determine if the conference is muted. (0 or 1)</para>
199                                         </enum>
200                                         <enum name="parties">
201                                                 <para>Get the number of users in the conference.</para>
202                                         </enum>
203                                 </enumlist>
204                         </parameter>
205                         <parameter name="conf" required="true">
206                                 <para>The name of the conference being referenced.</para>
207                         </parameter>
208                 </syntax>
209                 <description>
210                         <para>This function returns a non-negative integer for valid conference
211                         names and an empty string for invalid conference names.</para>
212                 </description>
213         </function>
214         <manager name="ConfbridgeList" language="en_US">
215                 <synopsis>
216                         List participants in a conference.
217                 </synopsis>
218                 <syntax>
219                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
220                         <parameter name="Conference" required="true">
221                                 <para>Conference number.</para>
222                         </parameter>
223                 </syntax>
224                 <description>
225                         <para>Lists all users in a particular ConfBridge conference.
226                         ConfbridgeList will follow as separate events, followed by a final event called
227                         ConfbridgeListComplete.</para>
228                 </description>
229         </manager>
230         <managerEvent language="en_US" name="ConfbridgeList">
231                 <managerEventInstance class="EVENT_FLAG_REPORTING">
232                         <synopsis>Raised as part of the ConfbridgeList action response list.</synopsis>
233                         <syntax>
234                                 <parameter name="Conference">
235                                         <para>The name of the Confbridge conference.</para>
236                                 </parameter>
237                                 <parameter name="Admin">
238                                         <para>Identifies this user as an admin user.</para>
239                                         <enumlist>
240                                                 <enum name="Yes"/>
241                                                 <enum name="No"/>
242                                         </enumlist>
243                                 </parameter>
244                                 <parameter name="MarkedUser">
245                                         <para>Identifies this user as a marked user.</para>
246                                         <enumlist>
247                                                 <enum name="Yes"/>
248                                                 <enum name="No"/>
249                                         </enumlist>
250                                 </parameter>
251                                 <parameter name="WaitMarked">
252                                         <para>Must this user wait for a marked user to join?</para>
253                                         <enumlist>
254                                                 <enum name="Yes"/>
255                                                 <enum name="No"/>
256                                         </enumlist>
257                                 </parameter>
258                                 <parameter name="EndMarked">
259                                         <para>Does this user get kicked after the last marked user leaves?</para>
260                                         <enumlist>
261                                                 <enum name="Yes"/>
262                                                 <enum name="No"/>
263                                         </enumlist>
264                                 </parameter>
265                                 <parameter name="Waiting">
266                                         <para>Is this user waiting for a marked user to join?</para>
267                                         <enumlist>
268                                                 <enum name="Yes"/>
269                                                 <enum name="No"/>
270                                         </enumlist>
271                                 </parameter>
272                                 <parameter name="Muted">
273                                         <para>The current mute status.</para>
274                                         <enumlist>
275                                                 <enum name="Yes"/>
276                                                 <enum name="No"/>
277                                         </enumlist>
278                                 </parameter>
279                                 <parameter name="AnsweredTime">
280                                         <para>The number of seconds the channel has been up.</para>
281                                 </parameter>
282                                 <channel_snapshot/>
283                         </syntax>
284                 </managerEventInstance>
285         </managerEvent>
286         <manager name="ConfbridgeListRooms" language="en_US">
287                 <synopsis>
288                         List active conferences.
289                 </synopsis>
290                 <syntax>
291                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
292                 </syntax>
293                 <description>
294                         <para>Lists data about all active conferences.
295                                 ConfbridgeListRooms will follow as separate events, followed by a final event called
296                                 ConfbridgeListRoomsComplete.</para>
297                 </description>
298         </manager>
299         <manager name="ConfbridgeMute" language="en_US">
300                 <synopsis>
301                         Mute a Confbridge user.
302                 </synopsis>
303                 <syntax>
304                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
305                         <parameter name="Conference" required="true" />
306                         <parameter name="Channel" required="true">
307                                 <para>If this parameter is not a complete channel name, the first channel with this prefix will be used.</para>
308                                 <para>If this parameter is "all", all channels will be muted.</para>
309                                 <para>If this parameter is "participants", all non-admin channels will be muted.</para>
310                         </parameter>
311                 </syntax>
312                 <description>
313                 </description>
314         </manager>
315         <manager name="ConfbridgeUnmute" language="en_US">
316                 <synopsis>
317                         Unmute a Confbridge user.
318                 </synopsis>
319                 <syntax>
320                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
321                         <parameter name="Conference" required="true" />
322                         <parameter name="Channel" required="true">
323                                 <para>If this parameter is not a complete channel name, the first channel with this prefix will be used.</para>
324                                 <para>If this parameter is "all", all channels will be unmuted.</para>
325                                 <para>If this parameter is "participants", all non-admin channels will be unmuted.</para>
326                         </parameter>
327                 </syntax>
328                 <description>
329                 </description>
330         </manager>
331         <manager name="ConfbridgeKick" language="en_US">
332                 <synopsis>
333                         Kick a Confbridge user.
334                 </synopsis>
335                 <syntax>
336                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
337                         <parameter name="Conference" required="true" />
338                         <parameter name="Channel" required="true" >
339                                 <para>If this parameter is "all", all channels will be kicked from the conference.</para>
340                                 <para>If this parameter is "participants", all non-admin channels will be kicked from the conference.</para>
341                         </parameter>
342                 </syntax>
343                 <description>
344                 </description>
345         </manager>
346         <manager name="ConfbridgeLock" language="en_US">
347                 <synopsis>
348                         Lock a Confbridge conference.
349                 </synopsis>
350                 <syntax>
351                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
352                         <parameter name="Conference" required="true" />
353                 </syntax>
354                 <description>
355                 </description>
356         </manager>
357         <manager name="ConfbridgeUnlock" language="en_US">
358                 <synopsis>
359                         Unlock a Confbridge conference.
360                 </synopsis>
361                 <syntax>
362                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
363                         <parameter name="Conference" required="true" />
364                 </syntax>
365                 <description>
366                 </description>
367         </manager>
368         <manager name="ConfbridgeStartRecord" language="en_US">
369                 <synopsis>
370                         Start recording a Confbridge conference.
371                 </synopsis>
372                 <syntax>
373                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
374                         <parameter name="Conference" required="true" />
375                         <parameter name="RecordFile" required="false" />
376                 </syntax>
377                 <description>
378                         <para>Start recording a conference. If recording is already present an error will be returned. If RecordFile is not provided, the default record file specified in the conference's bridge profile will be used, if that is not present either a file will automatically be generated in the monitor directory.</para>
379                 </description>
380         </manager>
381         <manager name="ConfbridgeStopRecord" language="en_US">
382                 <synopsis>
383                         Stop recording a Confbridge conference.
384                 </synopsis>
385                 <syntax>
386                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
387                         <parameter name="Conference" required="true" />
388                 </syntax>
389                 <description>
390                 </description>
391         </manager>
392         <manager name="ConfbridgeSetSingleVideoSrc" language="en_US">
393                 <synopsis>
394                         Set a conference user as the single video source distributed to all other participants.
395                 </synopsis>
396                 <syntax>
397                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
398                         <parameter name="Conference" required="true" />
399                         <parameter name="Channel" required="true">
400                                 <para>If this parameter is not a complete channel name, the first channel with this prefix will be used.</para>
401                         </parameter>
402                 </syntax>
403                 <description>
404                 </description>
405         </manager>
406
407 ***/
408
409 /*!
410  * \par Playing back a file to a channel in a conference
411  * You might notice in this application that while playing a sound file
412  * to a channel the actual conference bridge lock is not held. This is done so
413  * that other channels are not blocked from interacting with the conference bridge.
414  * Unfortunately because of this it is possible for things to change after the sound file
415  * is done being played. Data must therefore be checked after reacquiring the conference
416  * bridge lock if it is important.
417  */
418
419 static const char app[] = "ConfBridge";
420
421 /*! Number of buckets our conference bridges container can have */
422 #define CONFERENCE_BRIDGE_BUCKETS 53
423
424 /*! Initial recording filename space. */
425 #define RECORD_FILENAME_INITIAL_SPACE   128
426
427 /*! \brief Container to hold all conference bridges in progress */
428 struct ao2_container *conference_bridges;
429
430 static void leave_conference(struct confbridge_user *user);
431 static int play_sound_number(struct confbridge_conference *conference, int say_number);
432 static int execute_menu_entry(struct confbridge_conference *conference,
433         struct confbridge_user *user,
434         struct ast_bridge_channel *bridge_channel,
435         struct conf_menu_entry *menu_entry,
436         struct conf_menu *menu);
437
438 /*! \brief Hashing function used for conference bridges container */
439 static int conference_bridge_hash_cb(const void *obj, const int flags)
440 {
441         const struct confbridge_conference *conference = obj;
442         const char *name = obj;
443         int hash;
444
445         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
446         default:
447         case OBJ_POINTER:
448                 name = conference->name;
449                 /* Fall through */
450         case OBJ_KEY:
451                 hash = ast_str_case_hash(name);
452                 break;
453         case OBJ_PARTIAL_KEY:
454                 /* Should never happen in hash callback. */
455                 ast_assert(0);
456                 hash = 0;
457                 break;
458         }
459         return hash;
460 }
461
462 /*! \brief Comparison function used for conference bridges container */
463 static int conference_bridge_cmp_cb(void *obj, void *arg, int flags)
464 {
465         const struct confbridge_conference *left = obj;
466         const struct confbridge_conference *right = arg;
467         const char *right_name = arg;
468         int cmp;
469
470         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
471         default:
472         case OBJ_POINTER:
473                 right_name = right->name;
474                 /* Fall through */
475         case OBJ_KEY:
476                 cmp = strcasecmp(left->name, right_name);
477                 break;
478         case OBJ_PARTIAL_KEY:
479                 cmp = strncasecmp(left->name, right_name, strlen(right_name));
480                 break;
481         }
482         return cmp ? 0 : CMP_MATCH;
483 }
484
485 const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds)
486 {
487         switch (sound) {
488         case CONF_SOUND_HAS_JOINED:
489                 return S_OR(custom_sounds->hasjoin, "conf-hasjoin");
490         case CONF_SOUND_HAS_LEFT:
491                 return S_OR(custom_sounds->hasleft, "conf-hasleft");
492         case CONF_SOUND_KICKED:
493                 return S_OR(custom_sounds->kicked, "conf-kicked");
494         case CONF_SOUND_MUTED:
495                 return S_OR(custom_sounds->muted, "conf-muted");
496         case CONF_SOUND_UNMUTED:
497                 return S_OR(custom_sounds->unmuted, "conf-unmuted");
498         case CONF_SOUND_BINAURAL_ON:
499                 return S_OR(custom_sounds->binauralon, "confbridge-binaural-on");
500         case CONF_SOUND_BINAURAL_OFF:
501                 return S_OR(custom_sounds->binauraloff, "confbridge-binaural-off");
502         case CONF_SOUND_ONLY_ONE:
503                 return S_OR(custom_sounds->onlyone, "conf-onlyone");
504         case CONF_SOUND_THERE_ARE:
505                 return S_OR(custom_sounds->thereare, "conf-thereare");
506         case CONF_SOUND_OTHER_IN_PARTY:
507                 return S_OR(custom_sounds->otherinparty, "conf-otherinparty");
508         case CONF_SOUND_PLACE_IN_CONF:
509                 return S_OR(custom_sounds->placeintoconf, "conf-placeintoconf");
510         case CONF_SOUND_WAIT_FOR_LEADER:
511                 return S_OR(custom_sounds->waitforleader, "conf-waitforleader");
512         case CONF_SOUND_LEADER_HAS_LEFT:
513                 return S_OR(custom_sounds->leaderhasleft, "conf-leaderhasleft");
514         case CONF_SOUND_GET_PIN:
515                 return S_OR(custom_sounds->getpin, "conf-getpin");
516         case CONF_SOUND_INVALID_PIN:
517                 return S_OR(custom_sounds->invalidpin, "conf-invalidpin");
518         case CONF_SOUND_ONLY_PERSON:
519                 return S_OR(custom_sounds->onlyperson, "conf-onlyperson");
520         case CONF_SOUND_LOCKED:
521                 return S_OR(custom_sounds->locked, "conf-locked");
522         case CONF_SOUND_LOCKED_NOW:
523                 return S_OR(custom_sounds->lockednow, "conf-lockednow");
524         case CONF_SOUND_UNLOCKED_NOW:
525                 return S_OR(custom_sounds->unlockednow, "conf-unlockednow");
526         case CONF_SOUND_ERROR_MENU:
527                 return S_OR(custom_sounds->errormenu, "conf-errormenu");
528         case CONF_SOUND_JOIN:
529                 return S_OR(custom_sounds->join, "confbridge-join");
530         case CONF_SOUND_LEAVE:
531                 return S_OR(custom_sounds->leave, "confbridge-leave");
532         case CONF_SOUND_PARTICIPANTS_MUTED:
533                 return S_OR(custom_sounds->participantsmuted, "conf-now-muted");
534         case CONF_SOUND_PARTICIPANTS_UNMUTED:
535                 return S_OR(custom_sounds->participantsunmuted, "conf-now-unmuted");
536         case CONF_SOUND_BEGIN:
537                 return S_OR(custom_sounds->begin, "confbridge-conf-begin");
538         }
539
540         return "";
541 }
542
543 static void send_conf_stasis(struct confbridge_conference *conference, struct ast_channel *chan,
544         struct stasis_message_type *type, struct ast_json *extras, int channel_topic)
545 {
546         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
547         RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
548
549         json_object = ast_json_pack("{s: s}",
550                 "conference", conference->name);
551         if (!json_object) {
552                 return;
553         }
554
555         if (extras) {
556                 ast_json_object_update(json_object, extras);
557         }
558
559         ast_bridge_lock(conference->bridge);
560         msg = ast_bridge_blob_create(type,
561                 conference->bridge,
562                 chan,
563                 json_object);
564         ast_bridge_unlock(conference->bridge);
565         if (!msg) {
566                 return;
567         }
568
569         if (channel_topic) {
570                 stasis_publish(ast_channel_topic(chan), msg);
571         } else {
572                 stasis_publish(ast_bridge_topic(conference->bridge), msg);
573         }
574 }
575
576 static void send_conf_start_event(struct confbridge_conference *conference)
577 {
578         send_conf_stasis(conference, NULL, confbridge_start_type(), NULL, 0);
579 }
580
581 static void send_conf_end_event(struct confbridge_conference *conference)
582 {
583         send_conf_stasis(conference, NULL, confbridge_end_type(), NULL, 0);
584 }
585
586 static void send_join_event(struct confbridge_user *user, struct confbridge_conference *conference)
587 {
588         struct ast_json *json_object;
589
590         json_object = ast_json_pack("{s: b, s: b}",
591                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN),
592                 "muted", user->muted);
593         if (!json_object) {
594                 return;
595         }
596         send_conf_stasis(conference, user->chan, confbridge_join_type(), json_object, 0);
597         ast_json_unref(json_object);
598 }
599
600 static void send_leave_event(struct confbridge_user *user, struct confbridge_conference *conference)
601 {
602         struct ast_json *json_object;
603
604         json_object = ast_json_pack("{s: b}",
605                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
606         );
607         if (!json_object) {
608                 return;
609         }
610         send_conf_stasis(conference, user->chan, confbridge_leave_type(), json_object, 0);
611         ast_json_unref(json_object);
612 }
613
614 static void send_start_record_event(struct confbridge_conference *conference)
615 {
616         send_conf_stasis(conference, NULL, confbridge_start_record_type(), NULL, 0);
617 }
618
619 static void send_stop_record_event(struct confbridge_conference *conference)
620 {
621         send_conf_stasis(conference, NULL, confbridge_stop_record_type(), NULL, 0);
622 }
623
624 static void send_mute_event(struct confbridge_user *user, struct confbridge_conference *conference)
625 {
626         struct ast_json *json_object;
627
628         json_object = ast_json_pack("{s: b}",
629                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
630         );
631         if (!json_object) {
632                 return;
633         }
634         send_conf_stasis(conference, user->chan, confbridge_mute_type(), json_object, 1);
635         ast_json_unref(json_object);
636 }
637
638 static void send_unmute_event(struct confbridge_user *user, struct confbridge_conference *conference)
639 {
640         struct ast_json *json_object;
641
642         json_object = ast_json_pack("{s: b}",
643                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
644         );
645         if (!json_object) {
646                 return;
647         }
648         send_conf_stasis(conference, user->chan, confbridge_unmute_type(), json_object, 1);
649         ast_json_unref(json_object);
650 }
651
652 static void set_rec_filename(struct confbridge_conference *conference, struct ast_str **filename, int is_new)
653 {
654         char *rec_file = conference->b_profile.rec_file;
655         char *ext;
656         time_t now;
657
658         if (ast_str_strlen(*filename)
659                 && ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_APPEND)
660                 && !is_new) {
661                 return;
662         }
663
664         time(&now);
665
666         ast_str_reset(*filename);
667         if (ast_strlen_zero(rec_file)) {
668                 ast_str_set(filename, 0, "confbridge-%s-%u.wav", conference->name,
669                         (unsigned int) now);
670         } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_TIMESTAMP)) {
671                 /* insert time before file extension */
672                 ext = strrchr(rec_file, '.');
673                 if (ext) {
674                         ast_str_set_substr(filename, 0, rec_file, ext - rec_file);
675                         ast_str_append(filename, 0, "-%u%s", (unsigned int) now, ext);
676                 } else {
677                         ast_str_set(filename, 0, "%s-%u", rec_file, (unsigned int) now);
678                 }
679         } else {
680                 ast_str_set(filename, 0, "%s", rec_file);
681         }
682         ast_str_append(filename, 0, ",%s%s,%s",
683                 ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_APPEND) ? "a" : "",
684                 conference->b_profile.rec_options,
685                 conference->b_profile.rec_command);
686 }
687
688 static int is_new_rec_file(const char *rec_file, struct ast_str **orig_rec_file)
689 {
690         if (!ast_strlen_zero(rec_file)) {
691                 if (!*orig_rec_file) {
692                         *orig_rec_file = ast_str_create(RECORD_FILENAME_INITIAL_SPACE);
693                 }
694
695                 if (*orig_rec_file
696                         && strcmp(ast_str_buffer(*orig_rec_file), rec_file)) {
697                         ast_str_set(orig_rec_file, 0, "%s", rec_file);
698                         return 1;
699                 }
700         }
701         return 0;
702 }
703
704 /*!
705  * \internal
706  * \brief Returns whether or not conference is being recorded.
707  *
708  * \param conference The bridge to check for recording
709  *
710  * \note Must be called with the conference locked
711  *
712  * \retval 1, conference is recording.
713  * \retval 0, conference is NOT recording.
714  */
715 static int conf_is_recording(struct confbridge_conference *conference)
716 {
717         return conference->record_chan != NULL;
718 }
719
720 /*!
721  * \internal
722  * \brief Stop recording a conference bridge
723  *
724  * \param conference The conference bridge on which to stop the recording
725  *
726  * \note Must be called with the conference locked
727  *
728  * \retval -1 Failure
729  * \retval 0 Success
730  */
731 static int conf_stop_record(struct confbridge_conference *conference)
732 {
733         struct ast_channel *chan;
734         struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
735
736         if (!conf_is_recording(conference)) {
737                 return -1;
738         }
739
740         /* Remove the recording channel from the conference bridge. */
741         chan = conference->record_chan;
742         conference->record_chan = NULL;
743         ast_queue_frame(chan, &f);
744         ast_channel_unref(chan);
745
746         ast_test_suite_event_notify("CONF_STOP_RECORD", "Message: stopped conference recording channel\r\nConference: %s", conference->b_profile.name);
747         send_stop_record_event(conference);
748
749         return 0;
750 }
751
752 /*!
753  * \internal
754  * \brief Start recording the conference
755  *
756  * \param conference The conference bridge to start recording
757  *
758  * \note Must be called with the conference locked
759  *
760  * \retval 0 success
761  * \retval non-zero failure
762  */
763 static int conf_start_record(struct confbridge_conference *conference)
764 {
765         struct ast_app *mixmonapp;
766         struct ast_channel *chan;
767         struct ast_format_cap *cap;
768         struct ast_bridge_features *features;
769
770         if (conf_is_recording(conference)) {
771                 return -1;
772         }
773
774         mixmonapp = pbx_findapp("MixMonitor");
775         if (!mixmonapp) {
776                 ast_log(LOG_WARNING, "Cannot record ConfBridge, MixMonitor app is not installed\n");
777                 return -1;
778         }
779
780         features = ast_bridge_features_new();
781         if (!features) {
782                 return -1;
783         }
784         ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
785
786         cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
787         if (!cap) {
788                 ast_bridge_features_destroy(features);
789                 return -1;
790         }
791         ast_format_cap_append(cap, ast_format_slin, 0);
792
793         /* Create the recording channel. */
794         chan = ast_request("CBRec", cap, NULL, NULL, conference->name, NULL);
795         ao2_ref(cap, -1);
796         if (!chan) {
797                 ast_bridge_features_destroy(features);
798                 return -1;
799         }
800
801         /* Start recording. */
802         set_rec_filename(conference, &conference->record_filename,
803                 is_new_rec_file(conference->b_profile.rec_file, &conference->orig_rec_file));
804         ast_answer(chan);
805         pbx_exec(chan, mixmonapp, ast_str_buffer(conference->record_filename));
806
807         /* Put the channel into the conference bridge. */
808         ast_channel_ref(chan);
809         conference->record_chan = chan;
810         if (ast_bridge_impart(conference->bridge, chan, NULL, features,
811                 AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
812                 ast_hangup(chan);
813                 ast_channel_unref(chan);
814                 conference->record_chan = NULL;
815                 return -1;
816         }
817
818         ast_test_suite_event_notify("CONF_START_RECORD", "Message: started conference recording channel\r\nConference: %s", conference->b_profile.name);
819         send_start_record_event(conference);
820
821         return 0;
822 }
823
824 /* \brief Playback the given filename and monitor for any dtmf interrupts.
825  *
826  * This function is used to playback sound files on a given channel and optionally
827  * allow dtmf interrupts to occur.
828  *
829  * If the optional bridge_channel parameter is given then sound file playback
830  * is played on that channel and dtmf interruptions are allowed. However, if
831  * bridge_channel is not set then the channel parameter is expected to be set
832  * instead and non interruptible playback is played on that channel.
833  *
834  * \param bridge_channel Bridge channel to play file on
835  * \param channel Optional channel to play file on if bridge_channel not given
836  * \param filename The file name to playback
837  *
838  * \retval -1 failure during playback, 0 on file was fully played, 1 on dtmf interrupt.
839  */
840 static int play_file(struct ast_bridge_channel *bridge_channel, struct ast_channel *channel,
841                      const char *filename)
842 {
843         struct ast_channel *chan;
844         const char *stop_digits;
845         int digit;
846
847         if (bridge_channel) {
848                 chan = bridge_channel->chan;
849                 stop_digits = AST_DIGIT_ANY;
850         } else {
851                 chan = channel;
852                 stop_digits = AST_DIGIT_NONE;
853         }
854
855         digit = ast_stream_and_wait(chan, filename, stop_digits);
856         if (digit < 0) {
857                 ast_log(LOG_WARNING, "Failed to playback file '%s' to channel\n", filename);
858                 return -1;
859         }
860
861         if (digit > 0) {
862                 ast_stopstream(bridge_channel->chan);
863                 ast_bridge_channel_feature_digit_add(bridge_channel, digit);
864                 return 1;
865         }
866
867         return 0;
868 }
869
870 /*!
871  * \internal
872  * \brief Complain if the given sound file does not exist.
873  *
874  * \param filename Sound file to check if exists.
875  *
876  * \retval non-zero if the file exists.
877  */
878 static int sound_file_exists(const char *filename)
879 {
880         if (ast_fileexists(filename, NULL, NULL)) {
881                 return -1;
882         }
883         ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
884         return 0;
885 }
886
887 /*!
888  * \brief Announce number of users in the conference bridge to the caller
889  *
890  * \param conference Conference bridge to peek at
891  * \param user Optional Caller
892  * \param bridge_channel The bridged channel involved
893  *
894  * \note if caller is NULL, the announcment will be sent to all participants in the conference.
895  * \return Returns 0 on success, -1 if the user hung up
896  */
897 static int announce_user_count(struct confbridge_conference *conference, struct confbridge_user *user,
898                                struct ast_bridge_channel *bridge_channel)
899 {
900         const char *other_in_party = conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, conference->b_profile.sounds);
901         const char *only_one = conf_get_sound(CONF_SOUND_ONLY_ONE, conference->b_profile.sounds);
902         const char *there_are = conf_get_sound(CONF_SOUND_THERE_ARE, conference->b_profile.sounds);
903
904         if (conference->activeusers <= 1) {
905                 /* Awww we are the only person in the conference bridge OR we only have waitmarked users */
906                 return 0;
907         } else if (conference->activeusers == 2) {
908                 if (user) {
909                         /* Eep, there is one other person */
910                         if (play_file(bridge_channel, user->chan, only_one) < 0) {
911                                 return -1;
912                         }
913                 } else {
914                         play_sound_file(conference, only_one);
915                 }
916         } else {
917                 /* Alas multiple others in here */
918                 if (user) {
919                         if (ast_stream_and_wait(user->chan,
920                                 there_are,
921                                 "")) {
922                                 return -1;
923                         }
924                         if (ast_say_number(user->chan, conference->activeusers - 1, "", ast_channel_language(user->chan), NULL)) {
925                                 return -1;
926                         }
927                         if (play_file(bridge_channel, user->chan, other_in_party) < 0) {
928                                 return -1;
929                         }
930                 } else if (sound_file_exists(there_are) && sound_file_exists(other_in_party)) {
931                         play_sound_file(conference, there_are);
932                         play_sound_number(conference, conference->activeusers - 1);
933                         play_sound_file(conference, other_in_party);
934                 }
935         }
936         return 0;
937 }
938
939 /*!
940  * \brief Play back an audio file to a channel
941  *
942  * \param user User to play audio prompt to
943  * \param filename Prompt to play
944  *
945  * \return Returns 0 on success, -1 if the user hung up
946  * \note Generally this should be called when the conference is unlocked to avoid blocking
947  * the entire conference while the sound is played. But don't unlock the conference bridge
948  * in the middle of a state transition.
949  */
950 static int play_prompt_to_user(struct confbridge_user *user, const char *filename)
951 {
952         return ast_stream_and_wait(user->chan, filename, "");
953 }
954
955 static void handle_video_on_join(struct confbridge_conference *conference, struct ast_channel *chan, int marked)
956 {
957         /* Right now, only marked users are automatically set as the single src of video.*/
958         if (!marked) {
959                 return;
960         }
961
962         if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED)) {
963                 int set = 1;
964                 struct confbridge_user *user = NULL;
965
966                 ao2_lock(conference);
967                 /* see if anyone is already the video src */
968                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
969                         if (user->chan == chan) {
970                                 continue;
971                         }
972                         if (ast_bridge_is_video_src(conference->bridge, user->chan)) {
973                                 set = 0;
974                                 break;
975                         }
976                 }
977                 ao2_unlock(conference);
978                 if (set) {
979                         ast_bridge_set_single_src_video_mode(conference->bridge, chan);
980                 }
981         } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
982                 /* we joined and are video capable, we override anyone else that may have already been the video feed */
983                 ast_bridge_set_single_src_video_mode(conference->bridge, chan);
984         }
985 }
986
987 static void handle_video_on_exit(struct confbridge_conference *conference, struct ast_channel *chan)
988 {
989         struct confbridge_user *user = NULL;
990
991         /* if this isn't a video source, nothing to update */
992         if (!ast_bridge_is_video_src(conference->bridge, chan)) {
993                 return;
994         }
995
996         ast_bridge_remove_video_src(conference->bridge, chan);
997
998         /* If in follow talker mode, make sure to restore this mode on the
999          * bridge when a source is removed.  It is possible this channel was
1000          * only set temporarily as a video source by an AMI or DTMF action. */
1001         if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
1002                 ast_bridge_set_talker_src_video_mode(conference->bridge);
1003         }
1004
1005         /* if the video_mode isn't set to automatically pick the video source, do nothing on exit. */
1006         if (!ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED) &&
1007                 !ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
1008                 return;
1009         }
1010
1011         /* Make the next available marked user the video src.  */
1012         ao2_lock(conference);
1013         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
1014                 if (user->chan == chan) {
1015                         continue;
1016                 }
1017                 if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
1018                         ast_bridge_set_single_src_video_mode(conference->bridge, user->chan);
1019                         break;
1020                 }
1021         }
1022         ao2_unlock(conference);
1023 }
1024
1025 struct hangup_data
1026 {
1027         struct confbridge_conference *conference;
1028         ast_mutex_t lock;
1029         ast_cond_t cond;
1030         int hungup;
1031 };
1032
1033 /*!
1034  * \brief Hang up the announcer channel
1035  *
1036  * This hangs up the announcer channel in the conference. This
1037  * runs in the playback queue taskprocessor since we do not want
1038  * to hang up the channel while it's trying to play an announcement.
1039  *
1040  * This task is performed synchronously, so there is no need to
1041  * perform any cleanup on the passed-in data.
1042  *
1043  * \param data A hangup_data structure
1044  * \return 0
1045  */
1046 static int hangup_playback(void *data)
1047 {
1048         struct hangup_data *hangup = data;
1049
1050         ast_autoservice_stop(hangup->conference->playback_chan);
1051
1052         ast_hangup(hangup->conference->playback_chan);
1053         hangup->conference->playback_chan = NULL;
1054
1055         ast_mutex_lock(&hangup->lock);
1056         hangup->hungup = 1;
1057         ast_cond_signal(&hangup->cond);
1058         ast_mutex_unlock(&hangup->lock);
1059
1060         return 0;
1061 }
1062
1063 static void hangup_data_init(struct hangup_data *hangup, struct confbridge_conference *conference)
1064 {
1065         ast_mutex_init(&hangup->lock);
1066         ast_cond_init(&hangup->cond, NULL);
1067
1068         hangup->conference = conference;
1069         hangup->hungup = 0;
1070 }
1071
1072 static void hangup_data_destroy(struct hangup_data *hangup)
1073 {
1074         ast_mutex_destroy(&hangup->lock);
1075         ast_cond_destroy(&hangup->cond);
1076 }
1077
1078 /*!
1079  * \brief Destroy a conference bridge
1080  *
1081  * \param obj The conference bridge object
1082  *
1083  * \return Returns nothing
1084  */
1085 static void destroy_conference_bridge(void *obj)
1086 {
1087         struct confbridge_conference *conference = obj;
1088
1089         ast_debug(1, "Destroying conference bridge '%s'\n", conference->name);
1090
1091         if (conference->playback_chan) {
1092                 if (conference->playback_queue) {
1093                         struct hangup_data hangup;
1094                         hangup_data_init(&hangup, conference);
1095                         ast_taskprocessor_push(conference->playback_queue, hangup_playback, &hangup);
1096
1097                         ast_mutex_lock(&hangup.lock);
1098                         while (!hangup.hungup) {
1099                                 ast_cond_wait(&hangup.cond, &hangup.lock);
1100                         }
1101                         ast_mutex_unlock(&hangup.lock);
1102                         hangup_data_destroy(&hangup);
1103                 } else {
1104                         /* Playback queue is not yet allocated. Just hang up the channel straight */
1105                         ast_hangup(conference->playback_chan);
1106                         conference->playback_chan = NULL;
1107                 }
1108         }
1109
1110         /* Destroying a conference bridge is simple, all we have to do is destroy the bridging object */
1111         if (conference->bridge) {
1112                 ast_bridge_destroy(conference->bridge, 0);
1113                 conference->bridge = NULL;
1114         }
1115
1116         ast_channel_cleanup(conference->record_chan);
1117         ast_free(conference->orig_rec_file);
1118         ast_free(conference->record_filename);
1119
1120         conf_bridge_profile_destroy(&conference->b_profile);
1121         ast_taskprocessor_unreference(conference->playback_queue);
1122 }
1123
1124 /*! \brief Call the proper join event handler for the user for the conference bridge's current state
1125  * \internal
1126  * \param user The conference bridge user that is joining
1127  * \retval 0 success
1128  * \retval -1 failure
1129  */
1130 static int handle_conf_user_join(struct confbridge_user *user)
1131 {
1132         conference_event_fn handler;
1133         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
1134                 handler = user->conference->state->join_marked;
1135         } else if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
1136                 handler = user->conference->state->join_waitmarked;
1137         } else {
1138                 handler = user->conference->state->join_unmarked;
1139         }
1140
1141         ast_assert(handler != NULL);
1142
1143         if (!handler) {
1144                 conf_invalid_event_fn(user);
1145                 return -1;
1146         }
1147
1148         handler(user);
1149
1150         return 0;
1151 }
1152
1153 /*! \brief Call the proper leave event handler for the user for the conference bridge's current state
1154  * \internal
1155  * \param user The conference bridge user that is leaving
1156  * \retval 0 success
1157  * \retval -1 failure
1158  */
1159 static int handle_conf_user_leave(struct confbridge_user *user)
1160 {
1161         conference_event_fn handler;
1162         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
1163                 handler = user->conference->state->leave_marked;
1164         } else if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
1165                 handler = user->conference->state->leave_waitmarked;
1166         } else {
1167                 handler = user->conference->state->leave_unmarked;
1168         }
1169
1170         ast_assert(handler != NULL);
1171
1172         if (!handler) {
1173                 /* This should never happen. If it does, though, it is bad. The user will not have been removed
1174                  * from the appropriate list, so counts will be off and stuff. The conference won't be torn down, etc.
1175                  * Shouldn't happen, though. */
1176                 conf_invalid_event_fn(user);
1177                 return -1;
1178         }
1179
1180         handler(user);
1181
1182         return 0;
1183 }
1184
1185 void conf_update_user_mute(struct confbridge_user *user)
1186 {
1187         int mute_user;
1188         int mute_system;
1189         int mute_effective;
1190
1191         /* User level mute request. */
1192         mute_user = user->muted;
1193
1194         /* System level mute request. */
1195         mute_system = user->playing_moh
1196                 /*
1197                  * Do not allow waitmarked users to talk to anyone unless there
1198                  * is a marked user present.
1199                  */
1200                 || (!user->conference->markedusers
1201                         && ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED));
1202
1203         mute_effective = mute_user || mute_system;
1204
1205         ast_debug(1, "User %s is %s: user:%d system:%d.\n",
1206                 ast_channel_name(user->chan), mute_effective ? "muted" : "unmuted",
1207                 mute_user, mute_system);
1208         user->features.mute = mute_effective;
1209         ast_test_suite_event_notify("CONF_MUTE_UPDATE",
1210                 "Mode: %s\r\n"
1211                 "Conference: %s\r\n"
1212                 "Channel: %s",
1213                 mute_effective ? "muted" : "unmuted",
1214                 user->conference->b_profile.name,
1215                 ast_channel_name(user->chan));
1216 }
1217
1218 /*
1219  * \internal
1220  * \brief Mute/unmute a single user.
1221  */
1222 static void generic_mute_unmute_user(struct confbridge_conference *conference, struct confbridge_user *user, int mute)
1223 {
1224         /* Set user level mute request. */
1225         user->muted = mute ? 1 : 0;
1226
1227         conf_update_user_mute(user);
1228         ast_test_suite_event_notify("CONF_MUTE",
1229                 "Message: participant %s %s\r\n"
1230                 "Conference: %s\r\n"
1231                 "Channel: %s",
1232                 ast_channel_name(user->chan),
1233                 mute ? "muted" : "unmuted",
1234                 conference->b_profile.name,
1235                 ast_channel_name(user->chan));
1236         if (mute) {
1237                 send_mute_event(user, conference);
1238         } else {
1239                 send_unmute_event(user, conference);
1240         }
1241 }
1242
1243 void conf_moh_stop(struct confbridge_user *user)
1244 {
1245         user->playing_moh = 0;
1246         if (!user->suspended_moh) {
1247                 int in_bridge;
1248
1249                 /*
1250                  * Locking the ast_bridge here is the only way to hold off the
1251                  * call to ast_bridge_join() in confbridge_exec() from
1252                  * interfering with the bridge and MOH operations here.
1253                  */
1254                 ast_bridge_lock(user->conference->bridge);
1255
1256                 /*
1257                  * Temporarily suspend the user from the bridge so we have
1258                  * control to stop MOH if needed.
1259                  */
1260                 in_bridge = !ast_bridge_suspend(user->conference->bridge, user->chan);
1261                 ast_moh_stop(user->chan);
1262                 if (in_bridge) {
1263                         ast_bridge_unsuspend(user->conference->bridge, user->chan);
1264                 }
1265
1266                 ast_bridge_unlock(user->conference->bridge);
1267         }
1268 }
1269
1270 void conf_moh_start(struct confbridge_user *user)
1271 {
1272         user->playing_moh = 1;
1273         if (!user->suspended_moh) {
1274                 int in_bridge;
1275
1276                 /*
1277                  * Locking the ast_bridge here is the only way to hold off the
1278                  * call to ast_bridge_join() in confbridge_exec() from
1279                  * interfering with the bridge and MOH operations here.
1280                  */
1281                 ast_bridge_lock(user->conference->bridge);
1282
1283                 /*
1284                  * Temporarily suspend the user from the bridge so we have
1285                  * control to start MOH if needed.
1286                  */
1287                 in_bridge = !ast_bridge_suspend(user->conference->bridge, user->chan);
1288                 ast_moh_start(user->chan, user->u_profile.moh_class, NULL);
1289                 if (in_bridge) {
1290                         ast_bridge_unsuspend(user->conference->bridge, user->chan);
1291                 }
1292
1293                 ast_bridge_unlock(user->conference->bridge);
1294         }
1295 }
1296
1297 /*!
1298  * \internal
1299  * \brief Unsuspend MOH for the conference user.
1300  *
1301  * \param user Conference user to unsuspend MOH on.
1302  *
1303  * \return Nothing
1304  */
1305 static void conf_moh_unsuspend(struct confbridge_user *user)
1306 {
1307         ao2_lock(user->conference);
1308         if (--user->suspended_moh == 0 && user->playing_moh) {
1309                 ast_moh_start(user->chan, user->u_profile.moh_class, NULL);
1310         }
1311         ao2_unlock(user->conference);
1312 }
1313
1314 /*!
1315  * \internal
1316  * \brief Suspend MOH for the conference user.
1317  *
1318  * \param user Conference user to suspend MOH on.
1319  *
1320  * \return Nothing
1321  */
1322 static void conf_moh_suspend(struct confbridge_user *user)
1323 {
1324         ao2_lock(user->conference);
1325         if (user->suspended_moh++ == 0 && user->playing_moh) {
1326                 ast_moh_stop(user->chan);
1327         }
1328         ao2_unlock(user->conference);
1329 }
1330
1331 int conf_handle_inactive_waitmarked(struct confbridge_user *user)
1332 {
1333         /* If we have not been quieted play back that they are waiting for the leader */
1334         if (!ast_test_flag(&user->u_profile, USER_OPT_QUIET) && play_prompt_to_user(user,
1335                         conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, user->conference->b_profile.sounds))) {
1336                 /* user hungup while the sound was playing */
1337                 return -1;
1338         }
1339         return 0;
1340 }
1341
1342 int conf_handle_only_unmarked(struct confbridge_user *user)
1343 {
1344         /* If audio prompts have not been quieted or this prompt quieted play it on out */
1345         if (!ast_test_flag(&user->u_profile, USER_OPT_QUIET | USER_OPT_NOONLYPERSON)) {
1346                 if (play_prompt_to_user(user,
1347                         conf_get_sound(CONF_SOUND_ONLY_PERSON, user->conference->b_profile.sounds))) {
1348                         /* user hungup while the sound was playing */
1349                         return -1;
1350                 }
1351         }
1352         return 0;
1353 }
1354
1355 int conf_add_post_join_action(struct confbridge_user *user, int (*func)(struct confbridge_user *user))
1356 {
1357         struct post_join_action *action;
1358         if (!(action = ast_calloc(1, sizeof(*action)))) {
1359                 return -1;
1360         }
1361         action->func = func;
1362         AST_LIST_INSERT_TAIL(&user->post_join_list, action, list);
1363         return 0;
1364 }
1365
1366
1367 void conf_handle_first_join(struct confbridge_conference *conference)
1368 {
1369         ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "confbridge:%s", conference->name);
1370 }
1371
1372 void conf_handle_second_active(struct confbridge_conference *conference)
1373 {
1374         /* If we are the second participant we may need to stop music on hold on the first */
1375         struct confbridge_user *first_user = AST_LIST_FIRST(&conference->active_list);
1376
1377         if (ast_test_flag(&first_user->u_profile, USER_OPT_MUSICONHOLD)) {
1378                 conf_moh_stop(first_user);
1379         }
1380         conf_update_user_mute(first_user);
1381 }
1382
1383 void conf_ended(struct confbridge_conference *conference)
1384 {
1385         struct pbx_find_info q = { .stacklen = 0 };
1386
1387         /* Called with a reference to conference */
1388         ao2_unlink(conference_bridges, conference);
1389         send_conf_end_event(conference);
1390         if (!ast_strlen_zero(conference->b_profile.regcontext) &&
1391                         pbx_find_extension(NULL, NULL, &q, conference->b_profile.regcontext,
1392                                 conference->name, 1, NULL, "", E_MATCH)) {
1393                 ast_context_remove_extension(conference->b_profile.regcontext,
1394                                 conference->name, 1, NULL);
1395         }
1396         ao2_lock(conference);
1397         conf_stop_record(conference);
1398         ao2_unlock(conference);
1399 }
1400
1401 /*!
1402  * \internal
1403  * \brief Allocate playback channel for a conference.
1404  * \pre expects conference to be locked before calling this function
1405  */
1406 static int alloc_playback_chan(struct confbridge_conference *conference)
1407 {
1408         struct ast_format_cap *cap;
1409         char taskprocessor_name[AST_TASKPROCESSOR_MAX_NAME + 1];
1410
1411         cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1412         if (!cap) {
1413                 return -1;
1414         }
1415         ast_format_cap_append(cap, ast_format_slin, 0);
1416         conference->playback_chan = ast_request("CBAnn", cap, NULL, NULL,
1417                 conference->name, NULL);
1418         ao2_ref(cap, -1);
1419         if (!conference->playback_chan) {
1420                 return -1;
1421         }
1422
1423         /* To make sure playback_chan has the same language as the bridge */
1424         ast_channel_lock(conference->playback_chan);
1425         ast_channel_language_set(conference->playback_chan, conference->b_profile.language);
1426         ast_channel_unlock(conference->playback_chan);
1427
1428         ast_debug(1, "Created announcer channel '%s' to conference bridge '%s'\n",
1429                 ast_channel_name(conference->playback_chan), conference->name);
1430
1431         ast_taskprocessor_build_name(taskprocessor_name, sizeof(taskprocessor_name),
1432                 "Confbridge/%s", conference->name);
1433         conference->playback_queue = ast_taskprocessor_get(taskprocessor_name, TPS_REF_DEFAULT);
1434         if (!conference->playback_queue) {
1435                 ast_hangup(conference->playback_chan);
1436                 conference->playback_chan = NULL;
1437                 return -1;
1438         }
1439         return 0;
1440 }
1441
1442 /*!
1443  * \brief Push the announcer channel into the bridge
1444  *
1445  * This runs in the playback queue taskprocessor.
1446  *
1447  * \param data A confbridge_conference
1448  * \retval 0 Success
1449  * \retval -1 Failed to push the channel to the bridge
1450  */
1451 static int push_announcer(void *data)
1452 {
1453         struct confbridge_conference *conference = data;
1454
1455         if (conf_announce_channel_push(conference->playback_chan)) {
1456                 ast_hangup(conference->playback_chan);
1457                 conference->playback_chan = NULL;
1458                 ao2_cleanup(conference);
1459                 return -1;
1460         }
1461
1462         ast_autoservice_start(conference->playback_chan);
1463         ao2_cleanup(conference);
1464         return 0;
1465 }
1466
1467 /*!
1468  * \brief Join a conference bridge
1469  *
1470  * \param conference_name The conference name
1471  * \param user Conference bridge user structure
1472  *
1473  * \return A pointer to the conference bridge struct, or NULL if the conference room wasn't found.
1474  */
1475 static struct confbridge_conference *join_conference_bridge(const char *conference_name, struct confbridge_user *user)
1476 {
1477         struct confbridge_conference *conference;
1478         struct post_join_action *action;
1479         int max_members_reached = 0;
1480
1481         /* We explictly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same */
1482         ao2_lock(conference_bridges);
1483
1484         ast_debug(1, "Trying to find conference bridge '%s'\n", conference_name);
1485
1486         /* Attempt to find an existing conference bridge */
1487         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
1488         if (conference && conference->b_profile.max_members) {
1489                 max_members_reached = conference->b_profile.max_members > conference->activeusers ? 0 : 1;
1490         }
1491
1492         /* When finding a conference bridge that already exists make sure that it is not locked, and if so that we are not an admin */
1493         if (conference && (max_members_reached || conference->locked) && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
1494                 ao2_unlock(conference_bridges);
1495                 ast_debug(1, "Conference '%s' is locked and caller is not an admin\n", conference_name);
1496                 ast_stream_and_wait(user->chan,
1497                         conf_get_sound(CONF_SOUND_LOCKED, conference->b_profile.sounds),
1498                         "");
1499                 ao2_ref(conference, -1);
1500                 return NULL;
1501         }
1502
1503         /* If no conference bridge was found see if we can create one */
1504         if (!conference) {
1505                 /* Try to allocate memory for a new conference bridge, if we fail... this won't end well. */
1506                 if (!(conference = ao2_alloc(sizeof(*conference), destroy_conference_bridge))) {
1507                         ao2_unlock(conference_bridges);
1508                         ast_log(LOG_ERROR, "Conference '%s' could not be created.\n", conference_name);
1509                         return NULL;
1510                 }
1511
1512                 /* Setup for the record channel */
1513                 conference->record_filename = ast_str_create(RECORD_FILENAME_INITIAL_SPACE);
1514                 if (!conference->record_filename) {
1515                         ao2_ref(conference, -1);
1516                         ao2_unlock(conference_bridges);
1517                         return NULL;
1518                 }
1519
1520                 /* Setup conference bridge parameters */
1521                 ast_copy_string(conference->name, conference_name, sizeof(conference->name));
1522                 conf_bridge_profile_copy(&conference->b_profile, &user->b_profile);
1523
1524                 /* Create an actual bridge that will do the audio mixing */
1525                 conference->bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_MULTIMIX,
1526                         AST_BRIDGE_FLAG_MASQUERADE_ONLY | AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY,
1527                         app, conference_name, NULL);
1528                 if (!conference->bridge) {
1529                         ao2_ref(conference, -1);
1530                         ao2_unlock(conference_bridges);
1531                         ast_log(LOG_ERROR, "Conference '%s' mixing bridge could not be created.\n", conference_name);
1532                         return NULL;
1533                 }
1534
1535                 /* Set the internal sample rate on the bridge from the bridge profile */
1536                 ast_bridge_set_internal_sample_rate(conference->bridge, conference->b_profile.internal_sample_rate);
1537                 /* Set the internal mixing interval on the bridge from the bridge profile */
1538                 ast_bridge_set_mixing_interval(conference->bridge, conference->b_profile.mix_interval);
1539                 ast_bridge_set_binaural_active(conference->bridge, ast_test_flag(&conference->b_profile, BRIDGE_OPT_BINAURAL_ACTIVE));
1540
1541                 if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
1542                         ast_bridge_set_talker_src_video_mode(conference->bridge);
1543                 } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_SFU)) {
1544                         ast_bridge_set_sfu_video_mode(conference->bridge);
1545                         ast_bridge_set_video_update_discard(conference->bridge, conference->b_profile.video_update_discard);
1546                         ast_bridge_set_remb_send_interval(conference->bridge, conference->b_profile.remb_send_interval);
1547                 }
1548
1549                 /* Link it into the conference bridges container */
1550                 if (!ao2_link(conference_bridges, conference)) {
1551                         ao2_ref(conference, -1);
1552                         ao2_unlock(conference_bridges);
1553                         ast_log(LOG_ERROR,
1554                                 "Conference '%s' could not be added to the conferences list.\n", conference_name);
1555                         return NULL;
1556                 }
1557
1558                 /* Set the initial state to EMPTY */
1559                 conference->state = CONF_STATE_EMPTY;
1560
1561                 if (alloc_playback_chan(conference)) {
1562                         ao2_unlink(conference_bridges, conference);
1563                         ao2_ref(conference, -1);
1564                         ao2_unlock(conference_bridges);
1565                         ast_log(LOG_ERROR, "Could not allocate announcer channel for conference '%s'\n", conference_name);
1566                         return NULL;
1567                 }
1568
1569                 if (ast_taskprocessor_push(conference->playback_queue, push_announcer, ao2_bump(conference))) {
1570                         ao2_unlink(conference_bridges, conference);
1571                         ao2_ref(conference, -1);
1572                         ao2_unlock(conference_bridges);
1573                         ast_log(LOG_ERROR, "Could not add announcer channel for conference '%s' bridge\n", conference_name);
1574                         return NULL;
1575                 }
1576
1577                 if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_CONFERENCE)) {
1578                         ao2_lock(conference);
1579                         conf_start_record(conference);
1580                         ao2_unlock(conference);
1581                 }
1582
1583                 send_conf_start_event(conference);
1584
1585                 if (!ast_strlen_zero(conference->b_profile.regcontext)) {
1586                         if (!ast_exists_extension(NULL, conference->b_profile.regcontext, conference->name, 1, NULL)) {
1587                                 ast_add_extension(conference->b_profile.regcontext, 1, conference->name, 1, NULL, NULL, "Noop", NULL, NULL, "ConfBridge");
1588                         }
1589                 }
1590
1591                 ast_debug(1, "Created conference '%s' and linked to container.\n", conference_name);
1592         }
1593
1594         ao2_unlock(conference_bridges);
1595
1596         /* Setup conference bridge user parameters */
1597         user->conference = conference;
1598
1599         ao2_lock(conference);
1600
1601         /* Determine if the new user should join the conference muted. */
1602         if (ast_test_flag(&user->u_profile, USER_OPT_STARTMUTED)
1603                 || (!ast_test_flag(&user->u_profile, USER_OPT_ADMIN) && conference->muted)) {
1604                 /* Set user level mute request. */
1605                 user->muted = 1;
1606         }
1607
1608         /*
1609          * Suspend any MOH until the user actually joins the bridge of
1610          * the conference.  This way any pre-join file playback does not
1611          * need to worry about MOH.
1612          */
1613         user->suspended_moh = 1;
1614
1615         if (handle_conf_user_join(user)) {
1616                 /* Invalid event, nothing was done, so we don't want to process a leave. */
1617                 ao2_unlock(conference);
1618                 ao2_ref(conference, -1);
1619                 user->conference = NULL;
1620                 return NULL;
1621         }
1622
1623         if (ast_check_hangup(user->chan)) {
1624                 ao2_unlock(conference);
1625                 leave_conference(user);
1626                 return NULL;
1627         }
1628
1629         ao2_unlock(conference);
1630
1631         /* If an announcement is to be played play it */
1632         if (!ast_strlen_zero(user->u_profile.announcement)) {
1633                 if (play_prompt_to_user(user,
1634                         user->u_profile.announcement)) {
1635                         leave_conference(user);
1636                         return NULL;
1637                 }
1638         }
1639
1640         /* Announce number of users if need be */
1641         if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) {
1642                 if (announce_user_count(conference, user, NULL)) {
1643                         leave_conference(user);
1644                         return NULL;
1645                 }
1646         }
1647
1648         if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) &&
1649                 (conference->activeusers > user->u_profile.announce_user_count_all_after)) {
1650                 int user_count_res;
1651
1652                 /*
1653                  * We have to autoservice the new user because he has not quite
1654                  * joined the conference yet.
1655                  */
1656                 ast_autoservice_start(user->chan);
1657                 user_count_res = announce_user_count(conference, NULL, NULL);
1658                 ast_autoservice_stop(user->chan);
1659                 if (user_count_res) {
1660                         leave_conference(user);
1661                         return NULL;
1662                 }
1663         }
1664
1665         /* Handle post-join actions */
1666         while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
1667                 action->func(user);
1668                 ast_free(action);
1669         }
1670
1671         return conference;
1672 }
1673
1674 /*!
1675  * \brief Leave a conference
1676  *
1677  * \param user The conference user
1678  */
1679 static void leave_conference(struct confbridge_user *user)
1680 {
1681         struct post_join_action *action;
1682
1683         ao2_lock(user->conference);
1684         handle_conf_user_leave(user);
1685         ao2_unlock(user->conference);
1686
1687         /* Discard any post-join actions */
1688         while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
1689                 ast_free(action);
1690         }
1691
1692         /* Done mucking with the conference, huzzah */
1693         ao2_ref(user->conference, -1);
1694         user->conference = NULL;
1695 }
1696
1697 static void playback_common(struct confbridge_conference *conference, const char *filename, int say_number)
1698 {
1699         /* Don't try to play if the playback channel has been hung up */
1700         if (!conference->playback_chan) {
1701                 return;
1702         }
1703
1704         ast_autoservice_stop(conference->playback_chan);
1705
1706         /* The channel is all under our control, in goes the prompt */
1707         if (!ast_strlen_zero(filename)) {
1708                 ast_stream_and_wait(conference->playback_chan, filename, "");
1709         } else if (say_number >= 0) {
1710                 ast_say_number(conference->playback_chan, say_number, "",
1711                         ast_channel_language(conference->playback_chan), NULL);
1712         }
1713
1714         ast_autoservice_start(conference->playback_chan);
1715 }
1716
1717 struct playback_task_data {
1718         struct confbridge_conference *conference;
1719         const char *filename;
1720         int say_number;
1721         int playback_finished;
1722         ast_mutex_t lock;
1723         ast_cond_t cond;
1724 };
1725
1726 /*!
1727  * \brief Play an announcement into a confbridge
1728  *
1729  * This runs in the playback queue taskprocessor. This ensures that
1730  * all playbacks are handled in sequence and do not play over top one
1731  * another.
1732  *
1733  * This task runs synchronously so there is no need for performing any
1734  * sort of cleanup on the input parameter.
1735  *
1736  * \param data A playback_task_data
1737  * \return 0
1738  */
1739 static int playback_task(void *data)
1740 {
1741         struct playback_task_data *ptd = data;
1742
1743         playback_common(ptd->conference, ptd->filename, ptd->say_number);
1744
1745         ast_mutex_lock(&ptd->lock);
1746         ptd->playback_finished = 1;
1747         ast_cond_signal(&ptd->cond);
1748         ast_mutex_unlock(&ptd->lock);
1749
1750         return 0;
1751 }
1752
1753 static void playback_task_data_init(struct playback_task_data *ptd, struct confbridge_conference *conference,
1754                 const char *filename, int say_number)
1755 {
1756         ast_mutex_init(&ptd->lock);
1757         ast_cond_init(&ptd->cond, NULL);
1758
1759         ptd->filename = filename;
1760         ptd->say_number = say_number;
1761         ptd->conference = conference;
1762         ptd->playback_finished = 0;
1763 }
1764
1765 static void playback_task_data_destroy(struct playback_task_data *ptd)
1766 {
1767         ast_mutex_destroy(&ptd->lock);
1768         ast_cond_destroy(&ptd->cond);
1769 }
1770
1771 static int play_sound_helper(struct confbridge_conference *conference, const char *filename, int say_number)
1772 {
1773         struct playback_task_data ptd;
1774
1775         /* Do not waste resources trying to play files that do not exist */
1776         if (ast_strlen_zero(filename)) {
1777                 if (say_number < 0) {
1778                         return 0;
1779                 }
1780         } else if (!sound_file_exists(filename)) {
1781                 return 0;
1782         }
1783
1784         playback_task_data_init(&ptd, conference, filename, say_number);
1785         if (ast_taskprocessor_push(conference->playback_queue, playback_task, &ptd)) {
1786                 if (!ast_strlen_zero(filename)) {
1787                         ast_log(LOG_WARNING, "Unable to play file '%s' to conference %s\n",
1788                                 filename, conference->name);
1789                 } else {
1790                         ast_log(LOG_WARNING, "Unable to say number '%d' to conference %s\n",
1791                                 say_number, conference->name);
1792                 }
1793                 playback_task_data_destroy(&ptd);
1794                 return -1;
1795         }
1796
1797         /* Wait for the playback to complete */
1798         ast_mutex_lock(&ptd.lock);
1799         while (!ptd.playback_finished) {
1800                 ast_cond_wait(&ptd.cond, &ptd.lock);
1801         }
1802         ast_mutex_unlock(&ptd.lock);
1803
1804         playback_task_data_destroy(&ptd);
1805
1806         return 0;
1807 }
1808
1809 int play_sound_file(struct confbridge_conference *conference, const char *filename)
1810 {
1811         return play_sound_helper(conference, filename, -1);
1812 }
1813
1814 struct async_playback_task_data {
1815         struct confbridge_conference *conference;
1816         int say_number;
1817         struct ast_channel *initiator;
1818         char filename[0];
1819 };
1820
1821 struct async_datastore_data {
1822         ast_mutex_t lock;
1823         ast_cond_t cond;
1824         int wait;
1825 };
1826
1827 static void async_datastore_data_destroy(void *data)
1828 {
1829         struct async_datastore_data *add = data;
1830
1831         ast_mutex_destroy(&add->lock);
1832         ast_cond_destroy(&add->cond);
1833
1834         ast_free(add);
1835 }
1836
1837 /*!
1838  * \brief Datastore used for timing of async announcement playback
1839  *
1840  * Announcements that are played to the entire conference can be played
1841  * asynchronously (i.e. The channel that queues the playback does not wait
1842  * for the playback to complete before continuing)
1843  *
1844  * The thing about async announcements is that the channel that queues the
1845  * announcement is either not in the bridge or is in some other way "occupied"
1846  * at the time the announcement is queued. Because of that, the initiator of
1847  * the announcement may enter after the announcement has already started,
1848  * resulting in the sound being "clipped".
1849  *
1850  * This datastore makes it so that the channel that queues the async announcement
1851  * can say "I'm ready now". This way the announcement does not start until the
1852  * initiator of the announcement is ready to hear the sound.
1853  */
1854 static struct ast_datastore_info async_datastore_info = {
1855         .type = "Confbridge async playback",
1856         .destroy = async_datastore_data_destroy,
1857 };
1858
1859 static struct async_datastore_data *async_datastore_data_alloc(void)
1860 {
1861         struct async_datastore_data *add;
1862
1863         add = ast_malloc(sizeof(*add));
1864         if (!add) {
1865                 return NULL;
1866         }
1867
1868         ast_mutex_init(&add->lock);
1869         ast_cond_init(&add->cond, NULL);
1870         add->wait = 1;
1871
1872         return add;
1873 }
1874
1875 /*!
1876  * \brief Prepare the async playback datastore
1877  *
1878  * This is done prior to queuing an async announcement. If the
1879  * datastore has not yet been created, it is allocated and initialized.
1880  * If it already exists, we set it to be in "waiting" mode.
1881  *
1882  * \param initiator The channel that is queuing the async playback
1883  * \retval 0 Success
1884  * \retval -1 Failure :(
1885  */
1886 static int setup_async_playback_datastore(struct ast_channel *initiator)
1887 {
1888         struct ast_datastore *async_datastore;
1889
1890         async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
1891         if (async_datastore) {
1892                 struct async_datastore_data *add;
1893
1894                 add = async_datastore->data;
1895                 add->wait = 1;
1896
1897                 return 0;
1898         }
1899
1900         async_datastore = ast_datastore_alloc(&async_datastore_info, NULL);
1901         if (!async_datastore) {
1902                 return -1;
1903         }
1904
1905         async_datastore->data = async_datastore_data_alloc();
1906         if (!async_datastore->data) {
1907                 ast_datastore_free(async_datastore);
1908                 return -1;
1909         }
1910
1911         ast_channel_datastore_add(initiator, async_datastore);
1912         return 0;
1913 }
1914
1915 static struct async_playback_task_data *async_playback_task_data_alloc(
1916         struct confbridge_conference *conference, const char *filename, int say_number,
1917         struct ast_channel *initiator)
1918 {
1919         struct async_playback_task_data *aptd;
1920
1921         aptd = ast_malloc(sizeof(*aptd) + strlen(filename) + 1);
1922         if (!aptd) {
1923                 return NULL;
1924         }
1925
1926         /* Safe */
1927         strcpy(aptd->filename, filename);
1928         aptd->say_number = say_number;
1929
1930         /* You may think that we need to bump the conference refcount since we are pushing
1931          * this task to the taskprocessor.
1932          *
1933          * In this case, that actually causes a problem. The destructor for the conference
1934          * pushes a hangup task into the taskprocessor and waits for it to complete before
1935          * continuing. If the destructor gets called from a taskprocessor task, we're
1936          * deadlocked.
1937          *
1938          * So is there a risk of the conference being freed out from under us? No. Since
1939          * the destructor pushes a task into the taskprocessor and waits for it to complete,
1940          * the destructor cannot free the conference out from under us. No further tasks
1941          * can be queued onto the taskprocessor after the hangup since no channels are referencing
1942          * the conference at that point any more.
1943          */
1944         aptd->conference = conference;
1945
1946         aptd->initiator = initiator;
1947         if (initiator) {
1948                 ast_channel_ref(initiator);
1949                 ast_channel_lock(aptd->initiator);
1950                 /* We don't really care if this fails. If the datastore fails to get set up
1951                  * we'll still play the announcement. It's possible that the sound will be
1952                  * clipped for the initiator, but that's not the end of the world.
1953                  */
1954                 setup_async_playback_datastore(aptd->initiator);
1955                 ast_channel_unlock(aptd->initiator);
1956         }
1957
1958         return aptd;
1959 }
1960
1961 static void async_playback_task_data_destroy(struct async_playback_task_data *aptd)
1962 {
1963         ast_channel_cleanup(aptd->initiator);
1964         ast_free(aptd);
1965 }
1966
1967 /*!
1968  * \brief Wait for the initiator of an async playback to be ready
1969  *
1970  * See the description on the async_datastore_info structure for more
1971  * information about what this is about.
1972  *
1973  * \param initiator The channel that queued the async announcement
1974  */
1975 static void wait_for_initiator(struct ast_channel *initiator)
1976 {
1977         struct ast_datastore *async_datastore;
1978         struct async_datastore_data *add;
1979
1980         ast_channel_lock(initiator);
1981         async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
1982         ast_channel_unlock(initiator);
1983
1984         if (!async_datastore) {
1985                 return;
1986         }
1987
1988         add = async_datastore->data;
1989
1990         ast_mutex_lock(&add->lock);
1991         while (add->wait) {
1992                 ast_cond_wait(&add->cond, &add->lock);
1993         }
1994         ast_mutex_unlock(&add->lock);
1995 }
1996
1997 /*!
1998  * \brief Play an announcement into a confbridge asynchronously
1999  *
2000  * This runs in the playback queue taskprocessor. This ensures that
2001  * all playbacks are handled in sequence and do not play over top one
2002  * another.
2003  *
2004  * \param data An async_playback_task_data
2005  * \return 0
2006  */
2007 static int async_playback_task(void *data)
2008 {
2009         struct async_playback_task_data *aptd = data;
2010
2011         /* Wait for the initiator to get back in the bridge or be hung up */
2012         if (aptd->initiator) {
2013                 wait_for_initiator(aptd->initiator);
2014         }
2015
2016         playback_common(aptd->conference, aptd->filename, aptd->say_number);
2017
2018         async_playback_task_data_destroy(aptd);
2019         return 0;
2020 }
2021
2022 static int async_play_sound_helper(struct confbridge_conference *conference,
2023         const char *filename, int say_number, struct ast_channel *initiator)
2024 {
2025         struct async_playback_task_data *aptd;
2026
2027         /* Do not waste resources trying to play files that do not exist */
2028         if (ast_strlen_zero(filename)) {
2029                 if (say_number < 0) {
2030                         return 0;
2031                 }
2032         } else if (!sound_file_exists(filename)) {
2033                 return 0;
2034         }
2035
2036         aptd = async_playback_task_data_alloc(conference, filename, say_number, initiator);
2037         if (!aptd) {
2038                 return -1;
2039         }
2040
2041         if (ast_taskprocessor_push(conference->playback_queue, async_playback_task, aptd)) {
2042                 if (!ast_strlen_zero(filename)) {
2043                         ast_log(LOG_WARNING, "Unable to play file '%s' to conference '%s'\n",
2044                                 filename, conference->name);
2045                 } else {
2046                         ast_log(LOG_WARNING, "Unable to say number '%d' to conference '%s'\n",
2047                                 say_number, conference->name);
2048                 }
2049                 async_playback_task_data_destroy(aptd);
2050                 return -1;
2051         }
2052
2053         return 0;
2054 }
2055
2056 int async_play_sound_file(struct confbridge_conference *conference,
2057         const char *filename, struct ast_channel *initiator)
2058 {
2059         return async_play_sound_helper(conference, filename, -1, initiator);
2060 }
2061
2062 void async_play_sound_ready(struct ast_channel *chan)
2063 {
2064         struct ast_datastore *async_datastore;
2065         struct async_datastore_data *add;
2066
2067         ast_channel_lock(chan);
2068         async_datastore = ast_channel_datastore_find(chan, &async_datastore_info, NULL);
2069         ast_channel_unlock(chan);
2070         if (!async_datastore) {
2071                 return;
2072         }
2073
2074         add = async_datastore->data;
2075
2076         ast_mutex_lock(&add->lock);
2077         add->wait = 0;
2078         ast_cond_signal(&add->cond);
2079         ast_mutex_unlock(&add->lock);
2080 }
2081
2082 /*!
2083  * \brief Play number into the conference bridge
2084  *
2085  * \param conference The conference bridge to say the number into
2086  * \param say_number number to say
2087  *
2088  * \retval 0 success
2089  * \retval -1 failure
2090  */
2091 static int play_sound_number(struct confbridge_conference *conference, int say_number)
2092 {
2093         return play_sound_helper(conference, NULL, say_number);
2094 }
2095
2096 static int conf_handle_talker_cb(struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking)
2097 {
2098         const struct confbridge_user *user = hook_pvt;
2099         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
2100         struct ast_json *talking_extras;
2101
2102         conference = ao2_find(conference_bridges, user->conference->name, OBJ_KEY);
2103         if (!conference) {
2104                 /* Remove the hook since the conference does not exist. */
2105                 return -1;
2106         }
2107
2108         talking_extras = ast_json_pack("{s: s, s: b}",
2109                 "talking_status", talking ? "on" : "off",
2110                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN));
2111         if (!talking_extras) {
2112                 return 0;
2113         }
2114
2115         send_conf_stasis(conference, bridge_channel->chan, confbridge_talking_type(), talking_extras, 0);
2116         ast_json_unref(talking_extras);
2117         return 0;
2118 }
2119
2120 static int conf_get_pin(struct ast_channel *chan, struct confbridge_user *user)
2121 {
2122         char pin_guess[MAX_PIN+1] = { 0, };
2123         const char *pin = user->u_profile.pin;
2124         char *tmp = pin_guess;
2125         int i, res;
2126         unsigned int len = MAX_PIN;
2127
2128         /*
2129          * NOTE: We have not joined a conference yet so we have to use
2130          * the bridge profile requested by the user.
2131          */
2132
2133         /* give them three tries to get the pin right */
2134         for (i = 0; i < 3; i++) {
2135                 if (ast_app_getdata(chan,
2136                         conf_get_sound(CONF_SOUND_GET_PIN, user->b_profile.sounds),
2137                         tmp, len, 0) >= 0) {
2138                         if (!strcasecmp(pin, pin_guess)) {
2139                                 return 0;
2140                         }
2141                 }
2142                 ast_streamfile(chan,
2143                         conf_get_sound(CONF_SOUND_INVALID_PIN, user->b_profile.sounds),
2144                         ast_channel_language(chan));
2145                 res = ast_waitstream(chan, AST_DIGIT_ANY);
2146                 if (res > 0) {
2147                         /* Account for digit already read during ivalid pin playback
2148                          * resetting pin buf. */
2149                         pin_guess[0] = res;
2150                         pin_guess[1] = '\0';
2151                         tmp = pin_guess + 1;
2152                         len = MAX_PIN - 1;
2153                 } else {
2154                         /* reset pin buf as empty buffer. */
2155                         tmp = pin_guess;
2156                         len = MAX_PIN;
2157                 }
2158         }
2159         return -1;
2160 }
2161
2162 static int user_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
2163 {
2164         ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, 0);
2165         pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "TIMEOUT");
2166         return -1;
2167 }
2168
2169 static int conf_rec_name(struct confbridge_user *user, const char *conf_name)
2170 {
2171         char destdir[PATH_MAX];
2172         int res;
2173         int duration = 20;
2174
2175         snprintf(destdir, sizeof(destdir), "%s/confbridge", ast_config_AST_SPOOL_DIR);
2176
2177         if (ast_mkdir(destdir, 0777) != 0) {
2178                 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno));
2179                 return -1;
2180         }
2181         snprintf(user->name_rec_location, sizeof(user->name_rec_location),
2182                  "%s/confbridge-name-%s-%s", destdir,
2183                  conf_name, ast_channel_uniqueid(user->chan));
2184
2185         if (!(ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW))) {
2186                 res = ast_play_and_record(user->chan,
2187                         "vm-rec-name",
2188                         user->name_rec_location,
2189                         10,
2190                         "sln",
2191                         &duration,
2192                         NULL,
2193                         ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE),
2194                         0,
2195                         NULL);
2196         } else {
2197                 res = ast_record_review(user->chan,
2198                         "vm-rec-name",
2199                         user->name_rec_location,
2200                         10,
2201                         "sln",
2202                         &duration,
2203                         NULL);
2204         }
2205
2206         if (res == -1) {
2207                 ast_filedelete(user->name_rec_location, NULL);
2208                 user->name_rec_location[0] = '\0';
2209                 return -1;
2210         }
2211         return 0;
2212 }
2213
2214 struct async_delete_name_rec_task_data {
2215         struct confbridge_conference *conference;
2216         char filename[0];
2217 };
2218
2219 static struct async_delete_name_rec_task_data *async_delete_name_rec_task_data_alloc(
2220         struct confbridge_conference *conference, const char *filename)
2221 {
2222         struct async_delete_name_rec_task_data *atd;
2223
2224         atd = ast_malloc(sizeof(*atd) + strlen(filename) + 1);
2225         if (!atd) {
2226                 return NULL;
2227         }
2228
2229         /* Safe */
2230         strcpy(atd->filename, filename);
2231         atd->conference = conference;
2232
2233         return atd;
2234 }
2235
2236 static void async_delete_name_rec_task_data_destroy(struct async_delete_name_rec_task_data *atd)
2237 {
2238         ast_free(atd);
2239 }
2240
2241 /*!
2242  * \brief Delete user's name file asynchronously
2243  *
2244  * This runs in the playback queue taskprocessor. This ensures that
2245  * sound file is removed after playback is finished and not before.
2246  *
2247  * \param data An async_delete_name_rec_task_data
2248  * \return 0
2249  */
2250 static int async_delete_name_rec_task(void *data)
2251 {
2252         struct async_delete_name_rec_task_data *atd = data;
2253
2254         ast_filedelete(atd->filename, NULL);
2255         ast_log(LOG_DEBUG, "Conference '%s' removed user name file '%s'\n",
2256                 atd->conference->name, atd->filename);
2257
2258         async_delete_name_rec_task_data_destroy(atd);
2259         return 0;
2260 }
2261
2262 static int async_delete_name_rec(struct confbridge_conference *conference,
2263         const char *filename)
2264 {
2265         struct async_delete_name_rec_task_data *atd;
2266
2267         if (ast_strlen_zero(filename)) {
2268                 return 0;
2269         } else if (!sound_file_exists(filename)) {
2270                 return 0;
2271         }
2272
2273         atd = async_delete_name_rec_task_data_alloc(conference, filename);
2274         if (!atd) {
2275                 return -1;
2276         }
2277
2278         if (ast_taskprocessor_push(conference->playback_queue, async_delete_name_rec_task, atd)) {
2279                 ast_log(LOG_WARNING, "Conference '%s' was unable to remove user name file '%s'\n",
2280                         conference->name, filename);
2281                 async_delete_name_rec_task_data_destroy(atd);
2282                 return -1;
2283         }
2284
2285         return 0;
2286 }
2287
2288 static int join_callback(struct ast_bridge_channel *bridge_channel, void *ignore)
2289 {
2290         async_play_sound_ready(bridge_channel->chan);
2291         return 0;
2292 }
2293
2294 /*! \brief The ConfBridge application */
2295 static int confbridge_exec(struct ast_channel *chan, const char *data)
2296 {
2297         int res = 0, volume_adjustments[2];
2298         int quiet = 0;
2299         int async_delete_task_pushed = 0;
2300         char *parse;
2301         const char *b_profile_name = NULL;
2302         const char *u_profile_name = NULL;
2303         const char *menu_profile_name = NULL;
2304         struct confbridge_conference *conference = NULL;
2305         struct confbridge_user user = {
2306                 .chan = chan,
2307                 .tech_args.talking_threshold = DEFAULT_TALKING_THRESHOLD,
2308                 .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD,
2309                 .tech_args.drop_silence = 0,
2310         };
2311         AST_DECLARE_APP_ARGS(args,
2312                 AST_APP_ARG(conf_name);
2313                 AST_APP_ARG(b_profile_name);
2314                 AST_APP_ARG(u_profile_name);
2315                 AST_APP_ARG(menu_profile_name);
2316         );
2317
2318         if (ast_channel_state(chan) != AST_STATE_UP) {
2319                 ast_answer(chan);
2320         }
2321
2322         if (ast_bridge_features_init(&user.features)) {
2323                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2324                 res = -1;
2325                 goto confbridge_cleanup;
2326         }
2327
2328         /* We need to make a copy of the input string if we are going to modify it! */
2329         parse = ast_strdupa(data);
2330
2331         AST_STANDARD_APP_ARGS(args, parse);
2332
2333         if (ast_strlen_zero(args.conf_name)) {
2334                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2335                 ast_log(LOG_WARNING, "%s requires an argument (conference name[,options])\n", app);
2336                 res = -1;
2337                 goto confbridge_cleanup;
2338         }
2339
2340         if (strlen(args.conf_name) >= MAX_CONF_NAME) {
2341                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2342                 ast_log(LOG_WARNING, "%s does not accept conference names longer than %d\n", app, MAX_CONF_NAME - 1);
2343                 res = -1;
2344                 goto confbridge_cleanup;
2345         }
2346
2347         /* bridge profile name */
2348         if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) {
2349                 b_profile_name = args.b_profile_name;
2350         }
2351         if (!conf_find_bridge_profile(chan, b_profile_name, &user.b_profile)) {
2352                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2353                 ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name ?
2354                         b_profile_name : DEFAULT_BRIDGE_PROFILE);
2355                 res = -1;
2356                 goto confbridge_cleanup;
2357         }
2358
2359         /* user profile name */
2360         if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) {
2361                 u_profile_name = args.u_profile_name;
2362         }
2363         if (!conf_find_user_profile(chan, u_profile_name, &user.u_profile)) {
2364                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2365                 ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name ?
2366                         u_profile_name : DEFAULT_USER_PROFILE);
2367                 res = -1;
2368                 goto confbridge_cleanup;
2369         }
2370
2371         quiet = ast_test_flag(&user.u_profile, USER_OPT_QUIET);
2372
2373         /* ask for a PIN immediately after finding user profile.  This has to be
2374          * prompted for requardless of quiet setting. */
2375         if (!ast_strlen_zero(user.u_profile.pin)) {
2376                 if (conf_get_pin(chan, &user)) {
2377                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2378                         res = -1; /* invalid PIN */
2379                         goto confbridge_cleanup;
2380                 }
2381         }
2382
2383         /* See if we need them to record a intro name */
2384         if (!quiet &&
2385                 (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE) ||
2386                 (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW)))) {
2387                 if (conf_rec_name(&user, args.conf_name)) {
2388                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2389                         res = -1; /* Hangup during name recording */
2390                         goto confbridge_cleanup;
2391                 }
2392         }
2393
2394         /* menu name */
2395         if (args.argc > 3 && !ast_strlen_zero(args.menu_profile_name)) {
2396                 menu_profile_name = args.menu_profile_name;
2397         }
2398
2399         if (conf_set_menu_to_user(chan, &user, menu_profile_name)) {
2400                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2401                 ast_log(LOG_WARNING, "Conference menu profile %s does not exist\n", menu_profile_name ?
2402                         menu_profile_name : DEFAULT_MENU_PROFILE);
2403                 res = -1;
2404                 goto confbridge_cleanup;
2405         }
2406
2407         /* Set if DTMF should pass through for this user or not */
2408         if (ast_test_flag(&user.u_profile, USER_OPT_DTMF_PASS)) {
2409                 user.features.dtmf_passthrough = 1;
2410         } else {
2411                 user.features.dtmf_passthrough = 0;
2412         }
2413
2414         /* Set dsp threshold values if present */
2415         if (user.u_profile.talking_threshold) {
2416                 user.tech_args.talking_threshold = user.u_profile.talking_threshold;
2417         }
2418         if (user.u_profile.silence_threshold) {
2419                 user.tech_args.silence_threshold = user.u_profile.silence_threshold;
2420         }
2421
2422         /* Set a talker indicate call back if talking detection is requested */
2423         if (ast_test_flag(&user.u_profile, USER_OPT_TALKER_DETECT)) {
2424                 if (ast_bridge_talk_detector_hook(&user.features, conf_handle_talker_cb,
2425                         &user, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
2426                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2427                         res = -1;
2428                         goto confbridge_cleanup;
2429                 }
2430         }
2431
2432         /* Look for a conference bridge matching the provided name */
2433         if (!(conference = join_conference_bridge(args.conf_name, &user))) {
2434                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2435                 res = -1;
2436                 goto confbridge_cleanup;
2437         }
2438
2439         /* Keep a copy of volume adjustments so we can restore them later if need be */
2440         volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
2441         volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
2442
2443         if (ast_test_flag(&user.u_profile, USER_OPT_DROP_SILENCE)) {
2444                 user.tech_args.drop_silence = 1;
2445         }
2446
2447         if (ast_test_flag(&user.u_profile, USER_OPT_JITTERBUFFER)) {
2448                 ast_func_write(chan, "JITTERBUFFER(adaptive)", "default");
2449         }
2450
2451         if (ast_test_flag(&user.u_profile, USER_OPT_DENOISE)) {
2452                 ast_func_write(chan, "DENOISE(rx)", "on");
2453         }
2454
2455         /* if this user has a intro, play it before entering */
2456         if (!ast_strlen_zero(user.name_rec_location)) {
2457                 ast_autoservice_start(chan);
2458                 play_sound_file(conference, user.name_rec_location);
2459                 play_sound_file(conference,
2460                         conf_get_sound(CONF_SOUND_HAS_JOINED, conference->b_profile.sounds));
2461                 ast_autoservice_stop(chan);
2462         }
2463
2464         /* Play the Join sound to both the conference and the user entering. */
2465         if (!quiet) {
2466                 const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference->b_profile.sounds);
2467
2468                 if (strcmp(conference->b_profile.language, ast_channel_language(chan))) {
2469                         ast_stream_and_wait(chan, join_sound, "");
2470                         ast_autoservice_start(chan);
2471                         play_sound_file(conference, join_sound);
2472                         ast_autoservice_stop(chan);
2473                 } else {
2474                         async_play_sound_file(conference, join_sound, chan);
2475                 }
2476         }
2477
2478         if (user.u_profile.timeout) {
2479                 ast_bridge_interval_hook(&user.features,
2480                         0,
2481                         user.u_profile.timeout * 1000,
2482                         user_timeout,
2483                         NULL,
2484                         NULL,
2485                         AST_BRIDGE_HOOK_REMOVE_ON_PULL);
2486         }
2487
2488         /* See if we need to automatically set this user as a video source or not */
2489         handle_video_on_join(conference, user.chan, ast_test_flag(&user.u_profile, USER_OPT_MARKEDUSER));
2490
2491         conf_moh_unsuspend(&user);
2492
2493         /* Join our conference bridge for real */
2494         send_join_event(&user, conference);
2495
2496         if (ast_bridge_join_hook(&user.features, join_callback, NULL, NULL, 0)) {
2497                 async_play_sound_ready(user.chan);
2498         }
2499
2500         ast_bridge_join(conference->bridge,
2501                 chan,
2502                 NULL,
2503                 &user.features,
2504                 &user.tech_args,
2505                 0);
2506
2507         /* This is a catch-all in case joining the bridge failed or for some reason
2508          * an async announcement got queued up and hasn't been told to play yet
2509          */
2510         async_play_sound_ready(chan);
2511
2512         if (!user.kicked && ast_check_hangup(chan)) {
2513                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "HANGUP");
2514         }
2515
2516         send_leave_event(&user, conference);
2517
2518         /* if we're shutting down, don't attempt to do further processing */
2519         if (ast_shutting_down()) {
2520                 /*
2521                  * Not taking any new calls at this time.  We cannot create
2522                  * the announcer channel if this is the first channel into
2523                  * the conference and we certainly cannot create any
2524                  * recording channel.
2525                  */
2526                 leave_conference(&user);
2527                 conference = NULL;
2528                 goto confbridge_cleanup;
2529         }
2530
2531         /* If this user was a video source, we need to clean up and possibly pick a new source. */
2532         handle_video_on_exit(conference, user.chan);
2533
2534         /* if this user has a intro, play it when leaving */
2535         if (!quiet && !ast_strlen_zero(user.name_rec_location)) {
2536                 async_play_sound_file(conference, user.name_rec_location, NULL);
2537                 async_play_sound_file(conference,
2538                         conf_get_sound(CONF_SOUND_HAS_LEFT, conference->b_profile.sounds), NULL);
2539                 async_delete_name_rec(conference, user.name_rec_location);
2540                 async_delete_task_pushed = 1;
2541         }
2542
2543         /* play the leave sound */
2544         if (!quiet) {
2545                 const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, conference->b_profile.sounds);
2546                 async_play_sound_file(conference, leave_sound, NULL);
2547         }
2548
2549         /* If the user was kicked from the conference play back the audio prompt for it */
2550         if (!quiet && user.kicked) {
2551                 res = ast_stream_and_wait(chan,
2552                         conf_get_sound(CONF_SOUND_KICKED, conference->b_profile.sounds),
2553                         "");
2554         }
2555
2556         /* Easy as pie, depart this channel from the conference bridge */
2557         leave_conference(&user);
2558         conference = NULL;
2559
2560         /* Restore volume adjustments to previous values in case they were changed */
2561         if (volume_adjustments[0]) {
2562                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
2563         }
2564         if (volume_adjustments[1]) {
2565                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
2566         }
2567
2568 confbridge_cleanup:
2569         if (!async_delete_task_pushed && !ast_strlen_zero(user.name_rec_location)) {
2570                 ast_filedelete(user.name_rec_location, NULL);
2571         }
2572         ast_bridge_features_cleanup(&user.features);
2573         conf_bridge_profile_destroy(&user.b_profile);
2574         return res;
2575 }
2576
2577 static int action_toggle_mute(struct confbridge_conference *conference,
2578                               struct confbridge_user *user,
2579                               struct ast_bridge_channel *bridge_channel)
2580 {
2581         int mute;
2582
2583         /* Toggle user level mute request. */
2584         mute = !user->muted;
2585         generic_mute_unmute_user(conference, user, mute);
2586
2587         return play_file(bridge_channel, NULL,
2588                 conf_get_sound(mute ? CONF_SOUND_MUTED : CONF_SOUND_UNMUTED,
2589                         conference->b_profile.sounds)) < 0;
2590 }
2591
2592 static int action_toggle_binaural(struct confbridge_conference *conference,
2593                 struct confbridge_user *user,
2594                 struct ast_bridge_channel *bridge_channel)
2595 {
2596         unsigned int binaural;
2597         ast_bridge_channel_lock_bridge(bridge_channel);
2598         binaural = !bridge_channel->binaural_suspended;
2599         bridge_channel->binaural_suspended = binaural;
2600         ast_bridge_unlock(bridge_channel->bridge);
2601         return play_file(bridge_channel, NULL, (binaural ?
2602                                 conf_get_sound(CONF_SOUND_BINAURAL_OFF, user->b_profile.sounds) :
2603                                 conf_get_sound(CONF_SOUND_BINAURAL_ON, user->b_profile.sounds))) < 0;
2604 }
2605
2606 static int action_toggle_mute_participants(struct confbridge_conference *conference, struct confbridge_user *user)
2607 {
2608         struct confbridge_user *cur_user = NULL;
2609         const char *sound_to_play;
2610         int mute;
2611
2612         ao2_lock(conference);
2613
2614         /* Toggle bridge level mute request. */
2615         mute = !conference->muted;
2616         conference->muted = mute;
2617
2618         AST_LIST_TRAVERSE(&conference->active_list, cur_user, list) {
2619                 if (!ast_test_flag(&cur_user->u_profile, USER_OPT_ADMIN)) {
2620                         /* Set user level to bridge level mute request. */
2621                         cur_user->muted = mute;
2622                         conf_update_user_mute(cur_user);
2623                 }
2624         }
2625
2626         ao2_unlock(conference);
2627
2628         sound_to_play = conf_get_sound(
2629                 mute ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED,
2630                 conference->b_profile.sounds);
2631
2632         if (strcmp(conference->b_profile.language, ast_channel_language(user->chan))) {
2633                 /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */
2634                 ast_stream_and_wait(user->chan, sound_to_play, "");
2635
2636                 /* Announce to the group that all participants are muted */
2637                 ast_autoservice_start(user->chan);
2638                 play_sound_file(conference, sound_to_play);
2639                 ast_autoservice_stop(user->chan);
2640         } else {
2641                 /* Playing the sound asynchronously lets the sound be heard by everyone at once */
2642                 async_play_sound_file(conference, sound_to_play, user->chan);
2643         }
2644
2645         return 0;
2646 }
2647
2648 static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
2649 {
2650         char *file_copy = ast_strdupa(playback_file);
2651         char *file = NULL;
2652
2653         while ((file = strsep(&file_copy, "&"))) {
2654                 if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
2655                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
2656                         return -1;
2657                 }
2658         }
2659         return 0;
2660 }
2661
2662 static int action_playback_and_continue(struct confbridge_conference *conference,
2663         struct confbridge_user *user,
2664         struct ast_bridge_channel *bridge_channel,
2665         struct conf_menu *menu,
2666         const char *playback_file,
2667         const char *cur_dtmf,
2668         int *stop_prompts)
2669 {
2670         int i;
2671         int digit = 0;
2672         char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
2673         struct conf_menu_entry new_menu_entry = { { 0, }, };
2674         char *file_copy = ast_strdupa(playback_file);
2675         char *file = NULL;
2676
2677         while ((file = strsep(&file_copy, "&"))) {
2678                 if (ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan))) {
2679                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
2680                         return -1;
2681                 }
2682
2683                 /* now wait for more digits. */
2684                 if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) {
2685                         /* streaming finished and no DTMF was entered */
2686                         continue;
2687                 } else if (digit == -1) {
2688                         /* error */
2689                         return -1;
2690                 } else {
2691                         break; /* dtmf was entered */
2692                 }
2693         }
2694         if (!digit) {
2695                 /* streaming finished on all files and no DTMF was entered */
2696                 return -1;
2697         }
2698         ast_stopstream(bridge_channel->chan);
2699
2700         /* If we get here, then DTMF has been entered, This means no
2701          * additional prompts should be played for this menu entry */
2702         *stop_prompts = 1;
2703
2704         /* If a digit was pressed during the payback, update
2705          * the dtmf string and look for a new menu entry in the
2706          * menu structure */
2707         ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf));
2708         for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) {
2709                 dtmf[i] = cur_dtmf[i];
2710                 if (!dtmf[i]) {
2711                         dtmf[i] = (char) digit;
2712                         dtmf[i + 1] = '\0';
2713                         i = -1;
2714                         break;
2715                 }
2716         }
2717         /* If i is not -1 then the new dtmf digit was _NOT_ added to the string.
2718          * If this is the case, no new DTMF sequence should be looked for. */
2719         if (i != -1) {
2720                 return 0;
2721         }
2722
2723         if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) {
2724                 execute_menu_entry(conference,
2725                         user,
2726                         bridge_channel,
2727                         &new_menu_entry, menu);
2728                 conf_menu_entry_destroy(&new_menu_entry);
2729         }
2730         return 0;
2731 }
2732
2733 static int action_kick_last(struct confbridge_conference *conference,
2734         struct ast_bridge_channel *bridge_channel,
2735         struct confbridge_user *user)
2736 {
2737         struct confbridge_user *last_user = NULL;
2738         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
2739
2740         if (!isadmin) {
2741                 play_file(bridge_channel, NULL,
2742                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference->b_profile.sounds));
2743                 ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
2744                         ast_channel_name(bridge_channel->chan),
2745                         conference->name);
2746                 return -1;
2747         }
2748
2749         ao2_lock(conference);
2750         last_user = AST_LIST_LAST(&conference->active_list);
2751         if (!last_user) {
2752                 ao2_unlock(conference);
2753                 return 0;
2754         }
2755
2756         if (last_user == user || ast_test_flag(&last_user->u_profile, USER_OPT_ADMIN)) {
2757                 ao2_unlock(conference);
2758                 play_file(bridge_channel, NULL,
2759                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference->b_profile.sounds));
2760         } else if (!last_user->kicked) {
2761                 last_user->kicked = 1;
2762                 pbx_builtin_setvar_helper(last_user->chan, "CONFBRIDGE_RESULT", "KICKED");
2763                 ast_bridge_remove(conference->bridge, last_user->chan);
2764                 ao2_unlock(conference);
2765         }
2766
2767         return 0;
2768 }
2769
2770 static int action_dialplan_exec(struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
2771 {
2772         struct ast_pbx_args args;
2773         struct ast_pbx *pbx;
2774         char *exten;
2775         char *context;
2776         int priority;
2777         int res;
2778
2779         memset(&args, 0, sizeof(args));
2780         args.no_hangup_chan = 1;
2781
2782         ast_channel_lock(bridge_channel->chan);
2783
2784         /*save off*/
2785         exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
2786         context = ast_strdupa(ast_channel_context(bridge_channel->chan));
2787         priority = ast_channel_priority(bridge_channel->chan);
2788         pbx = ast_channel_pbx(bridge_channel->chan);
2789         ast_channel_pbx_set(bridge_channel->chan, NULL);
2790
2791         /*set new*/
2792         ast_channel_exten_set(bridge_channel->chan, menu_action->data.dialplan_args.exten);
2793         ast_channel_context_set(bridge_channel->chan, menu_action->data.dialplan_args.context);
2794         ast_channel_priority_set(bridge_channel->chan, menu_action->data.dialplan_args.priority);
2795
2796         ast_channel_unlock(bridge_channel->chan);
2797
2798         /*execute*/
2799         res = ast_pbx_run_args(bridge_channel->chan, &args);
2800
2801         /*restore*/
2802         ast_channel_lock(bridge_channel->chan);
2803
2804         ast_channel_exten_set(bridge_channel->chan, exten);
2805         ast_channel_context_set(bridge_channel->chan, context);
2806         ast_channel_priority_set(bridge_channel->chan, priority);
2807         ast_channel_pbx_set(bridge_channel->chan, pbx);
2808
2809         ast_channel_unlock(bridge_channel->chan);
2810
2811         return res;
2812 }
2813
2814 static int execute_menu_entry(struct confbridge_conference *conference,
2815         struct confbridge_user *user,
2816         struct ast_bridge_channel *bridge_channel,
2817         struct conf_menu_entry *menu_entry,
2818         struct conf_menu *menu)
2819 {
2820         struct conf_menu_action *menu_action;
2821         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
2822         int stop_prompts = 0;
2823         int res = 0;
2824
2825         AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
2826                 switch (menu_action->id) {
2827                 case MENU_ACTION_TOGGLE_MUTE:
2828                         res |= action_toggle_mute(conference, user, bridge_channel);
2829                         break;
2830                 case MENU_ACTION_TOGGLE_BINAURAL:
2831                         action_toggle_binaural(conference, user, bridge_channel);
2832                         break;
2833                 case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
2834                         if (!isadmin) {
2835                                 break;
2836                         }
2837                         action_toggle_mute_participants(conference, user);
2838                         break;
2839                 case MENU_ACTION_PARTICIPANT_COUNT:
2840                         announce_user_count(conference, user, bridge_channel);
2841                         break;
2842                 case MENU_ACTION_PLAYBACK:
2843                         if (!stop_prompts) {
2844                                 res |= action_playback(bridge_channel, menu_action->data.playback_file);
2845                                 ast_test_suite_event_notify("CONF_MENU_PLAYBACK",
2846                                         "Message: %s\r\nChannel: %s",
2847                                         menu_action->data.playback_file, ast_channel_name(bridge_channel->chan));
2848                         }
2849                         break;
2850                 case MENU_ACTION_RESET_LISTENING:
2851                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 0);
2852                         break;
2853                 case MENU_ACTION_RESET_TALKING:
2854                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_READ, 0);
2855                         break;
2856                 case MENU_ACTION_INCREASE_LISTENING:
2857                         ast_audiohook_volume_adjust(user->chan,
2858                                 AST_AUDIOHOOK_DIRECTION_WRITE, 1);
2859                         break;
2860                 case MENU_ACTION_DECREASE_LISTENING:
2861                         ast_audiohook_volume_adjust(user->chan,
2862                                 AST_AUDIOHOOK_DIRECTION_WRITE, -1);
2863                         break;
2864                 case MENU_ACTION_INCREASE_TALKING:
2865                         ast_audiohook_volume_adjust(user->chan,
2866                                 AST_AUDIOHOOK_DIRECTION_READ, 1);
2867                         break;
2868                 case MENU_ACTION_DECREASE_TALKING:
2869                         ast_audiohook_volume_adjust(user->chan,
2870                                 AST_AUDIOHOOK_DIRECTION_READ, -1);
2871                         break;
2872                 case MENU_ACTION_PLAYBACK_AND_CONTINUE:
2873                         if (!(stop_prompts)) {
2874                                 res |= action_playback_and_continue(conference,
2875                                         user,
2876                                         bridge_channel,
2877                                         menu,
2878                                         menu_action->data.playback_file,
2879                                         menu_entry->dtmf,
2880                                         &stop_prompts);
2881                         }
2882                         break;
2883                 case MENU_ACTION_DIALPLAN_EXEC:
2884                         res |= action_dialplan_exec(bridge_channel, menu_action);
2885                         break;
2886                 case MENU_ACTION_ADMIN_TOGGLE_LOCK:
2887                         if (!isadmin) {
2888                                 break;
2889                         }
2890                         conference->locked = (!conference->locked ? 1 : 0);
2891                         res |= play_file(bridge_channel, NULL,
2892                                 conf_get_sound(
2893                                         conference->locked ? CONF_SOUND_LOCKED_NOW : CONF_SOUND_UNLOCKED_NOW,
2894                                         conference->b_profile.sounds)) < 0;
2895                         break;
2896                 case MENU_ACTION_ADMIN_KICK_LAST:
2897                         res |= action_kick_last(conference, bridge_channel, user);
2898                         break;
2899                 case MENU_ACTION_LEAVE:
2900                         pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "DTMF");
2901                         ao2_lock(conference);
2902                         ast_bridge_remove(conference->bridge, bridge_channel->chan);
2903                         ast_test_suite_event_notify("CONF_MENU_LEAVE",
2904                                 "Channel: %s",
2905                                 ast_channel_name(bridge_channel->chan));
2906                         ao2_unlock(conference);
2907                         break;
2908                 case MENU_ACTION_NOOP:
2909                         break;
2910                 case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
2911                         ao2_lock(conference);
2912                         if (!ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_SFU)) {
2913                                 ast_bridge_set_single_src_video_mode(conference->bridge, bridge_channel->chan);
2914                         }
2915                         ao2_unlock(conference);
2916                         break;
2917                 case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
2918                         handle_video_on_exit(conference, bridge_channel->chan);
2919                         break;
2920                 }
2921         }
2922         return res;
2923 }
2924
2925 int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
2926         struct confbridge_user *user,
2927         struct conf_menu_entry *menu_entry,
2928         struct conf_menu *menu)
2929 {
2930         /* See if music on hold is playing */
2931         conf_moh_suspend(user);
2932
2933         /* execute the list of actions associated with this menu entry */
2934         execute_menu_entry(user->conference, user, bridge_channel, menu_entry, menu);
2935
2936         /* See if music on hold needs to be started back up again */
2937         conf_moh_unsuspend(user);
2938
2939         async_play_sound_ready(bridge_channel->chan);
2940
2941         return 0;
2942 }
2943
2944 static int kick_conference_participant(struct confbridge_conference *conference,
2945         const char *channel)
2946 {
2947         int res = -1;
2948         int match;
2949         struct confbridge_user *user = NULL;
2950         int all = !strcasecmp("all", channel);
2951         int participants = !strcasecmp("participants", channel);
2952
2953         SCOPED_AO2LOCK(bridge_lock, conference);
2954
2955         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2956                 if (user->kicked) {
2957                         continue;
2958                 }
2959                 match = !strcasecmp(channel, ast_channel_name(user->chan));
2960                 if (match || all
2961                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
2962                         user->kicked = 1;
2963                         pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
2964                         ast_bridge_remove(conference->bridge, user->chan);
2965                         res = 0;
2966                         if (match) {
2967                                 return res;
2968                         }
2969                 }
2970         }
2971         AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2972                 if (user->kicked) {
2973                         continue;
2974                 }
2975                 match = !strcasecmp(channel, ast_channel_name(user->chan));
2976                 if (match || all
2977                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
2978                         user->kicked = 1;
2979                         pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
2980                         ast_bridge_remove(conference->bridge, user->chan);
2981                         res = 0;
2982                         if (match) {
2983                                 return res;
2984                         }
2985                 }
2986         }
2987
2988         return res;
2989 }
2990
2991 static char *complete_confbridge_name(const char *line, const char *word, int pos, int state)
2992 {
2993         int which = 0;
2994         struct confbridge_conference *conference;
2995         char *res = NULL;
2996         int wordlen = strlen(word);
2997         struct ao2_iterator iter;
2998
2999         iter = ao2_iterator_init(conference_bridges, 0);
3000         while ((conference = ao2_iterator_next(&iter))) {
3001                 if (!strncasecmp(conference->name, word, wordlen) && ++which > state) {
3002                         res = ast_strdup(conference->name);
3003                         ao2_ref(conference, -1);
3004                         break;
3005                 }
3006                 ao2_ref(conference, -1);
3007         }
3008         ao2_iterator_destroy(&iter);
3009
3010         return res;
3011 }
3012
3013 static char *complete_confbridge_participant(const char *conference_name, const char *line, const char *word, int pos, int state)
3014 {
3015         int which = 0;
3016         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
3017         struct confbridge_user *user;
3018         char *res = NULL;
3019         int wordlen = strlen(word);
3020
3021         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3022         if (!conference) {
3023                 return NULL;
3024         }
3025
3026         if (!strncasecmp("all", word, wordlen) && ++which > state) {
3027                 return ast_strdup("all");
3028         }
3029
3030         if (!strncasecmp("participants", word, wordlen) && ++which > state) {
3031                 return ast_strdup("participants");
3032         }
3033
3034         {
3035                 SCOPED_AO2LOCK(bridge_lock, conference);
3036                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
3037                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
3038                                 res = ast_strdup(ast_channel_name(user->chan));
3039                                 return res;
3040                         }
3041                 }
3042                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
3043                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
3044                                 res = ast_strdup(ast_channel_name(user->chan));
3045                                 return res;
3046                         }
3047                 }
3048         }
3049
3050         return NULL;
3051 }
3052
3053 static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3054 {
3055         struct confbridge_conference *conference;
3056         int not_found;
3057
3058         switch (cmd) {
3059         case CLI_INIT:
3060                 e->command = "confbridge kick";
3061                 e->usage =
3062                         "Usage: confbridge kick <conference> <channel>\n"
3063                         "       Kicks a channel out of the conference bridge.\n"
3064                         "             (all to kick everyone, participants to kick non-admins).\n";
3065                 return NULL;
3066         case CLI_GENERATE:
3067                 if (a->pos == 2) {
3068                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3069                 }
3070                 if (a->pos == 3) {
3071                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
3072                 }
3073                 return NULL;
3074         }
3075
3076         if (a->argc != 4) {
3077                 return CLI_SHOWUSAGE;
3078         }
3079
3080         conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
3081         if (!conference) {
3082                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
3083                 return CLI_SUCCESS;
3084         }
3085         not_found = kick_conference_participant(conference, a->argv[3]);
3086         ao2_ref(conference, -1);
3087         if (not_found) {
3088                 if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
3089                         ast_cli(a->fd, "No participants found!\n");
3090                 } else {
3091                         ast_cli(a->fd, "No participant named '%s' found!\n", a->argv[3]);
3092                 }
3093                 return CLI_SUCCESS;
3094         }
3095         ast_cli(a->fd, "Kicked '%s' out of conference '%s'\n", a->argv[3], a->argv[2]);
3096         return CLI_SUCCESS;
3097 }
3098
3099 static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct confbridge_user *user, int waiting)
3100 {
3101         char flag_str[6 + 1];/* Max flags + terminator */
3102         int pos = 0;
3103
3104         /* Build flags column string. */
3105         if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
3106                 flag_str[pos++] = 'A';
3107         }
3108         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
3109                 flag_str[pos++] = 'M';
3110         }
3111         if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
3112                 flag_str[pos++] = 'W';
3113         }
3114         if (ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED)) {
3115                 flag_str[pos++] = 'E';
3116         }
3117         if (user->muted) {
3118                 flag_str[pos++] = 'm';
3119         }
3120         if (waiting) {
3121                 flag_str[pos++] = 'w';
3122         }
3123         flag_str[pos] = '\0';
3124
3125         ast_cli(a->fd, "%-30s %-6s %-16s %-16s %-16s %s\n",
3126                 ast_channel_name(user->chan),
3127                 flag_str,
3128                 user->u_profile.name,
3129                 user->conference->b_profile.name,
3130                 user->menu_name,
3131                 S_COR(ast_channel_caller(user->chan)->id.number.valid,
3132                         ast_channel_caller(user->chan)->id.number.str, "<unknown>"));
3133 }
3134
3135 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3136 {
3137         struct confbridge_conference *conference;
3138
3139         switch (cmd) {
3140         case CLI_INIT:
3141                 e->command = "confbridge list";
3142                 e->usage =
3143                         "Usage: confbridge list [<name>]\n"
3144                         "       Lists all currently active conference bridges or a specific conference bridge.\n"
3145                         "\n"
3146                         "       When a conference bridge name is provided, flags may be shown for users. Below\n"