1b8eab24b830e2fd6e62850ab0c2b6c60c77534b
[asterisk/asterisk.git] / apps / confbridge / confbridge_manager.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Jonathan Rose <jrose@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Confbridge manager events for stasis messages
22  *
23  * \author Jonathan Rose <jrose@digium.com>
24  */
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include "asterisk/channel.h"
31 #include "asterisk/bridge.h"
32 #include "asterisk/stasis.h"
33 #include "asterisk/stasis_channels.h"
34 #include "asterisk/stasis_bridges.h"
35 #include "asterisk/manager.h"
36 #include "asterisk/stasis_message_router.h"
37 #include "include/confbridge.h"
38
39 /*** DOCUMENTATION
40         <managerEvent language="en_US" name="ConfbridgeStart">
41                 <managerEventInstance class="EVENT_FLAG_CALL">
42                         <synopsis>Raised when a conference starts.</synopsis>
43                         <syntax>
44                                 <parameter name="Conference">
45                                         <para>The name of the Confbridge conference.</para>
46                                 </parameter>
47                                 <bridge_snapshot/>
48                         </syntax>
49                         <see-also>
50                                 <ref type="managerEvent">ConfbridgeEnd</ref>
51                                 <ref type="application">ConfBridge</ref>
52                         </see-also>
53                 </managerEventInstance>
54         </managerEvent>
55         <managerEvent language="en_US" name="ConfbridgeEnd">
56                 <managerEventInstance class="EVENT_FLAG_CALL">
57                         <synopsis>Raised when a conference ends.</synopsis>
58                         <syntax>
59                                 <parameter name="Conference">
60                                         <para>The name of the Confbridge conference.</para>
61                                 </parameter>
62                                 <bridge_snapshot/>
63                         </syntax>
64                         <see-also>
65                                 <ref type="managerEvent">ConfbridgeStart</ref>
66                                 <ref type="application">ConfBridge</ref>
67                         </see-also>
68                 </managerEventInstance>
69         </managerEvent>
70         <managerEvent language="en_US" name="ConfbridgeJoin">
71                 <managerEventInstance class="EVENT_FLAG_CALL">
72                         <synopsis>Raised when a channel joins a Confbridge conference.</synopsis>
73                         <syntax>
74                                 <parameter name="Conference">
75                                         <para>The name of the Confbridge conference.</para>
76                                 </parameter>
77                                 <bridge_snapshot/>
78                                 <channel_snapshot/>
79                         </syntax>
80                         <see-also>
81                                 <ref type="managerEvent">ConfbridgeLeave</ref>
82                                 <ref type="application">ConfBridge</ref>
83                         </see-also>
84                 </managerEventInstance>
85         </managerEvent>
86         <managerEvent language="en_US" name="ConfbridgeLeave">
87                 <managerEventInstance class="EVENT_FLAG_CALL">
88                         <synopsis>Raised when a channel leaves a Confbridge conference.</synopsis>
89                         <syntax>
90                                 <parameter name="Conference">
91                                         <para>The name of the Confbridge conference.</para>
92                                 </parameter>
93                                 <bridge_snapshot/>
94                                 <channel_snapshot/>
95                         </syntax>
96                         <see-also>
97                                 <ref type="managerEvent">ConfbridgeJoin</ref>
98                                 <ref type="application">ConfBridge</ref>
99                         </see-also>
100                 </managerEventInstance>
101         </managerEvent>
102         <managerEvent language="en_US" name="ConfbridgeRecord">
103                 <managerEventInstance class="EVENT_FLAG_CALL">
104                         <synopsis>Raised when a conference starts recording.</synopsis>
105                         <syntax>
106                                 <parameter name="Conference">
107                                         <para>The name of the Confbridge conference.</para>
108                                 </parameter>
109                                 <bridge_snapshot/>
110                         </syntax>
111                         <see-also>
112                                 <ref type="managerEvent">ConfbridgeStopRecord</ref>
113                                 <ref type="application">ConfBridge</ref>
114                         </see-also>
115                 </managerEventInstance>
116         </managerEvent>
117         <managerEvent language="en_US" name="ConfbridgeStopRecord">
118                 <managerEventInstance class="EVENT_FLAG_CALL">
119                         <synopsis>Raised when a conference that was recording stops recording.</synopsis>
120                         <syntax>
121                                 <parameter name="Conference">
122                                         <para>The name of the Confbridge conference.</para>
123                                 </parameter>
124                                 <bridge_snapshot/>
125                         </syntax>
126                         <see-also>
127                                 <ref type="managerEvent">ConfbridgeRecord</ref>
128                                 <ref type="application">ConfBridge</ref>
129                         </see-also>
130                 </managerEventInstance>
131         </managerEvent>
132         <managerEvent language="en_US" name="ConfbridgeMute">
133                 <managerEventInstance class="EVENT_FLAG_CALL">
134                         <synopsis>Raised when a Confbridge participant mutes.</synopsis>
135                         <syntax>
136                                 <parameter name="Conference">
137                                         <para>The name of the Confbridge conference.</para>
138                                 </parameter>
139                                 <bridge_snapshot/>
140                                 <channel_snapshot/>
141                         </syntax>
142                         <see-also>
143                                 <ref type="managerEvent">ConfbridgeUnmute</ref>
144                                 <ref type="application">ConfBridge</ref>
145                         </see-also>
146                 </managerEventInstance>
147         </managerEvent>
148         <managerEvent language="en_US" name="ConfbridgeUnmute">
149                 <managerEventInstance class="EVENT_FLAG_CALL">
150                         <synopsis>Raised when a confbridge participant unmutes.</synopsis>
151                         <syntax>
152                                 <parameter name="Conference">
153                                         <para>The name of the Confbridge conference.</para>
154                                 </parameter>
155                                 <bridge_snapshot/>
156                                 <channel_snapshot/>
157                         </syntax>
158                         <see-also>
159                                 <ref type="managerEvent">ConfbridgeMute</ref>
160                                 <ref type="application">ConfBridge</ref>
161                         </see-also>
162                 </managerEventInstance>
163         </managerEvent>
164         <managerEvent language="en_US" name="ConfbridgeTalking">
165                 <managerEventInstance class="EVENT_FLAG_CALL">
166                         <synopsis>Raised when a confbridge participant unmutes.</synopsis>
167                         <syntax>
168                                 <parameter name="Conference">
169                                         <para>The name of the Confbridge conference.</para>
170                                 </parameter>
171                                 <bridge_snapshot/>
172                                 <channel_snapshot/>
173                                 <parameter name="TalkingStatus">
174                                         <enumlist>
175                                                 <enum name="on"/>
176                                                 <enum name="off"/>
177                                         </enumlist>
178                                 </parameter>
179                         </syntax>
180                         <see-also>
181                                 <ref type="application">ConfBridge</ref>
182                         </see-also>
183                 </managerEventInstance>
184         </managerEvent>
185 ***/
186
187 static struct stasis_message_router *bridge_state_router;
188 static struct stasis_message_router *channel_state_router;
189
190 static void confbridge_publish_manager_event(
191         struct stasis_message *message,
192         const char *event,
193         struct ast_str *extra_text)
194 {
195         struct ast_bridge_blob *blob = stasis_message_data(message);
196         const char *conference_name;
197         RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free);
198         RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
199
200         ast_assert(blob != NULL);
201         ast_assert(event != NULL);
202
203         bridge_text = ast_manager_build_bridge_state_string(blob->bridge);
204         if (!bridge_text) {
205                 return;
206         }
207
208         conference_name = ast_json_string_get(ast_json_object_get(blob->blob, "conference"));
209         ast_assert(conference_name != NULL);
210
211         if (blob->channel) {
212                 channel_text = ast_manager_build_channel_state_string(blob->channel);
213         }
214
215         manager_event(EVENT_FLAG_CALL, event,
216                 "Conference: %s\r\n"
217                 "%s"
218                 "%s"
219                 "%s",
220                 conference_name,
221                 ast_str_buffer(bridge_text),
222                 S_COR(channel_text, ast_str_buffer(channel_text), ""),
223                 S_COR(extra_text, ast_str_buffer(extra_text), ""));
224 }
225
226 static void confbridge_start_cb(void *data, struct stasis_subscription *sub,
227         struct stasis_message *message)
228 {
229         confbridge_publish_manager_event(message, "ConfbridgeStart", NULL);
230 }
231
232 static void confbridge_end_cb(void *data, struct stasis_subscription *sub,
233         struct stasis_message *message)
234 {
235         confbridge_publish_manager_event(message, "ConfbridgeEnd", NULL);
236 }
237
238 static void confbridge_leave_cb(void *data, struct stasis_subscription *sub,
239         struct stasis_message *message)
240 {
241         confbridge_publish_manager_event(message, "ConfbridgeLeave", NULL);
242 }
243
244 static void confbridge_join_cb(void *data, struct stasis_subscription *sub,
245         struct stasis_message *message)
246 {
247         confbridge_publish_manager_event(message, "ConfbridgeJoin", NULL);
248 }
249
250 static void confbridge_start_record_cb(void *data, struct stasis_subscription *sub,
251         struct stasis_message *message)
252 {
253         confbridge_publish_manager_event(message, "ConfbridgeRecord", NULL);
254 }
255
256 static void confbridge_stop_record_cb(void *data, struct stasis_subscription *sub,
257         struct stasis_message *message)
258 {
259         confbridge_publish_manager_event(message, "ConfbridgeStopRecord", NULL);
260 }
261
262 static void confbridge_mute_cb(void *data, struct stasis_subscription *sub,
263         struct stasis_message *message)
264 {
265         confbridge_publish_manager_event(message, "ConfbridgeMute", NULL);
266 }
267
268 static void confbridge_unmute_cb(void *data, struct stasis_subscription *sub,
269         struct stasis_message *message)
270 {
271         confbridge_publish_manager_event(message, "ConfbridgeUnmute", NULL);
272 }
273
274 static void confbridge_talking_cb(void *data, struct stasis_subscription *sub,
275         struct stasis_message *message)
276 {
277         RAII_VAR(struct ast_str *, extra_text, NULL, ast_free);
278         struct ast_bridge_blob *blob = stasis_message_data(message);
279         const char *talking_status = ast_json_string_get(ast_json_object_get(blob->blob, "talking_status"));
280         if (!talking_status) {
281                 return;
282         }
283
284         ast_str_append_event_header(&extra_text, "TalkingStatus", talking_status);
285         if (!extra_text) {
286                 return;
287         }
288
289         confbridge_publish_manager_event(message, "ConfbridgeTalking", extra_text);
290 }
291
292 STASIS_MESSAGE_TYPE_DEFN(confbridge_start_type);
293 STASIS_MESSAGE_TYPE_DEFN(confbridge_end_type);
294 STASIS_MESSAGE_TYPE_DEFN(confbridge_join_type);
295 STASIS_MESSAGE_TYPE_DEFN(confbridge_leave_type);
296 STASIS_MESSAGE_TYPE_DEFN(confbridge_start_record_type);
297 STASIS_MESSAGE_TYPE_DEFN(confbridge_stop_record_type);
298 STASIS_MESSAGE_TYPE_DEFN(confbridge_mute_type);
299 STASIS_MESSAGE_TYPE_DEFN(confbridge_unmute_type);
300 STASIS_MESSAGE_TYPE_DEFN(confbridge_talking_type);
301
302 void manager_confbridge_shutdown(void) {
303         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_start_type);
304         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_end_type);
305         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_join_type);
306         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_leave_type);
307         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_start_record_type);
308         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_stop_record_type);
309         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_mute_type);
310         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_unmute_type);
311         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_talking_type);
312
313         if (bridge_state_router) {
314                 stasis_message_router_unsubscribe(bridge_state_router);
315                 bridge_state_router = NULL;
316         }
317
318         if (channel_state_router) {
319                 stasis_message_router_unsubscribe(channel_state_router);
320                 channel_state_router = NULL;
321         }
322 }
323
324 int manager_confbridge_init(void)
325 {
326         STASIS_MESSAGE_TYPE_INIT(confbridge_start_type);
327         STASIS_MESSAGE_TYPE_INIT(confbridge_end_type);
328         STASIS_MESSAGE_TYPE_INIT(confbridge_join_type);
329         STASIS_MESSAGE_TYPE_INIT(confbridge_leave_type);
330         STASIS_MESSAGE_TYPE_INIT(confbridge_start_record_type);
331         STASIS_MESSAGE_TYPE_INIT(confbridge_stop_record_type);
332         STASIS_MESSAGE_TYPE_INIT(confbridge_mute_type);
333         STASIS_MESSAGE_TYPE_INIT(confbridge_unmute_type);
334         STASIS_MESSAGE_TYPE_INIT(confbridge_talking_type);
335
336         bridge_state_router = stasis_message_router_create(
337                 ast_bridge_topic_all_cached());
338
339         if (!bridge_state_router) {
340                 return -1;
341         }
342
343         if (stasis_message_router_add(bridge_state_router,
344                         confbridge_start_type(),
345                         confbridge_start_cb,
346                         NULL)) {
347                 manager_confbridge_shutdown();
348                 return -1;
349         }
350         if (stasis_message_router_add(bridge_state_router,
351                         confbridge_end_type(),
352                         confbridge_end_cb,
353                         NULL)) {
354                 manager_confbridge_shutdown();
355                 return -1;
356         }
357         if (stasis_message_router_add(bridge_state_router,
358                         confbridge_join_type(),
359                         confbridge_join_cb,
360                         NULL)) {
361                 manager_confbridge_shutdown();
362                 return -1;
363         }
364         if (stasis_message_router_add(bridge_state_router,
365                         confbridge_leave_type(),
366                         confbridge_leave_cb,
367                         NULL)) {
368                 manager_confbridge_shutdown();
369                 return -1;
370         }
371         if (stasis_message_router_add(bridge_state_router,
372                         confbridge_start_record_type(),
373                         confbridge_start_record_cb,
374                         NULL)) {
375                 manager_confbridge_shutdown();
376                 return -1;
377         }
378         if (stasis_message_router_add(bridge_state_router,
379                         confbridge_stop_record_type(),
380                         confbridge_stop_record_cb,
381                         NULL)) {
382                 manager_confbridge_shutdown();
383                 return -1;
384         }
385         if (stasis_message_router_add(bridge_state_router,
386                         confbridge_mute_type(),
387                         confbridge_mute_cb,
388                         NULL)) {
389                 manager_confbridge_shutdown();
390                 return -1;
391         }
392         if (stasis_message_router_add(bridge_state_router,
393                         confbridge_unmute_type(),
394                         confbridge_unmute_cb,
395                         NULL)) {
396                 manager_confbridge_shutdown();
397                 return -1;
398         }
399         if (stasis_message_router_add(bridge_state_router,
400                         confbridge_talking_type(),
401                         confbridge_talking_cb,
402                         NULL)) {
403                 manager_confbridge_shutdown();
404                 return -1;
405         }
406
407         channel_state_router = stasis_message_router_create(
408                 ast_channel_topic_all_cached());
409
410         if (!channel_state_router) {
411                 manager_confbridge_shutdown();
412                 return -1;
413         }
414
415         if (stasis_message_router_add(channel_state_router,
416                         confbridge_start_type(),
417                         confbridge_start_cb,
418                         NULL)) {
419                 manager_confbridge_shutdown();
420                 return -1;
421         }
422         if (stasis_message_router_add(channel_state_router,
423                         confbridge_end_type(),
424                         confbridge_end_cb,
425                         NULL)) {
426                 manager_confbridge_shutdown();
427                 return -1;
428         }
429         if (stasis_message_router_add(channel_state_router,
430                         confbridge_join_type(),
431                         confbridge_join_cb,
432                         NULL)) {
433                 manager_confbridge_shutdown();
434                 return -1;
435         }
436         if (stasis_message_router_add(channel_state_router,
437                         confbridge_leave_type(),
438                         confbridge_leave_cb,
439                         NULL)) {
440                 manager_confbridge_shutdown();
441                 return -1;
442         }
443         if (stasis_message_router_add(channel_state_router,
444                         confbridge_start_record_type(),
445                         confbridge_start_record_cb,
446                         NULL)) {
447                 manager_confbridge_shutdown();
448                 return -1;
449         }
450         if (stasis_message_router_add(channel_state_router,
451                         confbridge_stop_record_type(),
452                         confbridge_stop_record_cb,
453                         NULL)) {
454                 manager_confbridge_shutdown();
455                 return -1;
456         }
457         if (stasis_message_router_add(channel_state_router,
458                         confbridge_mute_type(),
459                         confbridge_mute_cb,
460                         NULL)) {
461                 manager_confbridge_shutdown();
462                 return -1;
463         }
464         if (stasis_message_router_add(channel_state_router,
465                         confbridge_unmute_type(),
466                         confbridge_unmute_cb,
467                         NULL)) {
468                 manager_confbridge_shutdown();
469                 return -1;
470         }
471         if (stasis_message_router_add(channel_state_router,
472                         confbridge_talking_type(),
473                         confbridge_talking_cb,
474                         NULL)) {
475                 manager_confbridge_shutdown();
476                 return -1;
477         }
478
479         return 0;
480 }