BuildSystem: Remove unused variables.
[asterisk/asterisk.git] / main / manager_mwi.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Matt Jordan <mjordan@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 The Asterisk Management Interface - AMI (MWI event handling)
22  *
23  * \author Matt Jordan <mjordan@digium.com>
24  */
25
26 #include "asterisk.h"
27
28 #include "asterisk/manager.h"
29 #include "asterisk/app.h"
30 #include "asterisk/channel.h"
31 #include "asterisk/stasis_message_router.h"
32 #include "asterisk/stasis.h"
33
34 struct stasis_message_router *mwi_state_router;
35
36 /*** DOCUMENTATION
37  ***/
38
39 /*! \brief The \ref stasis subscription returned by the forwarding of the MWI topic
40  * to the manager topic
41  */
42 static struct stasis_forward *topic_forwarder;
43
44 /*! \brief Callback function used by \ref mwi_app_event_cb to weed out "Event" keys */
45 static int exclude_event_cb(const char *key)
46 {
47         if (!strcmp(key, "Event")) {
48                 return -1;
49         }
50         return 0;
51 }
52
53 /*! \brief Generic MWI event callback used for one-off events from voicemail modules */
54 static void mwi_app_event_cb(void *data, struct stasis_subscription *sub,
55                                     struct stasis_message *message)
56 {
57         struct ast_mwi_blob *payload = stasis_message_data(message);
58         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
59         RAII_VAR(struct ast_str *, event_buffer, NULL, ast_free);
60         struct ast_json *event_json = ast_json_object_get(payload->blob, "Event");
61
62         if (!event_json) {
63                 return;
64         }
65
66         if (payload->mwi_state && payload->mwi_state->snapshot) {
67                 channel_event_string = ast_manager_build_channel_state_string(payload->mwi_state->snapshot);
68         }
69
70         event_buffer = ast_manager_str_from_json_object(payload->blob, exclude_event_cb);
71         if (!event_buffer) {
72                 ast_log(AST_LOG_WARNING, "Failed to create payload for event %s\n", ast_json_string_get(event_json));
73                 return;
74         }
75
76         manager_event(EVENT_FLAG_CALL, ast_json_string_get(event_json),
77                         "Mailbox: %s\r\n"
78                         "%s"
79                         "%s",
80                         payload->mwi_state ? payload->mwi_state->uniqueid : "Unknown",
81                         ast_str_buffer(event_buffer),
82                         channel_event_string ? ast_str_buffer(channel_event_string) : "");
83 }
84
85 static void mwi_update_cb(void *data, struct stasis_subscription *sub,
86                                     struct stasis_message *message)
87 {
88         struct ast_mwi_state *mwi_state;
89         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
90
91         if (ast_mwi_state_type() != stasis_message_type(message)) {
92                 return;
93         }
94
95         mwi_state = stasis_message_data(message);
96         if (!mwi_state) {
97                 return;
98         }
99
100         if (mwi_state->snapshot) {
101                 channel_event_string = ast_manager_build_channel_state_string(mwi_state->snapshot);
102         }
103
104         /*** DOCUMENTATION
105                 <managerEventInstance>
106                         <synopsis>Raised when the state of messages in a voicemail mailbox
107                         has changed or when a channel has finished interacting with a
108                         mailbox.</synopsis>
109                         <syntax>
110                                 <channel_snapshot/>
111                                 <parameter name="Mailbox">
112                                         <para>The mailbox with the new message, specified as <literal>mailbox</literal>@<literal>context</literal></para>
113                                 </parameter>
114                                 <parameter name="Waiting">
115                                         <para>Whether or not the mailbox has messages waiting for it.</para>
116                                 </parameter>
117                                 <parameter name="New">
118                                         <para>The number of new messages.</para>
119                                 </parameter>
120                                 <parameter name="Old">
121                                         <para>The number of old messages.</para>
122                                 </parameter>
123                         </syntax>
124                         <description>
125                                 <note><para>The Channel related parameters are only present if a
126                                 channel was involved in the manipulation of a mailbox. If no
127                                 channel is involved, the parameters are not included with the
128                                 event.</para>
129                                 </note>
130                         </description>
131                 </managerEventInstance>
132         ***/
133         manager_event(EVENT_FLAG_CALL, "MessageWaiting",
134                         "%s"
135                         "Mailbox: %s\r\n"
136                         "Waiting: %d\r\n"
137                         "New: %d\r\n"
138                         "Old: %d\r\n",
139                         AS_OR(channel_event_string, ""),
140                         mwi_state->uniqueid,
141                         ast_app_has_voicemail(mwi_state->uniqueid, NULL),
142                         mwi_state->new_msgs,
143                         mwi_state->old_msgs);
144 }
145
146 static void manager_mwi_shutdown(void)
147 {
148         stasis_forward_cancel(topic_forwarder);
149         topic_forwarder = NULL;
150 }
151
152 int manager_mwi_init(void)
153 {
154         int ret = 0;
155         struct stasis_topic *manager_topic;
156         struct stasis_topic *mwi_topic;
157         struct stasis_message_router *message_router;
158
159         manager_topic = ast_manager_get_topic();
160         if (!manager_topic) {
161                 return -1;
162         }
163         message_router = ast_manager_get_message_router();
164         if (!message_router) {
165                 return -1;
166         }
167         mwi_topic = ast_mwi_topic_all();
168         if (!mwi_topic) {
169                 return -1;
170         }
171
172         topic_forwarder = stasis_forward_all(mwi_topic, manager_topic);
173         if (!topic_forwarder) {
174                 return -1;
175         }
176
177         ast_register_cleanup(manager_mwi_shutdown);
178
179         ret |= stasis_message_router_add(message_router,
180                                          ast_mwi_state_type(),
181                                          mwi_update_cb,
182                                          NULL);
183
184         ret |= stasis_message_router_add(message_router,
185                                          ast_mwi_vm_app_type(),
186                                          mwi_app_event_cb,
187                                          NULL);
188
189         /* If somehow we failed to add any routes, just shut down the whole
190          * thing and fail it.
191          */
192         if (ret) {
193                 manager_mwi_shutdown();
194                 return -1;
195         }
196
197         return 0;
198 }