Merge "AST-2018-005: Fix tdata leaks when calling pjsip_endpt_send_response(2)"
[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                 }
1547
1548                 /* Link it into the conference bridges container */
1549                 if (!ao2_link(conference_bridges, conference)) {
1550                         ao2_ref(conference, -1);
1551                         ao2_unlock(conference_bridges);
1552                         ast_log(LOG_ERROR,
1553                                 "Conference '%s' could not be added to the conferences list.\n", conference_name);
1554                         return NULL;
1555                 }
1556
1557                 /* Set the initial state to EMPTY */
1558                 conference->state = CONF_STATE_EMPTY;
1559
1560                 if (alloc_playback_chan(conference)) {
1561                         ao2_unlink(conference_bridges, conference);
1562                         ao2_ref(conference, -1);
1563                         ao2_unlock(conference_bridges);
1564                         ast_log(LOG_ERROR, "Could not allocate announcer channel for conference '%s'\n", conference_name);
1565                         return NULL;
1566                 }
1567
1568                 if (ast_taskprocessor_push(conference->playback_queue, push_announcer, ao2_bump(conference))) {
1569                         ao2_unlink(conference_bridges, conference);
1570                         ao2_ref(conference, -1);
1571                         ao2_unlock(conference_bridges);
1572                         ast_log(LOG_ERROR, "Could not add announcer channel for conference '%s' bridge\n", conference_name);
1573                         return NULL;
1574                 }
1575
1576                 if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_CONFERENCE)) {
1577                         ao2_lock(conference);
1578                         conf_start_record(conference);
1579                         ao2_unlock(conference);
1580                 }
1581
1582                 send_conf_start_event(conference);
1583
1584                 if (!ast_strlen_zero(conference->b_profile.regcontext)) {
1585                         if (!ast_exists_extension(NULL, conference->b_profile.regcontext, conference->name, 1, NULL)) {
1586                                 ast_add_extension(conference->b_profile.regcontext, 1, conference->name, 1, NULL, NULL, "Noop", NULL, NULL, "ConfBridge");
1587                         }
1588                 }
1589
1590                 ast_debug(1, "Created conference '%s' and linked to container.\n", conference_name);
1591         }
1592
1593         ao2_unlock(conference_bridges);
1594
1595         /* Setup conference bridge user parameters */
1596         user->conference = conference;
1597
1598         ao2_lock(conference);
1599
1600         /* Determine if the new user should join the conference muted. */
1601         if (ast_test_flag(&user->u_profile, USER_OPT_STARTMUTED)
1602                 || (!ast_test_flag(&user->u_profile, USER_OPT_ADMIN) && conference->muted)) {
1603                 /* Set user level mute request. */
1604                 user->muted = 1;
1605         }
1606
1607         /*
1608          * Suspend any MOH until the user actually joins the bridge of
1609          * the conference.  This way any pre-join file playback does not
1610          * need to worry about MOH.
1611          */
1612         user->suspended_moh = 1;
1613
1614         if (handle_conf_user_join(user)) {
1615                 /* Invalid event, nothing was done, so we don't want to process a leave. */
1616                 ao2_unlock(conference);
1617                 ao2_ref(conference, -1);
1618                 user->conference = NULL;
1619                 return NULL;
1620         }
1621
1622         if (ast_check_hangup(user->chan)) {
1623                 ao2_unlock(conference);
1624                 leave_conference(user);
1625                 return NULL;
1626         }
1627
1628         ao2_unlock(conference);
1629
1630         /* If an announcement is to be played play it */
1631         if (!ast_strlen_zero(user->u_profile.announcement)) {
1632                 if (play_prompt_to_user(user,
1633                         user->u_profile.announcement)) {
1634                         leave_conference(user);
1635                         return NULL;
1636                 }
1637         }
1638
1639         /* Announce number of users if need be */
1640         if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) {
1641                 if (announce_user_count(conference, user, NULL)) {
1642                         leave_conference(user);
1643                         return NULL;
1644                 }
1645         }
1646
1647         if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) &&
1648                 (conference->activeusers > user->u_profile.announce_user_count_all_after)) {
1649                 int user_count_res;
1650
1651                 /*
1652                  * We have to autoservice the new user because he has not quite
1653                  * joined the conference yet.
1654                  */
1655                 ast_autoservice_start(user->chan);
1656                 user_count_res = announce_user_count(conference, NULL, NULL);
1657                 ast_autoservice_stop(user->chan);
1658                 if (user_count_res) {
1659                         leave_conference(user);
1660                         return NULL;
1661                 }
1662         }
1663
1664         /* Handle post-join actions */
1665         while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
1666                 action->func(user);
1667                 ast_free(action);
1668         }
1669
1670         return conference;
1671 }
1672
1673 /*!
1674  * \brief Leave a conference
1675  *
1676  * \param user The conference user
1677  */
1678 static void leave_conference(struct confbridge_user *user)
1679 {
1680         struct post_join_action *action;
1681
1682         ao2_lock(user->conference);
1683         handle_conf_user_leave(user);
1684         ao2_unlock(user->conference);
1685
1686         /* Discard any post-join actions */
1687         while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
1688                 ast_free(action);
1689         }
1690
1691         /* Done mucking with the conference, huzzah */
1692         ao2_ref(user->conference, -1);
1693         user->conference = NULL;
1694 }
1695
1696 static void playback_common(struct confbridge_conference *conference, const char *filename, int say_number)
1697 {
1698         /* Don't try to play if the playback channel has been hung up */
1699         if (!conference->playback_chan) {
1700                 return;
1701         }
1702
1703         ast_autoservice_stop(conference->playback_chan);
1704
1705         /* The channel is all under our control, in goes the prompt */
1706         if (!ast_strlen_zero(filename)) {
1707                 ast_stream_and_wait(conference->playback_chan, filename, "");
1708         } else if (say_number >= 0) {
1709                 ast_say_number(conference->playback_chan, say_number, "",
1710                         ast_channel_language(conference->playback_chan), NULL);
1711         }
1712
1713         ast_autoservice_start(conference->playback_chan);
1714 }
1715
1716 struct playback_task_data {
1717         struct confbridge_conference *conference;
1718         const char *filename;
1719         int say_number;
1720         int playback_finished;
1721         ast_mutex_t lock;
1722         ast_cond_t cond;
1723 };
1724
1725 /*!
1726  * \brief Play an announcement into a confbridge
1727  *
1728  * This runs in the playback queue taskprocessor. This ensures that
1729  * all playbacks are handled in sequence and do not play over top one
1730  * another.
1731  *
1732  * This task runs synchronously so there is no need for performing any
1733  * sort of cleanup on the input parameter.
1734  *
1735  * \param data A playback_task_data
1736  * \return 0
1737  */
1738 static int playback_task(void *data)
1739 {
1740         struct playback_task_data *ptd = data;
1741
1742         playback_common(ptd->conference, ptd->filename, ptd->say_number);
1743
1744         ast_mutex_lock(&ptd->lock);
1745         ptd->playback_finished = 1;
1746         ast_cond_signal(&ptd->cond);
1747         ast_mutex_unlock(&ptd->lock);
1748
1749         return 0;
1750 }
1751
1752 static void playback_task_data_init(struct playback_task_data *ptd, struct confbridge_conference *conference,
1753                 const char *filename, int say_number)
1754 {
1755         ast_mutex_init(&ptd->lock);
1756         ast_cond_init(&ptd->cond, NULL);
1757
1758         ptd->filename = filename;
1759         ptd->say_number = say_number;
1760         ptd->conference = conference;
1761         ptd->playback_finished = 0;
1762 }
1763
1764 static void playback_task_data_destroy(struct playback_task_data *ptd)
1765 {
1766         ast_mutex_destroy(&ptd->lock);
1767         ast_cond_destroy(&ptd->cond);
1768 }
1769
1770 static int play_sound_helper(struct confbridge_conference *conference, const char *filename, int say_number)
1771 {
1772         struct playback_task_data ptd;
1773
1774         /* Do not waste resources trying to play files that do not exist */
1775         if (ast_strlen_zero(filename)) {
1776                 if (say_number < 0) {
1777                         return 0;
1778                 }
1779         } else if (!sound_file_exists(filename)) {
1780                 return 0;
1781         }
1782
1783         playback_task_data_init(&ptd, conference, filename, say_number);
1784         if (ast_taskprocessor_push(conference->playback_queue, playback_task, &ptd)) {
1785                 if (!ast_strlen_zero(filename)) {
1786                         ast_log(LOG_WARNING, "Unable to play file '%s' to conference %s\n",
1787                                 filename, conference->name);
1788                 } else {
1789                         ast_log(LOG_WARNING, "Unable to say number '%d' to conference %s\n",
1790                                 say_number, conference->name);
1791                 }
1792                 playback_task_data_destroy(&ptd);
1793                 return -1;
1794         }
1795
1796         /* Wait for the playback to complete */
1797         ast_mutex_lock(&ptd.lock);
1798         while (!ptd.playback_finished) {
1799                 ast_cond_wait(&ptd.cond, &ptd.lock);
1800         }
1801         ast_mutex_unlock(&ptd.lock);
1802
1803         playback_task_data_destroy(&ptd);
1804
1805         return 0;
1806 }
1807
1808 int play_sound_file(struct confbridge_conference *conference, const char *filename)
1809 {
1810         return play_sound_helper(conference, filename, -1);
1811 }
1812
1813 struct async_playback_task_data {
1814         struct confbridge_conference *conference;
1815         int say_number;
1816         struct ast_channel *initiator;
1817         char filename[0];
1818 };
1819
1820 struct async_datastore_data {
1821         ast_mutex_t lock;
1822         ast_cond_t cond;
1823         int wait;
1824 };
1825
1826 static void async_datastore_data_destroy(void *data)
1827 {
1828         struct async_datastore_data *add = data;
1829
1830         ast_mutex_destroy(&add->lock);
1831         ast_cond_destroy(&add->cond);
1832
1833         ast_free(add);
1834 }
1835
1836 /*!
1837  * \brief Datastore used for timing of async announcement playback
1838  *
1839  * Announcements that are played to the entire conference can be played
1840  * asynchronously (i.e. The channel that queues the playback does not wait
1841  * for the playback to complete before continuing)
1842  *
1843  * The thing about async announcements is that the channel that queues the
1844  * announcement is either not in the bridge or is in some other way "occupied"
1845  * at the time the announcement is queued. Because of that, the initiator of
1846  * the announcement may enter after the announcement has already started,
1847  * resulting in the sound being "clipped".
1848  *
1849  * This datastore makes it so that the channel that queues the async announcement
1850  * can say "I'm ready now". This way the announcement does not start until the
1851  * initiator of the announcement is ready to hear the sound.
1852  */
1853 static struct ast_datastore_info async_datastore_info = {
1854         .type = "Confbridge async playback",
1855         .destroy = async_datastore_data_destroy,
1856 };
1857
1858 static struct async_datastore_data *async_datastore_data_alloc(void)
1859 {
1860         struct async_datastore_data *add;
1861
1862         add = ast_malloc(sizeof(*add));
1863         if (!add) {
1864                 return NULL;
1865         }
1866
1867         ast_mutex_init(&add->lock);
1868         ast_cond_init(&add->cond, NULL);
1869         add->wait = 1;
1870
1871         return add;
1872 }
1873
1874 /*!
1875  * \brief Prepare the async playback datastore
1876  *
1877  * This is done prior to queuing an async announcement. If the
1878  * datastore has not yet been created, it is allocated and initialized.
1879  * If it already exists, we set it to be in "waiting" mode.
1880  *
1881  * \param initiator The channel that is queuing the async playback
1882  * \retval 0 Success
1883  * \retval -1 Failure :(
1884  */
1885 static int setup_async_playback_datastore(struct ast_channel *initiator)
1886 {
1887         struct ast_datastore *async_datastore;
1888
1889         async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
1890         if (async_datastore) {
1891                 struct async_datastore_data *add;
1892
1893                 add = async_datastore->data;
1894                 add->wait = 1;
1895
1896                 return 0;
1897         }
1898
1899         async_datastore = ast_datastore_alloc(&async_datastore_info, NULL);
1900         if (!async_datastore) {
1901                 return -1;
1902         }
1903
1904         async_datastore->data = async_datastore_data_alloc();
1905         if (!async_datastore->data) {
1906                 ast_datastore_free(async_datastore);
1907                 return -1;
1908         }
1909
1910         ast_channel_datastore_add(initiator, async_datastore);
1911         return 0;
1912 }
1913
1914 static struct async_playback_task_data *async_playback_task_data_alloc(
1915         struct confbridge_conference *conference, const char *filename, int say_number,
1916         struct ast_channel *initiator)
1917 {
1918         struct async_playback_task_data *aptd;
1919
1920         aptd = ast_malloc(sizeof(*aptd) + strlen(filename) + 1);
1921         if (!aptd) {
1922                 return NULL;
1923         }
1924
1925         /* Safe */
1926         strcpy(aptd->filename, filename);
1927         aptd->say_number = say_number;
1928
1929         /* You may think that we need to bump the conference refcount since we are pushing
1930          * this task to the taskprocessor.
1931          *
1932          * In this case, that actually causes a problem. The destructor for the conference
1933          * pushes a hangup task into the taskprocessor and waits for it to complete before
1934          * continuing. If the destructor gets called from a taskprocessor task, we're
1935          * deadlocked.
1936          *
1937          * So is there a risk of the conference being freed out from under us? No. Since
1938          * the destructor pushes a task into the taskprocessor and waits for it to complete,
1939          * the destructor cannot free the conference out from under us. No further tasks
1940          * can be queued onto the taskprocessor after the hangup since no channels are referencing
1941          * the conference at that point any more.
1942          */
1943         aptd->conference = conference;
1944
1945         aptd->initiator = initiator;
1946         if (initiator) {
1947                 ast_channel_ref(initiator);
1948                 ast_channel_lock(aptd->initiator);
1949                 /* We don't really care if this fails. If the datastore fails to get set up
1950                  * we'll still play the announcement. It's possible that the sound will be
1951                  * clipped for the initiator, but that's not the end of the world.
1952                  */
1953                 setup_async_playback_datastore(aptd->initiator);
1954                 ast_channel_unlock(aptd->initiator);
1955         }
1956
1957         return aptd;
1958 }
1959
1960 static void async_playback_task_data_destroy(struct async_playback_task_data *aptd)
1961 {
1962         ast_channel_cleanup(aptd->initiator);
1963         ast_free(aptd);
1964 }
1965
1966 /*!
1967  * \brief Wait for the initiator of an async playback to be ready
1968  *
1969  * See the description on the async_datastore_info structure for more
1970  * information about what this is about.
1971  *
1972  * \param initiator The channel that queued the async announcement
1973  */
1974 static void wait_for_initiator(struct ast_channel *initiator)
1975 {
1976         struct ast_datastore *async_datastore;
1977         struct async_datastore_data *add;
1978
1979         ast_channel_lock(initiator);
1980         async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
1981         ast_channel_unlock(initiator);
1982
1983         if (!async_datastore) {
1984                 return;
1985         }
1986
1987         add = async_datastore->data;
1988
1989         ast_mutex_lock(&add->lock);
1990         while (add->wait) {
1991                 ast_cond_wait(&add->cond, &add->lock);
1992         }
1993         ast_mutex_unlock(&add->lock);
1994 }
1995
1996 /*!
1997  * \brief Play an announcement into a confbridge asynchronously
1998  *
1999  * This runs in the playback queue taskprocessor. This ensures that
2000  * all playbacks are handled in sequence and do not play over top one
2001  * another.
2002  *
2003  * \param data An async_playback_task_data
2004  * \return 0
2005  */
2006 static int async_playback_task(void *data)
2007 {
2008         struct async_playback_task_data *aptd = data;
2009
2010         /* Wait for the initiator to get back in the bridge or be hung up */
2011         if (aptd->initiator) {
2012                 wait_for_initiator(aptd->initiator);
2013         }
2014
2015         playback_common(aptd->conference, aptd->filename, aptd->say_number);
2016
2017         async_playback_task_data_destroy(aptd);
2018         return 0;
2019 }
2020
2021 static int async_play_sound_helper(struct confbridge_conference *conference,
2022         const char *filename, int say_number, struct ast_channel *initiator)
2023 {
2024         struct async_playback_task_data *aptd;
2025
2026         /* Do not waste resources trying to play files that do not exist */
2027         if (ast_strlen_zero(filename)) {
2028                 if (say_number < 0) {
2029                         return 0;
2030                 }
2031         } else if (!sound_file_exists(filename)) {
2032                 return 0;
2033         }
2034
2035         aptd = async_playback_task_data_alloc(conference, filename, say_number, initiator);
2036         if (!aptd) {
2037                 return -1;
2038         }
2039
2040         if (ast_taskprocessor_push(conference->playback_queue, async_playback_task, aptd)) {
2041                 if (!ast_strlen_zero(filename)) {
2042                         ast_log(LOG_WARNING, "Unable to play file '%s' to conference '%s'\n",
2043                                 filename, conference->name);
2044                 } else {
2045                         ast_log(LOG_WARNING, "Unable to say number '%d' to conference '%s'\n",
2046                                 say_number, conference->name);
2047                 }
2048                 async_playback_task_data_destroy(aptd);
2049                 return -1;
2050         }
2051
2052         return 0;
2053 }
2054
2055 int async_play_sound_file(struct confbridge_conference *conference,
2056         const char *filename, struct ast_channel *initiator)
2057 {
2058         return async_play_sound_helper(conference, filename, -1, initiator);
2059 }
2060
2061 void async_play_sound_ready(struct ast_channel *chan)
2062 {
2063         struct ast_datastore *async_datastore;
2064         struct async_datastore_data *add;
2065
2066         ast_channel_lock(chan);
2067         async_datastore = ast_channel_datastore_find(chan, &async_datastore_info, NULL);
2068         ast_channel_unlock(chan);
2069         if (!async_datastore) {
2070                 return;
2071         }
2072
2073         add = async_datastore->data;
2074
2075         ast_mutex_lock(&add->lock);
2076         add->wait = 0;
2077         ast_cond_signal(&add->cond);
2078         ast_mutex_unlock(&add->lock);
2079 }
2080
2081 /*!
2082  * \brief Play number into the conference bridge
2083  *
2084  * \param conference The conference bridge to say the number into
2085  * \param say_number number to say
2086  *
2087  * \retval 0 success
2088  * \retval -1 failure
2089  */
2090 static int play_sound_number(struct confbridge_conference *conference, int say_number)
2091 {
2092         return play_sound_helper(conference, NULL, say_number);
2093 }
2094
2095 static int conf_handle_talker_cb(struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking)
2096 {
2097         const struct confbridge_user *user = hook_pvt;
2098         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
2099         struct ast_json *talking_extras;
2100
2101         conference = ao2_find(conference_bridges, user->conference->name, OBJ_KEY);
2102         if (!conference) {
2103                 /* Remove the hook since the conference does not exist. */
2104                 return -1;
2105         }
2106
2107         talking_extras = ast_json_pack("{s: s, s: b}",
2108                 "talking_status", talking ? "on" : "off",
2109                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN));
2110         if (!talking_extras) {
2111                 return 0;
2112         }
2113
2114         send_conf_stasis(conference, bridge_channel->chan, confbridge_talking_type(), talking_extras, 0);
2115         ast_json_unref(talking_extras);
2116         return 0;
2117 }
2118
2119 static int conf_get_pin(struct ast_channel *chan, struct confbridge_user *user)
2120 {
2121         char pin_guess[MAX_PIN+1] = { 0, };
2122         const char *pin = user->u_profile.pin;
2123         char *tmp = pin_guess;
2124         int i, res;
2125         unsigned int len = MAX_PIN;
2126
2127         /*
2128          * NOTE: We have not joined a conference yet so we have to use
2129          * the bridge profile requested by the user.
2130          */
2131
2132         /* give them three tries to get the pin right */
2133         for (i = 0; i < 3; i++) {
2134                 if (ast_app_getdata(chan,
2135                         conf_get_sound(CONF_SOUND_GET_PIN, user->b_profile.sounds),
2136                         tmp, len, 0) >= 0) {
2137                         if (!strcasecmp(pin, pin_guess)) {
2138                                 return 0;
2139                         }
2140                 }
2141                 ast_streamfile(chan,
2142                         conf_get_sound(CONF_SOUND_INVALID_PIN, user->b_profile.sounds),
2143                         ast_channel_language(chan));
2144                 res = ast_waitstream(chan, AST_DIGIT_ANY);
2145                 if (res > 0) {
2146                         /* Account for digit already read during ivalid pin playback
2147                          * resetting pin buf. */
2148                         pin_guess[0] = res;
2149                         pin_guess[1] = '\0';
2150                         tmp = pin_guess + 1;
2151                         len = MAX_PIN - 1;
2152                 } else {
2153                         /* reset pin buf as empty buffer. */
2154                         tmp = pin_guess;
2155                         len = MAX_PIN;
2156                 }
2157         }
2158         return -1;
2159 }
2160
2161 static int user_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
2162 {
2163         ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, 0);
2164         pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "TIMEOUT");
2165         return -1;
2166 }
2167
2168 static int conf_rec_name(struct confbridge_user *user, const char *conf_name)
2169 {
2170         char destdir[PATH_MAX];
2171         int res;
2172         int duration = 20;
2173
2174         snprintf(destdir, sizeof(destdir), "%s/confbridge", ast_config_AST_SPOOL_DIR);
2175
2176         if (ast_mkdir(destdir, 0777) != 0) {
2177                 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno));
2178                 return -1;
2179         }
2180         snprintf(user->name_rec_location, sizeof(user->name_rec_location),
2181                  "%s/confbridge-name-%s-%s", destdir,
2182                  conf_name, ast_channel_uniqueid(user->chan));
2183
2184         if (!(ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW))) {
2185                 res = ast_play_and_record(user->chan,
2186                         "vm-rec-name",
2187                         user->name_rec_location,
2188                         10,
2189                         "sln",
2190                         &duration,
2191                         NULL,
2192                         ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE),
2193                         0,
2194                         NULL);
2195         } else {
2196                 res = ast_record_review(user->chan,
2197                         "vm-rec-name",
2198                         user->name_rec_location,
2199                         10,
2200                         "sln",
2201                         &duration,
2202                         NULL);
2203         }
2204
2205         if (res == -1) {
2206                 ast_filedelete(user->name_rec_location, NULL);
2207                 user->name_rec_location[0] = '\0';
2208                 return -1;
2209         }
2210         return 0;
2211 }
2212
2213 struct async_delete_name_rec_task_data {
2214         struct confbridge_conference *conference;
2215         char filename[0];
2216 };
2217
2218 static struct async_delete_name_rec_task_data *async_delete_name_rec_task_data_alloc(
2219         struct confbridge_conference *conference, const char *filename)
2220 {
2221         struct async_delete_name_rec_task_data *atd;
2222
2223         atd = ast_malloc(sizeof(*atd) + strlen(filename) + 1);
2224         if (!atd) {
2225                 return NULL;
2226         }
2227
2228         /* Safe */
2229         strcpy(atd->filename, filename);
2230         atd->conference = conference;
2231
2232         return atd;
2233 }
2234
2235 static void async_delete_name_rec_task_data_destroy(struct async_delete_name_rec_task_data *atd)
2236 {
2237         ast_free(atd);
2238 }
2239
2240 /*!
2241  * \brief Delete user's name file asynchronously
2242  *
2243  * This runs in the playback queue taskprocessor. This ensures that
2244  * sound file is removed after playback is finished and not before.
2245  *
2246  * \param data An async_delete_name_rec_task_data
2247  * \return 0
2248  */
2249 static int async_delete_name_rec_task(void *data)
2250 {
2251         struct async_delete_name_rec_task_data *atd = data;
2252
2253         ast_filedelete(atd->filename, NULL);
2254         ast_log(LOG_DEBUG, "Conference '%s' removed user name file '%s'\n",
2255                 atd->conference->name, atd->filename);
2256
2257         async_delete_name_rec_task_data_destroy(atd);
2258         return 0;
2259 }
2260
2261 static int async_delete_name_rec(struct confbridge_conference *conference,
2262         const char *filename)
2263 {
2264         struct async_delete_name_rec_task_data *atd;
2265
2266         if (ast_strlen_zero(filename)) {
2267                 return 0;
2268         } else if (!sound_file_exists(filename)) {
2269                 return 0;
2270         }
2271
2272         atd = async_delete_name_rec_task_data_alloc(conference, filename);
2273         if (!atd) {
2274                 return -1;
2275         }
2276
2277         if (ast_taskprocessor_push(conference->playback_queue, async_delete_name_rec_task, atd)) {
2278                 ast_log(LOG_WARNING, "Conference '%s' was unable to remove user name file '%s'\n",
2279                         conference->name, filename);
2280                 async_delete_name_rec_task_data_destroy(atd);
2281                 return -1;
2282         }
2283
2284         return 0;
2285 }
2286
2287 static int join_callback(struct ast_bridge_channel *bridge_channel, void *ignore)
2288 {
2289         async_play_sound_ready(bridge_channel->chan);
2290         return 0;
2291 }
2292
2293 /*! \brief The ConfBridge application */
2294 static int confbridge_exec(struct ast_channel *chan, const char *data)
2295 {
2296         int res = 0, volume_adjustments[2];
2297         int quiet = 0;
2298         int async_delete_task_pushed = 0;
2299         char *parse;
2300         const char *b_profile_name = NULL;
2301         const char *u_profile_name = NULL;
2302         const char *menu_profile_name = NULL;
2303         struct confbridge_conference *conference = NULL;
2304         struct confbridge_user user = {
2305                 .chan = chan,
2306                 .tech_args.talking_threshold = DEFAULT_TALKING_THRESHOLD,
2307                 .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD,
2308                 .tech_args.drop_silence = 0,
2309         };
2310         AST_DECLARE_APP_ARGS(args,
2311                 AST_APP_ARG(conf_name);
2312                 AST_APP_ARG(b_profile_name);
2313                 AST_APP_ARG(u_profile_name);
2314                 AST_APP_ARG(menu_profile_name);
2315         );
2316
2317         if (ast_channel_state(chan) != AST_STATE_UP) {
2318                 ast_answer(chan);
2319         }
2320
2321         if (ast_bridge_features_init(&user.features)) {
2322                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2323                 res = -1;
2324                 goto confbridge_cleanup;
2325         }
2326
2327         /* We need to make a copy of the input string if we are going to modify it! */
2328         parse = ast_strdupa(data);
2329
2330         AST_STANDARD_APP_ARGS(args, parse);
2331
2332         if (ast_strlen_zero(args.conf_name)) {
2333                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2334                 ast_log(LOG_WARNING, "%s requires an argument (conference name[,options])\n", app);
2335                 res = -1;
2336                 goto confbridge_cleanup;
2337         }
2338
2339         if (strlen(args.conf_name) >= MAX_CONF_NAME) {
2340                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2341                 ast_log(LOG_WARNING, "%s does not accept conference names longer than %d\n", app, MAX_CONF_NAME - 1);
2342                 res = -1;
2343                 goto confbridge_cleanup;
2344         }
2345
2346         /* bridge profile name */
2347         if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) {
2348                 b_profile_name = args.b_profile_name;
2349         }
2350         if (!conf_find_bridge_profile(chan, b_profile_name, &user.b_profile)) {
2351                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2352                 ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name ?
2353                         b_profile_name : DEFAULT_BRIDGE_PROFILE);
2354                 res = -1;
2355                 goto confbridge_cleanup;
2356         }
2357
2358         /* user profile name */
2359         if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) {
2360                 u_profile_name = args.u_profile_name;
2361         }
2362         if (!conf_find_user_profile(chan, u_profile_name, &user.u_profile)) {
2363                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2364                 ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name ?
2365                         u_profile_name : DEFAULT_USER_PROFILE);
2366                 res = -1;
2367                 goto confbridge_cleanup;
2368         }
2369
2370         quiet = ast_test_flag(&user.u_profile, USER_OPT_QUIET);
2371
2372         /* ask for a PIN immediately after finding user profile.  This has to be
2373          * prompted for requardless of quiet setting. */
2374         if (!ast_strlen_zero(user.u_profile.pin)) {
2375                 if (conf_get_pin(chan, &user)) {
2376                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2377                         res = -1; /* invalid PIN */
2378                         goto confbridge_cleanup;
2379                 }
2380         }
2381
2382         /* See if we need them to record a intro name */
2383         if (!quiet &&
2384                 (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE) ||
2385                 (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW)))) {
2386                 if (conf_rec_name(&user, args.conf_name)) {
2387                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2388                         res = -1; /* Hangup during name recording */
2389                         goto confbridge_cleanup;
2390                 }
2391         }
2392
2393         /* menu name */
2394         if (args.argc > 3 && !ast_strlen_zero(args.menu_profile_name)) {
2395                 menu_profile_name = args.menu_profile_name;
2396         }
2397
2398         if (conf_set_menu_to_user(chan, &user, menu_profile_name)) {
2399                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2400                 ast_log(LOG_WARNING, "Conference menu profile %s does not exist\n", menu_profile_name ?
2401                         menu_profile_name : DEFAULT_MENU_PROFILE);
2402                 res = -1;
2403                 goto confbridge_cleanup;
2404         }
2405
2406         /* Set if DTMF should pass through for this user or not */
2407         if (ast_test_flag(&user.u_profile, USER_OPT_DTMF_PASS)) {
2408                 user.features.dtmf_passthrough = 1;
2409         } else {
2410                 user.features.dtmf_passthrough = 0;
2411         }
2412
2413         /* Set dsp threshold values if present */
2414         if (user.u_profile.talking_threshold) {
2415                 user.tech_args.talking_threshold = user.u_profile.talking_threshold;
2416         }
2417         if (user.u_profile.silence_threshold) {
2418                 user.tech_args.silence_threshold = user.u_profile.silence_threshold;
2419         }
2420
2421         /* Set a talker indicate call back if talking detection is requested */
2422         if (ast_test_flag(&user.u_profile, USER_OPT_TALKER_DETECT)) {
2423                 if (ast_bridge_talk_detector_hook(&user.features, conf_handle_talker_cb,
2424                         &user, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
2425                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2426                         res = -1;
2427                         goto confbridge_cleanup;
2428                 }
2429         }
2430
2431         /* Look for a conference bridge matching the provided name */
2432         if (!(conference = join_conference_bridge(args.conf_name, &user))) {
2433                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2434                 res = -1;
2435                 goto confbridge_cleanup;
2436         }
2437
2438         /* Keep a copy of volume adjustments so we can restore them later if need be */
2439         volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
2440         volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
2441
2442         if (ast_test_flag(&user.u_profile, USER_OPT_DROP_SILENCE)) {
2443                 user.tech_args.drop_silence = 1;
2444         }
2445
2446         if (ast_test_flag(&user.u_profile, USER_OPT_JITTERBUFFER)) {
2447                 ast_func_write(chan, "JITTERBUFFER(adaptive)", "default");
2448         }
2449
2450         if (ast_test_flag(&user.u_profile, USER_OPT_DENOISE)) {
2451                 ast_func_write(chan, "DENOISE(rx)", "on");
2452         }
2453
2454         /* if this user has a intro, play it before entering */
2455         if (!ast_strlen_zero(user.name_rec_location)) {
2456                 ast_autoservice_start(chan);
2457                 play_sound_file(conference, user.name_rec_location);
2458                 play_sound_file(conference,
2459                         conf_get_sound(CONF_SOUND_HAS_JOINED, conference->b_profile.sounds));
2460                 ast_autoservice_stop(chan);
2461         }
2462
2463         /* Play the Join sound to both the conference and the user entering. */
2464         if (!quiet) {
2465                 const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference->b_profile.sounds);
2466
2467                 if (strcmp(conference->b_profile.language, ast_channel_language(chan))) {
2468                         ast_stream_and_wait(chan, join_sound, "");
2469                         ast_autoservice_start(chan);
2470                         play_sound_file(conference, join_sound);
2471                         ast_autoservice_stop(chan);
2472                 } else {
2473                         async_play_sound_file(conference, join_sound, chan);
2474                 }
2475         }
2476
2477         if (user.u_profile.timeout) {
2478                 ast_bridge_interval_hook(&user.features,
2479                         0,
2480                         user.u_profile.timeout * 1000,
2481                         user_timeout,
2482                         NULL,
2483                         NULL,
2484                         AST_BRIDGE_HOOK_REMOVE_ON_PULL);
2485         }
2486
2487         /* See if we need to automatically set this user as a video source or not */
2488         handle_video_on_join(conference, user.chan, ast_test_flag(&user.u_profile, USER_OPT_MARKEDUSER));
2489
2490         conf_moh_unsuspend(&user);
2491
2492         /* Join our conference bridge for real */
2493         send_join_event(&user, conference);
2494
2495         if (ast_bridge_join_hook(&user.features, join_callback, NULL, NULL, 0)) {
2496                 async_play_sound_ready(user.chan);
2497         }
2498
2499         ast_bridge_join(conference->bridge,
2500                 chan,
2501                 NULL,
2502                 &user.features,
2503                 &user.tech_args,
2504                 0);
2505
2506         /* This is a catch-all in case joining the bridge failed or for some reason
2507          * an async announcement got queued up and hasn't been told to play yet
2508          */
2509         async_play_sound_ready(chan);
2510
2511         if (!user.kicked && ast_check_hangup(chan)) {
2512                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "HANGUP");
2513         }
2514
2515         send_leave_event(&user, conference);
2516
2517         /* if we're shutting down, don't attempt to do further processing */
2518         if (ast_shutting_down()) {
2519                 /*
2520                  * Not taking any new calls at this time.  We cannot create
2521                  * the announcer channel if this is the first channel into
2522                  * the conference and we certainly cannot create any
2523                  * recording channel.
2524                  */
2525                 leave_conference(&user);
2526                 conference = NULL;
2527                 goto confbridge_cleanup;
2528         }
2529
2530         /* If this user was a video source, we need to clean up and possibly pick a new source. */
2531         handle_video_on_exit(conference, user.chan);
2532
2533         /* if this user has a intro, play it when leaving */
2534         if (!quiet && !ast_strlen_zero(user.name_rec_location)) {
2535                 async_play_sound_file(conference, user.name_rec_location, NULL);
2536                 async_play_sound_file(conference,
2537                         conf_get_sound(CONF_SOUND_HAS_LEFT, conference->b_profile.sounds), NULL);
2538                 async_delete_name_rec(conference, user.name_rec_location);
2539                 async_delete_task_pushed = 1;
2540         }
2541
2542         /* play the leave sound */
2543         if (!quiet) {
2544                 const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, conference->b_profile.sounds);
2545                 async_play_sound_file(conference, leave_sound, NULL);
2546         }
2547
2548         /* If the user was kicked from the conference play back the audio prompt for it */
2549         if (!quiet && user.kicked) {
2550                 res = ast_stream_and_wait(chan,
2551                         conf_get_sound(CONF_SOUND_KICKED, conference->b_profile.sounds),
2552                         "");
2553         }
2554
2555         /* Easy as pie, depart this channel from the conference bridge */
2556         leave_conference(&user);
2557         conference = NULL;
2558
2559         /* Restore volume adjustments to previous values in case they were changed */
2560         if (volume_adjustments[0]) {
2561                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
2562         }
2563         if (volume_adjustments[1]) {
2564                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
2565         }
2566
2567 confbridge_cleanup:
2568         if (!async_delete_task_pushed && !ast_strlen_zero(user.name_rec_location)) {
2569                 ast_filedelete(user.name_rec_location, NULL);
2570         }
2571         ast_bridge_features_cleanup(&user.features);
2572         conf_bridge_profile_destroy(&user.b_profile);
2573         return res;
2574 }
2575
2576 static int action_toggle_mute(struct confbridge_conference *conference,
2577                               struct confbridge_user *user,
2578                               struct ast_bridge_channel *bridge_channel)
2579 {
2580         int mute;
2581
2582         /* Toggle user level mute request. */
2583         mute = !user->muted;
2584         generic_mute_unmute_user(conference, user, mute);
2585
2586         return play_file(bridge_channel, NULL,
2587                 conf_get_sound(mute ? CONF_SOUND_MUTED : CONF_SOUND_UNMUTED,
2588                         conference->b_profile.sounds)) < 0;
2589 }
2590
2591 static int action_toggle_binaural(struct confbridge_conference *conference,
2592                 struct confbridge_user *user,
2593                 struct ast_bridge_channel *bridge_channel)
2594 {
2595         unsigned int binaural;
2596         ast_bridge_channel_lock_bridge(bridge_channel);
2597         binaural = !bridge_channel->binaural_suspended;
2598         bridge_channel->binaural_suspended = binaural;
2599         ast_bridge_unlock(bridge_channel->bridge);
2600         return play_file(bridge_channel, NULL, (binaural ?
2601                                 conf_get_sound(CONF_SOUND_BINAURAL_OFF, user->b_profile.sounds) :
2602                                 conf_get_sound(CONF_SOUND_BINAURAL_ON, user->b_profile.sounds))) < 0;
2603 }
2604
2605 static int action_toggle_mute_participants(struct confbridge_conference *conference, struct confbridge_user *user)
2606 {
2607         struct confbridge_user *cur_user = NULL;
2608         const char *sound_to_play;
2609         int mute;
2610
2611         ao2_lock(conference);
2612
2613         /* Toggle bridge level mute request. */
2614         mute = !conference->muted;
2615         conference->muted = mute;
2616
2617         AST_LIST_TRAVERSE(&conference->active_list, cur_user, list) {
2618                 if (!ast_test_flag(&cur_user->u_profile, USER_OPT_ADMIN)) {
2619                         /* Set user level to bridge level mute request. */
2620                         cur_user->muted = mute;
2621                         conf_update_user_mute(cur_user);
2622                 }
2623         }
2624
2625         ao2_unlock(conference);
2626
2627         sound_to_play = conf_get_sound(
2628                 mute ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED,
2629                 conference->b_profile.sounds);
2630
2631         if (strcmp(conference->b_profile.language, ast_channel_language(user->chan))) {
2632                 /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */
2633                 ast_stream_and_wait(user->chan, sound_to_play, "");
2634
2635                 /* Announce to the group that all participants are muted */
2636                 ast_autoservice_start(user->chan);
2637                 play_sound_file(conference, sound_to_play);
2638                 ast_autoservice_stop(user->chan);
2639         } else {
2640                 /* Playing the sound asynchronously lets the sound be heard by everyone at once */
2641                 async_play_sound_file(conference, sound_to_play, user->chan);
2642         }
2643
2644         return 0;
2645 }
2646
2647 static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
2648 {
2649         char *file_copy = ast_strdupa(playback_file);
2650         char *file = NULL;
2651
2652         while ((file = strsep(&file_copy, "&"))) {
2653                 if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
2654                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
2655                         return -1;
2656                 }
2657         }
2658         return 0;
2659 }
2660
2661 static int action_playback_and_continue(struct confbridge_conference *conference,
2662         struct confbridge_user *user,
2663         struct ast_bridge_channel *bridge_channel,
2664         struct conf_menu *menu,
2665         const char *playback_file,
2666         const char *cur_dtmf,
2667         int *stop_prompts)
2668 {
2669         int i;
2670         int digit = 0;
2671         char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
2672         struct conf_menu_entry new_menu_entry = { { 0, }, };
2673         char *file_copy = ast_strdupa(playback_file);
2674         char *file = NULL;
2675
2676         while ((file = strsep(&file_copy, "&"))) {
2677                 if (ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan))) {
2678                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
2679                         return -1;
2680                 }
2681
2682                 /* now wait for more digits. */
2683                 if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) {
2684                         /* streaming finished and no DTMF was entered */
2685                         continue;
2686                 } else if (digit == -1) {
2687                         /* error */
2688                         return -1;
2689                 } else {
2690                         break; /* dtmf was entered */
2691                 }
2692         }
2693         if (!digit) {
2694                 /* streaming finished on all files and no DTMF was entered */
2695                 return -1;
2696         }
2697         ast_stopstream(bridge_channel->chan);
2698
2699         /* If we get here, then DTMF has been entered, This means no
2700          * additional prompts should be played for this menu entry */
2701         *stop_prompts = 1;
2702
2703         /* If a digit was pressed during the payback, update
2704          * the dtmf string and look for a new menu entry in the
2705          * menu structure */
2706         ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf));
2707         for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) {
2708                 dtmf[i] = cur_dtmf[i];
2709                 if (!dtmf[i]) {
2710                         dtmf[i] = (char) digit;
2711                         dtmf[i + 1] = '\0';
2712                         i = -1;
2713                         break;
2714                 }
2715         }
2716         /* If i is not -1 then the new dtmf digit was _NOT_ added to the string.
2717          * If this is the case, no new DTMF sequence should be looked for. */
2718         if (i != -1) {
2719                 return 0;
2720         }
2721
2722         if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) {
2723                 execute_menu_entry(conference,
2724                         user,
2725                         bridge_channel,
2726                         &new_menu_entry, menu);
2727                 conf_menu_entry_destroy(&new_menu_entry);
2728         }
2729         return 0;
2730 }
2731
2732 static int action_kick_last(struct confbridge_conference *conference,
2733         struct ast_bridge_channel *bridge_channel,
2734         struct confbridge_user *user)
2735 {
2736         struct confbridge_user *last_user = NULL;
2737         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
2738
2739         if (!isadmin) {
2740                 play_file(bridge_channel, NULL,
2741                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference->b_profile.sounds));
2742                 ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
2743                         ast_channel_name(bridge_channel->chan),
2744                         conference->name);
2745                 return -1;
2746         }
2747
2748         ao2_lock(conference);
2749         last_user = AST_LIST_LAST(&conference->active_list);
2750         if (!last_user) {
2751                 ao2_unlock(conference);
2752                 return 0;
2753         }
2754
2755         if (last_user == user || ast_test_flag(&last_user->u_profile, USER_OPT_ADMIN)) {
2756                 ao2_unlock(conference);
2757                 play_file(bridge_channel, NULL,
2758                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference->b_profile.sounds));
2759         } else if (!last_user->kicked) {
2760                 last_user->kicked = 1;
2761                 pbx_builtin_setvar_helper(last_user->chan, "CONFBRIDGE_RESULT", "KICKED");
2762                 ast_bridge_remove(conference->bridge, last_user->chan);
2763                 ao2_unlock(conference);
2764         }
2765
2766         return 0;
2767 }
2768
2769 static int action_dialplan_exec(struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
2770 {
2771         struct ast_pbx_args args;
2772         struct ast_pbx *pbx;
2773         char *exten;
2774         char *context;
2775         int priority;
2776         int res;
2777
2778         memset(&args, 0, sizeof(args));
2779         args.no_hangup_chan = 1;
2780
2781         ast_channel_lock(bridge_channel->chan);
2782
2783         /*save off*/
2784         exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
2785         context = ast_strdupa(ast_channel_context(bridge_channel->chan));
2786         priority = ast_channel_priority(bridge_channel->chan);
2787         pbx = ast_channel_pbx(bridge_channel->chan);
2788         ast_channel_pbx_set(bridge_channel->chan, NULL);
2789
2790         /*set new*/
2791         ast_channel_exten_set(bridge_channel->chan, menu_action->data.dialplan_args.exten);
2792         ast_channel_context_set(bridge_channel->chan, menu_action->data.dialplan_args.context);
2793         ast_channel_priority_set(bridge_channel->chan, menu_action->data.dialplan_args.priority);
2794
2795         ast_channel_unlock(bridge_channel->chan);
2796
2797         /*execute*/
2798         res = ast_pbx_run_args(bridge_channel->chan, &args);
2799
2800         /*restore*/
2801         ast_channel_lock(bridge_channel->chan);
2802
2803         ast_channel_exten_set(bridge_channel->chan, exten);
2804         ast_channel_context_set(bridge_channel->chan, context);
2805         ast_channel_priority_set(bridge_channel->chan, priority);
2806         ast_channel_pbx_set(bridge_channel->chan, pbx);
2807
2808         ast_channel_unlock(bridge_channel->chan);
2809
2810         return res;
2811 }
2812
2813 static int execute_menu_entry(struct confbridge_conference *conference,
2814         struct confbridge_user *user,
2815         struct ast_bridge_channel *bridge_channel,
2816         struct conf_menu_entry *menu_entry,
2817         struct conf_menu *menu)
2818 {
2819         struct conf_menu_action *menu_action;
2820         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
2821         int stop_prompts = 0;
2822         int res = 0;
2823
2824         AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
2825                 switch (menu_action->id) {
2826                 case MENU_ACTION_TOGGLE_MUTE:
2827                         res |= action_toggle_mute(conference, user, bridge_channel);
2828                         break;
2829                 case MENU_ACTION_TOGGLE_BINAURAL:
2830                         action_toggle_binaural(conference, user, bridge_channel);
2831                         break;
2832                 case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
2833                         if (!isadmin) {
2834                                 break;
2835                         }
2836                         action_toggle_mute_participants(conference, user);
2837                         break;
2838                 case MENU_ACTION_PARTICIPANT_COUNT:
2839                         announce_user_count(conference, user, bridge_channel);
2840                         break;
2841                 case MENU_ACTION_PLAYBACK:
2842                         if (!stop_prompts) {
2843                                 res |= action_playback(bridge_channel, menu_action->data.playback_file);
2844                                 ast_test_suite_event_notify("CONF_MENU_PLAYBACK",
2845                                         "Message: %s\r\nChannel: %s",
2846                                         menu_action->data.playback_file, ast_channel_name(bridge_channel->chan));
2847                         }
2848                         break;
2849                 case MENU_ACTION_RESET_LISTENING:
2850                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 0);
2851                         break;
2852                 case MENU_ACTION_RESET_TALKING:
2853                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_READ, 0);
2854                         break;
2855                 case MENU_ACTION_INCREASE_LISTENING:
2856                         ast_audiohook_volume_adjust(user->chan,
2857                                 AST_AUDIOHOOK_DIRECTION_WRITE, 1);
2858                         break;
2859                 case MENU_ACTION_DECREASE_LISTENING:
2860                         ast_audiohook_volume_adjust(user->chan,
2861                                 AST_AUDIOHOOK_DIRECTION_WRITE, -1);
2862                         break;
2863                 case MENU_ACTION_INCREASE_TALKING:
2864                         ast_audiohook_volume_adjust(user->chan,
2865                                 AST_AUDIOHOOK_DIRECTION_READ, 1);
2866                         break;
2867                 case MENU_ACTION_DECREASE_TALKING:
2868                         ast_audiohook_volume_adjust(user->chan,
2869                                 AST_AUDIOHOOK_DIRECTION_READ, -1);
2870                         break;
2871                 case MENU_ACTION_PLAYBACK_AND_CONTINUE:
2872                         if (!(stop_prompts)) {
2873                                 res |= action_playback_and_continue(conference,
2874                                         user,
2875                                         bridge_channel,
2876                                         menu,
2877                                         menu_action->data.playback_file,
2878                                         menu_entry->dtmf,
2879                                         &stop_prompts);
2880                         }
2881                         break;
2882                 case MENU_ACTION_DIALPLAN_EXEC:
2883                         res |= action_dialplan_exec(bridge_channel, menu_action);
2884                         break;
2885                 case MENU_ACTION_ADMIN_TOGGLE_LOCK:
2886                         if (!isadmin) {
2887                                 break;
2888                         }
2889                         conference->locked = (!conference->locked ? 1 : 0);
2890                         res |= play_file(bridge_channel, NULL,
2891                                 conf_get_sound(
2892                                         conference->locked ? CONF_SOUND_LOCKED_NOW : CONF_SOUND_UNLOCKED_NOW,
2893                                         conference->b_profile.sounds)) < 0;
2894                         break;
2895                 case MENU_ACTION_ADMIN_KICK_LAST:
2896                         res |= action_kick_last(conference, bridge_channel, user);
2897                         break;
2898                 case MENU_ACTION_LEAVE:
2899                         pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "DTMF");
2900                         ao2_lock(conference);
2901                         ast_bridge_remove(conference->bridge, bridge_channel->chan);
2902                         ast_test_suite_event_notify("CONF_MENU_LEAVE",
2903                                 "Channel: %s",
2904                                 ast_channel_name(bridge_channel->chan));
2905                         ao2_unlock(conference);
2906                         break;
2907                 case MENU_ACTION_NOOP:
2908                         break;
2909                 case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
2910                         ao2_lock(conference);
2911                         if (!ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_SFU)) {
2912                                 ast_bridge_set_single_src_video_mode(conference->bridge, bridge_channel->chan);
2913                         }
2914                         ao2_unlock(conference);
2915                         break;
2916                 case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
2917                         handle_video_on_exit(conference, bridge_channel->chan);
2918                         break;
2919                 }
2920         }
2921         return res;
2922 }
2923
2924 int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
2925         struct confbridge_user *user,
2926         struct conf_menu_entry *menu_entry,
2927         struct conf_menu *menu)
2928 {
2929         /* See if music on hold is playing */
2930         conf_moh_suspend(user);
2931
2932         /* execute the list of actions associated with this menu entry */
2933         execute_menu_entry(user->conference, user, bridge_channel, menu_entry, menu);
2934
2935         /* See if music on hold needs to be started back up again */
2936         conf_moh_unsuspend(user);
2937
2938         async_play_sound_ready(bridge_channel->chan);
2939
2940         return 0;
2941 }
2942
2943 static int kick_conference_participant(struct confbridge_conference *conference,
2944         const char *channel)
2945 {
2946         int res = -1;
2947         int match;
2948         struct confbridge_user *user = NULL;
2949         int all = !strcasecmp("all", channel);
2950         int participants = !strcasecmp("participants", channel);
2951
2952         SCOPED_AO2LOCK(bridge_lock, conference);
2953
2954         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2955                 if (user->kicked) {
2956                         continue;
2957                 }
2958                 match = !strcasecmp(channel, ast_channel_name(user->chan));
2959                 if (match || all
2960                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
2961                         user->kicked = 1;
2962                         pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
2963                         ast_bridge_remove(conference->bridge, user->chan);
2964                         res = 0;
2965                         if (match) {
2966                                 return res;
2967                         }
2968                 }
2969         }
2970         AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2971                 if (user->kicked) {
2972                         continue;
2973                 }
2974                 match = !strcasecmp(channel, ast_channel_name(user->chan));
2975                 if (match || all
2976                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
2977                         user->kicked = 1;
2978                         pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
2979                         ast_bridge_remove(conference->bridge, user->chan);
2980                         res = 0;
2981                         if (match) {
2982                                 return res;
2983                         }
2984                 }
2985         }
2986
2987         return res;
2988 }
2989
2990 static char *complete_confbridge_name(const char *line, const char *word, int pos, int state)
2991 {
2992         int which = 0;
2993         struct confbridge_conference *conference;
2994         char *res = NULL;
2995         int wordlen = strlen(word);
2996         struct ao2_iterator iter;
2997
2998         iter = ao2_iterator_init(conference_bridges, 0);
2999         while ((conference = ao2_iterator_next(&iter))) {
3000                 if (!strncasecmp(conference->name, word, wordlen) && ++which > state) {
3001                         res = ast_strdup(conference->name);
3002                         ao2_ref(conference, -1);
3003                         break;
3004                 }
3005                 ao2_ref(conference, -1);
3006         }
3007         ao2_iterator_destroy(&iter);
3008
3009         return res;
3010 }
3011
3012 static char *complete_confbridge_participant(const char *conference_name, const char *line, const char *word, int pos, int state)
3013 {
3014         int which = 0;
3015         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
3016         struct confbridge_user *user;
3017         char *res = NULL;
3018         int wordlen = strlen(word);
3019
3020         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3021         if (!conference) {
3022                 return NULL;
3023         }
3024
3025         if (!strncasecmp("all", word, wordlen) && ++which > state) {
3026                 return ast_strdup("all");
3027         }
3028
3029         if (!strncasecmp("participants", word, wordlen) && ++which > state) {
3030                 return ast_strdup("participants");
3031         }
3032
3033         {
3034                 SCOPED_AO2LOCK(bridge_lock, conference);
3035                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
3036                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
3037                                 res = ast_strdup(ast_channel_name(user->chan));
3038                                 return res;
3039                         }
3040                 }
3041                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
3042                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
3043                                 res = ast_strdup(ast_channel_name(user->chan));
3044                                 return res;
3045                         }
3046                 }
3047         }
3048
3049         return NULL;
3050 }
3051
3052 static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3053 {
3054         struct confbridge_conference *conference;
3055         int not_found;
3056
3057         switch (cmd) {
3058         case CLI_INIT:
3059                 e->command = "confbridge kick";
3060                 e->usage =
3061                         "Usage: confbridge kick <conference> <channel>\n"
3062                         "       Kicks a channel out of the conference bridge.\n"
3063                         "             (all to kick everyone, participants to kick non-admins).\n";
3064                 return NULL;
3065         case CLI_GENERATE:
3066                 if (a->pos == 2) {
3067                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3068                 }
3069                 if (a->pos == 3) {
3070                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
3071                 }
3072                 return NULL;
3073         }
3074
3075         if (a->argc != 4) {
3076                 return CLI_SHOWUSAGE;
3077         }
3078
3079         conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
3080         if (!conference) {
3081                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
3082                 return CLI_SUCCESS;
3083         }
3084         not_found = kick_conference_participant(conference, a->argv[3]);
3085         ao2_ref(conference, -1);
3086         if (not_found) {
3087                 if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
3088                         ast_cli(a->fd, "No participants found!\n");
3089                 } else {
3090                         ast_cli(a->fd, "No participant named '%s' found!\n", a->argv[3]);
3091                 }
3092                 return CLI_SUCCESS;
3093         }
3094         ast_cli(a->fd, "Kicked '%s' out of conference '%s'\n", a->argv[3], a->argv[2]);
3095         return CLI_SUCCESS;
3096 }
3097
3098 static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct confbridge_user *user, int waiting)
3099 {
3100         char flag_str[6 + 1];/* Max flags + terminator */
3101         int pos = 0;
3102
3103         /* Build flags column string. */
3104         if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
3105                 flag_str[pos++] = 'A';
3106         }
3107         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
3108                 flag_str[pos++] = 'M';
3109         }
3110         if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
3111                 flag_str[pos++] = 'W';
3112         }
3113         if (ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED)) {
3114                 flag_str[pos++] = 'E';
3115         }
3116         if (user->muted) {
3117                 flag_str[pos++] = 'm';
3118         }
3119         if (waiting) {
3120                 flag_str[pos++] = 'w';
3121         }
3122         flag_str[pos] = '\0';
3123
3124         ast_cli(a->fd, "%-30s %-6s %-16s %-16s %-16s %s\n",
3125                 ast_channel_name(user->chan),
3126                 flag_str,
3127                 user->u_profile.name,
3128                 user->conference->b_profile.name,
3129                 user->menu_name,
3130                 S_COR(ast_channel_caller(user->chan)->id.number.valid,
3131                         ast_channel_caller(user->chan)->id.number.str, "<unknown>"));
3132 }
3133
3134 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3135 {
3136         struct confbridge_conference *conference;
3137
3138         switch (cmd) {
3139         case CLI_INIT:
3140                 e->command = "confbridge list";
3141                 e->usage =
3142                         "Usage: confbridge list [<name>]\n"
3143                         "       Lists all currently active conference bridges or a specific conference bridge.\n"
3144                         "\n"
3145                         "       When a conference bridge name is provided, flags may be shown for users. Below\n"
3146                         "       are the flags and what they represent.\n"