Fix crash from bridge channel hangup race condition in ConfBridge
[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 /*** MODULEINFO
32         <support_level>core</support_level>
33  ***/
34
35 #include "asterisk.h"
36
37 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <string.h>
43 #include <signal.h>
44
45 #include "asterisk/cli.h"
46 #include "asterisk/file.h"
47 #include "asterisk/channel.h"
48 #include "asterisk/pbx.h"
49 #include "asterisk/pbx.h"
50 #include "asterisk/module.h"
51 #include "asterisk/lock.h"
52 #include "asterisk/bridging.h"
53 #include "asterisk/musiconhold.h"
54 #include "asterisk/say.h"
55 #include "asterisk/audiohook.h"
56 #include "asterisk/astobj2.h"
57 #include "confbridge/include/confbridge.h"
58 #include "asterisk/paths.h"
59 #include "asterisk/manager.h"
60 #include "asterisk/test.h"
61
62 /*** DOCUMENTATION
63     <application name="ConfBridge" language="en_US">
64             <synopsis>
65                     Conference bridge application.
66             </synopsis>
67             <syntax>
68                     <parameter name="confno">
69                             <para>The conference number</para>
70                     </parameter>
71                     <parameter name="bridge_profile">
72                             <para>The bridge profile name from confbridge.conf.  When left blank, a dynamically built bridge profile created by the CONFBRIDGE dialplan function is searched for on the channel and used.  If no dynamic profile is present, the 'default_bridge' profile found in confbridge.conf is used. </para>
73                             <para>It is important to note that while user profiles may be unique for each participant, mixing bridge profiles on a single conference is _NOT_ recommended and will produce undefined results.</para>
74                     </parameter>
75                     <parameter name="user_profile">
76                             <para>The user profile name from confbridge.conf.  When left blank, a dynamically built user profile created by the CONFBRIDGE dialplan function is searched for on the channel and used.  If no dynamic profile is present, the 'default_user' profile found in confbridge.conf is used.</para>
77                     </parameter>
78                     <parameter name="menu">
79                             <para>The name of the DTMF menu in confbridge.conf to be applied to this channel.  No menu is applied by default if this option is left blank.</para>
80                     </parameter>
81             </syntax>
82             <description>
83                     <para>Enters the user into a specified conference bridge. The user can exit the conference by hangup or DTMF menu option.</para>
84             </description>
85                         <see-also>
86                                 <ref type="application">ConfBridge</ref>
87                                 <ref type="function">CONFBRIDGE</ref>
88                                 <ref type="function">CONFBRIDGE_INFO</ref>
89                         </see-also>
90     </application>
91         <function name="CONFBRIDGE" language="en_US">
92                 <synopsis>
93                         Set a custom dynamic bridge and user profile on a channel for the ConfBridge application using the same options defined in confbridge.conf.
94                 </synopsis>
95                 <syntax>
96                         <parameter name="type" required="true">
97                                 <para>Type refers to which type of profile the option belongs too.  Type can be <literal>bridge</literal> or <literal>user</literal>.</para>
98                         </parameter>
99             <parameter name="option" required="true">
100                                 <para>Option refers to <filename>confbridge.conf</filename> option that is being set dynamically on this channel.</para>
101                         </parameter>
102                 </syntax>
103                 <description>
104                         <para>---- Example 1 ----</para>
105                         <para>In this example the custom set user profile on this channel will automatically be used by the ConfBridge app.</para> 
106                         <para>exten => 1,1,Answer() </para>
107                         <para>exten => 1,n,Set(CONFBRIDGE(user,announce_join_leave)=yes)</para>
108                         <para>exten => 1,n,Set(CONFBRIDGE(user,startmuted)=yes)</para>
109                         <para>exten => 1,n,ConfBridge(1) </para>
110                         <para>---- Example 2 ----</para>
111                         <para>This example shows how to use a predefined user or bridge profile in confbridge.conf as a template for a dynamic profile. Here we make a admin/marked user out of the default_user profile that is already defined in confbridge.conf.</para> 
112                         <para>exten => 1,1,Answer() </para>
113                         <para>exten => 1,n,Set(CONFBRIDGE(user,template)=default_user)</para>
114                         <para>exten => 1,n,Set(CONFBRIDGE(user,admin)=yes)</para>
115                         <para>exten => 1,n,Set(CONFBRIDGE(user,marked)=yes)</para>
116                         <para>exten => 1,n,ConfBridge(1)</para>
117                 </description>
118         </function>
119         <function name="CONFBRIDGE_INFO" language="en_US">
120                 <synopsis>
121                         Get information about a ConfBridge conference.
122                 </synopsis>
123                 <syntax>
124                         <parameter name="type" required="true">
125                                 <para>Type can be <literal>parties</literal>, <literal>admins</literal>, <literal>marked</literal>, or <literal>locked</literal>.</para>
126                         </parameter>
127                         <parameter name="conf" required="true">
128                                 <para>Conf refers to the name of the conference being referenced.</para>
129                         </parameter>
130                 </syntax>
131                 <description>
132                         <para>This function returns a non-negative integer for valid conference identifiers (0 or 1 for <literal>locked</literal>) and "" for invalid conference identifiers.</para> 
133                 </description>
134         </function>
135         <manager name="ConfbridgeList" language="en_US">
136                 <synopsis>
137                         List participants in a conference.
138                 </synopsis>
139                 <syntax>
140                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
141                         <parameter name="Conference" required="false">
142                                 <para>Conference number.</para>
143                         </parameter>
144                 </syntax>
145                 <description>
146                         <para>Lists all users in a particular ConfBridge conference.
147                         ConfbridgeList will follow as separate events, followed by a final event called
148                         ConfbridgeListComplete.</para>
149                 </description>
150         </manager>
151         <manager name="ConfbridgeListRooms" language="en_US">
152                 <synopsis>
153                         List active conferences.
154                 </synopsis>
155                 <syntax>
156                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
157                 </syntax>
158                 <description>
159                         <para>Lists data about all active conferences.
160                                 ConfbridgeListRooms will follow as separate events, followed by a final event called
161                                 ConfbridgeListRoomsComplete.</para>
162                 </description>
163         </manager>
164         <manager name="ConfbridgeMute" language="en_US">
165                 <synopsis>
166                         Mute a Confbridge user.
167                 </synopsis>
168                 <syntax>
169                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
170                         <parameter name="Conference" required="true" />
171                         <parameter name="Channel" required="true" />
172                 </syntax>
173                 <description>
174                 </description>
175         </manager>
176         <manager name="ConfbridgeUnmute" language="en_US">
177                 <synopsis>
178                         Unmute a Confbridge user.
179                 </synopsis>
180                 <syntax>
181                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
182                         <parameter name="Conference" required="true" />
183                         <parameter name="Channel" required="true" />
184                 </syntax>
185                 <description>
186                 </description>
187         </manager>
188         <manager name="ConfbridgeKick" language="en_US">
189                 <synopsis>
190                         Kick a Confbridge user.
191                 </synopsis>
192                 <syntax>
193                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
194                         <parameter name="Conference" required="true" />
195                         <parameter name="Channel" required="true" />
196                 </syntax>
197                 <description>
198                 </description>
199         </manager>
200         <manager name="ConfbridgeLock" language="en_US">
201                 <synopsis>
202                         Lock a Confbridge conference.
203                 </synopsis>
204                 <syntax>
205                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
206                         <parameter name="Conference" required="true" />
207                 </syntax>
208                 <description>
209                 </description>
210         </manager>
211         <manager name="ConfbridgeUnlock" language="en_US">
212                 <synopsis>
213                         Unlock a Confbridge conference.
214                 </synopsis>
215                 <syntax>
216                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
217                         <parameter name="Conference" required="true" />
218                 </syntax>
219                 <description>
220                 </description>
221         </manager>
222         <manager name="ConfbridgeStartRecord" language="en_US">
223                 <synopsis>
224                         Start recording a Confbridge conference.
225                 </synopsis>
226                 <syntax>
227                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
228                         <parameter name="Conference" required="true" />
229                         <parameter name="RecordFile" required="false" />
230                 </syntax>
231                 <description>
232                         <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>
233                 </description>
234         </manager>
235         <manager name="ConfbridgeStopRecord" language="en_US">
236                 <synopsis>
237                         Stop recording a Confbridge conference.
238                 </synopsis>
239                 <syntax>
240                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
241                         <parameter name="Conference" required="true" />
242                 </syntax>
243                 <description>
244                 </description>
245         </manager>
246         <manager name="ConfbridgeSetSingleVideoSrc" language="en_US">
247                 <synopsis>
248                         Set a conference user as the single video source distributed to all other participants.
249                 </synopsis>
250                 <syntax>
251                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
252                         <parameter name="Conference" required="true" />
253                         <parameter name="Channel" required="true" />
254                 </syntax>
255                 <description>
256                 </description>
257         </manager>
258
259 ***/
260
261 /*!
262  * \par Playing back a file to a channel in a conference
263  * You might notice in this application that while playing a sound file
264  * to a channel the actual conference bridge lock is not held. This is done so
265  * that other channels are not blocked from interacting with the conference bridge.
266  * Unfortunately because of this it is possible for things to change after the sound file
267  * is done being played. Data must therefore be checked after reacquiring the conference
268  * bridge lock if it is important.
269  */
270
271 static const char app[] = "ConfBridge";
272
273 /* Number of buckets our conference bridges container can have */
274 #define CONFERENCE_BRIDGE_BUCKETS 53
275
276 /*! \brief Container to hold all conference bridges in progress */
277 static struct ao2_container *conference_bridges;
278
279 static int play_sound_file(struct conference_bridge *conference_bridge, const char *filename);
280 static int play_sound_number(struct conference_bridge *conference_bridge, int say_number);
281 static int execute_menu_entry(struct conference_bridge *conference_bridge,
282         struct conference_bridge_user *conference_bridge_user,
283         struct ast_bridge_channel *bridge_channel,
284         struct conf_menu_entry *menu_entry,
285         struct conf_menu *menu);
286
287 /*! \brief Hashing function used for conference bridges container */
288 static int conference_bridge_hash_cb(const void *obj, const int flags)
289 {
290         const struct conference_bridge *conference_bridge = obj;
291         return ast_str_case_hash(conference_bridge->name);
292 }
293
294 /*! \brief Comparison function used for conference bridges container */
295 static int conference_bridge_cmp_cb(void *obj, void *arg, int flags)
296 {
297         const struct conference_bridge *conference_bridge0 = obj, *conference_bridge1 = arg;
298         return (!strcasecmp(conference_bridge0->name, conference_bridge1->name) ? CMP_MATCH | CMP_STOP : 0);
299 }
300
301 const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds)
302 {
303         switch (sound) {
304         case CONF_SOUND_HAS_JOINED:
305                 return S_OR(custom_sounds->hasjoin, "conf-hasjoin");
306         case CONF_SOUND_HAS_LEFT:
307                 return S_OR(custom_sounds->hasleft, "conf-hasleft");
308         case CONF_SOUND_KICKED:
309                 return S_OR(custom_sounds->kicked, "conf-kicked");
310         case CONF_SOUND_MUTED:
311                 return S_OR(custom_sounds->muted, "conf-muted");
312         case CONF_SOUND_UNMUTED:
313                 return S_OR(custom_sounds->unmuted, "conf-unmuted");
314         case CONF_SOUND_ONLY_ONE:
315                 return S_OR(custom_sounds->onlyone, "conf-onlyone");
316         case CONF_SOUND_THERE_ARE:
317                 return S_OR(custom_sounds->thereare, "conf-thereare");
318         case CONF_SOUND_OTHER_IN_PARTY:
319                 return S_OR(custom_sounds->otherinparty, "conf-otherinparty");
320         case CONF_SOUND_PLACE_IN_CONF:
321                 return S_OR(custom_sounds->placeintoconf, "conf-placeintoconf");
322         case CONF_SOUND_WAIT_FOR_LEADER:
323                 return S_OR(custom_sounds->waitforleader, "conf-waitforleader");
324         case CONF_SOUND_LEADER_HAS_LEFT:
325                 return S_OR(custom_sounds->leaderhasleft, "conf-leaderhasleft");
326         case CONF_SOUND_GET_PIN:
327                 return S_OR(custom_sounds->getpin, "conf-getpin");
328         case CONF_SOUND_INVALID_PIN:
329                 return S_OR(custom_sounds->invalidpin, "conf-invalidpin");
330         case CONF_SOUND_ONLY_PERSON:
331                 return S_OR(custom_sounds->onlyperson, "conf-onlyperson");
332         case CONF_SOUND_LOCKED:
333                 return S_OR(custom_sounds->locked, "conf-locked");
334         case CONF_SOUND_LOCKED_NOW:
335                 return S_OR(custom_sounds->lockednow, "conf-lockednow");
336         case CONF_SOUND_UNLOCKED_NOW:
337                 return S_OR(custom_sounds->unlockednow, "conf-unlockednow");
338         case CONF_SOUND_ERROR_MENU:
339                 return S_OR(custom_sounds->errormenu, "conf-errormenu");
340         case CONF_SOUND_JOIN:
341                 return S_OR(custom_sounds->join, "confbridge-join");
342         case CONF_SOUND_LEAVE:
343                 return S_OR(custom_sounds->leave, "confbridge-leave");
344         case CONF_SOUND_PARTICIPANTS_MUTED:
345                 return S_OR(custom_sounds->participantsmuted, "conf-now-muted");
346         case CONF_SOUND_PARTICIPANTS_UNMUTED:
347                 return S_OR(custom_sounds->participantsunmuted, "conf-now-unmuted");
348         }
349
350         return "";
351 }
352
353 static struct ast_frame *rec_read(struct ast_channel *ast)
354 {
355         return &ast_null_frame;
356 }
357 static int rec_write(struct ast_channel *ast, struct ast_frame *f)
358 {
359         return 0;
360 }
361 static struct ast_channel *rec_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause);
362 static struct ast_channel_tech record_tech = {
363         .type = "ConfBridgeRec",
364         .description = "Conference Bridge Recording Channel",
365         .requester = rec_request,
366         .read = rec_read,
367         .write = rec_write,
368 };
369 static struct ast_channel *rec_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause)
370 {
371         struct ast_channel *tmp;
372         struct ast_format fmt;
373         const char *conf_name = data;
374         if (!(tmp = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", NULL, 0,
375                 "ConfBridgeRecorder/conf-%s-uid-%d",
376                 conf_name,
377                 (int) ast_random()))) {
378                 return NULL;
379         }
380         ast_format_set(&fmt, AST_FORMAT_SLINEAR, 0);
381         tmp->tech = &record_tech;
382         ast_format_cap_add_all(tmp->nativeformats);
383         ast_format_copy(&tmp->writeformat, &fmt);
384         ast_format_copy(&tmp->rawwriteformat, &fmt);
385         ast_format_copy(&tmp->readformat, &fmt);
386         ast_format_copy(&tmp->rawreadformat, &fmt);
387         return tmp;
388 }
389
390 static void *record_thread(void *obj)
391 {
392         struct conference_bridge *conference_bridge = obj;
393         struct ast_app *mixmonapp = pbx_findapp("MixMonitor");
394         struct ast_channel *chan;
395         struct ast_str *filename = ast_str_alloca(PATH_MAX);
396
397         if (!mixmonapp) {
398                 ao2_ref(conference_bridge, -1);
399                 return NULL;
400         }
401
402         ao2_lock(conference_bridge);
403         if (!(conference_bridge->record_chan)) {
404                 conference_bridge->record_thread = AST_PTHREADT_NULL;
405                 ao2_unlock(conference_bridge);
406                 ao2_ref(conference_bridge, -1);
407                 return NULL;
408         }
409         chan = ast_channel_ref(conference_bridge->record_chan);
410
411         if (!(ast_strlen_zero(conference_bridge->b_profile.rec_file))) {
412                 ast_str_append(&filename, 0, "%s", conference_bridge->b_profile.rec_file);
413         } else {
414                 time_t now;
415                 time(&now);
416                 ast_str_append(&filename, 0, "confbridge-%s-%u.wav",
417                         conference_bridge->name,
418                         (unsigned int) now);
419         }
420         ao2_unlock(conference_bridge);
421
422         ast_answer(chan);
423         pbx_exec(chan, mixmonapp, ast_str_buffer(filename));
424         ast_bridge_join(conference_bridge->bridge, chan, NULL, NULL, NULL);
425
426         ao2_lock(conference_bridge);
427         conference_bridge->record_thread = AST_PTHREADT_NULL;
428         ao2_unlock(conference_bridge);
429
430         ast_hangup(chan); /* This will eat this threads reference to the channel as well */
431         ao2_ref(conference_bridge, -1);
432         return NULL;
433 }
434
435 /*!
436  * \internal
437  * \brief Returns whether or not conference is being recorded.
438  * \retval 1, conference is recording.
439  * \retval 0, conference is NOT recording.
440  */
441 static int conf_is_recording(struct conference_bridge *conference_bridge)
442 {
443         int res = 0;
444         ao2_lock(conference_bridge);
445         if (conference_bridge->record_chan || conference_bridge->record_thread != AST_PTHREADT_NULL) {
446                 res = 1;
447         }
448         ao2_unlock(conference_bridge);
449         return res;
450 }
451
452 /*!
453  * \internal
454  * \brief Stops the confbridge recording thread.
455  *
456  * \note do not call this function with any locks
457  */
458 static int conf_stop_record(struct conference_bridge *conference_bridge)
459 {
460         ao2_lock(conference_bridge);
461
462         if (conference_bridge->record_thread != AST_PTHREADT_NULL) {
463                 struct ast_channel *chan = ast_channel_ref(conference_bridge->record_chan);
464                 pthread_t thread = conference_bridge->record_thread;
465                 ao2_unlock(conference_bridge);
466
467                 ast_bridge_remove(conference_bridge->bridge, chan);
468                 ast_queue_frame(chan, &ast_null_frame);
469
470                 chan = ast_channel_unref(chan);
471                 pthread_join(thread, NULL);
472                 ast_test_suite_event_notify("CONF_STOP_RECORD", "Message: stopped conference recording channel\r\nConference: %s", conference_bridge->b_profile.name);
473
474                 ao2_lock(conference_bridge);
475         }
476
477         /* this is the reference given to the channel during the channel alloc */
478         if (conference_bridge->record_chan) {
479                 conference_bridge->record_chan = ast_channel_unref(conference_bridge->record_chan);
480         }
481
482         ao2_unlock(conference_bridge);
483         return 0;
484 }
485
486 static int conf_start_record(struct conference_bridge *conference_bridge)
487 {
488         struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
489         struct ast_format tmpfmt;
490         int cause;
491
492         ao2_lock(conference_bridge);
493         if (conference_bridge->record_chan || conference_bridge->record_thread != AST_PTHREADT_NULL) {
494                 ao2_unlock(conference_bridge);
495                 return -1; /* already recording */
496         }
497         if (!cap) {
498                 ao2_unlock(conference_bridge);
499                 return -1;
500         }
501         if (!pbx_findapp("MixMonitor")) {
502                 ast_log(LOG_WARNING, "Can not record ConfBridge, MixMonitor app is not installed\n");
503                 cap = ast_format_cap_destroy(cap);
504                 ao2_unlock(conference_bridge);
505                 return -1;
506         }
507         ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
508         if (!(conference_bridge->record_chan = ast_request("ConfBridgeRec", cap, NULL, conference_bridge->name, &cause))) {
509                 cap = ast_format_cap_destroy(cap);
510                 ao2_unlock(conference_bridge);
511                 return -1;
512         }
513
514         cap = ast_format_cap_destroy(cap);
515         ao2_ref(conference_bridge, +1); /* give the record thread a ref */
516
517         if (ast_pthread_create_background(&conference_bridge->record_thread, NULL, record_thread, conference_bridge)) {
518                 ast_log(LOG_WARNING, "Failed to create recording channel for conference %s\n", conference_bridge->name);
519
520                 ao2_unlock(conference_bridge);
521                 ao2_ref(conference_bridge, -1); /* error so remove ref */
522                 return -1;
523         }
524
525         ast_test_suite_event_notify("CONF_START_RECORD", "Message: started conference recording channel\r\nConference: %s", conference_bridge->b_profile.name);
526         ao2_unlock(conference_bridge);
527         return 0;
528 }
529
530 static void send_conf_start_event(const char *conf_name)
531 {
532         manager_event(EVENT_FLAG_CALL, "ConfbridgeStart", "Conference: %s\r\n", conf_name);
533 }
534
535 static void send_conf_end_event(const char *conf_name)
536 {
537         manager_event(EVENT_FLAG_CALL, "ConfbridgeEnd", "Conference: %s\r\n", conf_name);
538 }
539
540 static void send_join_event(struct ast_channel *chan, const char *conf_name)
541 {
542         ast_manager_event(chan, EVENT_FLAG_CALL, "ConfbridgeJoin",
543                 "Channel: %s\r\n"
544                 "Uniqueid: %s\r\n"
545                 "Conference: %s\r\n"
546                 "CallerIDnum: %s\r\n"
547                 "CallerIDname: %s\r\n",
548                 ast_channel_name(chan),
549                 chan->uniqueid,
550                 conf_name,
551                 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<unknown>"),
552                 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>")
553         );
554 }
555
556 static void send_leave_event(struct ast_channel *chan, const char *conf_name)
557 {
558         ast_manager_event(chan, EVENT_FLAG_CALL, "ConfbridgeLeave",
559                 "Channel: %s\r\n"
560                 "Uniqueid: %s\r\n"
561                 "Conference: %s\r\n"
562                 "CallerIDnum: %s\r\n"
563                 "CallerIDname: %s\r\n",
564                 ast_channel_name(chan),
565                 chan->uniqueid,
566                 conf_name,
567                 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<unknown>"),
568                 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>")
569         );
570 }
571
572 /*!
573  * \brief Announce number of users in the conference bridge to the caller
574  *
575  * \param conference_bridge Conference bridge to peek at
576  * \param (OPTIONAL) conference_bridge_user Caller
577  *
578  * \note if caller is NULL, the announcment will be sent to all participants in the conference.
579  * \return Returns 0 on success, -1 if the user hung up
580  */
581 static int announce_user_count(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
582 {
583         const char *other_in_party = conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, conference_bridge->b_profile.sounds);
584         const char *only_one = conf_get_sound(CONF_SOUND_ONLY_ONE, conference_bridge->b_profile.sounds);
585         const char *there_are = conf_get_sound(CONF_SOUND_THERE_ARE, conference_bridge->b_profile.sounds);
586
587         if (conference_bridge->users == 1) {
588                 /* Awww we are the only person in the conference bridge */
589                 return 0;
590         } else if (conference_bridge->users == 2) {
591                 if (conference_bridge_user) {
592                         /* Eep, there is one other person */
593                         if (ast_stream_and_wait(conference_bridge_user->chan,
594                                 only_one,
595                                 "")) {
596                                 return -1;
597                         }
598                 } else {
599                         play_sound_file(conference_bridge, only_one);
600                 }
601         } else {
602                 /* Alas multiple others in here */
603                 if (conference_bridge_user) {
604                         if (ast_stream_and_wait(conference_bridge_user->chan,
605                                 there_are,
606                                 "")) {
607                                 return -1;
608                         }
609                         if (ast_say_number(conference_bridge_user->chan, conference_bridge->users - 1, "", conference_bridge_user->chan->language, NULL)) {
610                                 return -1;
611                         }
612                         if (ast_stream_and_wait(conference_bridge_user->chan,
613                                 other_in_party,
614                                 "")) {
615                                 return -1;
616                         }
617                 } else {
618                         play_sound_file(conference_bridge, there_are);
619                         play_sound_number(conference_bridge, conference_bridge->users - 1);
620                         play_sound_file(conference_bridge, other_in_party);
621                 }
622         }
623         return 0;
624 }
625
626 /*!
627  * \brief Play back an audio file to a channel
628  *
629  * \param conference_bridge Conference bridge they are in
630  * \param chan Channel to play audio prompt to
631  * \param file Prompt to play
632  *
633  * \return Returns 0 on success, -1 if the user hung up
634  *
635  * \note This function assumes that conference_bridge is locked
636  */
637 static int play_prompt_to_channel(struct conference_bridge *conference_bridge, struct ast_channel *chan, const char *file)
638 {
639         int res;
640         ao2_unlock(conference_bridge);
641         res = ast_stream_and_wait(chan, file, "");
642         ao2_lock(conference_bridge);
643         return res;
644 }
645
646 static void handle_video_on_join(struct conference_bridge *conference_bridge, struct ast_channel *chan, int marked)
647 {
648         /* Right now, only marked users are automatically set as the single src of video.*/
649         if (!marked) {
650                 return;
651         }
652
653         if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED)) {
654                 int set = 1;
655                 struct conference_bridge_user *tmp_user = NULL;
656                 ao2_lock(conference_bridge);
657                 /* see if anyone is already the video src */
658                 AST_LIST_TRAVERSE(&conference_bridge->users_list, tmp_user, list) {
659                         if (tmp_user->chan == chan) {
660                                 continue;
661                         }
662                         if (ast_bridge_is_video_src(conference_bridge->bridge, tmp_user->chan)) {
663                                 set = 0;
664                                 break;
665                         }
666                 }
667                 ao2_unlock(conference_bridge);
668                 if (set) {
669                         ast_bridge_set_single_src_video_mode(conference_bridge->bridge, chan);
670                 }
671         } else if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
672                 /* we joined and are video capable, we override anyone else that may have already been the video feed */
673                 ast_bridge_set_single_src_video_mode(conference_bridge->bridge, chan);
674         }
675 }
676
677 static void handle_video_on_exit(struct conference_bridge *conference_bridge, struct ast_channel *chan)
678 {
679         struct conference_bridge_user *tmp_user = NULL;
680
681         /* if this isn't a video source, nothing to update */
682         if (!ast_bridge_is_video_src(conference_bridge->bridge, chan)) {
683                 return;
684         }
685
686         ast_bridge_remove_video_src(conference_bridge->bridge, chan);
687
688         /* If in follow talker mode, make sure to restore this mode on the
689          * bridge when a source is removed.  It is possible this channel was
690          * only set temporarily as a video source by an AMI or DTMF action. */
691         if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
692                 ast_bridge_set_talker_src_video_mode(conference_bridge->bridge);
693         }
694
695         /* if the video_mode isn't set to automatically pick the video source, do nothing on exit. */
696         if (!ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED) &&
697                 !ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
698                 return;
699         }
700
701         /* Make the next available marked user the video src.  */
702         ao2_lock(conference_bridge);
703         AST_LIST_TRAVERSE(&conference_bridge->users_list, tmp_user, list) {
704                 if (tmp_user->chan == chan) {
705                         continue;
706                 }
707                 if (ast_test_flag(&tmp_user->u_profile, USER_OPT_MARKEDUSER)) {
708                         ast_bridge_set_single_src_video_mode(conference_bridge->bridge, tmp_user->chan);
709                         break;
710                 }
711         }
712         ao2_unlock(conference_bridge);
713 }
714
715 /*!
716  * \brief Perform post-joining marked specific actions
717  *
718  * \param conference_bridge Conference bridge being joined
719  * \param conference_bridge_user Conference bridge user joining
720  *
721  * \return Returns 0 on success, -1 if the user hung up
722  */
723 static int post_join_marked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
724 {
725         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) {
726                 struct conference_bridge_user *other_conference_bridge_user = NULL;
727
728                 /* If we are not the first user to join, then the users are already
729                  * in the conference so we do not need to update them. */
730                 if (conference_bridge->markedusers >= 2) {
731                         return 0;
732                 }
733
734                 /* Iterate through every participant stopping MOH on them if need be */
735                 AST_LIST_TRAVERSE(&conference_bridge->users_list, other_conference_bridge_user, list) {
736                         if (other_conference_bridge_user == conference_bridge_user) {
737                                 continue;
738                         }
739                         if (other_conference_bridge_user->playing_moh && !ast_bridge_suspend(conference_bridge->bridge, other_conference_bridge_user->chan)) {
740                                 other_conference_bridge_user->playing_moh = 0;
741                                 ast_moh_stop(other_conference_bridge_user->chan);
742                                 ast_bridge_unsuspend(conference_bridge->bridge, other_conference_bridge_user->chan);
743                         }
744                 }
745
746                 /* Next play the audio file stating they are going to be placed into the conference */
747                 if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
748                         ao2_unlock(conference_bridge);
749                         ast_autoservice_start(conference_bridge_user->chan);
750                         play_sound_file(conference_bridge,
751                                 conf_get_sound(CONF_SOUND_PLACE_IN_CONF, conference_bridge_user->b_profile.sounds));
752                         ast_autoservice_stop(conference_bridge_user->chan);
753                         ao2_lock(conference_bridge);
754                 }
755
756                 /* Finally iterate through and unmute them all */
757                 AST_LIST_TRAVERSE(&conference_bridge->users_list, other_conference_bridge_user, list) {
758                         if (other_conference_bridge_user == conference_bridge_user) {
759                                 continue;
760                         }
761                         /* only unmute them if they are not supposed to start muted */
762                         if (!ast_test_flag(&other_conference_bridge_user->u_profile, USER_OPT_STARTMUTED)) {
763                                 other_conference_bridge_user->features.mute = 0;
764                         }
765                 }
766         } else {
767                 /* If a marked user already exists in the conference bridge we can just bail out now */
768                 if (conference_bridge->markedusers) {
769                         return 0;
770                 }
771                 /* Be sure we are muted so we can't talk to anybody else waiting */
772                 conference_bridge_user->features.mute = 1;
773                 /* If we have not been quieted play back that they are waiting for the leader */
774                 if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
775                         if (play_prompt_to_channel(conference_bridge,
776                                 conference_bridge_user->chan,
777                                 conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, conference_bridge_user->b_profile.sounds))) {
778                                 /* user hungup while the sound was playing */
779                                 return -1;
780                         }
781                 }
782                 /* Start music on hold if needed */
783                 /* We need to recheck the markedusers value here. play_prompt_to_channel unlocks the conference bridge, potentially
784                  * allowing a marked user to enter while the prompt was playing
785                  */
786                 if (!conference_bridge->markedusers && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) {
787                         ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL);
788                         conference_bridge_user->playing_moh = 1;
789                 }
790         }
791         return 0;
792 }
793
794 /*!
795  * \brief Perform post-joining non-marked specific actions
796  *
797  * \param conference_bridge Conference bridge being joined
798  * \param conference_bridge_user Conference bridge user joining
799  *
800  * \return Returns 0 on success, -1 if the user hung up
801  */
802 static int post_join_unmarked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
803 {
804         /* Play back audio prompt and start MOH if need be if we are the first participant */
805         if (conference_bridge->users == 1) {
806                 /* If audio prompts have not been quieted or this prompt quieted play it on out */
807                 if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET | USER_OPT_NOONLYPERSON)) {
808                         if (play_prompt_to_channel(conference_bridge,
809                                 conference_bridge_user->chan,
810                                 conf_get_sound(CONF_SOUND_ONLY_PERSON, conference_bridge_user->b_profile.sounds))) {
811                                 /* user hungup while the sound was playing */
812                                 return -1;
813                         }
814                 }
815                 /* If we need to start music on hold on the channel do so now */
816                 /* We need to re-check the number of users in the conference bridge here because another conference bridge
817                  * participant could have joined while the above prompt was playing for the first user.
818                  */
819                 if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) {
820                         ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL);
821                         conference_bridge_user->playing_moh = 1;
822                 }
823                 return 0;
824         }
825
826         /* Announce number of users if need be */
827         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) {
828                 ao2_unlock(conference_bridge);
829                 if (announce_user_count(conference_bridge, conference_bridge_user)) {
830                         ao2_lock(conference_bridge);
831                         return -1;
832                 }
833                 ao2_lock(conference_bridge);
834         }
835
836         /* If we are the second participant we may need to stop music on hold on the first */
837         if (conference_bridge->users == 2) {
838                 struct conference_bridge_user *first_participant = AST_LIST_FIRST(&conference_bridge->users_list);
839
840                 /* Temporarily suspend the above participant from the bridge so we have control to stop MOH if needed */
841                 if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
842                         first_participant->playing_moh = 0;
843                         ast_moh_stop(first_participant->chan);
844                         ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
845                 }
846         }
847
848         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) &&
849                 (conference_bridge->users > conference_bridge_user->u_profile.announce_user_count_all_after)) {
850                 ao2_unlock(conference_bridge);
851                 if (announce_user_count(conference_bridge, NULL)) {
852                         ao2_lock(conference_bridge);
853                         return -1;
854                 }
855                 ao2_lock(conference_bridge);
856         }
857         return 0;
858 }
859
860 /*!
861  * \brief Destroy a conference bridge
862  *
863  * \param obj The conference bridge object
864  *
865  * \return Returns nothing
866  */
867 static void destroy_conference_bridge(void *obj)
868 {
869         struct conference_bridge *conference_bridge = obj;
870
871         ast_debug(1, "Destroying conference bridge '%s'\n", conference_bridge->name);
872
873         ast_mutex_destroy(&conference_bridge->playback_lock);
874
875         if (conference_bridge->playback_chan) {
876                 struct ast_channel *underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL);
877                 if (underlying_channel) {
878                         ast_hangup(underlying_channel);
879                 }
880                 ast_hangup(conference_bridge->playback_chan);
881                 conference_bridge->playback_chan = NULL;
882         }
883
884         /* Destroying a conference bridge is simple, all we have to do is destroy the bridging object */
885         if (conference_bridge->bridge) {
886                 ast_bridge_destroy(conference_bridge->bridge);
887                 conference_bridge->bridge = NULL;
888         }
889         conf_bridge_profile_destroy(&conference_bridge->b_profile);
890 }
891
892 static void leave_conference_bridge(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user);
893
894 /*!
895  * \brief Join a conference bridge
896  *
897  * \param name The conference name
898  * \param conference_bridge_user Conference bridge user structure
899  *
900  * \return A pointer to the conference bridge struct, or NULL if the conference room wasn't found.
901  */
902 static struct conference_bridge *join_conference_bridge(const char *name, struct conference_bridge_user *conference_bridge_user)
903 {
904         struct conference_bridge *conference_bridge = NULL;
905         struct conference_bridge tmp;
906         int start_record = 0;
907         int max_members_reached = 0;
908
909         ast_copy_string(tmp.name, name, sizeof(tmp.name));
910
911         /* We explictly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same */
912         ao2_lock(conference_bridges);
913
914         ast_debug(1, "Trying to find conference bridge '%s'\n", name);
915
916         /* Attempt to find an existing conference bridge */
917         conference_bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
918
919         if (conference_bridge && conference_bridge->b_profile.max_members) {
920                 max_members_reached = conference_bridge->b_profile.max_members > conference_bridge->users ? 0 : 1;
921         }
922
923         /* When finding a conference bridge that already exists make sure that it is not locked, and if so that we are not an admin */
924         if (conference_bridge && (max_members_reached || conference_bridge->locked) && !ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN)) {
925                 ao2_unlock(conference_bridges);
926                 ao2_ref(conference_bridge, -1);
927                 ast_debug(1, "Conference bridge '%s' is locked and caller is not an admin\n", name);
928                 ast_stream_and_wait(conference_bridge_user->chan,
929                                 conf_get_sound(CONF_SOUND_LOCKED, conference_bridge_user->b_profile.sounds),
930                                 "");
931                 return NULL;
932         }
933
934         /* If no conference bridge was found see if we can create one */
935         if (!conference_bridge) {
936                 /* Try to allocate memory for a new conference bridge, if we fail... this won't end well. */
937                 if (!(conference_bridge = ao2_alloc(sizeof(*conference_bridge), destroy_conference_bridge))) {
938                         ao2_unlock(conference_bridges);
939                         ast_log(LOG_ERROR, "Conference bridge '%s' does not exist.\n", name);
940                         return NULL;
941                 }
942
943                 /* Setup conference bridge parameters */
944                 conference_bridge->record_thread = AST_PTHREADT_NULL;
945                 ast_copy_string(conference_bridge->name, name, sizeof(conference_bridge->name));
946                 conf_bridge_profile_copy(&conference_bridge->b_profile, &conference_bridge_user->b_profile);
947
948                 /* Create an actual bridge that will do the audio mixing */
949                 if (!(conference_bridge->bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_MULTIMIX, 0))) {
950                         ao2_ref(conference_bridge, -1);
951                         conference_bridge = NULL;
952                         ao2_unlock(conference_bridges);
953                         ast_log(LOG_ERROR, "Conference bridge '%s' could not be created.\n", name);
954                         return NULL;
955                 }
956
957                 /* Set the internal sample rate on the bridge from the bridge profile */
958                 ast_bridge_set_internal_sample_rate(conference_bridge->bridge, conference_bridge->b_profile.internal_sample_rate);
959                 /* Set the internal mixing interval on the bridge from the bridge profile */
960                 ast_bridge_set_mixing_interval(conference_bridge->bridge, conference_bridge->b_profile.mix_interval);
961
962                 if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
963                         ast_bridge_set_talker_src_video_mode(conference_bridge->bridge);
964                 }
965
966                 /* Setup lock for playback channel */
967                 ast_mutex_init(&conference_bridge->playback_lock);
968
969                 /* Link it into the conference bridges container */
970                 ao2_link(conference_bridges, conference_bridge);
971
972
973                 send_conf_start_event(conference_bridge->name);
974                 ast_debug(1, "Created conference bridge '%s' and linked to container '%p'\n", name, conference_bridges);
975         }
976
977         ao2_unlock(conference_bridges);
978
979         /* Setup conference bridge user parameters */
980         conference_bridge_user->conference_bridge = conference_bridge;
981
982         ao2_lock(conference_bridge);
983
984         /* All good to go, add them in */
985         AST_LIST_INSERT_TAIL(&conference_bridge->users_list, conference_bridge_user, list);
986
987         /* Increment the users count on the bridge, but record it as it is going to need to be known right after this */
988         conference_bridge->users++;
989
990         /* If the caller is a marked user bump up the count */
991         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) {
992                 conference_bridge->markedusers++;
993         }
994
995         /* Set the device state for this conference */
996         if (conference_bridge->users == 1) {
997                 ast_devstate_changed(AST_DEVICE_INUSE, "confbridge:%s", conference_bridge->name);
998         }
999
1000         /* If the caller is a marked user or is waiting for a marked user to enter pass 'em off, otherwise pass them off to do regular joining stuff */
1001         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER | USER_OPT_WAITMARKED)) {
1002                 if (post_join_marked(conference_bridge, conference_bridge_user)) {
1003                         ao2_unlock(conference_bridge);
1004                         leave_conference_bridge(conference_bridge, conference_bridge_user);
1005                         return NULL;
1006                 }
1007         } else {
1008                 if (post_join_unmarked(conference_bridge, conference_bridge_user)) {
1009                         ao2_unlock(conference_bridge);
1010                         leave_conference_bridge(conference_bridge, conference_bridge_user);
1011                         return NULL;
1012                 }
1013         }
1014
1015         /* check to see if recording needs to be started or not */
1016         if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_RECORD_CONFERENCE) && !conf_is_recording(conference_bridge)) {
1017                 start_record = 1;
1018         }
1019
1020         ao2_unlock(conference_bridge);
1021
1022         if (start_record) {
1023                 conf_start_record(conference_bridge);
1024         }
1025
1026         return conference_bridge;
1027 }
1028
1029 /*!
1030  * \brief Leave a conference bridge
1031  *
1032  * \param conference_bridge The conference bridge to leave
1033  * \param conference_bridge_user The conference bridge user structure
1034  *
1035  */
1036 static void leave_conference_bridge(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
1037 {
1038         ao2_lock(conference_bridge);
1039
1040         /* If this caller is a marked user bump down the count */
1041         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) {
1042                 conference_bridge->markedusers--;
1043         }
1044
1045         /* Decrement the users count while keeping the previous participant count */
1046         conference_bridge->users--;
1047
1048         /* Drop conference bridge user from the list, they be going bye bye */
1049         AST_LIST_REMOVE(&conference_bridge->users_list, conference_bridge_user, list);
1050
1051         /* If there are still users in the conference bridge we may need to do things (such as start MOH on them) */
1052         if (conference_bridge->users) {
1053                 if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER) && !conference_bridge->markedusers) {
1054                         struct conference_bridge_user *other_participant = NULL;
1055
1056                         /* Start out with muting everyone */
1057                         AST_LIST_TRAVERSE(&conference_bridge->users_list, other_participant, list) {
1058                                 other_participant->features.mute = 1;
1059                         }
1060
1061                         /* Play back the audio prompt saying the leader has left the conference */
1062                         if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
1063                                 ao2_unlock(conference_bridge);
1064                                 ast_autoservice_start(conference_bridge_user->chan);
1065                                 play_sound_file(conference_bridge,
1066                                         conf_get_sound(CONF_SOUND_LEADER_HAS_LEFT, conference_bridge_user->b_profile.sounds));
1067                                 ast_autoservice_stop(conference_bridge_user->chan);
1068                                 ao2_lock(conference_bridge);
1069                         }
1070
1071                         /* Now on to starting MOH or kick if needed */
1072                         AST_LIST_TRAVERSE(&conference_bridge->users_list, other_participant, list) {
1073                                 if (ast_test_flag(&other_participant->u_profile, USER_OPT_ENDMARKED)) {
1074                                         other_participant->kicked = 1;
1075                                         ast_bridge_remove(conference_bridge->bridge, other_participant->chan);
1076                                 } else if (ast_test_flag(&other_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_participant->chan)) {
1077                                         ast_moh_start(other_participant->chan, other_participant->u_profile.moh_class, NULL);
1078                                         other_participant->playing_moh = 1;
1079                                         ast_bridge_unsuspend(conference_bridge->bridge, other_participant->chan);
1080                                 }
1081                         }
1082                 } else if (conference_bridge->users == 1) {
1083                         /* Of course if there is one other person in here we may need to start up MOH on them */
1084                         struct conference_bridge_user *first_participant = AST_LIST_FIRST(&conference_bridge->users_list);
1085
1086                         if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
1087                                 ast_moh_start(first_participant->chan, first_participant->u_profile.moh_class, NULL);
1088                                 first_participant->playing_moh = 1;
1089                                 ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
1090                         }
1091                 }
1092         } else {
1093                 /* Set device state to "not in use" */
1094                 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "confbridge:%s", conference_bridge->name);
1095
1096                 ao2_unlink(conference_bridges, conference_bridge);
1097                 send_conf_end_event(conference_bridge->name);
1098         }
1099
1100         /* Done mucking with the conference bridge, huzzah */
1101         ao2_unlock(conference_bridge);
1102
1103         if (!conference_bridge->users) {
1104                 conf_stop_record(conference_bridge);
1105         }
1106
1107         ao2_ref(conference_bridge, -1);
1108 }
1109
1110 /*!
1111  * \internal
1112  * \brief allocates playback chan on a channel
1113  * \pre expects conference to be locked before calling this function
1114  */
1115 static int alloc_playback_chan(struct conference_bridge *conference_bridge)
1116 {
1117         int cause;
1118         struct ast_format_cap *cap;
1119         struct ast_format tmpfmt;
1120
1121         if (conference_bridge->playback_chan) {
1122                 return 0;
1123         }
1124         if (!(cap = ast_format_cap_alloc_nolock())) {
1125                 return -1;
1126         }
1127         ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
1128         if (!(conference_bridge->playback_chan = ast_request("Bridge", cap, NULL, "", &cause))) {
1129                 cap = ast_format_cap_destroy(cap);
1130                 return -1;
1131         }
1132         cap = ast_format_cap_destroy(cap);
1133
1134         conference_bridge->playback_chan->bridge = conference_bridge->bridge;
1135
1136         if (ast_call(conference_bridge->playback_chan, "", 0)) {
1137                 ast_hangup(conference_bridge->playback_chan);
1138                 conference_bridge->playback_chan = NULL;
1139                 return -1;
1140         }
1141
1142         ast_debug(1, "Created a playback channel to conference bridge '%s'\n", conference_bridge->name);
1143         return 0;
1144 }
1145
1146 static int play_sound_helper(struct conference_bridge *conference_bridge, const char *filename, int say_number)
1147 {
1148         struct ast_channel *underlying_channel;
1149
1150         ast_mutex_lock(&conference_bridge->playback_lock);
1151         if (!(conference_bridge->playback_chan)) {
1152                 if (alloc_playback_chan(conference_bridge)) {
1153                         ast_mutex_unlock(&conference_bridge->playback_lock);
1154                         return -1;
1155                 }
1156                 underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL);
1157         } else {
1158                 /* Channel was already available so we just need to add it back into the bridge */
1159                 underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL);
1160                 ast_bridge_impart(conference_bridge->bridge, underlying_channel, NULL, NULL, 0);
1161         }
1162
1163         /* The channel is all under our control, in goes the prompt */
1164         if (!ast_strlen_zero(filename)) {
1165                 ast_stream_and_wait(conference_bridge->playback_chan, filename, "");
1166         } else {
1167                 ast_say_number(conference_bridge->playback_chan, say_number, "", conference_bridge->playback_chan->language, NULL);
1168         }
1169
1170         ast_debug(1, "Departing underlying channel '%s' from bridge '%p'\n", ast_channel_name(underlying_channel), conference_bridge->bridge);
1171         ast_bridge_depart(conference_bridge->bridge, underlying_channel);
1172
1173         ast_mutex_unlock(&conference_bridge->playback_lock);
1174
1175         return 0;
1176 }
1177
1178 /*!
1179  * \brief Play sound file into conference bridge
1180  *
1181  * \param conference_bridge The conference bridge to play sound file into
1182  * \param filename Sound file to play
1183  *
1184  * \retval 0 success
1185  * \retval -1 failure
1186  */
1187 static int play_sound_file(struct conference_bridge *conference_bridge, const char *filename)
1188 {
1189         return play_sound_helper(conference_bridge, filename, 0);
1190 }
1191
1192 /*!
1193  * \brief Play number into the conference bridge
1194  *
1195  * \param conference_bridge The conference bridge to say the number into
1196  * \param number to say
1197  *
1198  * \retval 0 success
1199  * \retval -1 failure
1200  */
1201 static int play_sound_number(struct conference_bridge *conference_bridge, int say_number)
1202 {
1203         return play_sound_helper(conference_bridge, NULL, say_number);
1204 }
1205
1206 static void conf_handle_talker_destructor(void *pvt_data)
1207 {
1208         ast_free(pvt_data);
1209 }
1210
1211 static void conf_handle_talker_cb(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *pvt_data)
1212 {
1213         char *conf_name = pvt_data;
1214         int talking;
1215
1216         switch (bridge_channel->state) {
1217         case AST_BRIDGE_CHANNEL_STATE_START_TALKING:
1218                 talking = 1;
1219                 break;
1220         case AST_BRIDGE_CHANNEL_STATE_STOP_TALKING:
1221                 talking = 0;
1222                 break;
1223         default:
1224                 return; /* uhh this shouldn't happen, but bail if it does. */
1225         }
1226
1227         /* notify AMI someone is has either started or stopped talking */
1228         ast_manager_event(bridge_channel->chan, EVENT_FLAG_CALL, "ConfbridgeTalking",
1229               "Channel: %s\r\n"
1230               "Uniqueid: %s\r\n"
1231               "Conference: %s\r\n"
1232               "TalkingStatus: %s\r\n",
1233               ast_channel_name(bridge_channel->chan), bridge_channel->chan->uniqueid, conf_name, talking ? "on" : "off");
1234 }
1235
1236 static int conf_get_pin(struct ast_channel *chan, struct conference_bridge_user *conference_bridge_user)
1237 {
1238         char pin_guess[MAX_PIN+1] = { 0, };
1239         const char *pin = conference_bridge_user->u_profile.pin;
1240         char *tmp = pin_guess;
1241         int i, res;
1242         unsigned int len = MAX_PIN ;
1243
1244         /* give them three tries to get the pin right */
1245         for (i = 0; i < 3; i++) {
1246                 if (ast_app_getdata(chan,
1247                         conf_get_sound(CONF_SOUND_GET_PIN, conference_bridge_user->b_profile.sounds),
1248                         tmp, len, 0) >= 0) {
1249                         if (!strcasecmp(pin, pin_guess)) {
1250                                 return 0;
1251                         }
1252                 }
1253                 ast_streamfile(chan,
1254                         conf_get_sound(CONF_SOUND_INVALID_PIN, conference_bridge_user->b_profile.sounds),
1255                         chan->language);
1256                 res = ast_waitstream(chan, AST_DIGIT_ANY);
1257                 if (res > 0) {
1258                         /* Account for digit already read during ivalid pin playback
1259                          * resetting pin buf. */
1260                         pin_guess[0] = res;
1261                         pin_guess[1] = '\0';
1262                         tmp = pin_guess + 1;
1263                         len = MAX_PIN - 1;
1264                 } else {
1265                         /* reset pin buf as empty buffer. */
1266                         tmp = pin_guess;
1267                         len = MAX_PIN;
1268                 }
1269         }
1270         return -1;
1271 }
1272
1273 static int conf_rec_name(struct conference_bridge_user *user, const char *conf_name)
1274 {
1275         char destdir[PATH_MAX];
1276         int res;
1277         int duration = 20;
1278
1279         snprintf(destdir, sizeof(destdir), "%s/confbridge", ast_config_AST_SPOOL_DIR);
1280
1281         if (ast_mkdir(destdir, 0777) != 0) {
1282                 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno));
1283                 return -1;
1284         }
1285         snprintf(user->name_rec_location, sizeof(user->name_rec_location),
1286                  "%s/confbridge-name-%s-%s", destdir,
1287                  conf_name, user->chan->uniqueid);
1288
1289         res = ast_play_and_record(user->chan,
1290                 "vm-rec-name",
1291                 user->name_rec_location,
1292                 10,
1293                 "sln",
1294                 &duration,
1295                 NULL,
1296                 ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE),
1297                 0,
1298                 NULL);
1299
1300         if (res == -1) {
1301                 user->name_rec_location[0] = '\0';
1302                 return -1;
1303         }
1304         return 0;
1305 }
1306
1307 /*! \brief The ConfBridge application */
1308 static int confbridge_exec(struct ast_channel *chan, const char *data)
1309 {
1310         int res = 0, volume_adjustments[2];
1311         int quiet = 0;
1312         char *parse;
1313         const char *b_profile_name = DEFAULT_BRIDGE_PROFILE;
1314         const char *u_profile_name = DEFAULT_USER_PROFILE;
1315         struct conference_bridge *conference_bridge = NULL;
1316         struct conference_bridge_user conference_bridge_user = {
1317                 .chan = chan,
1318                 .tech_args.talking_threshold = DEFAULT_TALKING_THRESHOLD,
1319                 .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD,
1320                 .tech_args.drop_silence = 0,
1321         };
1322         AST_DECLARE_APP_ARGS(args,
1323                 AST_APP_ARG(conf_name);
1324                 AST_APP_ARG(b_profile_name);
1325                 AST_APP_ARG(u_profile_name);
1326                 AST_APP_ARG(menu_name);
1327         );
1328         ast_bridge_features_init(&conference_bridge_user.features);
1329
1330         if (chan->_state != AST_STATE_UP) {
1331                 ast_answer(chan);
1332         }
1333
1334         if (ast_strlen_zero(data)) {
1335                 ast_log(LOG_WARNING, "%s requires an argument (conference name[,options])\n", app);
1336                 res = -1; /* invalid PIN */
1337                 goto confbridge_cleanup;
1338         }
1339
1340         /* We need to make a copy of the input string if we are going to modify it! */
1341         parse = ast_strdupa(data);
1342
1343         AST_STANDARD_APP_ARGS(args, parse);
1344
1345         /* bridge profile name */
1346         if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) {
1347                 b_profile_name = args.b_profile_name;
1348         }
1349         if (!conf_find_bridge_profile(chan, b_profile_name, &conference_bridge_user.b_profile)) {
1350                 ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name);
1351                 res = -1;
1352                 goto confbridge_cleanup;
1353         }
1354
1355         /* user profile name */
1356         if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) {
1357                 u_profile_name = args.u_profile_name;
1358         }
1359
1360         if (!conf_find_user_profile(chan, u_profile_name, &conference_bridge_user.u_profile)) {
1361                 ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name);
1362                 res = -1;
1363                 goto confbridge_cleanup;
1364         }
1365         quiet = ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_QUIET);
1366
1367         /* ask for a PIN immediately after finding user profile.  This has to be
1368          * prompted for requardless of quiet setting. */
1369         if (!ast_strlen_zero(conference_bridge_user.u_profile.pin)) {
1370                 if (conf_get_pin(chan, &conference_bridge_user)) {
1371                         res = -1; /* invalid PIN */
1372                         goto confbridge_cleanup;
1373                 }
1374         }
1375
1376         /* See if we need them to record a intro name */
1377         if (!quiet && ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE)) {
1378                 conf_rec_name(&conference_bridge_user, args.conf_name);
1379         }
1380
1381         /* menu name */
1382         if (args.argc > 3 && !ast_strlen_zero(args.menu_name)) {
1383                 ast_copy_string(conference_bridge_user.menu_name, args.menu_name, sizeof(conference_bridge_user.menu_name));
1384                 if (conf_set_menu_to_user(conference_bridge_user.menu_name, &conference_bridge_user)) {
1385                         ast_log(LOG_WARNING, "Conference menu %s does not exist and can not be applied to confbridge user.\n",
1386                                 args.menu_name);
1387                         res = -1; /* invalid PIN */
1388                         goto confbridge_cleanup;
1389                 }
1390         }
1391
1392         /* Set if DTMF should pass through for this user or not */
1393         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DTMF_PASS)) {
1394                 conference_bridge_user.features.dtmf_passthrough = 1;
1395         }
1396
1397         /* Set dsp threshold values if present */
1398         if (conference_bridge_user.u_profile.talking_threshold) {
1399                 conference_bridge_user.tech_args.talking_threshold = conference_bridge_user.u_profile.talking_threshold;
1400         }
1401         if (conference_bridge_user.u_profile.silence_threshold) {
1402                 conference_bridge_user.tech_args.silence_threshold = conference_bridge_user.u_profile.silence_threshold;
1403         }
1404
1405         /* Set a talker indicate call back if talking detection is requested */
1406         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_TALKER_DETECT)) {
1407                 char *conf_name = ast_strdup(args.conf_name); /* this is freed during feature cleanup */
1408                 if (!(conf_name)) {
1409                         res = -1; /* invalid PIN */
1410                         goto confbridge_cleanup;
1411                 }
1412                 ast_bridge_features_set_talk_detector(&conference_bridge_user.features,
1413                         conf_handle_talker_cb,
1414                         conf_handle_talker_destructor,
1415                         conf_name);
1416         }
1417
1418         /* Look for a conference bridge matching the provided name */
1419         if (!(conference_bridge = join_conference_bridge(args.conf_name, &conference_bridge_user))) {
1420                 res = -1; /* invalid PIN */
1421                 goto confbridge_cleanup;
1422         }
1423
1424         /* Keep a copy of volume adjustments so we can restore them later if need be */
1425         volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
1426         volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
1427
1428         /* If the caller should be joined already muted, make it so */
1429         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_STARTMUTED)) {
1430                 conference_bridge_user.features.mute = 1;
1431         }
1432
1433         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DROP_SILENCE)) {
1434                 conference_bridge_user.tech_args.drop_silence = 1;
1435         }
1436
1437         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_JITTERBUFFER)) {
1438                 char *func_jb;
1439                 if ((func_jb = ast_module_helper("", "func_jitterbuffer", 0, 0, 0, 0))) {
1440                         ast_free(func_jb);
1441                         ast_func_write(chan, "JITTERBUFFER(adaptive)", "default");
1442                 }
1443         }
1444
1445         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DENOISE)) {
1446                 char *mod_speex;
1447                 /* Reduce background noise from each participant */
1448                 if ((mod_speex = ast_module_helper("", "codec_speex", 0, 0, 0, 0))) {
1449                         ast_free(mod_speex);
1450                         ast_func_write(chan, "DENOISE(rx)", "on");
1451                 }
1452         }
1453
1454         /* if this user has a intro, play it before entering */
1455         if (!ast_strlen_zero(conference_bridge_user.name_rec_location)) {
1456                 ast_autoservice_start(chan);
1457                 play_sound_file(conference_bridge, conference_bridge_user.name_rec_location);
1458                 play_sound_file(conference_bridge,
1459                         conf_get_sound(CONF_SOUND_HAS_JOINED, conference_bridge_user.b_profile.sounds));
1460                 ast_autoservice_stop(chan);
1461         }
1462
1463         /* Play the Join sound to both the conference and the user entering. */
1464         if (!quiet) {
1465                 const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference_bridge_user.b_profile.sounds);
1466                 if (conference_bridge_user.playing_moh) {
1467                         ast_moh_stop(chan);
1468                 }
1469                 ast_stream_and_wait(chan, join_sound, "");
1470                 ast_autoservice_start(chan);
1471                 play_sound_file(conference_bridge, join_sound);
1472                 ast_autoservice_stop(chan);
1473                 if (conference_bridge_user.playing_moh) {
1474                         ast_moh_start(chan, conference_bridge_user.u_profile.moh_class, NULL);
1475                 }
1476         }
1477
1478         /* See if we need to automatically set this user as a video source or not */
1479         handle_video_on_join(conference_bridge, conference_bridge_user.chan, ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_MARKEDUSER));
1480
1481         /* Join our conference bridge for real */
1482         send_join_event(conference_bridge_user.chan, conference_bridge->name);
1483         ast_bridge_join(conference_bridge->bridge,
1484                 chan,
1485                 NULL,
1486                 &conference_bridge_user.features,
1487                 &conference_bridge_user.tech_args);
1488         send_leave_event(conference_bridge_user.chan, conference_bridge->name);
1489
1490         /* if we're shutting down, don't attempt to do further processing */
1491         if (ast_shutting_down()) {
1492                 leave_conference_bridge(conference_bridge, &conference_bridge_user);
1493                 conference_bridge = NULL;
1494                 goto confbridge_cleanup;
1495         }
1496
1497         /* If this user was a video source, we need to clean up and possibly pick a new source. */
1498         handle_video_on_exit(conference_bridge, conference_bridge_user.chan);
1499
1500         /* if this user has a intro, play it when leaving */
1501         if (!quiet && !ast_strlen_zero(conference_bridge_user.name_rec_location)) {
1502                 ast_autoservice_start(chan);
1503                 play_sound_file(conference_bridge, conference_bridge_user.name_rec_location);
1504                 play_sound_file(conference_bridge,
1505                         conf_get_sound(CONF_SOUND_HAS_LEFT, conference_bridge_user.b_profile.sounds));
1506                 ast_autoservice_stop(chan);
1507         }
1508
1509         /* play the leave sound */
1510         if (!quiet) {
1511                 const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, conference_bridge_user.b_profile.sounds);
1512                 ast_autoservice_start(chan);
1513                 play_sound_file(conference_bridge, leave_sound);
1514                 ast_autoservice_stop(chan);
1515         }
1516
1517         /* Easy as pie, depart this channel from the conference bridge */
1518         leave_conference_bridge(conference_bridge, &conference_bridge_user);
1519         conference_bridge = NULL;
1520
1521         /* If the user was kicked from the conference play back the audio prompt for it */
1522         if (!quiet && conference_bridge_user.kicked) {
1523                 res = ast_stream_and_wait(chan,
1524                         conf_get_sound(CONF_SOUND_KICKED, conference_bridge_user.b_profile.sounds),
1525                         "");
1526         }
1527
1528         /* Restore volume adjustments to previous values in case they were changed */
1529         if (volume_adjustments[0]) {
1530                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
1531         }
1532         if (volume_adjustments[1]) {
1533                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
1534         }
1535
1536         if (!ast_strlen_zero(conference_bridge_user.name_rec_location)) {
1537                 ast_filedelete(conference_bridge_user.name_rec_location, NULL);
1538         }
1539
1540 confbridge_cleanup:
1541         ast_bridge_features_cleanup(&conference_bridge_user.features);
1542         conf_bridge_profile_destroy(&conference_bridge_user.b_profile);
1543         return res;
1544 }
1545
1546 static int action_toggle_mute(struct conference_bridge *conference_bridge,
1547         struct conference_bridge_user *conference_bridge_user,
1548         struct ast_channel *chan)
1549 {
1550         /* Mute or unmute yourself, note we only allow manipulation if they aren't waiting for a marked user or if marked users exist */
1551         if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_WAITMARKED) || conference_bridge->markedusers) {
1552                 conference_bridge_user->features.mute = (!conference_bridge_user->features.mute ? 1 : 0);
1553                 ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", ast_channel_name(chan), conference_bridge_user->features.mute ? "muted" : "unmuted", conference_bridge_user->b_profile.name, ast_channel_name(chan));
1554         }
1555         return ast_stream_and_wait(chan, (conference_bridge_user->features.mute ?
1556                 conf_get_sound(CONF_SOUND_MUTED, conference_bridge_user->b_profile.sounds) :
1557                 conf_get_sound(CONF_SOUND_UNMUTED, conference_bridge_user->b_profile.sounds)),
1558                 "");
1559 }
1560
1561 static int action_toggle_mute_participants(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
1562 {
1563         struct conference_bridge_user *participant = NULL;
1564         const char *sound_to_play;
1565
1566         ao2_lock(conference_bridge);
1567
1568         /* If already muted, then unmute */
1569         conference_bridge->muted = conference_bridge->muted ? 0 : 1;
1570         sound_to_play = conf_get_sound((conference_bridge->muted ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED),
1571                 conference_bridge_user->b_profile.sounds);
1572
1573         AST_LIST_TRAVERSE(&conference_bridge->users_list, participant, list) {
1574                 if (!ast_test_flag(&participant->u_profile, USER_OPT_ADMIN)) {
1575                         participant->features.mute = conference_bridge->muted;
1576                 }
1577         }
1578
1579         ao2_unlock(conference_bridge);
1580
1581         /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */
1582         ast_stream_and_wait(conference_bridge_user->chan, sound_to_play, "");
1583
1584         /* Announce to the group that all participants are muted */
1585         ast_autoservice_start(conference_bridge_user->chan);
1586         play_sound_helper(conference_bridge, sound_to_play, 0);
1587         ast_autoservice_stop(conference_bridge_user->chan);
1588
1589         return 0;
1590 }
1591
1592 static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
1593 {
1594         char *file_copy = ast_strdupa(playback_file);
1595         char *file = NULL;
1596
1597         while ((file = strsep(&file_copy, "&"))) {
1598                 if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
1599                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
1600                         return -1;
1601                 }
1602         }
1603         return 0;
1604 }
1605
1606 static int action_playback_and_continue(struct conference_bridge *conference_bridge,
1607         struct conference_bridge_user *conference_bridge_user,
1608         struct ast_bridge_channel *bridge_channel,
1609         struct conf_menu *menu,
1610         const char *playback_file,
1611         const char *cur_dtmf,
1612         int *stop_prompts)
1613 {
1614         int i;
1615         int digit = 0;
1616         char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
1617         struct conf_menu_entry new_menu_entry = { { 0, }, };
1618         char *file_copy = ast_strdupa(playback_file);
1619         char *file = NULL;
1620
1621         while ((file = strsep(&file_copy, "&"))) {
1622                 if (ast_streamfile(bridge_channel->chan, file, bridge_channel->chan->language)) {
1623                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
1624                         return -1;
1625                 }
1626
1627                 /* now wait for more digits. */
1628                 if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) {
1629                         /* streaming finished and no DTMF was entered */
1630                         continue;
1631                 } else if (digit == -1) {
1632                         /* error */
1633                         return -1;
1634                 } else {
1635                         break; /* dtmf was entered */
1636                 }
1637         }
1638         if (!digit) {
1639                 /* streaming finished on all files and no DTMF was entered */
1640                 return -1;
1641         }
1642         ast_stopstream(bridge_channel->chan);
1643
1644         /* If we get here, then DTMF has been entered, This means no
1645          * additional prompts should be played for this menu entry */
1646         *stop_prompts = 1;
1647
1648         /* If a digit was pressed during the payback, update
1649          * the dtmf string and look for a new menu entry in the
1650          * menu structure */
1651         ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf));
1652         for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) {
1653                 dtmf[i] = cur_dtmf[i];
1654                 if (!dtmf[i]) {
1655                         dtmf[i] = (char) digit;
1656                         dtmf[i + 1] = '\0';
1657                         i = -1;
1658                         break;
1659                 }
1660         }
1661         /* If i is not -1 then the new dtmf digit was _NOT_ added to the string.
1662          * If this is the case, no new DTMF sequence should be looked for. */
1663         if (i != -1) {
1664                 return 0;
1665         }
1666
1667         if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) {
1668                 execute_menu_entry(conference_bridge,
1669                         conference_bridge_user,
1670                         bridge_channel,
1671                         &new_menu_entry, menu);
1672                 conf_menu_entry_destroy(&new_menu_entry);
1673         }
1674         return 0;
1675 }
1676
1677 static int action_kick_last(struct conference_bridge *conference_bridge,
1678         struct ast_bridge_channel *bridge_channel,
1679         struct conference_bridge_user *conference_bridge_user)
1680 {
1681         struct conference_bridge_user *last_participant = NULL;
1682         int isadmin = ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN);
1683
1684         if (!isadmin) {
1685                 ast_stream_and_wait(bridge_channel->chan,
1686                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds),
1687                         "");
1688                 ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
1689                         ast_channel_name(bridge_channel->chan),
1690                         conference_bridge->name);
1691                 return -1;
1692         }
1693
1694         ao2_lock(conference_bridge);
1695         if (((last_participant = AST_LIST_LAST(&conference_bridge->users_list)) == conference_bridge_user)
1696                 || (ast_test_flag(&last_participant->u_profile, USER_OPT_ADMIN))) {
1697                 ao2_unlock(conference_bridge);
1698                 ast_stream_and_wait(bridge_channel->chan,
1699                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds),
1700                         "");
1701         } else if (last_participant) {
1702                 last_participant->kicked = 1;
1703                 ast_bridge_remove(conference_bridge->bridge, last_participant->chan);
1704                 ao2_unlock(conference_bridge);
1705         }
1706         return 0;
1707 }
1708
1709 static int action_dialplan_exec(struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
1710 {
1711         struct ast_pbx_args args;
1712         struct ast_pbx *pbx;
1713         char *exten;
1714         char *context;
1715         int priority;
1716         int res;
1717
1718         memset(&args, 0, sizeof(args));
1719         args.no_hangup_chan = 1;
1720
1721         ast_channel_lock(bridge_channel->chan);
1722
1723         /*save off*/
1724         exten = ast_strdupa(bridge_channel->chan->exten);
1725         context = ast_strdupa(bridge_channel->chan->context);
1726         priority = bridge_channel->chan->priority;
1727         pbx = bridge_channel->chan->pbx;
1728         bridge_channel->chan->pbx = NULL;
1729
1730         /*set new*/
1731         ast_copy_string(bridge_channel->chan->exten, menu_action->data.dialplan_args.exten, sizeof(bridge_channel->chan->exten));
1732         ast_copy_string(bridge_channel->chan->context, menu_action->data.dialplan_args.context, sizeof(bridge_channel->chan->context));
1733         bridge_channel->chan->priority = menu_action->data.dialplan_args.priority;
1734
1735         ast_channel_unlock(bridge_channel->chan);
1736
1737         /*execute*/
1738         res = ast_pbx_run_args(bridge_channel->chan, &args);
1739
1740         /*restore*/
1741         ast_channel_lock(bridge_channel->chan);
1742
1743         ast_copy_string(bridge_channel->chan->exten, exten, sizeof(bridge_channel->chan->exten));
1744         ast_copy_string(bridge_channel->chan->context, context, sizeof(bridge_channel->chan->context));
1745         bridge_channel->chan->priority = priority;
1746         bridge_channel->chan->pbx = pbx;
1747
1748         ast_channel_unlock(bridge_channel->chan);
1749
1750         return res;
1751 }
1752
1753 static int execute_menu_entry(struct conference_bridge *conference_bridge,
1754         struct conference_bridge_user *conference_bridge_user,
1755         struct ast_bridge_channel *bridge_channel,
1756         struct conf_menu_entry *menu_entry,
1757         struct conf_menu *menu)
1758 {
1759         struct conf_menu_action *menu_action;
1760         int isadmin = ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN);
1761         int stop_prompts = 0;
1762         int res = 0;
1763
1764         AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
1765                 switch (menu_action->id) {
1766                 case MENU_ACTION_TOGGLE_MUTE:
1767                         res |= action_toggle_mute(conference_bridge,
1768                                 conference_bridge_user,
1769                                 bridge_channel->chan);
1770                         break;
1771                 case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
1772                         if (!isadmin) {
1773                                 break;
1774                         }
1775                         action_toggle_mute_participants(conference_bridge, conference_bridge_user);
1776                         break;
1777                 case MENU_ACTION_PARTICIPANT_COUNT:
1778                         announce_user_count(conference_bridge, conference_bridge_user);
1779                         break;
1780                 case MENU_ACTION_PLAYBACK:
1781                         if (!stop_prompts) {
1782                                 res |= action_playback(bridge_channel, menu_action->data.playback_file);
1783                         }
1784                         break;
1785                 case MENU_ACTION_RESET_LISTENING:
1786                         ast_audiohook_volume_set(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 0);
1787                         break;
1788                 case MENU_ACTION_RESET_TALKING:
1789                         ast_audiohook_volume_set(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_READ, 0);
1790                         break;
1791                 case MENU_ACTION_INCREASE_LISTENING:
1792                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1793                                 AST_AUDIOHOOK_DIRECTION_WRITE, 1);
1794                         break;
1795                 case MENU_ACTION_DECREASE_LISTENING:
1796                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1797                                 AST_AUDIOHOOK_DIRECTION_WRITE, -1);
1798                         break;
1799                 case MENU_ACTION_INCREASE_TALKING:
1800                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1801                                 AST_AUDIOHOOK_DIRECTION_READ, 1);
1802                         break;
1803                 case MENU_ACTION_DECREASE_TALKING:
1804                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1805                                 AST_AUDIOHOOK_DIRECTION_READ, -1);
1806                         break;
1807                 case MENU_ACTION_PLAYBACK_AND_CONTINUE:
1808                         if (!(stop_prompts)) {
1809                                 res |= action_playback_and_continue(conference_bridge,
1810                                         conference_bridge_user,
1811                                         bridge_channel,
1812                                         menu,
1813                                         menu_action->data.playback_file,
1814                                         menu_entry->dtmf,
1815                                         &stop_prompts);
1816                         }
1817                         break;
1818                 case MENU_ACTION_DIALPLAN_EXEC:
1819                         res |= action_dialplan_exec(bridge_channel, menu_action);
1820                         break;
1821                 case MENU_ACTION_ADMIN_TOGGLE_LOCK:
1822                         if (!isadmin) {
1823                                 break;
1824                         }
1825                         conference_bridge->locked = (!conference_bridge->locked ? 1 : 0);
1826                         res |= ast_stream_and_wait(bridge_channel->chan,
1827                                 (conference_bridge->locked ?
1828                                 conf_get_sound(CONF_SOUND_LOCKED_NOW, conference_bridge_user->b_profile.sounds) :
1829                                 conf_get_sound(CONF_SOUND_UNLOCKED_NOW, conference_bridge_user->b_profile.sounds)),
1830                                 "");
1831
1832                         break;
1833                 case MENU_ACTION_ADMIN_KICK_LAST:
1834                         res |= action_kick_last(conference_bridge, bridge_channel, conference_bridge_user);
1835                         break;
1836                 case MENU_ACTION_LEAVE:
1837                         ao2_lock(conference_bridge);
1838                         ast_bridge_remove(conference_bridge->bridge, bridge_channel->chan);
1839                         ao2_unlock(conference_bridge);
1840                         break;
1841                 case MENU_ACTION_NOOP:
1842                         break;
1843                 case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
1844                         ao2_lock(conference_bridge);
1845                         ast_bridge_set_single_src_video_mode(conference_bridge->bridge, bridge_channel->chan);
1846                         ao2_unlock(conference_bridge);
1847                         break;
1848                 case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
1849                         handle_video_on_exit(conference_bridge, bridge_channel->chan);
1850                         break;
1851                 }
1852         }
1853         return res;
1854 }
1855
1856 int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
1857         struct conference_bridge_user *conference_bridge_user,
1858         struct conf_menu_entry *menu_entry,
1859         struct conf_menu *menu)
1860 {
1861         struct conference_bridge *conference_bridge = conference_bridge_user->conference_bridge;
1862
1863         /* See if music on hold is playing */
1864         ao2_lock(conference_bridge);
1865         if (conference_bridge_user->playing_moh) {
1866                 /* MOH is going, let's stop it */
1867                 ast_moh_stop(bridge_channel->chan);
1868         }
1869         ao2_unlock(conference_bridge);
1870
1871         /* execute the list of actions associated with this menu entry */
1872         execute_menu_entry(conference_bridge, conference_bridge_user, bridge_channel, menu_entry, menu);
1873
1874         /* See if music on hold needs to be started back up again */
1875         ao2_lock(conference_bridge);
1876         if (conference_bridge_user->playing_moh) {
1877                 ast_moh_start(bridge_channel->chan, conference_bridge_user->u_profile.moh_class, NULL);
1878         }
1879         ao2_unlock(conference_bridge);
1880
1881         return 0;
1882 }
1883
1884 static char *complete_confbridge_name(const char *line, const char *word, int pos, int state)
1885 {
1886         int which = 0;
1887         struct conference_bridge *bridge = NULL;
1888         char *res = NULL;
1889         int wordlen = strlen(word);
1890         struct ao2_iterator i;
1891
1892         i = ao2_iterator_init(conference_bridges, 0);
1893         while ((bridge = ao2_iterator_next(&i))) {
1894                 if (!strncasecmp(bridge->name, word, wordlen) && ++which > state) {
1895                         res = ast_strdup(bridge->name);
1896                         ao2_ref(bridge, -1);
1897                         break;
1898                 }
1899                 ao2_ref(bridge, -1);
1900         }
1901         ao2_iterator_destroy(&i);
1902
1903         return res;
1904 }
1905
1906 static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1907 {
1908         struct conference_bridge *bridge = NULL;
1909         struct conference_bridge tmp;
1910         struct conference_bridge_user *participant = NULL;
1911
1912         switch (cmd) {
1913         case CLI_INIT:
1914                 e->command = "confbridge kick";
1915                 e->usage =
1916                         "Usage: confbridge kick <conference> <channel>\n"
1917                         "       Kicks a channel out of the conference bridge.\n";
1918                 return NULL;
1919         case CLI_GENERATE:
1920                 if (a->pos == 2) {
1921                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
1922                 }
1923                 /*
1924                 if (a->pos == 3) {
1925                         return complete_confbridge_channel(a->line, a->word, a->pos, a->n);
1926                 }
1927                 */
1928                 return NULL;
1929         }
1930
1931         if (a->argc != 4) {
1932                 return CLI_SHOWUSAGE;
1933         }
1934
1935         ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name));
1936         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
1937         if (!bridge) {
1938                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
1939                 return CLI_SUCCESS;
1940         }
1941         ao2_lock(bridge);
1942         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
1943                 if (!strncmp(a->argv[3], ast_channel_name(participant->chan), strlen(ast_channel_name(participant->chan)))) {
1944                         break;
1945                 }
1946         }
1947         if (participant) {
1948                 ast_cli(a->fd, "Kicking %s from confbridge %s\n", ast_channel_name(participant->chan), bridge->name);
1949                 participant->kicked = 1;
1950                 ast_bridge_remove(bridge->bridge, participant->chan);
1951         }
1952         ao2_unlock(bridge);
1953         ao2_ref(bridge, -1);
1954         return CLI_SUCCESS;
1955 }
1956
1957 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1958 {
1959         struct ao2_iterator i;
1960         struct conference_bridge *bridge = NULL;
1961         struct conference_bridge tmp;
1962         struct conference_bridge_user *participant = NULL;
1963
1964         switch (cmd) {
1965         case CLI_INIT:
1966                 e->command = "confbridge list";
1967                 e->usage =
1968                         "Usage: confbridge list [<name>]\n"
1969                         "       Lists all currently active conference bridges.\n";
1970                 return NULL;
1971         case CLI_GENERATE:
1972                 if (a->pos == 2) {
1973                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
1974                 }
1975                 return NULL;
1976         }
1977
1978         if (a->argc == 2) {
1979                 ast_cli(a->fd, "Conference Bridge Name           Users  Marked Locked?\n");
1980                 ast_cli(a->fd, "================================ ====== ====== ========\n");
1981                 i = ao2_iterator_init(conference_bridges, 0);
1982                 while ((bridge = ao2_iterator_next(&i))) {
1983                         ast_cli(a->fd, "%-32s %6i %6i %s\n", bridge->name, bridge->users, bridge->markedusers, (bridge->locked ? "locked" : "unlocked"));
1984                         ao2_ref(bridge, -1);
1985                 }
1986                 ao2_iterator_destroy(&i);
1987                 return CLI_SUCCESS;
1988         }
1989
1990         if (a->argc == 3) {
1991                 ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name));
1992                 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
1993                 if (!bridge) {
1994                         ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
1995                         return CLI_SUCCESS;
1996                 }
1997                 ast_cli(a->fd, "Channel                       User Profile     Bridge Profile   Menu             CallerID\n");
1998                 ast_cli(a->fd, "============================= ================ ================ ================ ================\n");
1999                 ao2_lock(bridge);
2000                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2001                         ast_cli(a->fd, "%-29s ", ast_channel_name(participant->chan));
2002                         ast_cli(a->fd, "%-17s", participant->u_profile.name);
2003                         ast_cli(a->fd, "%-17s", participant->b_profile.name);
2004                         ast_cli(a->fd, "%-17s", participant->menu_name);
2005                         ast_cli(a->fd, "%-17s", S_COR(participant->chan->caller.id.number.valid, participant->chan->caller.id.number.str, "<unknown>"));
2006                         ast_cli(a->fd, "\n");
2007                 }
2008                 ao2_unlock(bridge);
2009                 ao2_ref(bridge, -1);
2010                 return CLI_SUCCESS;
2011         }
2012
2013         return CLI_SHOWUSAGE;
2014 }
2015
2016 /* \internal
2017  * \brief finds a conference by name and locks/unlocks.
2018  *
2019  * \retval 0 success
2020  * \retval -1 conference not found
2021  */
2022 static int generic_lock_unlock_helper(int lock, const char *conference)
2023 {
2024         struct conference_bridge *bridge = NULL;
2025         struct conference_bridge tmp;
2026         int res = 0;
2027
2028         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2029         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2030         if (!bridge) {
2031                 return -1;
2032         }
2033         ao2_lock(bridge);
2034         bridge->locked = lock;
2035         ast_test_suite_event_notify("CONF_LOCK", "Message: conference %s\r\nConference: %s", bridge->locked ? "locked" : "unlocked", bridge->b_profile.name);
2036         ao2_unlock(bridge);
2037         ao2_ref(bridge, -1);
2038
2039         return res;
2040 }
2041
2042 /* \internal
2043  * \brief finds a conference user by channel name and mutes/unmutes them.
2044  *
2045  * \retval 0 success
2046  * \retval -1 conference not found
2047  * \retval -2 user not found
2048  */
2049 static int generic_mute_unmute_helper(int mute, const char *conference, const char *user)
2050 {
2051         struct conference_bridge *bridge = NULL;
2052         struct conference_bridge tmp;
2053         struct conference_bridge_user *participant = NULL;
2054         int res = 0;
2055         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2056         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2057         if (!bridge) {
2058                 return -1;
2059         }
2060         ao2_lock(bridge);
2061         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2062                 if (!strncmp(user, ast_channel_name(participant->chan), strlen(user))) {
2063                         break;
2064                 }
2065         }
2066         if (participant) {
2067                 participant->features.mute = mute;
2068                 ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", ast_channel_name(participant->chan), participant->features.mute ? "muted" : "unmuted", bridge->b_profile.name, ast_channel_name(participant->chan));
2069         } else {
2070                 res = -2;;
2071         }
2072         ao2_unlock(bridge);
2073         ao2_ref(bridge, -1);
2074
2075         return res;
2076 }
2077
2078 static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
2079 {
2080         int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]);
2081
2082         if (res == -1) {
2083                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
2084                 return -1;
2085         } else if (res == -2) {
2086                 ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
2087                 return -1;
2088         }
2089         ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
2090         return 0;
2091 }
2092
2093 static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2094 {
2095         switch (cmd) {
2096         case CLI_INIT:
2097                 e->command = "confbridge mute";
2098                 e->usage =
2099                         "Usage: confbridge mute <conference> <channel>\n";
2100                 return NULL;
2101         case CLI_GENERATE:
2102                 if (a->pos == 2) {
2103                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2104                 }
2105                 return NULL;
2106         }
2107         if (a->argc != 4) {
2108                 return CLI_SHOWUSAGE;
2109         }
2110
2111         cli_mute_unmute_helper(1, a);
2112
2113         return CLI_SUCCESS;
2114 }
2115
2116 static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2117 {
2118         switch (cmd) {
2119         case CLI_INIT:
2120                 e->command = "confbridge unmute";
2121                 e->usage =
2122                         "Usage: confbridge unmute <conference> <channel>\n";
2123                 return NULL;
2124         case CLI_GENERATE:
2125                 if (a->pos == 2) {
2126                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2127                 }
2128                 return NULL;
2129         }
2130         if (a->argc != 4) {
2131                 return CLI_SHOWUSAGE;
2132         }
2133
2134         cli_mute_unmute_helper(0, a);
2135
2136         return CLI_SUCCESS;
2137 }
2138
2139 static char *handle_cli_confbridge_lock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2140 {
2141         switch (cmd) {
2142         case CLI_INIT:
2143                 e->command = "confbridge lock";
2144                 e->usage =
2145                         "Usage: confbridge lock <conference>\n";
2146                 return NULL;
2147         case CLI_GENERATE:
2148                 if (a->pos == 2) {
2149                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2150                 }
2151                 return NULL;
2152         }
2153         if (a->argc != 3) {
2154                 return CLI_SHOWUSAGE;
2155         }
2156         if (generic_lock_unlock_helper(1, a->argv[2])) {
2157                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
2158         } else {
2159                 ast_cli(a->fd, "Conference %s is locked.\n", a->argv[2]);
2160         }
2161         return CLI_SUCCESS;
2162 }
2163
2164 static char *handle_cli_confbridge_unlock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2165 {
2166         switch (cmd) {
2167         case CLI_INIT:
2168                 e->command = "confbridge unlock";
2169                 e->usage =
2170                         "Usage: confbridge unlock <conference>\n";
2171                 return NULL;
2172         case CLI_GENERATE:
2173                 if (a->pos == 2) {
2174                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2175                 }
2176                 return NULL;
2177         }
2178         if (a->argc != 3) {
2179                 return CLI_SHOWUSAGE;
2180         }
2181         if (generic_lock_unlock_helper(0, a->argv[2])) {
2182                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
2183         } else {
2184                 ast_cli(a->fd, "Conference %s is unlocked.\n", a->argv[2]);
2185         }
2186         return CLI_SUCCESS;
2187 }
2188
2189 static char *handle_cli_confbridge_start_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2190 {
2191         const char *rec_file = NULL;
2192         struct conference_bridge *bridge = NULL;
2193         struct conference_bridge tmp;
2194
2195         switch (cmd) {
2196         case CLI_INIT:
2197                 e->command = "confbridge record start";
2198                 e->usage =
2199                         "Usage: confbridge record start <conference> <file>\n"
2200                         "       <file> is optional, Otherwise the bridge profile\n"
2201                         "       record file will be used.  If the bridge profile\n"
2202                         "       has no record file specified, a file will automatically\n"
2203                         "       be generated in the monitor directory\n";
2204                 return NULL;
2205         case CLI_GENERATE:
2206                 if (a->pos == 3) {
2207                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2208                 }
2209                 return NULL;
2210         }
2211         if (a->argc < 4) {
2212                 return CLI_SHOWUSAGE;
2213         }
2214         if (a->argc == 5) {
2215                 rec_file = a->argv[4];
2216         }
2217
2218         ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name));
2219         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2220         if (!bridge) {
2221                 ast_cli(a->fd, "Conference not found.\n");
2222                 return CLI_FAILURE;
2223         }
2224         if (conf_is_recording(bridge)) {
2225                 ast_cli(a->fd, "Conference is already being recorded.\n");
2226                 ao2_ref(bridge, -1);
2227                 return CLI_SUCCESS;
2228         }
2229         if (!ast_strlen_zero(rec_file)) {
2230                 ao2_lock(bridge);
2231                 ast_copy_string(bridge->b_profile.rec_file, rec_file, sizeof(bridge->b_profile.rec_file));
2232                 ao2_unlock(bridge);
2233         }
2234         if (conf_start_record(bridge)) {
2235                 ast_cli(a->fd, "Could not start recording due to internal error.\n");
2236                 ao2_ref(bridge, -1);
2237                 return CLI_FAILURE;
2238         }
2239         ast_cli(a->fd, "Recording started\n");
2240         ao2_ref(bridge, -1);
2241         return CLI_SUCCESS;
2242 }
2243
2244 static char *handle_cli_confbridge_stop_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2245 {
2246         struct conference_bridge *bridge = NULL;
2247         struct conference_bridge tmp;
2248
2249         switch (cmd) {
2250         case CLI_INIT:
2251                 e->command = "confbridge record stop";
2252                 e->usage =
2253                         "Usage: confbridge record stop <conference>\n";
2254                 return NULL;
2255         case CLI_GENERATE:
2256                 if (a->pos == 3) {
2257                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2258                 }
2259                 return NULL;
2260         }
2261         if (a->argc != 4) {
2262                 return CLI_SHOWUSAGE;
2263         }
2264
2265         ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name));
2266         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2267         if (!bridge) {
2268                 ast_cli(a->fd, "Conference not found.\n");
2269                 return CLI_SUCCESS;
2270         }
2271         conf_stop_record(bridge);
2272         ast_cli(a->fd, "Recording stopped.\n");
2273         ao2_ref(bridge, -1);
2274         return CLI_SUCCESS;
2275 }
2276
2277 static struct ast_cli_entry cli_confbridge[] = {
2278         AST_CLI_DEFINE(handle_cli_confbridge_list, "List conference bridges and participants."),
2279         AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."),
2280         AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute a participant."),
2281         AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Unmute a participant."),
2282         AST_CLI_DEFINE(handle_cli_confbridge_lock, "Lock a conference."),
2283         AST_CLI_DEFINE(handle_cli_confbridge_unlock, "Unlock a conference."),
2284         AST_CLI_DEFINE(handle_cli_confbridge_start_record, "Start recording a conference"),
2285         AST_CLI_DEFINE(handle_cli_confbridge_stop_record, "Stop recording a conference."),
2286 };
2287 static struct ast_custom_function confbridge_function = {
2288         .name = "CONFBRIDGE",
2289         .write = func_confbridge_helper,
2290 };
2291
2292 static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
2293 static struct ast_custom_function confbridge_info_function = {
2294         .name = "CONFBRIDGE_INFO",
2295         .read = func_confbridge_info,
2296 };
2297
2298 static int action_confbridgelist(struct mansession *s, const struct message *m)
2299 {
2300         const char *actionid = astman_get_header(m, "ActionID");
2301         const char *conference = astman_get_header(m, "Conference");
2302         struct conference_bridge_user *participant = NULL;
2303         struct conference_bridge *bridge = NULL;
2304         struct conference_bridge tmp;
2305         char id_text[80] = "";
2306         int total = 0;
2307
2308         if (!ast_strlen_zero(actionid)) {
2309                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
2310         }
2311         if (ast_strlen_zero(conference)) {
2312                 astman_send_error(s, m, "No Conference name provided.");
2313                 return 0;
2314         }
2315         if (!ao2_container_count(conference_bridges)) {
2316                 astman_send_error(s, m, "No active conferences.");
2317                 return 0;
2318         }
2319         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2320         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2321         if (!bridge) {
2322                 astman_send_error(s, m, "No Conference by that name found.");
2323                 return 0;
2324         }
2325
2326         astman_send_listack(s, m, "Confbridge user list will follow", "start");
2327
2328         ao2_lock(bridge);
2329         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2330                 total++;
2331                 astman_append(s,
2332                         "Event: ConfbridgeList\r\n"
2333                         "%s"
2334                         "Conference: %s\r\n"
2335                         "CallerIDNum: %s\r\n"
2336                         "CallerIDName: %s\r\n"
2337                         "Channel: %s\r\n"
2338                         "Admin: %s\r\n"
2339                         "MarkedUser: %s\r\n"
2340                         "\r\n",
2341                         id_text,
2342                         bridge->name,
2343                         S_COR(participant->chan->caller.id.number.valid, participant->chan->caller.id.number.str, "<unknown>"),
2344                         S_COR(participant->chan->caller.id.name.valid, participant->chan->caller.id.name.str, "<no name>"),
2345                         ast_channel_name(participant->chan),
2346                         ast_test_flag(&participant->u_profile, USER_OPT_ADMIN) ? "Yes" : "No",
2347                         ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No");
2348         }
2349         ao2_unlock(bridge);
2350         ao2_ref(bridge, -1);
2351
2352         astman_append(s,
2353         "Event: ConfbridgeListComplete\r\n"
2354         "EventList: Complete\r\n"
2355         "ListItems: %d\r\n"
2356         "%s"
2357         "\r\n", total, id_text);
2358
2359         return 0;
2360 }
2361
2362 static int action_confbridgelistrooms(struct mansession *s, const struct message *m)
2363 {
2364         const char *actionid = astman_get_header(m, "ActionID");
2365         struct conference_bridge *bridge = NULL;
2366         struct ao2_iterator i;
2367         char id_text[512] = "";
2368         int totalitems = 0;
2369
2370         if (!ast_strlen_zero(actionid)) {
2371                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
2372         }
2373
2374         if (!ao2_container_count(conference_bridges)) {
2375                 astman_send_error(s, m, "No active conferences.");
2376                 return 0;
2377         }
2378
2379         astman_send_listack(s, m, "Confbridge conferences will follow", "start");
2380
2381         /* Traverse the conference list */
2382         i = ao2_iterator_init(conference_bridges, 0);
2383         while ((bridge = ao2_iterator_next(&i))) {
2384                 totalitems++;
2385
2386                 ao2_lock(bridge);
2387                 astman_append(s,
2388                 "Event: ConfbridgeListRooms\r\n"
2389                 "%s"
2390                 "Conference: %s\r\n"
2391                 "Parties: %d\r\n"
2392                 "Marked: %d\r\n"
2393                 "Locked: %s\r\n"
2394                 "\r\n",
2395                 id_text,
2396                 bridge->name,
2397                 bridge->users,
2398                 bridge->markedusers,
2399                 bridge->locked ? "Yes" : "No"); 
2400                 ao2_unlock(bridge);
2401
2402                 ao2_ref(bridge, -1);
2403         }
2404         ao2_iterator_destroy(&i);
2405
2406         /* Send final confirmation */
2407         astman_append(s,
2408         "Event: ConfbridgeListRoomsComplete\r\n"
2409         "EventList: Complete\r\n"
2410         "ListItems: %d\r\n"
2411         "%s"
2412         "\r\n", totalitems, id_text);
2413         return 0;
2414 }
2415
2416 static int action_mute_unmute_helper(struct mansession *s, const struct message *m, int mute)
2417 {
2418         const char *conference = astman_get_header(m, "Conference");
2419         const char *channel = astman_get_header(m, "Channel");
2420         int res = 0;
2421
2422         if (ast_strlen_zero(conference)) {
2423                 astman_send_error(s, m, "No Conference name provided.");
2424                 return 0;
2425         }
2426         if (ast_strlen_zero(channel)) {
2427                 astman_send_error(s, m, "No channel name provided.");
2428                 return 0;
2429         }
2430         if (!ao2_container_count(conference_bridges)) {
2431                 astman_send_error(s, m, "No active conferences.");
2432                 return 0;
2433         }
2434
2435         res = generic_mute_unmute_helper(mute, conference, channel);
2436
2437         if (res == -1) {
2438                 astman_send_error(s, m, "No Conference by that name found.");
2439                 return 0;
2440         } else if (res == -2) {
2441                 astman_send_error(s, m, "No Channel by that name found in Conference.");
2442                 return 0;
2443         }
2444
2445         astman_send_ack(s, m, mute ? "User muted" : "User unmuted");
2446         return 0;
2447 }
2448
2449 static int action_confbridgeunmute(struct mansession *s, const struct message *m)
2450 {
2451         return action_mute_unmute_helper(s, m, 0);
2452 }
2453 static int action_confbridgemute(struct mansession *s, const struct message *m)
2454 {
2455         return action_mute_unmute_helper(s, m, 1);
2456 }
2457
2458 static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock)
2459 {
2460         const char *conference = astman_get_header(m, "Conference");
2461         int res = 0;
2462
2463         if (ast_strlen_zero(conference)) {
2464                 astman_send_error(s, m, "No Conference name provided.");
2465                 return 0;
2466         }
2467         if (!ao2_container_count(conference_bridges)) {
2468                 astman_send_error(s, m, "No active conferences.");
2469                 return 0;
2470         }
2471         if ((res = generic_lock_unlock_helper(lock, conference))) {
2472                 astman_send_error(s, m, "No Conference by that name found.");
2473                 return 0;
2474         }
2475         astman_send_ack(s, m, lock ? "Conference locked" : "Conference unlocked");
2476         return 0;
2477 }
2478 static int action_confbridgeunlock(struct mansession *s, const struct message *m)
2479 {
2480         return action_lock_unlock_helper(s, m, 0);
2481 }
2482 static int action_confbridgelock(struct mansession *s, const struct message *m)
2483 {
2484         return action_lock_unlock_helper(s, m, 1);
2485 }
2486
2487 static int action_confbridgekick(struct mansession *s, const struct message *m)
2488 {
2489         const char *conference = astman_get_header(m, "Conference");
2490         const char *channel = astman_get_header(m, "Channel");
2491         struct conference_bridge_user *participant = NULL;
2492         struct conference_bridge *bridge = NULL;
2493         struct conference_bridge tmp;
2494         int found = 0;
2495
2496         if (ast_strlen_zero(conference)) {
2497                 astman_send_error(s, m, "No Conference name provided.");
2498                 return 0;
2499         }
2500         if (!ao2_container_count(conference_bridges)) {
2501                 astman_send_error(s, m, "No active conferences.");
2502                 return 0;
2503         }
2504         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2505         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2506         if (!bridge) {
2507                 astman_send_error(s, m, "No Conference by that name found.");
2508                 return 0;
2509         }
2510
2511         ao2_lock(bridge);
2512         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2513                 if (!strcasecmp(ast_channel_name(participant->chan), channel)) {
2514                         participant->kicked = 1;
2515                         ast_bridge_remove(bridge->bridge, participant->chan);
2516                         found = 1;
2517                         break;
2518                 }
2519         }
2520         ao2_unlock(bridge);
2521         ao2_ref(bridge, -1);
2522
2523         if (found) {
2524                 astman_send_ack(s, m, "User kicked");
2525         } else {
2526                 astman_send_error(s, m, "No Channel by that name found in Conference.");
2527         }
2528         return 0;
2529 }
2530
2531 static int action_confbridgestartrecord(struct mansession *s, const struct message *m)
2532 {
2533         const char *conference = astman_get_header(m, "Conference");
2534         const char *recordfile = astman_get_header(m, "RecordFile");
2535         struct conference_bridge *bridge = NULL;
2536         struct conference_bridge tmp;
2537
2538         if (ast_strlen_zero(conference)) {
2539                 astman_send_error(s, m, "No Conference name provided.");
2540                 return 0;
2541         }
2542         if (!ao2_container_count(conference_bridges)) {
2543                 astman_send_error(s, m, "No active conferences.");
2544                 return 0;
2545         }
2546
2547         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2548         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2549         if (!bridge) {
2550                 astman_send_error(s, m, "No Conference by that name found.");
2551                 return 0;
2552         }
2553
2554         if (conf_is_recording(bridge)) {
2555                 astman_send_error(s, m, "Conference is already being recorded.");
2556                 ao2_ref(bridge, -1);
2557                 return 0;
2558         }
2559
2560         if (!ast_strlen_zero(recordfile)) {
2561                 ao2_lock(bridge);
2562                 ast_copy_string(bridge->b_profile.rec_file, recordfile, sizeof(bridge->b_profile.rec_file));
2563                 ao2_unlock(bridge);
2564         }
2565
2566         if (conf_start_record(bridge)) {
2567                 astman_send_error(s, m, "Internal error starting conference recording.");
2568                 ao2_ref(bridge, -1);
2569                 return 0;
2570         }
2571
2572         ao2_ref(bridge, -1);
2573         astman_send_ack(s, m, "Conference Recording Started.");
2574         return 0;
2575 }
2576 static int action_confbridgestoprecord(struct mansession *s, const struct message *m)
2577 {
2578         const char *conference = astman_get_header(m, "Conference");
2579         struct conference_bridge *bridge = NULL;
2580         struct conference_bridge tmp;
2581
2582         if (ast_strlen_zero(conference)) {
2583                 astman_send_error(s, m, "No Conference name provided.");
2584                 return 0;
2585         }
2586         if (!ao2_container_count(conference_bridges)) {
2587                 astman_send_error(s, m, "No active conferences.");
2588                 return 0;
2589         }
2590
2591         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2592         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2593         if (!bridge) {
2594                 astman_send_error(s, m, "No Conference by that name found.");
2595                 return 0;
2596         }
2597
2598         if (conf_stop_record(bridge)) {
2599                 astman_send_error(s, m, "Internal error while stopping recording.");
2600                 ao2_ref(bridge, -1);
2601                 return 0;
2602         }
2603
2604         ao2_ref(bridge, -1);
2605         astman_send_ack(s, m, "Conference Recording Stopped.");
2606         return 0;
2607 }
2608
2609 static int action_confbridgesetsinglevideosrc(struct mansession *s, const struct message *m)
2610 {
2611         const char *conference = astman_get_header(m, "Conference");
2612         const char *channel = astman_get_header(m, "Channel");
2613         struct conference_bridge_user *participant = NULL;
2614         struct conference_bridge *bridge = NULL;
2615         struct conference_bridge tmp;
2616
2617         if (ast_strlen_zero(conference)) {
2618                 astman_send_error(s, m, "No Conference name provided.");
2619                 return 0;
2620         }
2621         if (ast_strlen_zero(channel)) {
2622                 astman_send_error(s, m, "No channel name provided.");
2623                 return 0;
2624         }
2625         if (!ao2_container_count(conference_bridges)) {
2626                 astman_send_error(s, m, "No active conferences.");
2627                 return 0;
2628         }
2629
2630         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2631         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2632         if (!bridge) {
2633                 astman_send_error(s, m, "No Conference by that name found.");
2634                 return 0;
2635         }
2636
2637         /* find channel and set as video src. */
2638         ao2_lock(bridge);
2639         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2640                 if (!strncmp(channel, ast_channel_name(participant->chan), strlen(channel))) {
2641                         ast_bridge_set_single_src_video_mode(bridge->bridge, participant->chan);
2642                         break;
2643                 }
2644         }
2645         ao2_unlock(bridge);
2646         ao2_ref(bridge, -1);
2647
2648         /* do not access participant after bridge unlock.  We are just
2649          * using this check to see if it was found or not */
2650         if (!participant) {
2651                 astman_send_error(s, m, "No channel by that name found in conference.");
2652                 return 0;
2653         }
2654         astman_send_ack(s, m, "Conference single video source set.");
2655         return 0;
2656 }
2657
2658 static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
2659 {
2660         char *parse = NULL;
2661         struct conference_bridge *bridge = NULL;
2662         struct conference_bridge_user *participant = NULL;
2663         struct conference_bridge tmp;
2664         int count = 0;
2665         AST_DECLARE_APP_ARGS(args,
2666                 AST_APP_ARG(type);
2667                 AST_APP_ARG(confno);
2668         );
2669
2670         /* parse all the required arguments and make sure they exist. */
2671         if (ast_strlen_zero(data)) {
2672                 return -1;
2673         }
2674         parse = ast_strdupa(data);
2675         AST_STANDARD_APP_ARGS(args, parse);
2676         if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) {
2677                 return -1;
2678         }
2679         if (!ao2_container_count(conference_bridges)) {
2680                 snprintf(buf, len, "0");
2681                 return 0;
2682         }
2683         ast_copy_string(tmp.name, args.confno, sizeof(tmp.name));
2684         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2685         if (!bridge) {
2686                 snprintf(buf, len, "0");
2687                 return 0;
2688         }
2689
2690         /* get the correct count for the type requested */
2691         ao2_lock(bridge);
2692         if (!strncasecmp(args.type, "parties", 7)) {
2693                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2694                         count++;
2695                 }
2696         } else if (!strncasecmp(args.type, "admins", 6)) {
2697                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2698                         if (ast_test_flag(&participant->u_profile, USER_OPT_ADMIN)) {
2699                                 count++;
2700                         }
2701                 }
2702         } else if (!strncasecmp(args.type, "marked", 6)) {
2703                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2704                         if (ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER)) {
2705                                 count++;
2706                         }
2707                 }
2708         } else if (!strncasecmp(args.type, "locked", 6)) {
2709                 count = bridge->locked;
2710         } else {
2711                 ast_log(LOG_ERROR, "Invalid keyword '%s' passed to CONFBRIDGE_INFO.  Should be one of: "
2712                         "parties, admins, marked, or locked.\n", args.type);
2713         }
2714         snprintf(buf, len, "%d", count);
2715         ao2_unlock(bridge);
2716         ao2_ref(bridge, -1);
2717         return 0;
2718 }
2719
2720 /*! \brief Called when module is being unloaded */
2721 static int unload_module(void)
2722 {
2723         int res = ast_unregister_application(app);
2724
2725         ast_custom_function_unregister(&confbridge_function);
2726         ast_custom_function_unregister(&confbridge_info_function);
2727
2728         ast_cli_unregister_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry));
2729
2730         /* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */
2731         ao2_ref(conference_bridges, -1);
2732
2733         conf_destroy_config();
2734
2735         ast_channel_unregister(&record_tech);
2736         record_tech.capabilities = ast_format_cap_destroy(record_tech.capabilities);
2737
2738         res |= ast_manager_unregister("ConfbridgeList");
2739         res |= ast_manager_unregister("ConfbridgeListRooms");
2740         res |= ast_manager_unregister("ConfbridgeMute");
2741         res |= ast_manager_unregister("ConfbridgeUnmute");
2742         res |= ast_manager_unregister("ConfbridgeKick");
2743         res |= ast_manager_unregister("ConfbridgeUnlock");
2744         res |= ast_manager_unregister("ConfbridgeLock");
2745         res |= ast_manager_unregister("ConfbridgeStartRecord");
2746         res |= ast_manager_unregister("ConfbridgeStopRecord");
2747
2748         return res;
2749 }
2750
2751 /*! \brief Called when module is being loaded */
2752 static int load_module(void)
2753 {
2754         int res = 0;
2755         if ((ast_custom_function_register(&confbridge_function))) {
2756                 return AST_MODULE_LOAD_FAILURE;
2757         }
2758         if ((ast_custom_function_register(&confbridge_info_function))) {
2759                 return AST_MODULE_LOAD_FAILURE;
2760         }
2761         if (!(record_tech.capabilities = ast_format_cap_alloc())) {
2762                 return AST_MODULE_LOAD_FAILURE;
2763         }
2764         ast_format_cap_add_all(record_tech.capabilities);
2765         if (ast_channel_register(&record_tech)) {
2766                 ast_log(LOG_ERROR, "Unable to register ConfBridge recorder.\n");
2767                 return AST_MODULE_LOAD_FAILURE;
2768         }
2769         /* Create a container to hold the conference bridges */
2770         if (!(conference_bridges = ao2_container_alloc(CONFERENCE_BRIDGE_BUCKETS, conference_bridge_hash_cb, conference_bridge_cmp_cb))) {
2771                 return AST_MODULE_LOAD_FAILURE;
2772         }
2773         if (ast_register_application_xml(app, confbridge_exec)) {
2774                 ao2_ref(conference_bridges, -1);
2775                 return AST_MODULE_LOAD_FAILURE;
2776         }
2777
2778         res |= ast_cli_register_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry));
2779         res |= ast_manager_register_xml("ConfbridgeList", EVENT_FLAG_REPORTING, action_confbridgelist);
2780         res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms);
2781         res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute);
2782         res |= ast_manager_register_xml("ConfbridgeUnmute", EVENT_FLAG_CALL, action_confbridgeunmute);
2783         res |= ast_manager_register_xml("ConfbridgeKick", EVENT_FLAG_CALL, action_confbridgekick);
2784         res |= ast_manager_register_xml("ConfbridgeUnlock", EVENT_FLAG_CALL, action_confbridgeunlock);
2785         res |= ast_manager_register_xml("ConfbridgeLock", EVENT_FLAG_CALL, action_confbridgelock);
2786         res |= ast_manager_register_xml("ConfbridgeStartRecord", EVENT_FLAG_CALL, action_confbridgestartrecord);
2787         res |= ast_manager_register_xml("ConfbridgeStopRecord", EVENT_FLAG_CALL, action_confbridgestoprecord);
2788         res |= ast_manager_register_xml("ConfbridgeSetSingleVideoSrc", EVENT_FLAG_CALL, action_confbridgesetsinglevideosrc);
2789
2790         conf_load_config(0);
2791         return res;
2792 }
2793
2794 static int reload(void)
2795 {
2796         return conf_load_config(1);
2797 }
2798
2799 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Conference Bridge Application",
2800         .load = load_module,
2801         .unload = unload_module,
2802         .reload = reload,
2803         .load_pri = AST_MODPRI_DEVSTATE_PROVIDER,
2804 );