Asterisk - The Open Source Telephony Project  21.4.1
manager_mwi.c
Go to the documentation of this file.
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/mwi.h"
31 #include "asterisk/channel.h"
32 #include "asterisk/stasis_message_router.h"
33 #include "asterisk/stasis.h"
34 
35 struct stasis_message_router *mwi_state_router;
36 
37 /*** DOCUMENTATION
38  ***/
39 
40 /*! \brief The \ref stasis subscription returned by the forwarding of the MWI topic
41  * to the manager topic
42  */
44 
45 /*! \brief Callback function used by \ref mwi_app_event_cb to weed out "Event" keys */
46 static int exclude_event_cb(const char *key)
47 {
48  if (!strcmp(key, "Event")) {
49  return -1;
50  }
51  return 0;
52 }
53 
54 /*! \brief Generic MWI event callback used for one-off events from voicemail modules */
55 static void mwi_app_event_cb(void *data, struct stasis_subscription *sub,
56  struct stasis_message *message)
57 {
58  struct ast_mwi_blob *payload = stasis_message_data(message);
59  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
60  RAII_VAR(struct ast_str *, event_buffer, NULL, ast_free);
61  struct ast_json *event_json = ast_json_object_get(payload->blob, "Event");
62 
63  if (!event_json) {
64  return;
65  }
66 
67  if (payload->mwi_state && payload->mwi_state->snapshot) {
68  channel_event_string = ast_manager_build_channel_state_string(payload->mwi_state->snapshot);
69  }
70 
71  event_buffer = ast_manager_str_from_json_object(payload->blob, exclude_event_cb);
72  if (!event_buffer) {
73  ast_log(AST_LOG_WARNING, "Failed to create payload for event %s\n", ast_json_string_get(event_json));
74  return;
75  }
76 
77  manager_event(EVENT_FLAG_CALL, ast_json_string_get(event_json),
78  "Mailbox: %s\r\n"
79  "%s"
80  "%s",
81  payload->mwi_state ? payload->mwi_state->uniqueid : "Unknown",
82  ast_str_buffer(event_buffer),
83  channel_event_string ? ast_str_buffer(channel_event_string) : "");
84 }
85 
86 static void mwi_update_cb(void *data, struct stasis_subscription *sub,
87  struct stasis_message *message)
88 {
89  struct ast_mwi_state *mwi_state;
90  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
91 
92  if (ast_mwi_state_type() != stasis_message_type(message)) {
93  return;
94  }
95 
96  mwi_state = stasis_message_data(message);
97  if (!mwi_state) {
98  return;
99  }
100 
101  if (mwi_state->snapshot) {
102  channel_event_string = ast_manager_build_channel_state_string(mwi_state->snapshot);
103  }
104 
105  /*** DOCUMENTATION
106  <managerEvent language="en_US" name="MessageWaiting">
107  <managerEventInstance class="EVENT_FLAG_CALL">
108  <synopsis>Raised when the state of messages in a voicemail mailbox
109  has changed or when a channel has finished interacting with a
110  mailbox.</synopsis>
111  <syntax>
112  <channel_snapshot/>
113  <parameter name="Mailbox">
114  <para>The mailbox with the new message, specified as <literal>mailbox</literal>@<literal>context</literal></para>
115  </parameter>
116  <parameter name="Waiting">
117  <para>Whether or not the mailbox has messages waiting for it.</para>
118  </parameter>
119  <parameter name="New">
120  <para>The number of new messages.</para>
121  </parameter>
122  <parameter name="Old">
123  <para>The number of old messages.</para>
124  </parameter>
125  </syntax>
126  <description>
127  <note><para>The Channel related parameters are only present if a
128  channel was involved in the manipulation of a mailbox. If no
129  channel is involved, the parameters are not included with the
130  event.</para>
131  </note>
132  </description>
133  </managerEventInstance>
134  </managerEvent>
135  ***/
136  manager_event(EVENT_FLAG_CALL, "MessageWaiting",
137  "%s"
138  "Mailbox: %s\r\n"
139  "Waiting: %d\r\n"
140  "New: %d\r\n"
141  "Old: %d\r\n",
142  AS_OR(channel_event_string, ""),
143  mwi_state->uniqueid,
144  ast_app_has_voicemail(mwi_state->uniqueid, NULL),
145  mwi_state->new_msgs,
146  mwi_state->old_msgs);
147 }
148 
149 static void manager_mwi_shutdown(void)
150 {
151  stasis_forward_cancel(topic_forwarder);
152  topic_forwarder = NULL;
153 }
154 
156 {
157  int ret = 0;
158  struct stasis_topic *manager_topic;
159  struct stasis_topic *mwi_topic;
160  struct stasis_message_router *message_router;
161 
162  manager_topic = ast_manager_get_topic();
163  if (!manager_topic) {
164  return -1;
165  }
166  message_router = ast_manager_get_message_router();
167  if (!message_router) {
168  return -1;
169  }
170  mwi_topic = ast_mwi_topic_all();
171  if (!mwi_topic) {
172  return -1;
173  }
174 
175  topic_forwarder = stasis_forward_all(mwi_topic, manager_topic);
176  if (!topic_forwarder) {
177  return -1;
178  }
179 
180  ast_register_cleanup(manager_mwi_shutdown);
181 
182  ret |= stasis_message_router_add(message_router,
184  mwi_update_cb,
185  NULL);
186 
187  ret |= stasis_message_router_add(message_router,
190  NULL);
191 
192  /* If somehow we failed to add any routes, just shut down the whole
193  * thing and fail it.
194  */
195  if (ret) {
196  manager_mwi_shutdown();
197  return -1;
198  }
199 
200  return 0;
201 }
static int exclude_event_cb(const char *key)
Callback function used by mwi_app_event_cb to weed out "Event" keys.
Definition: manager_mwi.c:46
Asterisk main include file. File version handling, generic pbx functions.
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
struct ast_mwi_state * mwi_state
Definition: mwi.h:472
static struct stasis_topic * manager_topic
A stasis_topic that all topics AMI cares about will be forwarded to.
Definition: manager.c:1644
struct ast_str * ast_manager_str_from_json_object(struct ast_json *blob, key_exclusion_cb exclusion_cb)
Convert a JSON object into an AMI compatible string.
Definition: manager.c:1981
General Asterisk PBX channel definitions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
int new_msgs
Definition: mwi.h:459
Support for dynamic strings.
Definition: strings.h:623
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
int manager_mwi_init(void)
Initialize support for AMI MWI events.
Definition: manager_mwi.c:155
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
static void mwi_app_event_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Generic MWI event callback used for one-off events from voicemail modules.
Definition: manager_mwi.c:55
struct stasis_message_router * ast_manager_get_message_router(void)
Get the stasis_message_router for AMI.
Definition: manager.c:1885
static struct stasis_forward * topic_forwarder
The Stasis Message Bus API subscription returned by the forwarding of the MWI topic to the manager to...
Definition: manager_mwi.c:43
Object that represents an MWI update with some additional application defined data.
Definition: mwi.h:471
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:1880
const ast_string_field uniqueid
Definition: mwi.h:458
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
Definition: main/app.c:582
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
int old_msgs
Definition: mwi.h:460
Asterisk MWI API.
Abstract JSON element (object, array, string, int, ...).
Forwarding information.
Definition: stasis.c:1531
struct stasis_topic * ast_mwi_topic_all(void)
Get the Stasis Message Bus API topic for MWI messages.
Definition: mwi.c:89
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
Definition: stasis.c:1578
struct stasis_message_type * ast_mwi_vm_app_type(void)
Get the Stasis Message Bus API message type for voicemail application specific messages.
The structure that contains MWI state.
Definition: mwi.h:455
struct ast_channel_snapshot * snapshot
Definition: mwi.h:462
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:253
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct ast_json * blob
Definition: mwi.h:473