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