Asterisk - The Open Source Telephony Project  21.4.1
main/message.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2010, Digium, Inc.
5  *
6  * Russell Bryant <russell@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 Out-of-call text message support
22  *
23  * \author Russell Bryant <russell@digium.com>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 #include "asterisk/_private.h"
33 
34 #include "asterisk/module.h"
35 #include "asterisk/datastore.h"
36 #include "asterisk/pbx.h"
37 #include "asterisk/manager.h"
38 #include "asterisk/strings.h"
39 #include "asterisk/astobj2.h"
40 #include "asterisk/vector.h"
41 #include "asterisk/app.h"
42 #include "asterisk/taskprocessor.h"
43 #include "asterisk/message.h"
44 
45 /*** DOCUMENTATION
46  <function name="MESSAGE" language="en_US">
47  <synopsis>
48  Create a message or read fields from a message.
49  </synopsis>
50  <syntax argsep="/">
51  <parameter name="argument" required="true">
52  <para>Field of the message to get or set.</para>
53  <enumlist>
54  <enum name="to">
55  <para>When processing an
56  incoming message, this will be set to the destination listed as
57  the recipient of the message that was received by Asterisk.</para>
58  <para>
59  </para>
60  <para>For an ourgoing message, this will set the To header in the
61  outgoing SIP message. This may be overridden by the "to" parameter
62  of MessageSend.
63  </para>
64  </enum>
65  <enum name="from">
66  <para>When processing an
67  incoming message, this will be set to the source of the message.</para>
68  <para>
69  </para>
70  <para>For an ourgoing message, this will set the From header in the
71  outgoing SIP message. This may be overridden by the "from" parameter
72  of MessageSend.
73  </para>
74  </enum>
75  <enum name="custom_data">
76  <para>Write-only. Mark or unmark all message headers for an outgoing
77  message. The following values can be set:</para>
78  <enumlist>
79  <enum name="mark_all_outbound">
80  <para>Mark all headers for an outgoing message.</para>
81  </enum>
82  <enum name="clear_all_outbound">
83  <para>Unmark all headers for an outgoing message.</para>
84  </enum>
85  </enumlist>
86  </enum>
87  <enum name="body">
88  <para>Read/Write. The message body. When processing an incoming
89  message, this includes the body of the message that Asterisk
90  received. When MessageSend() is executed, the contents of this
91  field are used as the body of the outgoing message. The body
92  will always be UTF-8.</para>
93  </enum>
94  </enumlist>
95  </parameter>
96  </syntax>
97  <description>
98  <para>This function will read from or write a value to a text message.
99  It is used both to read the data out of an incoming message, as well as
100  modify or create a message that will be sent outbound.</para>
101  </description>
102  <see-also>
103  <ref type="application">MessageSend</ref>
104  </see-also>
105  </function>
106  <function name="MESSAGE_DATA" language="en_US">
107  <synopsis>
108  Read or write custom data attached to a message.
109  </synopsis>
110  <syntax argsep="/">
111  <parameter name="argument" required="true">
112  <para>Field of the message to get or set.</para>
113  </parameter>
114  </syntax>
115  <description>
116  <para>This function will read from or write a value to a text message.
117  It is used both to read the data out of an incoming message, as well as
118  modify a message that will be sent outbound.</para>
119  <note>
120  <para>If you want to set an outbound message to carry data in the
121  current message, do
122  Set(MESSAGE_DATA(<replaceable>key</replaceable>)=${MESSAGE_DATA(<replaceable>key</replaceable>)}).</para>
123  </note>
124  </description>
125  <see-also>
126  <ref type="application">MessageSend</ref>
127  </see-also>
128  </function>
129  <application name="MessageSend" language="en_US">
130  <synopsis>
131  Send a text message.
132  </synopsis>
133  <syntax>
134  <parameter name="destination" required="true">
135  <para>A To URI for the message.</para>
136  <xi:include xpointer="xpointer(/docs/info[@name='MessageDestinationInfo'])" />
137  </parameter>
138  <parameter name="from" required="false">
139  <para>A From URI for the message if needed for the
140  message technology being used to send this message. This can be a
141  SIP(S) URI, such as <literal>Alice &lt;sip:alice@atlanta.com&gt;</literal>,
142  or a string in the format <literal>alice@atlanta.com</literal>.
143  This will override a <literal>from</literal>
144  specified using the MESSAGE dialplan function or the <literal>from</literal>
145  that may have been on an incoming message.
146  </para>
147  <xi:include xpointer="xpointer(/docs/info[@name='MessageFromInfo'])" />
148  </parameter>
149  <parameter name="to" required="false">
150  <para>A To URI for the message if needed for the
151  message technology being used to send this message. This can be a
152  SIP(S) URI, such as <literal>Alice &lt;sip:alice@atlanta.com&gt;</literal>,
153  or a string in the format <literal>alice@atlanta.com</literal>.
154  This will override a <literal>to</literal>
155  specified using the MESSAGE dialplan function or the <literal>to</literal>
156  that may have been on an incoming message.
157  </para>
158  <xi:include xpointer="xpointer(/docs/info[@name='MessageToInfo'])" />
159  </parameter>
160  </syntax>
161  <description>
162  <para>Send a text message. The body of the message that will be
163  sent is what is currently set to <literal>MESSAGE(body)</literal>.
164  This may he come from an incoming message.
165  The technology chosen for sending the message is determined
166  based on a prefix to the <literal>destination</literal> parameter.</para>
167  <para>This application sets the following channel variables:</para>
168  <variablelist>
169  <variable name="MESSAGE_SEND_STATUS">
170  <para>This is the message delivery status returned by this application.</para>
171  <value name="INVALID_PROTOCOL">
172  No handler for the technology part of the URI was found.
173  </value>
174  <value name="INVALID_URI">
175  The protocol handler reported that the URI was not valid.
176  </value>
177  <value name="SUCCESS">
178  Successfully passed on to the protocol handler, but delivery has not necessarily been guaranteed.
179  </value>
180  <value name="FAILURE">
181  The protocol handler reported that it was unabled to deliver the message for some reason.
182  </value>
183  </variable>
184  </variablelist>
185  </description>
186  </application>
187  <manager name="MessageSend" language="en_US">
188  <synopsis>
189  Send an out of call message to an endpoint.
190  </synopsis>
191  <syntax>
192  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
193  <parameter name="Destination" required="false">
194  <para>A To URI for the message. If Destination is provided, the To
195  parameter can also be supplied and may alter the message based on
196  the specified message technology.</para>
197  <para>For backwards compatibility, if Destination is not provided,
198  the To parameter must be provided and will be used as the message
199  destination.</para>
200  <xi:include xpointer="xpointer(/docs/info[@name='MessageDestinationInfo'])" />
201  </parameter>
202  <parameter name="To" required="false">
203  <para>A To URI for the message if needed for the
204  message technology being used to send this message. This can be a
205  SIP(S) URI, such as <literal>Alice &lt;sip:alice@atlanta.com&gt;</literal>,
206  or a string in the format <literal>alice@atlanta.com</literal>.</para>
207  <para>This parameter is required if the Destination parameter is not
208  provided.</para>
209  <xi:include xpointer="xpointer(/docs/info[@name='MessageToInfo'])" />
210  </parameter>
211  <parameter name="From">
212  <para>A From URI for the message if needed for the
213  message technology being used to send this message.</para>
214  <xi:include xpointer="xpointer(/docs/info[@name='MessageFromInfo'])" />
215  </parameter>
216  <parameter name="Body">
217  <para>The message body text. This must not contain any newlines as that
218  conflicts with the AMI protocol.</para>
219  </parameter>
220  <parameter name="Base64Body">
221  <para>Text bodies requiring the use of newlines have to be base64 encoded
222  in this field. Base64Body will be decoded before being sent out.
223  Base64Body takes precedence over Body.</para>
224  </parameter>
225  <parameter name="Variable">
226  <para>Message variable to set, multiple Variable: headers are
227  allowed. The header value is a comma separated list of
228  name=value pairs.</para>
229  </parameter>
230  </syntax>
231  </manager>
232  ***/
233 
234 struct msg_data {
236  AST_STRING_FIELD(name);
237  AST_STRING_FIELD(value);
238  );
239  unsigned int send; /* Whether to send out on outbound messages */
240 };
241 
243 
244 /*!
245  * \brief A message.
246  */
247 struct ast_msg {
249  /*! Where the message is going */
251  /*! Where we "say" the message came from */
253  /*! The text to send */
255  /*! The dialplan context for the message */
257  /*! The dialplan extension for the message */
259  /*! An endpoint associated with this message */
261  /*! The technology of the endpoint associated with this message */
263  );
264  /*! Technology/dialplan specific variables associated with the message */
266 };
267 
268 /*! \brief Lock for \c msg_techs vector */
270 
271 /*! \brief Vector of message technologies */
272 AST_VECTOR(, const struct ast_msg_tech *) msg_techs;
273 
274 /*! \brief Lock for \c msg_handlers vector */
276 
277 /*! \brief Vector of received message handlers */
278 AST_VECTOR(, const struct ast_msg_handler *) msg_handlers;
279 
280 static struct ast_taskprocessor *msg_q_tp;
281 
282 static const char app_msg_send[] = "MessageSend";
283 
284 static void msg_ds_destroy(void *data);
285 
286 static const struct ast_datastore_info msg_datastore = {
287  .type = "message",
288  .destroy = msg_ds_destroy,
289 };
290 
291 static int msg_func_read(struct ast_channel *chan, const char *function,
292  char *data, char *buf, size_t len);
293 static int msg_func_write(struct ast_channel *chan, const char *function,
294  char *data, const char *value);
295 
296 static struct ast_custom_function msg_function = {
297  .name = "MESSAGE",
298  .read = msg_func_read,
299  .write = msg_func_write,
300 };
301 
302 static int msg_data_func_read(struct ast_channel *chan, const char *function,
303  char *data, char *buf, size_t len);
304 static int msg_data_func_write(struct ast_channel *chan, const char *function,
305  char *data, const char *value);
306 
307 static struct ast_custom_function msg_data_function = {
308  .name = "MESSAGE_DATA",
309  .read = msg_data_func_read,
310  .write = msg_data_func_write,
311 };
312 
313 static struct ast_frame *chan_msg_read(struct ast_channel *chan);
314 static int chan_msg_write(struct ast_channel *chan, struct ast_frame *fr);
315 static int chan_msg_indicate(struct ast_channel *chan, int condition,
316  const void *data, size_t datalen);
317 static int chan_msg_send_digit_begin(struct ast_channel *chan, char digit);
318 static int chan_msg_send_digit_end(struct ast_channel *chan, char digit,
319  unsigned int duration);
320 
321 /*!
322  * \internal
323  * \brief A bare minimum channel technology
324  *
325  * This will not be registered as we never want anything to try
326  * to create Message channels other than internally in this file.
327  */
328 static struct ast_channel_tech msg_chan_tech_hack = {
329  .type = "Message",
330  .description = "Internal Text Message Processing",
331  .read = chan_msg_read,
332  .write = chan_msg_write,
333  .indicate = chan_msg_indicate,
334  .send_digit_begin = chan_msg_send_digit_begin,
335  .send_digit_end = chan_msg_send_digit_end,
336 };
337 
338 /*!
339  * \internal
340  * \brief ast_channel_tech read callback
341  *
342  * This should never be called. However, we say that about chan_iax2's
343  * read callback, too, and it seems to randomly get called for some
344  * reason. If it does, a simple NULL frame will suffice.
345  */
346 static struct ast_frame *chan_msg_read(struct ast_channel *chan)
347 {
348  return &ast_null_frame;
349 }
350 
351 /*!
352  * \internal
353  * \brief ast_channel_tech write callback
354  *
355  * Throw all frames away. We don't care about any of them.
356  */
357 static int chan_msg_write(struct ast_channel *chan, struct ast_frame *fr)
358 {
359  return 0;
360 }
361 
362 /*!
363  * \internal
364  * \brief ast_channel_tech indicate callback
365  *
366  * The indicate callback is here just so it can return success.
367  * We don't want any callers of ast_indicate() to think something
368  * has failed. We also don't want ast_indicate() itself to try
369  * to generate inband tones since we didn't tell it that we took
370  * care of it ourselves.
371  */
372 static int chan_msg_indicate(struct ast_channel *chan, int condition,
373  const void *data, size_t datalen)
374 {
375  return 0;
376 }
377 
378 /*!
379  * \internal
380  * \brief ast_channel_tech send_digit_begin callback
381  *
382  * This is here so that just in case a digit comes at a message channel
383  * that the Asterisk core doesn't waste any time trying to generate
384  * inband DTMF in audio. It's a waste of resources.
385  */
386 static int chan_msg_send_digit_begin(struct ast_channel *chan, char digit)
387 {
388  return 0;
389 }
390 
391 /*!
392  * \internal
393  * \brief ast_channel_tech send_digit_end callback
394  *
395  * This is here so that just in case a digit comes at a message channel
396  * that the Asterisk core doesn't waste any time trying to generate
397  * inband DTMF in audio. It's a waste of resources.
398  */
399 static int chan_msg_send_digit_end(struct ast_channel *chan, char digit,
400  unsigned int duration)
401 {
402  return 0;
403 }
404 
405 static void msg_ds_destroy(void *data)
406 {
407  struct ast_msg *msg = data;
408 
409  ao2_ref(msg, -1);
410 }
411 
412 static int msg_data_cmp_fn(void *obj, void *arg, int flags)
413 {
414  const struct msg_data *one = obj, *two = arg;
415  return !strcasecmp(one->name, two->name) ? CMP_MATCH | CMP_STOP : 0;
416 }
417 
418 static void msg_data_destructor(void *obj)
419 {
420  struct msg_data *data = obj;
422 }
423 
424 static void msg_destructor(void *obj)
425 {
426  struct ast_msg *msg = obj;
427 
429  ao2_cleanup(msg->vars);
430 }
431 
432 struct ast_msg *ast_msg_alloc(void)
433 {
434  struct ast_msg *msg;
435 
436  if (!(msg = ao2_alloc(sizeof(*msg), msg_destructor))) {
437  return NULL;
438  }
439 
440  if (ast_string_field_init(msg, 128)) {
441  ao2_ref(msg, -1);
442  return NULL;
443  }
444 
446  NULL, msg_data_cmp_fn);
447  if (!msg->vars) {
448  ao2_ref(msg, -1);
449  return NULL;
450  }
451  ast_string_field_set(msg, context, "default");
452 
453  return msg;
454 }
455 
456 struct ast_msg *ast_msg_ref(struct ast_msg *msg)
457 {
458  ao2_ref(msg, 1);
459  return msg;
460 }
461 
462 struct ast_msg *ast_msg_destroy(struct ast_msg *msg)
463 {
464  ao2_ref(msg, -1);
465  return NULL;
466 }
467 
468 int ast_msg_set_to(struct ast_msg *msg, const char *fmt, ...)
469 {
470  va_list ap;
471 
472  va_start(ap, fmt);
473  ast_string_field_build_va(msg, to, fmt, ap);
474  va_end(ap);
475 
476  return 0;
477 }
478 
479 int ast_msg_set_from(struct ast_msg *msg, const char *fmt, ...)
480 {
481  va_list ap;
482 
483  va_start(ap, fmt);
484  ast_string_field_build_va(msg, from, fmt, ap);
485  va_end(ap);
486 
487  return 0;
488 }
489 
490 int ast_msg_set_body(struct ast_msg *msg, const char *fmt, ...)
491 {
492  va_list ap;
493 
494  va_start(ap, fmt);
495  ast_string_field_build_va(msg, body, fmt, ap);
496  va_end(ap);
497 
498  return 0;
499 }
500 
501 int ast_msg_set_context(struct ast_msg *msg, const char *fmt, ...)
502 {
503  va_list ap;
504 
505  va_start(ap, fmt);
506  ast_string_field_build_va(msg, context, fmt, ap);
507  va_end(ap);
508 
509  return 0;
510 }
511 
512 int ast_msg_set_exten(struct ast_msg *msg, const char *fmt, ...)
513 {
514  va_list ap;
515 
516  va_start(ap, fmt);
517  ast_string_field_build_va(msg, exten, fmt, ap);
518  va_end(ap);
519 
520  return 0;
521 }
522 
523 int ast_msg_set_tech(struct ast_msg *msg, const char *fmt, ...)
524 {
525  va_list ap;
526 
527  va_start(ap, fmt);
528  ast_string_field_build_va(msg, tech, fmt, ap);
529  va_end(ap);
530 
531  return 0;
532 }
533 
534 int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt, ...)
535 {
536  va_list ap;
537 
538  va_start(ap, fmt);
539  ast_string_field_build_va(msg, endpoint, fmt, ap);
540  va_end(ap);
541 
542  return 0;
543 }
544 
545 const char *ast_msg_get_body(const struct ast_msg *msg)
546 {
547  return msg->body;
548 }
549 
550 const char *ast_msg_get_from(const struct ast_msg *msg)
551 {
552  return msg->from;
553 }
554 
555 const char *ast_msg_get_to(const struct ast_msg *msg)
556 {
557  return msg->to;
558 }
559 
560 const char *ast_msg_get_tech(const struct ast_msg *msg)
561 {
562  return msg->tech;
563 }
564 
565 const char *ast_msg_get_endpoint(const struct ast_msg *msg)
566 {
567  return msg->endpoint;
568 }
569 
570 static struct msg_data *msg_data_alloc(void)
571 {
572  struct msg_data *data;
573 
574  if (!(data = ao2_alloc(sizeof(*data), msg_data_destructor))) {
575  return NULL;
576  }
577 
578  if (ast_string_field_init(data, 32)) {
579  ao2_ref(data, -1);
580  return NULL;
581  }
582 
583  return data;
584 }
585 
586 static struct msg_data *msg_data_find(struct ao2_container *vars, const char *name)
587 {
588  struct msg_data tmp = {
589  .name = name,
590  };
591  return ao2_find(vars, &tmp, OBJ_POINTER);
592 }
593 
594 static int msg_set_var_full(struct ast_msg *msg, const char *name, const char *value, unsigned int outbound)
595 {
596  struct msg_data *data;
597 
598  if (!(data = msg_data_find(msg->vars, name))) {
599  if (ast_strlen_zero(value)) {
600  return 0;
601  }
602  if (!(data = msg_data_alloc())) {
603  return -1;
604  };
605 
606  ast_string_field_set(data, name, name);
607  ast_string_field_set(data, value, value);
608  data->send = outbound;
609  ao2_link(msg->vars, data);
610  } else {
611  if (ast_strlen_zero(value)) {
612  ao2_unlink(msg->vars, data);
613  } else {
614  ast_string_field_set(data, value, value);
615  data->send = outbound;
616  }
617  }
618 
619  ao2_ref(data, -1);
620 
621  return 0;
622 }
623 
624 int ast_msg_set_var_outbound(struct ast_msg *msg, const char *name, const char *value)
625 {
626  return msg_set_var_full(msg, name, value, 1);
627 }
628 
629 int ast_msg_set_var(struct ast_msg *msg, const char *name, const char *value)
630 {
631  return msg_set_var_full(msg, name, value, 0);
632 }
633 
634 const char *ast_msg_get_var(struct ast_msg *msg, const char *name)
635 {
636  struct msg_data *data;
637  const char *val = NULL;
638 
639  if (!(data = msg_data_find(msg->vars, name))) {
640  return NULL;
641  }
642 
643  /* Yep, this definitely looks like val would be a dangling pointer
644  * after the ref count is decremented. As long as the message structure
645  * is used in a thread safe manner, this will not be the case though.
646  * The ast_msg holds a reference to this object in the msg->vars container. */
647  val = data->value;
648  ao2_ref(data, -1);
649 
650  return val;
651 }
652 
654  struct ao2_iterator iter;
655  struct msg_data *current_used;
656 };
657 
659 {
660  struct ast_msg_var_iterator *iter;
661 
662  iter = ast_calloc(1, sizeof(*iter));
663  if (!iter) {
664  return NULL;
665  }
666 
667  iter->iter = ao2_iterator_init(msg->vars, 0);
668 
669  return iter;
670 }
671 
672 static int ast_msg_var_iterator_get_next(const struct ast_msg *msg,
673  struct ast_msg_var_iterator *iter, const char **name, const char **value,
674  unsigned int send)
675 {
676  struct msg_data *data;
677 
678  if (!iter) {
679  return 0;
680  }
681 
682  /* Skip any that we're told to */
683  while ((data = ao2_iterator_next(&iter->iter)) && (data->send != send)) {
684  ao2_ref(data, -1);
685  }
686 
687  if (!data) {
688  return 0;
689  }
690 
691  if (data->send == send) {
692  *name = data->name;
693  *value = data->value;
694  }
695 
696  /* Leave the refcount to be cleaned up by the caller with
697  * ast_msg_var_unref_current after they finish with the pointers to the data */
698  iter->current_used = data;
699 
700  return 1;
701 }
702 
703 int ast_msg_var_iterator_next(const struct ast_msg *msg, struct ast_msg_var_iterator *iter, const char **name, const char **value)
704 {
705  return ast_msg_var_iterator_get_next(msg, iter, name, value, 1);
706 }
707 
709  struct ast_msg_var_iterator *iter, const char **name, const char **value)
710 {
711  return ast_msg_var_iterator_get_next(msg, iter, name, value, 0);
712 }
713 
715 {
716  ao2_cleanup(iter->current_used);
717  iter->current_used = NULL;
718 }
719 
721 {
722  if (iter) {
723  ao2_iterator_destroy(&iter->iter);
725  ast_free(iter);
726  }
727 }
728 
729 static struct ast_channel *create_msg_q_chan(void)
730 {
731  struct ast_channel *chan;
732  struct ast_datastore *ds;
733 
735  NULL, NULL, NULL,
736  NULL, NULL, NULL, NULL, 0,
737  "%s", "Message/ast_msg_queue");
738 
739  if (!chan) {
740  return NULL;
741  }
742 
743  if (ast_opt_hide_messaging_ami_events) {
744  msg_chan_tech_hack.properties |= AST_CHAN_TP_INTERNAL;
745  }
746 
747  ast_channel_tech_set(chan, &msg_chan_tech_hack);
748  ast_channel_unlock(chan);
749  ast_channel_unlink(chan);
750 
751  if (!(ds = ast_datastore_alloc(&msg_datastore, NULL))) {
752  ast_hangup(chan);
753  return NULL;
754  }
755 
756  ast_channel_lock(chan);
757  ast_channel_datastore_add(chan, ds);
758  ast_channel_unlock(chan);
759 
760  return chan;
761 }
762 
763 /*!
764  * \internal
765  * \brief Run the dialplan for message processing
766  *
767  * \pre The message has already been set up on the msg datastore
768  * on this channel.
769  */
770 static void msg_route(struct ast_channel *chan, struct ast_msg *msg)
771 {
772  struct ast_pbx_args pbx_args;
773 
774  ast_explicit_goto(chan, msg->context, S_OR(msg->exten, "s"), 1);
775 
776  memset(&pbx_args, 0, sizeof(pbx_args));
777  pbx_args.no_hangup_chan = 1,
778  ast_pbx_run_args(chan, &pbx_args);
779 }
780 
781 /*!
782  * \internal
783  * \brief Clean up ast_channel after each message
784  *
785  * Reset various bits of state after routing each message so the same ast_channel
786  * can just be reused.
787  */
788 static void chan_cleanup(struct ast_channel *chan)
789 {
790  struct ast_datastore *msg_ds, *ds;
791  struct varshead *headp;
792  struct ast_var_t *vardata;
793  struct ast_frame *cur;
794 
795  ast_channel_lock(chan);
796 
797  /*
798  * Remove the msg datastore. Free its data but keep around the datastore
799  * object and just reuse it.
800  */
801  if ((msg_ds = ast_channel_datastore_find(chan, &msg_datastore, NULL)) && msg_ds->data) {
802  ast_channel_datastore_remove(chan, msg_ds);
803  ao2_ref(msg_ds->data, -1);
804  msg_ds->data = NULL;
805  }
806 
807  /*
808  * Destroy all other datastores.
809  */
810  while ((ds = AST_LIST_REMOVE_HEAD(ast_channel_datastores(chan), entry))) {
811  ast_datastore_free(ds);
812  }
813 
814  /*
815  * Destroy all channel variables.
816  */
817  headp = ast_channel_varshead(chan);
818  while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
819  ast_var_delete(vardata);
820  }
821 
822  /*
823  * Remove frames from read queue
824  */
825  while ((cur = AST_LIST_REMOVE_HEAD(ast_channel_readq(chan), frame_list))) {
826  ast_frfree(cur);
827  }
828 
829  /*
830  * Restore msg datastore.
831  */
832  if (msg_ds) {
833  ast_channel_datastore_add(chan, msg_ds);
834  }
835 
836  /*
837  * Clear softhangup flags.
838  */
840 
841  /*
842  * Flush the alert pipe in case we miscounted somewhere when
843  * messing with frames on the read queue, we had to flush the
844  * read queue above, or we had an "Exceptionally long queue
845  * length" event.
846  */
847  ast_channel_internal_alert_flush(chan);
848 
849  ast_channel_unlock(chan);
850 }
851 
852 static void destroy_msg_q_chan(void *data)
853 {
854  struct ast_channel **chan = data;
855 
856  if (!*chan) {
857  return;
858  }
859 
860  ast_channel_release(*chan);
861 }
862 
863 AST_THREADSTORAGE_CUSTOM(msg_q_chan, NULL, destroy_msg_q_chan);
864 
865 /*! \internal \brief Handle a message bound for the dialplan */
866 static int dialplan_handle_msg_cb(struct ast_msg *msg)
867 {
868  struct ast_channel **chan_p, *chan;
869  struct ast_datastore *ds;
870 
871  if (!(chan_p = ast_threadstorage_get(&msg_q_chan, sizeof(struct ast_channel *)))) {
872  return -1;
873  }
874  if (!*chan_p) {
875  if (!(*chan_p = create_msg_q_chan())) {
876  return -1;
877  }
878  }
879  chan = *chan_p;
880 
881  ast_channel_lock(chan);
882  if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
883  ast_channel_unlock(chan);
884  return -1;
885  }
886  ao2_ref(msg, +1);
887  ds->data = msg;
888  ast_channel_unlock(chan);
889 
890  msg_route(chan, msg);
891  chan_cleanup(chan);
892 
893  return 0;
894 }
895 
896 /*! \internal \brief Determine if a message has a destination in the dialplan */
897 static int dialplan_has_destination_cb(const struct ast_msg *msg)
898 {
899  if (ast_strlen_zero(msg->context)) {
900  return 0;
901  }
902 
903  return ast_exists_extension(NULL, msg->context, S_OR(msg->exten, "s"), 1, NULL);
904 }
905 
906 static struct ast_msg_handler dialplan_msg_handler = {
907  .name = "dialplan",
908  .handle_msg = dialplan_handle_msg_cb,
909  .has_destination = dialplan_has_destination_cb,
910 };
911 
912 /*!
913  * \internal
914  * \brief Message queue task processor callback
915  *
916  * \retval 0 success
917  * \retval non-zero failure
918  *
919  * \note Even though this returns a value, the taskprocessor code ignores the value.
920  */
921 static int msg_q_cb(void *data)
922 {
923  struct ast_msg *msg = data;
924  int res = 1;
925  int i;
926 
927  ast_rwlock_rdlock(&msg_handlers_lock);
928  for (i = 0; i < AST_VECTOR_SIZE(&msg_handlers); i++) {
929  const struct ast_msg_handler *handler = AST_VECTOR_GET(&msg_handlers, i);
930 
931  if (!handler->has_destination(msg)) {
932  ast_debug(5, "Handler %s doesn't want message, moving on\n", handler->name);
933  continue;
934  }
935 
936  ast_debug(5, "Dispatching message to %s handler\n", handler->name);
937  res &= handler->handle_msg(msg);
938  }
939  ast_rwlock_unlock(&msg_handlers_lock);
940 
941  if (res != 0) {
942  ast_log(LOG_WARNING, "No handler processed message from %s to %s\n",
943  S_OR(msg->from, "<unknown>"), S_OR(msg->to, "<unknown>"));
944  }
945 
946  ao2_ref(msg, -1);
947 
948  return res;
949 }
950 
951 int ast_msg_has_destination(const struct ast_msg *msg)
952 {
953  int i;
954  int result = 0;
955 
956  ast_rwlock_rdlock(&msg_handlers_lock);
957  for (i = 0; i < AST_VECTOR_SIZE(&msg_handlers); i++) {
958  const struct ast_msg_handler *handler = AST_VECTOR_GET(&msg_handlers, i);
959 
960  ast_debug(5, "Seeing if %s can handle message\n", handler->name);
961  if (handler->has_destination(msg)) {
962  ast_debug(5, "%s can handle message\n", handler->name);
963  result = 1;
964  break;
965  }
966  }
967  ast_rwlock_unlock(&msg_handlers_lock);
968 
969  return result;
970 }
971 
972 int ast_msg_queue(struct ast_msg *msg)
973 {
974  int res;
975  res = ast_taskprocessor_push(msg_q_tp, msg_q_cb, msg);
976  if (res == -1) {
977  ao2_ref(msg, -1);
978  }
979 
980  return res;
981 }
982 
983 /*!
984  * \internal
985  * \brief Find or create a message datastore on a channel
986  *
987  * \pre chan is locked
988  *
989  * \param chan the relevant channel
990  *
991  * \return the channel's message datastore
992  * \retval NULL on error
993  */
994 static struct ast_datastore *msg_datastore_find_or_create(struct ast_channel *chan)
995 {
996  struct ast_datastore *ds;
997 
998  if ((ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
999  return ds;
1000  }
1001 
1002  if (!(ds = ast_datastore_alloc(&msg_datastore, NULL))) {
1003  return NULL;
1004  }
1005 
1006  if (!(ds->data = ast_msg_alloc())) {
1007  ast_datastore_free(ds);
1008  return NULL;
1009  }
1010 
1011  ast_channel_datastore_add(chan, ds);
1012 
1013  return ds;
1014 }
1015 
1016 static int msg_func_read(struct ast_channel *chan, const char *function,
1017  char *data, char *buf, size_t len)
1018 {
1019  struct ast_datastore *ds;
1020  struct ast_msg *msg;
1021 
1022  if (!chan) {
1023  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
1024  return -1;
1025  }
1026 
1027  ast_channel_lock(chan);
1028 
1029  if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
1030  ast_channel_unlock(chan);
1031  ast_log(LOG_ERROR, "No MESSAGE data found on the channel to read.\n");
1032  return -1;
1033  }
1034 
1035  msg = ds->data;
1036  ao2_ref(msg, +1);
1037  ast_channel_unlock(chan);
1038 
1039  ao2_lock(msg);
1040 
1041  if (!strcasecmp(data, "to")) {
1042  ast_copy_string(buf, msg->to, len);
1043  } else if (!strcasecmp(data, "from")) {
1044  ast_copy_string(buf, msg->from, len);
1045  } else if (!strcasecmp(data, "body")) {
1046  ast_copy_string(buf, msg->body, len);
1047  } else {
1048  ast_log(LOG_WARNING, "Invalid argument to MESSAGE(): '%s'\n", data);
1049  }
1050 
1051  ao2_unlock(msg);
1052  ao2_ref(msg, -1);
1053 
1054  return 0;
1055 }
1056 
1057 static int msg_func_write(struct ast_channel *chan, const char *function,
1058  char *data, const char *value)
1059 {
1060  struct ast_datastore *ds;
1061  struct ast_msg *msg;
1062 
1063  if (!chan) {
1064  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
1065  return -1;
1066  }
1067 
1068  ast_channel_lock(chan);
1069 
1070  if (!(ds = msg_datastore_find_or_create(chan))) {
1071  ast_channel_unlock(chan);
1072  return -1;
1073  }
1074 
1075  msg = ds->data;
1076  ao2_ref(msg, +1);
1077  ast_channel_unlock(chan);
1078 
1079  ao2_lock(msg);
1080 
1081  if (!strcasecmp(data, "to")) {
1082  ast_msg_set_to(msg, "%s", value);
1083  } else if (!strcasecmp(data, "from")) {
1084  ast_msg_set_from(msg, "%s", value);
1085  } else if (!strcasecmp(data, "body")) {
1086  ast_msg_set_body(msg, "%s", value);
1087  } else if (!strcasecmp(data, "custom_data")) {
1088  int outbound = -1;
1089  if (!strcasecmp(value, "mark_all_outbound")) {
1090  outbound = 1;
1091  } else if (!strcasecmp(value, "clear_all_outbound")) {
1092  outbound = 0;
1093  } else {
1094  ast_log(LOG_WARNING, "'%s' is not a valid value for custom_data\n", value);
1095  }
1096 
1097  if (outbound != -1) {
1098  struct msg_data *hdr_data;
1099  struct ao2_iterator iter = ao2_iterator_init(msg->vars, 0);
1100 
1101  while ((hdr_data = ao2_iterator_next(&iter))) {
1102  hdr_data->send = outbound;
1103  ao2_ref(hdr_data, -1);
1104  }
1105  ao2_iterator_destroy(&iter);
1106  }
1107  } else {
1108  ast_log(LOG_WARNING, "'%s' is not a valid write argument.\n", data);
1109  }
1110 
1111  ao2_unlock(msg);
1112  ao2_ref(msg, -1);
1113 
1114  return 0;
1115 }
1116 
1117 static int msg_data_func_read(struct ast_channel *chan, const char *function,
1118  char *data, char *buf, size_t len)
1119 {
1120  struct ast_datastore *ds;
1121  struct ast_msg *msg;
1122  const char *val;
1123 
1124  if (!chan) {
1125  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
1126  return -1;
1127  }
1128 
1129  ast_channel_lock(chan);
1130 
1131  if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
1132  ast_channel_unlock(chan);
1133  ast_log(LOG_ERROR, "No MESSAGE data found on the channel to read.\n");
1134  return -1;
1135  }
1136 
1137  msg = ds->data;
1138  ao2_ref(msg, +1);
1139  ast_channel_unlock(chan);
1140 
1141  ao2_lock(msg);
1142 
1143  if ((val = ast_msg_get_var(msg, data))) {
1144  ast_copy_string(buf, val, len);
1145  }
1146 
1147  ao2_unlock(msg);
1148  ao2_ref(msg, -1);
1149 
1150  return 0;
1151 }
1152 
1153 static int msg_data_func_write(struct ast_channel *chan, const char *function,
1154  char *data, const char *value)
1155 {
1156  struct ast_datastore *ds;
1157  struct ast_msg *msg;
1158 
1159  if (!chan) {
1160  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
1161  return -1;
1162  }
1163 
1164  ast_channel_lock(chan);
1165 
1166  if (!(ds = msg_datastore_find_or_create(chan))) {
1167  ast_channel_unlock(chan);
1168  return -1;
1169  }
1170 
1171  msg = ds->data;
1172  ao2_ref(msg, +1);
1173  ast_channel_unlock(chan);
1174 
1175  ao2_lock(msg);
1176 
1177  ast_msg_set_var_outbound(msg, data, value);
1178 
1179  ao2_unlock(msg);
1180  ao2_ref(msg, -1);
1181 
1182  return 0;
1183 }
1184 
1185 /*!
1186  * \internal \brief Find a \c ast_msg_tech by its technology name
1187  *
1188  * \param tech_name The name of the message technology
1189  *
1190  * \note \c msg_techs should be locked via \c msg_techs_lock prior to
1191  * calling this function
1192  *
1193  * \retval NULL if no \ref ast_msg_tech has been registered
1194  * \return \ref ast_msg_tech if registered
1195  */
1196 static const struct ast_msg_tech *msg_find_by_tech_name(const char *tech_name)
1197 {
1198  const struct ast_msg_tech *current;
1199  int i;
1200 
1201  for (i = 0; i < AST_VECTOR_SIZE(&msg_techs); i++) {
1202  current = AST_VECTOR_GET(&msg_techs, i);
1203  if (!strcmp(current->name, tech_name)) {
1204  return current;
1205  }
1206  }
1207 
1208  return NULL;
1209 }
1210 
1211 /*!
1212  * \internal \brief Find a \c ast_msg_handler by its technology name
1213  *
1214  * \param tech_name The name of the message technology
1215  *
1216  * \note \c msg_handlers should be locked via \c msg_handlers_lock
1217  * prior to calling this function
1218  *
1219  * \retval NULL if no \ref ast_msg_handler has been registered
1220  * \return \ref ast_msg_handler if registered
1221  */
1222 static const struct ast_msg_handler *msg_handler_find_by_tech_name(const char *tech_name)
1223 {
1224  const struct ast_msg_handler *current;
1225  int i;
1226 
1227  for (i = 0; i < AST_VECTOR_SIZE(&msg_handlers); i++) {
1228  current = AST_VECTOR_GET(&msg_handlers, i);
1229  if (!strcmp(current->name, tech_name)) {
1230  return current;
1231  }
1232  }
1233 
1234  return NULL;
1235 }
1236 
1237 /*!
1238  * \internal
1239  * \brief MessageSend() application
1240  */
1241 static int msg_send_exec(struct ast_channel *chan, const char *data)
1242 {
1243  struct ast_datastore *ds;
1244  struct ast_msg *msg;
1245  char *tech_name;
1246  const struct ast_msg_tech *msg_tech;
1247  char *parse;
1248  int res = -1;
1249  AST_DECLARE_APP_ARGS(args,
1250  AST_APP_ARG(destination);
1251  AST_APP_ARG(from);
1252  AST_APP_ARG(to);
1253  );
1254 
1255  if (ast_strlen_zero(data)) {
1256  ast_log(LOG_WARNING, "An argument is required to MessageSend()\n");
1257  pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_URI");
1258  return 0;
1259  }
1260 
1261  parse = ast_strdupa(data);
1262  AST_STANDARD_APP_ARGS(args, parse);
1263 
1264  if (ast_strlen_zero(args.destination)) {
1265  ast_log(LOG_WARNING, "A 'to' URI is required for MessageSend()\n");
1266  pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_URI");
1267  return 0;
1268  }
1269 
1270  ast_channel_lock(chan);
1271 
1272  if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
1273  ast_channel_unlock(chan);
1274  ast_log(LOG_WARNING, "No message data found on channel to send.\n");
1275  pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "FAILURE");
1276  return 0;
1277  }
1278 
1279  msg = ds->data;
1280  ao2_ref(msg, +1);
1281  ast_channel_unlock(chan);
1282 
1283  tech_name = ast_strdupa(args.destination);
1284  tech_name = strsep(&tech_name, ":");
1285 
1286  ast_rwlock_rdlock(&msg_techs_lock);
1287  msg_tech = msg_find_by_tech_name(tech_name);
1288 
1289  if (!msg_tech) {
1290  ast_log(LOG_WARNING, "No message technology '%s' found.\n", tech_name);
1291  pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_PROTOCOL");
1292  goto exit_cleanup;
1293  }
1294 
1295  /*
1296  * If there was a "to" in the call to MessageSend,
1297  * replace the to already in the channel datastore.
1298  */
1299  if (!ast_strlen_zero(args.to)) {
1300  ast_string_field_set(msg, to, args.to);
1301  }
1302 
1303  /*
1304  * The message lock is held here to safely allow the technology
1305  * implementation to access the message fields without worrying
1306  * that they could change.
1307  */
1308  ao2_lock(msg);
1309  res = msg_tech->msg_send(msg, S_OR(args.destination, ""), S_OR(args.from, ""));
1310  ao2_unlock(msg);
1311 
1312  pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", res ? "FAILURE" : "SUCCESS");
1313 
1314 exit_cleanup:
1315  ast_rwlock_unlock(&msg_techs_lock);
1316  ao2_ref(msg, -1);
1317 
1318  return 0;
1319 }
1320 
1321 static int action_messagesend(struct mansession *s, const struct message *m)
1322 {
1323  const char *destination = astman_get_header(m, "Destination");
1324  const char *to = astman_get_header(m, "To");
1325  const char *from = astman_get_header(m, "From");
1326  const char *body = astman_get_header(m, "Body");
1327  const char *base64body = astman_get_header(m, "Base64Body");
1328  const char *to_override = NULL;
1329  char base64decoded[1301] = { 0, };
1330  char *tech_name = NULL;
1331  struct ast_variable *vars = NULL;
1332  struct ast_variable *data = NULL;
1333  const struct ast_msg_tech *msg_tech;
1334  struct ast_msg *msg;
1335  int res = -1;
1336 
1337  if (!ast_strlen_zero(destination)) {
1338  if (!ast_strlen_zero(to)) {
1339  to_override = to;
1340  }
1341  to = destination;
1342  } else {
1343  if (ast_strlen_zero(to)) {
1344  astman_send_error(s, m, "No 'To' address specified.");
1345  return 0;
1346  }
1347  }
1348 
1349  if (!ast_strlen_zero(base64body)) {
1350  ast_base64decode((unsigned char *) base64decoded, base64body, sizeof(base64decoded) - 1);
1351  body = base64decoded;
1352  }
1353 
1354  tech_name = ast_strdupa(to);
1355  tech_name = strsep(&tech_name, ":");
1356 
1357  ast_rwlock_rdlock(&msg_techs_lock);
1358  msg_tech = msg_find_by_tech_name(tech_name);
1359  if (!msg_tech) {
1360  ast_rwlock_unlock(&msg_techs_lock);
1361  astman_send_error(s, m, "Message technology not found.");
1362  return 0;
1363  }
1364 
1365  if (!(msg = ast_msg_alloc())) {
1366  ast_rwlock_unlock(&msg_techs_lock);
1367  astman_send_error(s, m, "Internal failure\n");
1368  return 0;
1369  }
1370 
1371  data = astman_get_variables_order(m, ORDER_NATURAL);
1372  for (vars = data; vars; vars = vars->next) {
1373  ast_msg_set_var_outbound(msg, vars->name, vars->value);
1374  }
1375 
1376  ast_msg_set_body(msg, "%s", body);
1377 
1378  if (to_override) {
1379  ast_string_field_set(msg, to, to_override);
1380  }
1381 
1382  res = msg_tech->msg_send(msg, S_OR(to, ""), S_OR(from, ""));
1383 
1384  ast_rwlock_unlock(&msg_techs_lock);
1385 
1386  ast_variables_destroy(vars);
1387  ao2_ref(msg, -1);
1388 
1389  if (res) {
1390  astman_send_error(s, m, "Message failed to send.");
1391  } else {
1392  astman_send_ack(s, m, "Message successfully sent");
1393  }
1394  return 0;
1395 }
1396 
1397 int ast_msg_send(struct ast_msg *msg, const char *to, const char *from)
1398 {
1399  char *tech_name = NULL;
1400  const struct ast_msg_tech *msg_tech;
1401  int res = -1;
1402 
1403  if (ast_strlen_zero(to)) {
1404  ao2_ref(msg, -1);
1405  return -1;
1406  }
1407 
1408  tech_name = ast_strdupa(to);
1409  tech_name = strsep(&tech_name, ":");
1410 
1411  ast_rwlock_rdlock(&msg_techs_lock);
1412  msg_tech = msg_find_by_tech_name(tech_name);
1413 
1414  if (!msg_tech) {
1415  ast_log(LOG_ERROR, "Unknown message tech: %s\n", tech_name);
1416  ast_rwlock_unlock(&msg_techs_lock);
1417  return -1;
1418  }
1419 
1420  res = msg_tech->msg_send(msg, S_OR(to, ""), S_OR(from, ""));
1421 
1422  ast_rwlock_unlock(&msg_techs_lock);
1423 
1424  ao2_ref(msg, -1);
1425 
1426  return res;
1427 }
1428 
1429 /*!
1430  * \brief Structure used to transport a message through the frame core
1431  * \since 13.22.0
1432  * \since 15.5.0
1433  */
1435  /*! The length of this structure plus the actual length of the allocated buffer */
1436  size_t length;
1437  enum ast_msg_data_source_type source;
1438  /*! These are indices into the buffer where teh attribute starts */
1439  int attribute_value_offsets[__AST_MSG_DATA_ATTR_LAST];
1440  /*! The buffer containing the NULL separated attributes */
1441  char buf[0];
1442 };
1443 
1444 #define ATTRIBUTE_UNSET -1
1445 
1446 struct ast_msg_data *ast_msg_data_alloc(enum ast_msg_data_source_type source,
1447  struct ast_msg_data_attribute attributes[], size_t count)
1448 {
1449  struct ast_msg_data *msg;
1450  size_t len = sizeof(*msg);
1451  size_t i;
1452  size_t current_offset = 0;
1453  enum ast_msg_data_attribute_type attr_type;
1454 
1455  if (!attributes) {
1456  ast_assert(attributes != NULL);
1457  return NULL;
1458  }
1459 
1460  if (!count) {
1461  ast_assert(count > 0);
1462  return NULL;
1463  }
1464 
1465  /* Calculate the length required for the buffer */
1466  for (i=0; i < count; i++) {
1467  if (!attributes[i].value) {
1468  ast_assert(attributes[i].value != NULL);
1469  return NULL;
1470  }
1471  len += (strlen(attributes[i].value) + 1);
1472  }
1473 
1474  msg = ast_calloc(1, len);
1475  if (!msg) {
1476  return NULL;
1477  }
1478  msg->source = source;
1479  msg->length = len;
1480 
1481  /* Mark all of the attributes as unset */
1482  for (attr_type = 0; attr_type < __AST_MSG_DATA_ATTR_LAST; attr_type++) {
1483  msg->attribute_value_offsets[attr_type] = ATTRIBUTE_UNSET;
1484  }
1485 
1486  /* Set the ones we have and increment the offset */
1487  for (i=0; i < count; i++) {
1488  len = (strlen(attributes[i].value) + 1);
1489  ast_copy_string(msg->buf + current_offset, attributes[i].value, len); /* Safe */
1490  msg->attribute_value_offsets[attributes[i].type] = current_offset;
1491  current_offset += len;
1492  }
1493 
1494  return msg;
1495 }
1496 
1497 struct ast_msg_data *ast_msg_data_alloc2(enum ast_msg_data_source_type source_type,
1498  const char *to, const char *from, const char *content_type, const char *body)
1499 {
1500  struct ast_msg_data_attribute attrs[] =
1501  {
1502  {
1503  .type = AST_MSG_DATA_ATTR_TO,
1504  .value = (char *)S_OR(to, ""),
1505  },
1506  {
1507  .type = AST_MSG_DATA_ATTR_FROM,
1508  .value = (char *)S_OR(from, ""),
1509  },
1510  {
1511  .type = AST_MSG_DATA_ATTR_CONTENT_TYPE,
1512  .value = (char *)S_OR(content_type, ""),
1513  },
1514  {
1515  .type = AST_MSG_DATA_ATTR_BODY,
1516  .value = (char *)S_OR(body, ""),
1517  },
1518  };
1519 
1520  return ast_msg_data_alloc(source_type, attrs, ARRAY_LEN(attrs));
1521 }
1522 
1524 {
1525  struct ast_msg_data *dest;
1526 
1527  if (!msg) {
1528  ast_assert(msg != NULL);
1529  return NULL;
1530  }
1531 
1532  dest = ast_malloc(msg->length);
1533  if (!dest) {
1534  return NULL;
1535  }
1536  memcpy(dest, msg, msg->length);
1537 
1538  return dest;
1539 }
1540 
1542 {
1543  if (!msg) {
1544  ast_assert(msg != NULL);
1545  return 0;
1546  }
1547 
1548  return msg->length;
1549 }
1550 
1551 enum ast_msg_data_source_type ast_msg_data_get_source_type(struct ast_msg_data *msg)
1552 {
1553  if (!msg) {
1554  ast_assert(msg != NULL);
1555  return AST_MSG_DATA_SOURCE_TYPE_UNKNOWN;
1556  }
1557 
1558  return msg->source;
1559 }
1560 
1562  enum ast_msg_data_attribute_type attribute_type)
1563 {
1564  if (!msg) {
1565  ast_assert(msg != NULL);
1566  return "";
1567  }
1568 
1569  if (msg->attribute_value_offsets[attribute_type] > ATTRIBUTE_UNSET) {
1570  return msg->buf + msg->attribute_value_offsets[attribute_type];
1571  }
1572 
1573  return "";
1574 }
1575 
1576 int ast_msg_data_queue_frame(struct ast_channel *channel, struct ast_msg_data *msg)
1577 {
1578  struct ast_frame f;
1579 
1580  if (!channel) {
1581  ast_assert(channel != NULL);
1582  return -1;
1583  }
1584 
1585  if (!msg) {
1586  ast_assert(msg != NULL);
1587  return -1;
1588  }
1589 
1590  memset(&f, 0, sizeof(f));
1592  f.data.ptr = msg;
1593  f.datalen = msg->length;
1594  return ast_queue_frame(channel, &f);
1595 }
1596 
1597 int ast_msg_tech_register(const struct ast_msg_tech *tech)
1598 {
1599  const struct ast_msg_tech *match;
1600 
1601  ast_rwlock_wrlock(&msg_techs_lock);
1602 
1603  match = msg_find_by_tech_name(tech->name);
1604  if (match) {
1605  ast_log(LOG_ERROR, "Message technology already registered for '%s'\n",
1606  tech->name);
1607  ast_rwlock_unlock(&msg_techs_lock);
1608  return -1;
1609  }
1610 
1611  if (AST_VECTOR_APPEND(&msg_techs, tech)) {
1612  ast_log(LOG_ERROR, "Failed to register message technology for '%s'\n",
1613  tech->name);
1614  ast_rwlock_unlock(&msg_techs_lock);
1615  return -1;
1616  }
1617  ast_verb(5, "Message technology '%s' registered.\n", tech->name);
1618 
1619  ast_rwlock_unlock(&msg_techs_lock);
1620 
1621  return 0;
1622 }
1623 
1624 /*!
1625  * \brief Comparison callback for \c ast_msg_tech vector removal
1626  *
1627  * \param vec_elem The element in the vector being compared
1628  * \param srch The element being looked up
1629  *
1630  * \retval non-zero The items are equal
1631  * \retval 0 The items are not equal
1632  */
1633 static int msg_tech_cmp(const struct ast_msg_tech *vec_elem, const struct ast_msg_tech *srch)
1634 {
1635  return !strcmp(vec_elem->name, srch->name);
1636 }
1637 
1638 int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
1639 {
1640  int match;
1641 
1642  ast_rwlock_wrlock(&msg_techs_lock);
1645  ast_rwlock_unlock(&msg_techs_lock);
1646 
1647  if (match) {
1648  ast_log(LOG_ERROR, "No '%s' message technology found.\n", tech->name);
1649  return -1;
1650  }
1651 
1652  ast_verb(5, "Message technology '%s' unregistered.\n", tech->name);
1653 
1654  return 0;
1655 }
1656 
1657 int ast_msg_handler_register(const struct ast_msg_handler *handler)
1658 {
1659  const struct ast_msg_handler *match;
1660 
1661  ast_rwlock_wrlock(&msg_handlers_lock);
1662 
1663  match = msg_handler_find_by_tech_name(handler->name);
1664  if (match) {
1665  ast_log(LOG_ERROR, "Message handler already registered for '%s'\n",
1666  handler->name);
1667  ast_rwlock_unlock(&msg_handlers_lock);
1668  return -1;
1669  }
1670 
1671  if (AST_VECTOR_APPEND(&msg_handlers, handler)) {
1672  ast_log(LOG_ERROR, "Failed to register message handler for '%s'\n",
1673  handler->name);
1674  ast_rwlock_unlock(&msg_handlers_lock);
1675  return -1;
1676  }
1677  ast_verb(5, "Message handler '%s' registered.\n", handler->name);
1678 
1679  ast_rwlock_unlock(&msg_handlers_lock);
1680 
1681  return 0;
1682 
1683 }
1684 
1685 /*!
1686  * \brief Comparison callback for \c ast_msg_handler vector removal
1687  *
1688  * \param vec_elem The element in the vector being compared
1689  * \param srch The element being looked up
1690  *
1691  * \retval non-zero The items are equal
1692  * \retval 0 The items are not equal
1693  */
1694 static int msg_handler_cmp(const struct ast_msg_handler *vec_elem, const struct ast_msg_handler *srch)
1695 {
1696  return !strcmp(vec_elem->name, srch->name);
1697 }
1698 
1700 {
1701  int match;
1702 
1703  ast_rwlock_wrlock(&msg_handlers_lock);
1706  ast_rwlock_unlock(&msg_handlers_lock);
1707 
1708  if (match) {
1709  ast_log(LOG_ERROR, "No '%s' message handler found.\n", handler->name);
1710  return -1;
1711  }
1712 
1713  ast_verb(5, "Message handler '%s' unregistered.\n", handler->name);
1714  return 0;
1715 }
1716 
1718 {
1719  if (msg_q_tp) {
1720  msg_q_tp = ast_taskprocessor_unreference(msg_q_tp);
1721  }
1722 }
1723 
1724 /*!
1725  * \internal
1726  * \brief Clean up other resources on Asterisk shutdown
1727  *
1728  * \note This does not include the msg_q_tp object, which must be disposed
1729  * of prior to Asterisk checking for channel destruction in its shutdown
1730  * sequence. The atexit handlers are executed after this occurs.
1731  */
1732 static void message_shutdown(void)
1733 {
1734  ast_msg_handler_unregister(&dialplan_msg_handler);
1735 
1736  ast_custom_function_unregister(&msg_function);
1737  ast_custom_function_unregister(&msg_data_function);
1738  ast_unregister_application(app_msg_send);
1739  ast_manager_unregister("MessageSend");
1740 
1742  ast_rwlock_destroy(&msg_techs_lock);
1743 
1745  ast_rwlock_destroy(&msg_handlers_lock);
1746 }
1747 
1748 /*!
1749  * \internal
1750  * \brief Initialize stuff during Asterisk startup.
1751  *
1752  * Cleanup isn't a big deal in this function. If we return non-zero,
1753  * Asterisk is going to exit.
1754  *
1755  * \retval 0 success
1756  * \retval non-zero failure
1757  */
1758 int ast_msg_init(void)
1759 {
1760  int res;
1761 
1762  msg_q_tp = ast_taskprocessor_get("ast_msg_queue", TPS_REF_DEFAULT);
1763  if (!msg_q_tp) {
1764  return -1;
1765  }
1766 
1767  ast_rwlock_init(&msg_techs_lock);
1768  if (AST_VECTOR_INIT(&msg_techs, 8)) {
1769  return -1;
1770  }
1771 
1773  if (AST_VECTOR_INIT(&msg_handlers, 4)) {
1774  return -1;
1775  }
1776 
1777  res = ast_msg_handler_register(&dialplan_msg_handler);
1778 
1779  res |= __ast_custom_function_register(&msg_function, NULL);
1780  res |= __ast_custom_function_register(&msg_data_function, NULL);
1781  res |= ast_register_application2(app_msg_send, msg_send_exec, NULL, NULL, NULL);
1782  res |= ast_manager_register_xml_core("MessageSend", EVENT_FLAG_MESSAGE, action_messagesend);
1783 
1784  ast_register_cleanup(message_shutdown);
1785 
1786  return res;
1787 }
const char * name
Definition: pbx.h:119
size_t ast_msg_data_get_length(struct ast_msg_data *msg)
Get length of the structure.
const char * type
Definition: datastore.h:32
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
struct ast_variable * next
int ast_msg_set_exten(struct ast_msg *msg, const char *fmt,...)
Set the dialplan extension for this message.
Definition: main/message.c:512
Options for ast_pbx_run()
Definition: pbx.h:407
Main Channel structure associated with a channel.
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:971
Asterisk main include file. File version handling, generic pbx functions.
enum ast_msg_data_source_type ast_msg_data_get_source_type(struct ast_msg_data *msg)
Get "source type" from ast_msg_data.
struct ast_msg_var_iterator * ast_msg_var_iterator_init(const struct ast_msg *msg)
Create a new message variable iterator.
Definition: main/message.c:658
struct ast_msg * ast_msg_ref(struct ast_msg *msg)
Bump a msg's ref count.
Definition: main/message.c:456
void ast_msg_var_unref_current(struct ast_msg_var_iterator *iter)
Unref a message var from inside an iterator loop.
Definition: main/message.c:714
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
int(*const handle_msg)(struct ast_msg *msg)
The function callback that will handle the message.
Definition: message.h:112
void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *iter)
Destroy a message variable iterator.
Definition: main/message.c:720
String manipulation functions.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
struct ast_msg_data * ast_msg_data_dup(struct ast_msg_data *msg)
Clone an ast_msg_data structure.
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison.
Definition: vector.h:488
int ast_msg_tech_register(const struct ast_msg_tech *tech)
Register a message technology.
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
Definition: main/message.c:462
An external processor of received messages.
Definition: message.h:98
const char * ast_msg_get_to(const struct ast_msg *msg)
Retrieve the destination of this message.
Definition: main/message.c:555
#define OBJ_POINTER
Definition: astobj2.h:1150
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
Definition: channel.c:1584
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:224
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary...
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
const ast_string_field to
Definition: main/message.c:263
Structure for variables, used for configurations and for channel variables.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
return a reference to a taskprocessor, create one if it does not exist
Definition: taskprocessor.h:76
struct @378 msg_handlers
Vector of received message handlers.
const char *const name
Name of this message technology.
Definition: message.h:61
Structure for a data store type.
Definition: datastore.h:31
Structure used to transport a message through the frame core.
int ast_msg_set_var_outbound(struct ast_msg *msg, const char *name, const char *value)
Set a variable on the message being sent to a message tech directly.
Definition: main/message.c:624
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
Definition: main/message.c:972
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
const ast_string_field endpoint
Definition: main/message.c:263
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:341
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6945
int ast_msg_var_iterator_next(const struct ast_msg *msg, struct ast_msg_var_iterator *iter, const char **name, const char **value)
Get the next variable name and value that is set for sending outbound.
Definition: main/message.c:703
static ast_rwlock_t msg_techs_lock
Lock for msg_techs vector.
Definition: main/message.c:269
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3421
struct ast_msg_data * ast_msg_data_alloc(enum ast_msg_data_source_type source, struct ast_msg_data_attribute attributes[], size_t count)
Allocates an ast_msg_data structure.
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the 'to' URI of a message.
Definition: main/message.c:468
Structure for a data store object.
Definition: datastore.h:64
int ast_msg_set_from(struct ast_msg *msg, const char *fmt,...)
Set the 'from' URI of a message.
Definition: main/message.c:479
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
const char * data
int(*const has_destination)(const struct ast_msg *msg)
Return whether or not the message has a valid destination.
Definition: message.h:127
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:202
Out-of-call text message support.
int ast_msg_handler_unregister(const struct ast_msg_handler *handler)
Unregister a ast_msg_handler.
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
const ast_string_field exten
Definition: main/message.c:263
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3050
static int msg_handler_cmp(const struct ast_msg_handler *vec_elem, const struct ast_msg_handler *srch)
Comparison callback for ast_msg_handler vector removal.
Asterisk datastore objects.
int ast_msg_handler_register(const struct ast_msg_handler *handler)
Register a ast_msg_handler.
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
Definition: utils.c:296
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
struct ao2_container * vars
Definition: main/message.c:265
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2432
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:571
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
Execute the PBX in the current thread.
Definition: pbx.c:4735
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
const ast_string_field body
Definition: main/message.c:263
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:303
struct @377 msg_techs
Vector of message technologies.
const char * ast_msg_get_tech(const struct ast_msg *msg)
Retrieve the technology associated with this message.
Definition: main/message.c:560
In case you didn't read that giant block of text above the mansession_session struct, the 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:1785
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
const char * ast_msg_get_var(struct ast_msg *msg, const char *name)
Get the specified variable on the message.
Definition: main/message.c:634
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:628
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1139
const char * ast_msg_get_endpoint(const struct ast_msg *msg)
Retrieve the endpoint associated with this message.
Definition: main/message.c:565
void ast_msg_shutdown(void)
static int msg_tech_cmp(const struct ast_msg_tech *vec_elem, const struct ast_msg_tech *srch)
Comparison callback for ast_msg_tech vector removal.
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8057
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: linkedlists.h:225
int ast_msg_data_queue_frame(struct ast_channel *channel, struct ast_msg_data *msg)
Queue an AST_FRAME_TEXT_DATA frame containing an ast_msg_data structure.
int ast_msg_init(void)
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
Definition: main/message.c:432
int ast_msg_var_iterator_next_received(const struct ast_msg *msg, struct ast_msg_var_iterator *iter, const char **name, const char **value)
Get the next variable name and value that was set on a received message.
Definition: main/message.c:708
int attribute_value_offsets[__AST_MSG_DATA_ATTR_LAST]
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
const char * ast_msg_get_from(const struct ast_msg *msg)
Retrieve the source of this message.
Definition: main/message.c:550
const char * ast_msg_data_get_attribute(struct ast_msg_data *msg, enum ast_msg_data_attribute_type attribute_type)
Get attribute from ast_msg_data.
A message technology.
Definition: message.h:52
int ast_msg_set_body(struct ast_msg *msg, const char *fmt,...)
Set the 'body' text of a message (in UTF-8)
Definition: main/message.c:490
union ast_frame::@224 data
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology's endpoint associated with this message.
Definition: main/message.c:534
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
const ast_string_field from
Definition: main/message.c:263
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
All softhangup flags.
Definition: channel.h:1161
Prototypes for public functions only of internal interest,.
Vector container support.
An API for managing task processing threads that can be shared across modules.
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology associated with this message.
Definition: main/message.c:523
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
const char * name
Name of the message handler.
Definition: message.h:102
struct ast_frame ast_null_frame
Definition: main/frame.c:79
void * data
Definition: datastore.h:66
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
struct ast_variable * astman_get_variables_order(const struct message *m, enum variable_orders order)
Get a linked list of the Variable: headers with order specified.
Definition: manager.c:3141
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Structure for rwlock and tracking information.
Definition: lock.h:157
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
static ast_rwlock_t msg_handlers_lock
Lock for msg_handlers vector.
Definition: main/message.c:275
struct ast_msg_data * ast_msg_data_alloc2(enum ast_msg_data_source_type source_type, const char *to, const char *from, const char *content_type, const char *body)
Allocates an ast_msg_data structure.
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
Definition: main/message.c:545
Data structure associated with a single frame of data.
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.
int ast_msg_set_context(struct ast_msg *msg, const char *fmt,...)
Set the dialplan context for this message.
Definition: main/message.c:501
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
Definition: pbx_app.c:103
const ast_string_field context
Definition: main/message.c:263
Definition: search.h:40
int ast_msg_set_var(struct ast_msg *msg, const char *name, const char *value)
Set a variable on the message going to the dialplan.
Definition: main/message.c:629
enum ast_frame_type frametype
int(*const msg_send)(const struct ast_msg *msg, const char *to, const char *from)
Send a message.
Definition: message.h:75
Generic container type.
A message.
Definition: main/message.c:247
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1258
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3389
Asterisk module definitions.
int ast_msg_has_destination(const struct ast_msg *msg)
Determine if a particular message has a destination via some handler.
Definition: main/message.c:951
int ast_msg_send(struct ast_msg *msg, const char *to, const char *from)
Send a msg directly to an endpoint.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
const ast_string_field tech
Definition: main/message.c:263
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2394
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
void ast_channel_unlink(struct ast_channel *chan)
Remove a channel from the global channels container.
Definition: channel.c:10529
#define ast_string_field_build_va(x, field, fmt, args)
Set a field to a complex (built) value.
Definition: stringfields.h:591
#define AST_APP_ARG(name)
Define an application argument.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532