Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
res_mwi_external_ami.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 * Richard Mudgett <rmudgett@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/*!
20 * \file
21 * \brief AMI wrapper for external MWI.
22 *
23 * \author Richard Mudgett <rmudgett@digium.com>
24 *
25 * See Also:
26 * \arg \ref AstCREDITS
27 */
28
29/*** MODULEINFO
30 <depend>res_mwi_external</depend>
31 <support_level>core</support_level>
32 ***/
33
34
35/*** DOCUMENTATION
36 <manager name="MWIGet" language="en_US">
37 <since>
38 <version>12.1.0</version>
39 </since>
40 <synopsis>
41 Get selected mailboxes with message counts.
42 </synopsis>
43 <syntax>
44 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
45 <parameter name="Mailbox" required="true">
46 <para>Mailbox ID in the form of
47 /<replaceable>regex</replaceable>/ for all mailboxes matching the regular
48 expression. Otherwise it is for a specific mailbox.</para>
49 </parameter>
50 </syntax>
51 <description>
52 <para>Get a list of mailboxes with their message counts.</para>
53 </description>
54 </manager>
55 <managerEvent language="en_US" name="MWIGet">
56 <managerEventInstance class="EVENT_FLAG_REPORTING">
57 <since>
58 <version>12.1.0</version>
59 </since>
60 <synopsis>
61 Raised in response to a MWIGet command.
62 </synopsis>
63 <syntax>
64 <parameter name="ActionID" required="false"/>
65 <parameter name="Mailbox">
66 <para>Specific mailbox ID.</para>
67 </parameter>
68 <parameter name="OldMessages">
69 <para>The number of old messages in the mailbox.</para>
70 </parameter>
71 <parameter name="NewMessages">
72 <para>The number of new messages in the mailbox.</para>
73 </parameter>
74 </syntax>
75 <see-also>
76 <ref type="manager">MWIGet</ref>
77 </see-also>
78 </managerEventInstance>
79 </managerEvent>
80 <managerEvent language="en_US" name="MWIGetComplete">
81 <managerEventInstance class="EVENT_FLAG_REPORTING">
82 <since>
83 <version>12.1.0</version>
84 </since>
85 <synopsis>
86 Raised in response to a MWIGet command.
87 </synopsis>
88 <syntax>
89 <parameter name="ActionID" required="false"/>
90 <parameter name="EventList" />
91 <parameter name="ListItems">
92 <para>The number of mailboxes reported.</para>
93 </parameter>
94 </syntax>
95 <see-also>
96 <ref type="manager">MWIGet</ref>
97 </see-also>
98 </managerEventInstance>
99 </managerEvent>
100 <manager name="MWIDelete" language="en_US">
101 <since>
102 <version>12.1.0</version>
103 </since>
104 <synopsis>
105 Delete selected mailboxes.
106 </synopsis>
107 <syntax>
108 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
109 <xi:include xpointer="xpointer(/docs/manager[@name='MWIGet']/syntax/parameter[@name='Mailbox'])" />
110 </syntax>
111 <description>
112 <para>Delete the specified mailboxes.</para>
113 </description>
114 </manager>
115 <manager name="MWIUpdate" language="en_US">
116 <since>
117 <version>12.1.0</version>
118 </since>
119 <synopsis>
120 Update the mailbox message counts.
121 </synopsis>
122 <syntax>
123 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
124 <parameter name="Mailbox" required="true">
125 <para>Specific mailbox ID.</para>
126 </parameter>
127 <parameter name="OldMessages">
128 <para>The number of old messages in the mailbox. Defaults
129 to zero if missing.</para>
130 </parameter>
131 <parameter name="NewMessages">
132 <para>The number of new messages in the mailbox. Defaults
133 to zero if missing.</para>
134 </parameter>
135 </syntax>
136 <description>
137 <para>Update the mailbox message counts.</para>
138 </description>
139 </manager>
140 ***/
141
142
143#include "asterisk.h"
144
145#include "asterisk/module.h"
147#include "asterisk/manager.h"
148
149/* ------------------------------------------------------------------- */
150
151/*!
152 * \internal
153 * \brief Get the requested mailboxes.
154 * \since 12.1.0
155 *
156 * \param s AMI session.
157 * \param m AMI message.
158 *
159 * \retval 0 to keep AMI connection.
160 * \retval -1 to disconnect AMI connection.
161 */
162static int mwi_mailbox_get(struct mansession *s, const struct message *m)
163{
164 char id_text[256];
165 const char *id;
166 const char *mailbox_id = astman_get_header(m, "Mailbox");
167 const struct ast_mwi_mailbox_object *mailbox;
168 struct ao2_container *mailboxes;
169 unsigned count;
170 struct ao2_iterator iter;
171
172 if (ast_strlen_zero(mailbox_id)) {
173 astman_send_error(s, m, "Missing mailbox parameter in request");
174 return 0;
175 }
176
177 if (*mailbox_id == '/') {
178 struct ast_str *regex_string;
179
180 regex_string = ast_str_create(strlen(mailbox_id) + 1);
181 if (!regex_string) {
182 astman_send_error(s, m, "Memory Allocation Failure");
183 return 0;
184 }
185
186 /* Make "/regex/" into "regex" */
187 if (ast_regex_string_to_regex_pattern(mailbox_id, &regex_string) != 0) {
188 astman_send_error_va(s, m, "Mailbox regex format invalid in: %s", mailbox_id);
189 ast_free(regex_string);
190 return 0;
191 }
192
194 ast_free(regex_string);
195 } else {
197 if (mailboxes) {
198 mailbox = ast_mwi_mailbox_get(mailbox_id);
199 if (mailbox) {
200 if (!ao2_link(mailboxes, (void *) mailbox)) {
201 ao2_ref(mailboxes, -1);
202 mailboxes = NULL;
203 }
205 }
206 }
207 }
208 if (!mailboxes) {
209 astman_send_error(s, m, "Mailbox container creation failure");
210 return 0;
211 }
212
213 astman_send_listack(s, m, "Mailboxes will follow", "start");
214
215 id = astman_get_header(m, "ActionID");
216 if (!ast_strlen_zero(id)) {
217 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
218 } else {
219 id_text[0] = '\0';
220 }
221
222 /* Output mailbox list. */
223 count = 0;
226 ++count;
228 "Event: MWIGet\r\n"
229 "Mailbox: %s\r\n"
230 "OldMessages: %u\r\n"
231 "NewMessages: %u\r\n"
232 "%s"
233 "\r\n",
237 id_text);
238 }
240 ao2_ref(mailboxes, -1);
241
242 astman_send_list_complete_start(s, m, "MWIGetComplete", count);
244
245 return 0;
246}
247
248/*!
249 * \internal
250 * \brief Delete the requested mailboxes.
251 * \since 12.1.0
252 *
253 * \param s AMI session.
254 * \param m AMI message.
255 *
256 * \retval 0 to keep AMI connection.
257 * \retval -1 to disconnect AMI connection.
258 */
259static int mwi_mailbox_delete(struct mansession *s, const struct message *m)
260{
261 const char *mailbox_id = astman_get_header(m, "Mailbox");
262
263 if (ast_strlen_zero(mailbox_id)) {
264 astman_send_error(s, m, "Missing mailbox parameter in request");
265 return 0;
266 }
267
268 if (*mailbox_id == '/') {
269 struct ast_str *regex_string;
270
271 regex_string = ast_str_create(strlen(mailbox_id) + 1);
272 if (!regex_string) {
273 astman_send_error(s, m, "Memory Allocation Failure");
274 return 0;
275 }
276
277 /* Make "/regex/" into "regex" */
278 if (ast_regex_string_to_regex_pattern(mailbox_id, &regex_string) != 0) {
279 astman_send_error_va(s, m, "Mailbox regex format invalid in: %s", mailbox_id);
280 ast_free(regex_string);
281 return 0;
282 }
283
285 ast_free(regex_string);
286 } else {
287 ast_mwi_mailbox_delete(mailbox_id);
288 }
289
290 astman_send_ack(s, m, NULL);
291 return 0;
292}
293
294/*!
295 * \internal
296 * \brief Update the specified mailbox.
297 * \since 12.1.0
298 *
299 * \param s AMI session.
300 * \param m AMI message.
301 *
302 * \retval 0 to keep AMI connection.
303 * \retval -1 to disconnect AMI connection.
304 */
305static int mwi_mailbox_update(struct mansession *s, const struct message *m)
306{
307 const char *mailbox_id = astman_get_header(m, "Mailbox");
308 const char *msgs_old = astman_get_header(m, "OldMessages");
309 const char *msgs_new = astman_get_header(m, "NewMessages");
311 unsigned int num_old;
312 unsigned int num_new;
313
314 if (ast_strlen_zero(mailbox_id)) {
315 astman_send_error(s, m, "Missing mailbox parameter in request");
316 return 0;
317 }
318
319 num_old = 0;
321 if (sscanf(msgs_old, "%u", &num_old) != 1) {
322 astman_send_error_va(s, m, "Invalid OldMessages: %s", msgs_old);
323 return 0;
324 }
325 }
326
327 num_new = 0;
329 if (sscanf(msgs_new, "%u", &num_new) != 1) {
330 astman_send_error_va(s, m, "Invalid NewMessages: %s", msgs_new);
331 return 0;
332 }
333 }
334
335 mailbox = ast_mwi_mailbox_alloc(mailbox_id);
336 if (!mailbox) {
337 astman_send_error(s, m, "Mailbox object creation failure");
338 return 0;
339 }
340
341 /* Update external mailbox. */
345 astman_send_error(s, m, "Update attempt failed");
346 } else {
347 astman_send_ack(s, m, NULL);
348 }
350
351 return 0;
352}
353
354static int unload_module(void)
355{
356 ast_manager_unregister("MWIGet");
357 ast_manager_unregister("MWIDelete");
358 ast_manager_unregister("MWIUpdate");
359
360 return 0;
361}
362
363static int load_module(void)
364{
365 int res;
366
367 res = 0;
371 if (res) {
374 }
375
377}
378
379AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "AMI support for external MWI",
380 .support_level = AST_MODULE_SUPPORT_CORE,
381 .load = load_module,
382 .unload = unload_module,
383 .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,
384 .requires = "res_mwi_external",
enum queue_result id
Definition: app_queue.c:1808
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
@ AO2_ITERATOR_UNLINK
Definition: astobj2.h:1863
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:2028
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1986
void astman_send_error_va(struct mansession *s, const struct message *m, const char *fmt,...)
Send error in manager transaction (with va_args support)
Definition: manager.c:1991
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:2064
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2018
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1647
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2072
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1907
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7697
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define EVENT_FLAG_REPORTING
Definition: manager.h:84
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:192
#define EVENT_FLAG_CALL
Definition: manager.h:76
Asterisk module definitions.
@ AST_MODFLAG_DEFAULT
Definition: module.h:329
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:557
@ AST_MODPRI_CHANNEL_DEPEND
Definition: module.h:340
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
Core external MWI support.
int ast_mwi_mailbox_update(struct ast_mwi_mailbox_object *mailbox)
Update the external MWI counts with the given object.
struct ast_mwi_mailbox_object * ast_mwi_mailbox_alloc(const char *mailbox_id)
Allocate an external MWI object.
int ast_mwi_mailbox_delete_by_regex(const char *regex)
Delete all external MWI objects selected by the regular expression.
int ast_mwi_mailbox_delete(const char *mailbox_id)
Delete matching external MWI object.
const struct ast_mwi_mailbox_object * ast_mwi_mailbox_get(const char *mailbox_id)
Get matching external MWI object.
const char * ast_mwi_mailbox_get_id(const struct ast_mwi_mailbox_object *mailbox)
Get mailbox id.
unsigned int ast_mwi_mailbox_get_msgs_old(const struct ast_mwi_mailbox_object *mailbox)
Get the number of old messages.
void ast_mwi_mailbox_set_msgs_new(struct ast_mwi_mailbox_object *mailbox, unsigned int num_msgs)
Set the number of new messages.
unsigned int ast_mwi_mailbox_get_msgs_new(const struct ast_mwi_mailbox_object *mailbox)
Get the number of new messages.
#define ast_mwi_mailbox_unref(mailbox)
Convenience unref function for mailbox object.
struct ao2_container * ast_mwi_mailbox_get_by_regex(const char *regex)
Get all external MWI objects selected by the regular expression.
void ast_mwi_mailbox_set_msgs_old(struct ast_mwi_mailbox_object *mailbox, unsigned int num_msgs)
Set the number of old messages.
static int mwi_mailbox_get(struct mansession *s, const struct message *m)
static int load_module(void)
static int unload_module(void)
static int mwi_mailbox_delete(struct mansession *s, const struct message *m)
static int mwi_mailbox_update(struct mansession *s, const struct message *m)
#define NULL
Definition: resample.c:96
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_regex_string_to_regex_pattern(const char *regex_string, struct ast_str **regex_pattern)
Given a string regex_string in the form of "/regex/", convert it into the form of "regex".
Definition: utils.c:2179
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Support for dynamic strings.
Definition: strings.h:623
In case you didn't read that giant block of text above the mansession_session struct,...
Definition: manager.c:327