Asterisk - The Open Source Telephony Project GIT-master-f36a736
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 <synopsis>
38 Get selected mailboxes with message counts.
39 </synopsis>
40 <syntax>
41 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
42 <parameter name="Mailbox" required="true">
43 <para>Mailbox ID in the form of
44 /<replaceable>regex</replaceable>/ for all mailboxes matching the regular
45 expression. Otherwise it is for a specific mailbox.</para>
46 </parameter>
47 </syntax>
48 <description>
49 <para>Get a list of mailboxes with their message counts.</para>
50 </description>
51 </manager>
52 <managerEvent language="en_US" name="MWIGet">
53 <managerEventInstance class="EVENT_FLAG_REPORTING">
54 <synopsis>
55 Raised in response to a MWIGet command.
56 </synopsis>
57 <syntax>
58 <parameter name="ActionID" required="false"/>
59 <parameter name="Mailbox">
60 <para>Specific mailbox ID.</para>
61 </parameter>
62 <parameter name="OldMessages">
63 <para>The number of old messages in the mailbox.</para>
64 </parameter>
65 <parameter name="NewMessages">
66 <para>The number of new messages in the mailbox.</para>
67 </parameter>
68 </syntax>
69 <see-also>
70 <ref type="manager">MWIGet</ref>
71 </see-also>
72 </managerEventInstance>
73 </managerEvent>
74 <managerEvent language="en_US" name="MWIGetComplete">
75 <managerEventInstance class="EVENT_FLAG_REPORTING">
76 <synopsis>
77 Raised in response to a MWIGet command.
78 </synopsis>
79 <syntax>
80 <parameter name="ActionID" required="false"/>
81 <parameter name="EventList" />
82 <parameter name="ListItems">
83 <para>The number of mailboxes reported.</para>
84 </parameter>
85 </syntax>
86 <see-also>
87 <ref type="manager">MWIGet</ref>
88 </see-also>
89 </managerEventInstance>
90 </managerEvent>
91 <manager name="MWIDelete" language="en_US">
92 <synopsis>
93 Delete selected mailboxes.
94 </synopsis>
95 <syntax>
96 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
97 <xi:include xpointer="xpointer(/docs/manager[@name='MWIGet']/syntax/parameter[@name='Mailbox'])" />
98 </syntax>
99 <description>
100 <para>Delete the specified mailboxes.</para>
101 </description>
102 </manager>
103 <manager name="MWIUpdate" language="en_US">
104 <synopsis>
105 Update the mailbox message counts.
106 </synopsis>
107 <syntax>
108 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
109 <parameter name="Mailbox" required="true">
110 <para>Specific mailbox ID.</para>
111 </parameter>
112 <parameter name="OldMessages">
113 <para>The number of old messages in the mailbox. Defaults
114 to zero if missing.</para>
115 </parameter>
116 <parameter name="NewMessages">
117 <para>The number of new messages in the mailbox. Defaults
118 to zero if missing.</para>
119 </parameter>
120 </syntax>
121 <description>
122 <para>Update the mailbox message counts.</para>
123 </description>
124 </manager>
125 ***/
126
127
128#include "asterisk.h"
129
130#include "asterisk/module.h"
132#include "asterisk/manager.h"
133
134/* ------------------------------------------------------------------- */
135
136/*!
137 * \internal
138 * \brief Get the requested mailboxes.
139 * \since 12.1.0
140 *
141 * \param s AMI session.
142 * \param m AMI message.
143 *
144 * \retval 0 to keep AMI connection.
145 * \retval -1 to disconnect AMI connection.
146 */
147static int mwi_mailbox_get(struct mansession *s, const struct message *m)
148{
149 char id_text[256];
150 const char *id;
151 const char *mailbox_id = astman_get_header(m, "Mailbox");
152 const struct ast_mwi_mailbox_object *mailbox;
153 struct ao2_container *mailboxes;
154 unsigned count;
155 struct ao2_iterator iter;
156
157 if (ast_strlen_zero(mailbox_id)) {
158 astman_send_error(s, m, "Missing mailbox parameter in request");
159 return 0;
160 }
161
162 if (*mailbox_id == '/') {
163 struct ast_str *regex_string;
164
165 regex_string = ast_str_create(strlen(mailbox_id) + 1);
166 if (!regex_string) {
167 astman_send_error(s, m, "Memory Allocation Failure");
168 return 0;
169 }
170
171 /* Make "/regex/" into "regex" */
172 if (ast_regex_string_to_regex_pattern(mailbox_id, &regex_string) != 0) {
173 astman_send_error_va(s, m, "Mailbox regex format invalid in: %s", mailbox_id);
174 ast_free(regex_string);
175 return 0;
176 }
177
179 ast_free(regex_string);
180 } else {
182 if (mailboxes) {
183 mailbox = ast_mwi_mailbox_get(mailbox_id);
184 if (mailbox) {
185 if (!ao2_link(mailboxes, (void *) mailbox)) {
186 ao2_ref(mailboxes, -1);
187 mailboxes = NULL;
188 }
190 }
191 }
192 }
193 if (!mailboxes) {
194 astman_send_error(s, m, "Mailbox container creation failure");
195 return 0;
196 }
197
198 astman_send_listack(s, m, "Mailboxes will follow", "start");
199
200 id = astman_get_header(m, "ActionID");
201 if (!ast_strlen_zero(id)) {
202 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
203 } else {
204 id_text[0] = '\0';
205 }
206
207 /* Output mailbox list. */
208 count = 0;
211 ++count;
213 "Event: MWIGet\r\n"
214 "Mailbox: %s\r\n"
215 "OldMessages: %u\r\n"
216 "NewMessages: %u\r\n"
217 "%s"
218 "\r\n",
222 id_text);
223 }
225 ao2_ref(mailboxes, -1);
226
227 astman_send_list_complete_start(s, m, "MWIGetComplete", count);
229
230 return 0;
231}
232
233/*!
234 * \internal
235 * \brief Delete the requested mailboxes.
236 * \since 12.1.0
237 *
238 * \param s AMI session.
239 * \param m AMI message.
240 *
241 * \retval 0 to keep AMI connection.
242 * \retval -1 to disconnect AMI connection.
243 */
244static int mwi_mailbox_delete(struct mansession *s, const struct message *m)
245{
246 const char *mailbox_id = astman_get_header(m, "Mailbox");
247
248 if (ast_strlen_zero(mailbox_id)) {
249 astman_send_error(s, m, "Missing mailbox parameter in request");
250 return 0;
251 }
252
253 if (*mailbox_id == '/') {
254 struct ast_str *regex_string;
255
256 regex_string = ast_str_create(strlen(mailbox_id) + 1);
257 if (!regex_string) {
258 astman_send_error(s, m, "Memory Allocation Failure");
259 return 0;
260 }
261
262 /* Make "/regex/" into "regex" */
263 if (ast_regex_string_to_regex_pattern(mailbox_id, &regex_string) != 0) {
264 astman_send_error_va(s, m, "Mailbox regex format invalid in: %s", mailbox_id);
265 ast_free(regex_string);
266 return 0;
267 }
268
270 ast_free(regex_string);
271 } else {
272 ast_mwi_mailbox_delete(mailbox_id);
273 }
274
275 astman_send_ack(s, m, NULL);
276 return 0;
277}
278
279/*!
280 * \internal
281 * \brief Update the specified mailbox.
282 * \since 12.1.0
283 *
284 * \param s AMI session.
285 * \param m AMI message.
286 *
287 * \retval 0 to keep AMI connection.
288 * \retval -1 to disconnect AMI connection.
289 */
290static int mwi_mailbox_update(struct mansession *s, const struct message *m)
291{
292 const char *mailbox_id = astman_get_header(m, "Mailbox");
293 const char *msgs_old = astman_get_header(m, "OldMessages");
294 const char *msgs_new = astman_get_header(m, "NewMessages");
296 unsigned int num_old;
297 unsigned int num_new;
298
299 if (ast_strlen_zero(mailbox_id)) {
300 astman_send_error(s, m, "Missing mailbox parameter in request");
301 return 0;
302 }
303
304 num_old = 0;
306 if (sscanf(msgs_old, "%u", &num_old) != 1) {
307 astman_send_error_va(s, m, "Invalid OldMessages: %s", msgs_old);
308 return 0;
309 }
310 }
311
312 num_new = 0;
314 if (sscanf(msgs_new, "%u", &num_new) != 1) {
315 astman_send_error_va(s, m, "Invalid NewMessages: %s", msgs_new);
316 return 0;
317 }
318 }
319
320 mailbox = ast_mwi_mailbox_alloc(mailbox_id);
321 if (!mailbox) {
322 astman_send_error(s, m, "Mailbox object creation failure");
323 return 0;
324 }
325
326 /* Update external mailbox. */
330 astman_send_error(s, m, "Update attempt failed");
331 } else {
332 astman_send_ack(s, m, NULL);
333 }
335
336 return 0;
337}
338
339static int unload_module(void)
340{
341 ast_manager_unregister("MWIGet");
342 ast_manager_unregister("MWIDelete");
343 ast_manager_unregister("MWIUpdate");
344
345 return 0;
346}
347
348static int load_module(void)
349{
350 int res;
351
352 res = 0;
356 if (res) {
359 }
360
362}
363
364AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "AMI support for external MWI",
365 .support_level = AST_MODULE_SUPPORT_CORE,
366 .load = load_module,
367 .unload = unload_module,
368 .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,
369 .requires = "res_mwi_external",
enum queue_result id
Definition: app_queue.c:1667
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:2011
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1969
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:1974
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:2047
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2001
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1630
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2055
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1890
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7608
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:191
#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:326