Remove remnant of snapshot blob JSON types
[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/bridging.h"
32 #include "asterisk/stasis.h"
33 #include "asterisk/stasis_channels.h"
34 #include "asterisk/stasis_bridging.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                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
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                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
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                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
78                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
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                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
94                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
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                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
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                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
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                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
140                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
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                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
156                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
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
165         <managerEvent language="en_US" name="ConfbridgeTalking">
166                 <managerEventInstance class="EVENT_FLAG_CALL">
167                         <synopsis>Raised when a confbridge participant unmutes.</synopsis>
168                         <syntax>
169                                 <parameter name="Conference">
170                                         <para>The name of the Confbridge conference.</para>
171                                 </parameter>
172                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
173                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
174                                 <parameter name="TalkingStatus">
175                                         <enumlist>
176                                                 <enum name="on"/>
177                                                 <enum name="off"/>
178                                         </enumlist>
179                                 </parameter>
180                         </syntax>
181                         <see-also>
182                                 <ref type="application">ConfBridge</ref>
183                         </see-also>
184                 </managerEventInstance>
185         </managerEvent>
186 ***/
187
188 static struct stasis_message_router *bridge_state_router;
189 static struct stasis_message_router *channel_state_router;
190
191 static void append_event_header(struct ast_str **fields_string,
192                                         const char *header, const char *value)
193 {
194         struct ast_str *working_str = *fields_string;
195
196         if (!working_str) {
197                 working_str = ast_str_create(128);
198                 if (!working_str) {
199                         return;
200                 }
201                 *fields_string = working_str;
202         }
203
204         ast_str_append(&working_str, 0,
205                 "%s: %s\r\n",
206                 header, value);
207 }
208
209 static void confbridge_publish_manager_event(
210         struct stasis_message *message,
211         const char *event,
212         struct ast_str *extra_text)
213 {
214         struct ast_bridge_blob *blob = stasis_message_data(message);
215         const char *conference_name;
216         RAII_VAR(struct ast_str *, bridge_text,
217                 ast_manager_build_bridge_state_string(blob->bridge, ""),
218                 ast_free);
219         RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
220
221         ast_assert(blob != NULL);
222         ast_assert(event != NULL);
223
224         conference_name = ast_json_string_get(ast_json_object_get(blob->blob, "conference"));
225         ast_assert(conference_name != NULL);
226
227         if (blob->channel) {
228                 channel_text = ast_manager_build_channel_state_string(blob->channel);
229         }
230
231         manager_event(EVENT_FLAG_CALL, event,
232                 "Conference: %s\r\n"
233                 "%s"
234                 "%s"
235                 "%s",
236                 conference_name,
237                 ast_str_buffer(bridge_text),
238                 S_COR(channel_text, ast_str_buffer(channel_text), ""),
239                 S_COR(extra_text, ast_str_buffer(extra_text), ""));
240 }
241
242 static void confbridge_start_cb(void *data, struct stasis_subscription *sub,
243         struct stasis_topic *topic,
244         struct stasis_message *message)
245 {
246         confbridge_publish_manager_event(message, "ConfbridgeStart", NULL);
247 }
248
249 static void confbridge_end_cb(void *data, struct stasis_subscription *sub,
250         struct stasis_topic *topic,
251         struct stasis_message *message)
252 {
253         confbridge_publish_manager_event(message, "ConfbridgeEnd", NULL);
254 }
255
256 static void confbridge_leave_cb(void *data, struct stasis_subscription *sub,
257         struct stasis_topic *topic,
258         struct stasis_message *message)
259 {
260         confbridge_publish_manager_event(message, "ConfbridgeLeave", NULL);
261 }
262
263 static void confbridge_join_cb(void *data, struct stasis_subscription *sub,
264         struct stasis_topic *topic,
265         struct stasis_message *message)
266 {
267         confbridge_publish_manager_event(message, "ConfbridgeJoin", NULL);
268 }
269
270 static void confbridge_start_record_cb(void *data, struct stasis_subscription *sub,
271         struct stasis_topic *topic,
272         struct stasis_message *message)
273 {
274         confbridge_publish_manager_event(message, "ConfbridgeRecord", NULL);
275 }
276
277 static void confbridge_stop_record_cb(void *data, struct stasis_subscription *sub,
278         struct stasis_topic *topic,
279         struct stasis_message *message)
280 {
281         confbridge_publish_manager_event(message, "ConfbridgeStopRecord", NULL);
282 }
283
284 static void confbridge_mute_cb(void *data, struct stasis_subscription *sub,
285         struct stasis_topic *topic,
286         struct stasis_message *message)
287 {
288         confbridge_publish_manager_event(message, "ConfbridgeMute", NULL);
289 }
290
291 static void confbridge_unmute_cb(void *data, struct stasis_subscription *sub,
292         struct stasis_topic *topic,
293         struct stasis_message *message)
294 {
295         confbridge_publish_manager_event(message, "ConfbridgeUnmute", NULL);
296 }
297
298 static void confbridge_talking_cb(void *data, struct stasis_subscription *sub,
299         struct stasis_topic *topic,
300         struct stasis_message *message)
301 {
302         RAII_VAR(struct ast_str *, extra_text, NULL, ast_free);
303         struct ast_bridge_blob *blob = stasis_message_data(message);
304         const char *talking_status = ast_json_string_get(ast_json_object_get(blob->blob, "talking_status"));
305         if (!talking_status) {
306                 return;
307         }
308
309         append_event_header(&extra_text, "TalkingStatus", talking_status);
310         if (!extra_text) {
311                 return;
312         }
313
314         confbridge_publish_manager_event(message, "ConfbridgeTalking", extra_text);
315 }
316
317 STASIS_MESSAGE_TYPE_DEFN(confbridge_start_type);
318 STASIS_MESSAGE_TYPE_DEFN(confbridge_end_type);
319 STASIS_MESSAGE_TYPE_DEFN(confbridge_join_type);
320 STASIS_MESSAGE_TYPE_DEFN(confbridge_leave_type);
321 STASIS_MESSAGE_TYPE_DEFN(confbridge_start_record_type);
322 STASIS_MESSAGE_TYPE_DEFN(confbridge_stop_record_type);
323 STASIS_MESSAGE_TYPE_DEFN(confbridge_mute_type);
324 STASIS_MESSAGE_TYPE_DEFN(confbridge_unmute_type);
325 STASIS_MESSAGE_TYPE_DEFN(confbridge_talking_type);
326
327 void manager_confbridge_shutdown(void) {
328         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_start_type);
329         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_end_type);
330         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_join_type);
331         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_leave_type);
332         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_start_record_type);
333         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_stop_record_type);
334         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_mute_type);
335         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_unmute_type);
336         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_talking_type);
337
338         if (bridge_state_router) {
339                 stasis_message_router_unsubscribe(bridge_state_router);
340                 bridge_state_router = NULL;
341         }
342
343         if (channel_state_router) {
344                 stasis_message_router_unsubscribe(channel_state_router);
345                 channel_state_router = NULL;
346         }
347 }
348
349 int manager_confbridge_init(void)
350 {
351         STASIS_MESSAGE_TYPE_INIT(confbridge_start_type);
352         STASIS_MESSAGE_TYPE_INIT(confbridge_end_type);
353         STASIS_MESSAGE_TYPE_INIT(confbridge_join_type);
354         STASIS_MESSAGE_TYPE_INIT(confbridge_leave_type);
355         STASIS_MESSAGE_TYPE_INIT(confbridge_start_record_type);
356         STASIS_MESSAGE_TYPE_INIT(confbridge_stop_record_type);
357         STASIS_MESSAGE_TYPE_INIT(confbridge_mute_type);
358         STASIS_MESSAGE_TYPE_INIT(confbridge_unmute_type);
359         STASIS_MESSAGE_TYPE_INIT(confbridge_talking_type);
360
361         bridge_state_router = stasis_message_router_create(
362                 stasis_caching_get_topic(ast_bridge_topic_all_cached()));
363
364         if (!bridge_state_router) {
365                 return -1;
366         }
367
368         if (stasis_message_router_add(bridge_state_router,
369                         confbridge_start_type(),
370                         confbridge_start_cb,
371                         NULL)) {
372                 manager_confbridge_shutdown();
373                 return -1;
374         }
375         if (stasis_message_router_add(bridge_state_router,
376                         confbridge_end_type(),
377                         confbridge_end_cb,
378                         NULL)) {
379                 manager_confbridge_shutdown();
380                 return -1;
381         }
382         if (stasis_message_router_add(bridge_state_router,
383                         confbridge_join_type(),
384                         confbridge_join_cb,
385                         NULL)) {
386                 manager_confbridge_shutdown();
387                 return -1;
388         }
389         if (stasis_message_router_add(bridge_state_router,
390                         confbridge_leave_type(),
391                         confbridge_leave_cb,
392                         NULL)) {
393                 manager_confbridge_shutdown();
394                 return -1;
395         }
396         if (stasis_message_router_add(bridge_state_router,
397                         confbridge_start_record_type(),
398                         confbridge_start_record_cb,
399                         NULL)) {
400                 manager_confbridge_shutdown();
401                 return -1;
402         }
403         if (stasis_message_router_add(bridge_state_router,
404                         confbridge_stop_record_type(),
405                         confbridge_stop_record_cb,
406                         NULL)) {
407                 manager_confbridge_shutdown();
408                 return -1;
409         }
410         if (stasis_message_router_add(bridge_state_router,
411                         confbridge_mute_type(),
412                         confbridge_mute_cb,
413                         NULL)) {
414                 manager_confbridge_shutdown();
415                 return -1;
416         }
417         if (stasis_message_router_add(bridge_state_router,
418                         confbridge_unmute_type(),
419                         confbridge_unmute_cb,
420                         NULL)) {
421                 manager_confbridge_shutdown();
422                 return -1;
423         }
424         if (stasis_message_router_add(bridge_state_router,
425                         confbridge_talking_type(),
426                         confbridge_talking_cb,
427                         NULL)) {
428                 manager_confbridge_shutdown();
429                 return -1;
430         }
431
432         channel_state_router = stasis_message_router_create(
433                 stasis_caching_get_topic(ast_channel_topic_all_cached()));
434
435         if (!channel_state_router) {
436                 manager_confbridge_shutdown();
437                 return -1;
438         }
439
440         if (stasis_message_router_add(channel_state_router,
441                         confbridge_start_type(),
442                         confbridge_start_cb,
443                         NULL)) {
444                 manager_confbridge_shutdown();
445                 return -1;
446         }
447         if (stasis_message_router_add(channel_state_router,
448                         confbridge_end_type(),
449                         confbridge_end_cb,
450                         NULL)) {
451                 manager_confbridge_shutdown();
452                 return -1;
453         }
454         if (stasis_message_router_add(channel_state_router,
455                         confbridge_join_type(),
456                         confbridge_join_cb,
457                         NULL)) {
458                 manager_confbridge_shutdown();
459                 return -1;
460         }
461         if (stasis_message_router_add(channel_state_router,
462                         confbridge_leave_type(),
463                         confbridge_leave_cb,
464                         NULL)) {
465                 manager_confbridge_shutdown();
466                 return -1;
467         }
468         if (stasis_message_router_add(channel_state_router,
469                         confbridge_start_record_type(),
470                         confbridge_start_record_cb,
471                         NULL)) {
472                 manager_confbridge_shutdown();
473                 return -1;
474         }
475         if (stasis_message_router_add(channel_state_router,
476                         confbridge_stop_record_type(),
477                         confbridge_stop_record_cb,
478                         NULL)) {
479                 manager_confbridge_shutdown();
480                 return -1;
481         }
482         if (stasis_message_router_add(channel_state_router,
483                         confbridge_mute_type(),
484                         confbridge_mute_cb,
485                         NULL)) {
486                 manager_confbridge_shutdown();
487                 return -1;
488         }
489         if (stasis_message_router_add(channel_state_router,
490                         confbridge_unmute_type(),
491                         confbridge_unmute_cb,
492                         NULL)) {
493                 manager_confbridge_shutdown();
494                 return -1;
495         }
496         if (stasis_message_router_add(channel_state_router,
497                         confbridge_talking_type(),
498                         confbridge_talking_cb,
499                         NULL)) {
500                 manager_confbridge_shutdown();
501                 return -1;
502         }
503
504         return 0;
505 }