Asterisk - The Open Source Telephony Project  18.5.0
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 <[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 /*!
20  * \file
21  * \brief AMI wrapper for external MWI.
22  *
23  * \author Richard Mudgett <[email protected]>
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  */
147 static 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 
178  mailboxes = ast_mwi_mailbox_get_by_regex(ast_str_buffer(regex_string));
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  }
189  ast_mwi_mailbox_unref(mailbox);
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;
209  iter = ao2_iterator_init(mailboxes, AO2_ITERATOR_UNLINK);
210  for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) {
211  ++count;
212  astman_append(s,
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",
219  ast_mwi_mailbox_get_id(mailbox),
222  id_text);
223  }
224  ao2_iterator_destroy(&iter);
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  */
244 static 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  */
290 static 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;
305  if (!ast_strlen_zero(msgs_old)) {
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;
313  if (!ast_strlen_zero(msgs_new)) {
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. */
327  ast_mwi_mailbox_set_msgs_old(mailbox, num_old);
328  ast_mwi_mailbox_set_msgs_new(mailbox, num_new);
329  if (ast_mwi_mailbox_update(mailbox)) {
330  astman_send_error(s, m, "Update attempt failed");
331  } else {
332  astman_send_ack(s, m, NULL);
333  }
334  ast_mwi_mailbox_unref(mailbox);
335 
336  return 0;
337 }
338 
339 static 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 
348 static int load_module(void)
349 {
350  int res;
351 
352  res = 0;
356  if (res) {
357  unload_module();
359  }
360 
362 }
363 
364 AST_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",
370 );
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_mwi_mailbox_get_id(const struct ast_mwi_mailbox_object *mailbox)
Get mailbox id.
struct ast_mwi_mailbox_object * ast_mwi_mailbox_alloc(const char *mailbox_id)
Allocate an external MWI object.
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:3237
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
void ast_mwi_mailbox_set_msgs_new(struct ast_mwi_mailbox_object *mailbox, unsigned int num_msgs)
Set the number of new messages.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
static int mwi_mailbox_get(struct mansession *s, const struct message *m)
#define EVENT_FLAG_CALL
Definition: manager.h:72
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
Core external MWI support.
#define NULL
Definition: resample.c:96
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:3164
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_mwi_mailbox_update(struct ast_mwi_mailbox_object *mailbox)
Update the external MWI counts with the given object.
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
const struct ast_mwi_mailbox_object * ast_mwi_mailbox_get(const char *mailbox_id)
Get matching external MWI object.
static int unload_module(void)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
In case you didn&#39;t read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Definition: manager.c:1625
static int mwi_mailbox_update(struct mansession *s, const struct message *m)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
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
int ast_mwi_mailbox_delete(const char *mailbox_id)
Delete matching external MWI object.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
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: main/utils.c:1931
#define ast_free(a)
Definition: astmm.h:182
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)
Convienience unref function for mailbox object.
static int mwi_mailbox_delete(struct mansession *s, const struct message *m)
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
#define EVENT_FLAG_REPORTING
Definition: manager.h:80
static int load_module(void)
void ast_mwi_mailbox_set_msgs_old(struct ast_mwi_mailbox_object *mailbox, unsigned int num_msgs)
Set the number of old messages.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
enum queue_result id
Definition: app_queue.c:1507
Generic container type.
unsigned int ast_mwi_mailbox_get_msgs_old(const struct ast_mwi_mailbox_object *mailbox)
Get the number of old messages.
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
Asterisk module definitions.
int ast_mwi_mailbox_delete_by_regex(const char *regex)
Delete all external MWI objects selected by the regular expression.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
struct ao2_container * ast_mwi_mailbox_get_by_regex(const char *regex)
Get all external MWI objects selected by the regular expression.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
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:3201
#define ao2_link(container, obj)
Definition: astobj2.h:1549