Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 <[email protected]>
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"
33 #include "asterisk/stasis.h"
34 
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 
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  <managerEventInstance>
107  <synopsis>Raised when the state of messages in a voicemail mailbox
108  has changed or when a channel has finished interacting with a
109  mailbox.</synopsis>
110  <syntax>
111  <channel_snapshot/>
112  <parameter name="Mailbox">
113  <para>The mailbox with the new message, specified as <literal>mailbox</literal>@<literal>context</literal></para>
114  </parameter>
115  <parameter name="Waiting">
116  <para>Whether or not the mailbox has messages waiting for it.</para>
117  </parameter>
118  <parameter name="New">
119  <para>The number of new messages.</para>
120  </parameter>
121  <parameter name="Old">
122  <para>The number of old messages.</para>
123  </parameter>
124  </syntax>
125  <description>
126  <note><para>The Channel related parameters are only present if a
127  channel was involved in the manipulation of a mailbox. If no
128  channel is involved, the parameters are not included with the
129  event.</para>
130  </note>
131  </description>
132  </managerEventInstance>
133  ***/
134  manager_event(EVENT_FLAG_CALL, "MessageWaiting",
135  "%s"
136  "Mailbox: %s\r\n"
137  "Waiting: %d\r\n"
138  "New: %d\r\n"
139  "Old: %d\r\n",
140  AS_OR(channel_event_string, ""),
141  mwi_state->uniqueid,
142  ast_app_has_voicemail(mwi_state->uniqueid, NULL),
143  mwi_state->new_msgs,
144  mwi_state->old_msgs);
145 }
146 
147 static void manager_mwi_shutdown(void)
148 {
149  stasis_forward_cancel(topic_forwarder);
150  topic_forwarder = NULL;
151 }
152 
154 {
155  int ret = 0;
156  struct stasis_topic *manager_topic;
157  struct stasis_topic *mwi_topic;
158  struct stasis_message_router *message_router;
159 
160  manager_topic = ast_manager_get_topic();
161  if (!manager_topic) {
162  return -1;
163  }
164  message_router = ast_manager_get_message_router();
165  if (!message_router) {
166  return -1;
167  }
168  mwi_topic = ast_mwi_topic_all();
169  if (!mwi_topic) {
170  return -1;
171  }
172 
173  topic_forwarder = stasis_forward_all(mwi_topic, manager_topic);
174  if (!topic_forwarder) {
175  return -1;
176  }
177 
179 
180  ret |= stasis_message_router_add(message_router,
183  NULL);
184 
185  ret |= stasis_message_router_add(message_router,
188  NULL);
189 
190  /* If somehow we failed to add any routes, just shut down the whole
191  * thing and fail it.
192  */
193  if (ret) {
195  return -1;
196  }
197 
198  return 0;
199 }
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
struct ast_mwi_state * mwi_state
Definition: mwi.h:474
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:714
static void manager_mwi_shutdown(void)
Definition: manager_mwi.c:147
#define AST_LOG_WARNING
Definition: logger.h:279
#define EVENT_FLAG_CALL
Definition: manager.h:72
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
struct stasis_topic * ast_mwi_topic_all(void)
Get the Stasis Message Bus API topic for MWI messages.
Definition: mwi.c:85
#define NULL
Definition: resample.c:96
static struct stasis_topic * manager_topic
A stasis_topic that all topics AMI cares about will be forwarded to.
Definition: manager.c:1490
struct ast_json * blob
Definition: mwi.h:475
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:1821
#define ast_log
Definition: astobj2.c:42
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
#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:911
int old_msgs
Definition: mwi.h:462
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
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 ...
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
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:153
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:1725
#define ast_free(a)
Definition: astmm.h:182
struct ast_channel_snapshot * snapshot
Definition: mwi.h:464
struct stasis_forward * stasis_forward_cancel(struct stasis_forward *forward)
Definition: stasis.c:1548
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
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:473
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:1720
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:655
#define AS_OR(a, b)
Definition: strings.h:49
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
int new_msgs
Definition: mwi.h:461
const ast_string_field uniqueid
Definition: mwi.h:460
Asterisk MWI API.
struct stasis_forward * sub
Definition: res_corosync.c:240
Abstract JSON element (object, array, string, int, ...).
struct stasis_message_router * mwi_state_router
Definition: manager_mwi.c:35
Forwarding information.
Definition: stasis.c:1531
static void mwi_update_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: manager_mwi.c:86
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
The structure that contains MWI state.
Definition: mwi.h:457
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:248
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct stasis_message_type * ast_mwi_vm_app_type(void)
Get the Stasis Message Bus API message type for voicemail application specific messages.