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