Add the ability to specify technology specific documentation
[asterisk/asterisk.git] / main / message.c
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 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/_private.h"
35
36 #include "asterisk/module.h"
37 #include "asterisk/datastore.h"
38 #include "asterisk/pbx.h"
39 #include "asterisk/manager.h"
40 #include "asterisk/strings.h"
41 #include "asterisk/astobj2.h"
42 #include "asterisk/app.h"
43 #include "asterisk/taskprocessor.h"
44 #include "asterisk/message.h"
45
46 /*** DOCUMENTATION
47         <function name="MESSAGE" language="en_US">
48                 <synopsis>
49                         Create a message or read fields from a message.
50                 </synopsis>
51                 <syntax argsep="/">
52                         <parameter name="argument" required="true">
53                         <para>Field of the message to get or set.</para>
54                         <enumlist>
55                                 <enum name="to">
56                                         <para>Read-only.  The destination of the message.  When processing an
57                                         incoming message, this will be set to the destination listed as
58                                         the recipient of the message that was received by Asterisk.</para>
59                                 </enum>
60                                 <enum name="from">
61                                         <para>Read-only.  The source of the message.  When processing an
62                                         incoming message, this will be set to the source of the message.</para>
63                                 </enum>
64                                 <enum name="custom_data">
65                                         <para>Write-only.  Mark or unmark all message headers for an outgoing
66                                         message.  The following values can be set:</para>
67                                         <enumlist>
68                                                 <enum name="mark_all_outbound">
69                                                         <para>Mark all headers for an outgoing message.</para>
70                                                 </enum>
71                                                 <enum name="clear_all_outbound">
72                                                         <para>Unmark all headers for an outgoing message.</para>
73                                                 </enum>
74                                         </enumlist>
75                                 </enum>
76                                 <enum name="body">
77                                         <para>Read/Write.  The message body.  When processing an incoming
78                                         message, this includes the body of the message that Asterisk
79                                         received.  When MessageSend() is executed, the contents of this
80                                         field are used as the body of the outgoing message.  The body
81                                         will always be UTF-8.</para>
82                                 </enum>
83                         </enumlist>
84                         </parameter>
85                 </syntax>
86                 <description>
87                         <para>This function will read from or write a value to a text message.
88                         It is used both to read the data out of an incoming message, as well as
89                         modify or create a message that will be sent outbound.</para>
90                 </description>
91                 <see-also>
92                         <ref type="application">MessageSend</ref>
93                 </see-also>
94         </function>
95         <function name="MESSAGE_DATA" language="en_US">
96                 <synopsis>
97                         Read or write custom data attached to a message.
98                 </synopsis>
99                 <syntax argsep="/">
100                         <parameter name="argument" required="true">
101                         <para>Field of the message to get or set.</para>
102                         </parameter>
103                 </syntax>
104                 <description>
105                         <para>This function will read from or write a value to a text message.
106                         It is used both to read the data out of an incoming message, as well as
107                         modify a message that will be sent outbound.</para>
108                         <note>
109                                 <para>If you want to set an outbound message to carry data in the
110                                 current message, do
111                                 Set(MESSAGE_DATA(<replaceable>key</replaceable>)=${MESSAGE_DATA(<replaceable>key</replaceable>)}).</para>
112                         </note>
113                 </description>
114                 <see-also>
115                         <ref type="application">MessageSend</ref>
116                 </see-also>
117         </function>
118         <application name="MessageSend" language="en_US">
119                 <synopsis>
120                         Send a text message.
121                 </synopsis>
122                 <syntax>
123                         <parameter name="to" required="true">
124                                 <para>A To URI for the message.</para>
125                                 <xi:include xpointer="xpointer(/docs/info[@name='SIPMessageToInfo'])" />
126                                 <xi:include xpointer="xpointer(/docs/info[@name='XMPPMessageToInfo'])" />
127                         </parameter>
128                         <parameter name="from" required="false">
129                                 <para>A From URI for the message if needed for the
130                                 message technology being used to send this message.</para>
131                                 <xi:include xpointer="xpointer(/docs/info[@name='SIPMessageFromInfo'])" />
132                         </parameter>
133                 </syntax>
134                 <description>
135                         <para>Send a text message.  The body of the message that will be
136                         sent is what is currently set to <literal>MESSAGE(body)</literal>.
137                           The technology chosen for sending the message is determined
138                         based on a prefix to the <literal>to</literal> parameter.</para>
139                         <para>This application sets the following channel variables:</para>
140                         <variablelist>
141                                 <variable name="MESSAGE_SEND_STATUS">
142                                         <para>This is the message delivery status returned by this application.</para>
143                                         <value name="INVALID_PROTOCOL">
144                                                 No handler for the technology part of the URI was found.
145                                         </value>
146                                         <value name="INVALID_URI">
147                                                 The protocol handler reported that the URI was not valid.
148                                         </value>
149                                         <value name="SUCCESS">
150                                                 Successfully passed on to the protocol handler, but delivery has not necessarily been guaranteed.
151                                         </value>
152                                         <value name="FAILURE">
153                                                 The protocol handler reported that it was unabled to deliver the message for some reason.
154                                         </value>
155                                 </variable>
156                         </variablelist>
157                 </description>
158         </application>
159         <manager name="MessageSend" language="en_US">
160                 <synopsis>
161                         Send an out of call message to an endpoint.
162                 </synopsis>
163                 <syntax>
164                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
165                         <parameter name="To" required="true">
166                                 <para>The URI the message is to be sent to.</para>
167                                 <xi:include xpointer="xpointer(/docs/info[@name='SIPMessageToInfo'])" />
168                                 <xi:include xpointer="xpointer(/docs/info[@name='XMPPMessageToInfo'])" />
169                         </parameter>
170                         <parameter name="From">
171                                 <para>A From URI for the message if needed for the
172                                 message technology being used to send this message.</para>
173                                 <xi:include xpointer="xpointer(/docs/info[@name='SIPMessageFromInfo'])" />
174                         </parameter>
175                         <parameter name="Body">
176                                 <para>The message body text.  This must not contain any newlines as that
177                                 conflicts with the AMI protocol.</para>
178                         </parameter>
179                         <parameter name="Base64Body">
180                                 <para>Text bodies requiring the use of newlines have to be base64 encoded
181                                 in this field.  Base64Body will be decoded before being sent out.
182                                 Base64Body takes precedence over Body.</para>
183                         </parameter>
184                         <parameter name="Variable">
185                                 <para>Message variable to set, multiple Variable: headers are
186                                 allowed.  The header value is a comma separated list of
187                                 name=value pairs.</para>
188                         </parameter>
189                 </syntax>
190         </manager>
191  ***/
192
193 struct msg_data {
194         AST_DECLARE_STRING_FIELDS(
195                 AST_STRING_FIELD(name);
196                 AST_STRING_FIELD(value);
197         );
198         unsigned int send:1; /* Whether to send out on outbound messages */
199 };
200
201 AST_LIST_HEAD_NOLOCK(outhead, msg_data);
202
203 /*!
204  * \brief A message.
205  *
206  * \todo Consider whether stringfields would be an appropriate optimization here.
207  */
208 struct ast_msg {
209         struct ast_str *to;
210         struct ast_str *from;
211         struct ast_str *body;
212         struct ast_str *context;
213         struct ast_str *exten;
214         struct ao2_container *vars;
215 };
216
217 struct ast_msg_tech_holder {
218         const struct ast_msg_tech *tech;
219         /*!
220          * \brief A rwlock for this object
221          *
222          * a read/write lock must be used to protect the wrapper instead
223          * of the ao2 lock. A rdlock must be held to read tech_holder->tech.
224          */
225         ast_rwlock_t tech_lock;
226 };
227
228 static struct ao2_container *msg_techs;
229
230 static struct ast_taskprocessor *msg_q_tp;
231
232 static const char app_msg_send[] = "MessageSend";
233
234 static void msg_ds_destroy(void *data);
235
236 static const struct ast_datastore_info msg_datastore = {
237         .type = "message",
238         .destroy = msg_ds_destroy,
239 };
240
241 static int msg_func_read(struct ast_channel *chan, const char *function,
242                 char *data, char *buf, size_t len);
243 static int msg_func_write(struct ast_channel *chan, const char *function,
244                 char *data, const char *value);
245
246 static struct ast_custom_function msg_function = {
247         .name = "MESSAGE",
248         .read = msg_func_read,
249         .write = msg_func_write,
250 };
251
252 static int msg_data_func_read(struct ast_channel *chan, const char *function,
253                 char *data, char *buf, size_t len);
254 static int msg_data_func_write(struct ast_channel *chan, const char *function,
255                 char *data, const char *value);
256
257 static struct ast_custom_function msg_data_function = {
258         .name = "MESSAGE_DATA",
259         .read = msg_data_func_read,
260         .write = msg_data_func_write,
261 };
262
263 static struct ast_frame *chan_msg_read(struct ast_channel *chan);
264 static int chan_msg_write(struct ast_channel *chan, struct ast_frame *fr);
265 static int chan_msg_indicate(struct ast_channel *chan, int condition,
266                 const void *data, size_t datalen);
267 static int chan_msg_send_digit_begin(struct ast_channel *chan, char digit);
268 static int chan_msg_send_digit_end(struct ast_channel *chan, char digit,
269                 unsigned int duration);
270
271 /*!
272  * \internal
273  * \brief A bare minimum channel technology
274  *
275  * This will not be registered as we never want anything to try
276  * to create Message channels other than internally in this file.
277  */
278 static const struct ast_channel_tech msg_chan_tech_hack = {
279         .type             = "Message",
280         .description      = "Internal Text Message Processing",
281         .read             = chan_msg_read,
282         .write            = chan_msg_write,
283         .indicate         = chan_msg_indicate,
284         .send_digit_begin = chan_msg_send_digit_begin,
285         .send_digit_end   = chan_msg_send_digit_end,
286 };
287
288 /*!
289  * \internal
290  * \brief ast_channel_tech read callback
291  *
292  * This should never be called.  However, we say that about chan_iax2's
293  * read callback, too, and it seems to randomly get called for some
294  * reason.  If it does, a simple NULL frame will suffice.
295  */
296 static struct ast_frame *chan_msg_read(struct ast_channel *chan)
297 {
298         return &ast_null_frame;
299 }
300
301 /*!
302  * \internal
303  * \brief ast_channel_tech write callback
304  *
305  * Throw all frames away.  We don't care about any of them.
306  */
307 static int chan_msg_write(struct ast_channel *chan, struct ast_frame *fr)
308 {
309         return 0;
310 }
311
312 /*!
313  * \internal
314  * \brief ast_channel_tech indicate callback
315  *
316  * The indicate callback is here just so it can return success.
317  * We don't want any callers of ast_indicate() to think something
318  * has failed.  We also don't want ast_indicate() itself to try
319  * to generate inband tones since we didn't tell it that we took
320  * care of it ourselves.
321  */
322 static int chan_msg_indicate(struct ast_channel *chan, int condition,
323                 const void *data, size_t datalen)
324 {
325         return 0;
326 }
327
328 /*!
329  * \internal
330  * \brief ast_channel_tech send_digit_begin callback
331  *
332  * This is here so that just in case a digit comes at a message channel
333  * that the Asterisk core doesn't waste any time trying to generate
334  * inband DTMF in audio.  It's a waste of resources.
335  */
336 static int chan_msg_send_digit_begin(struct ast_channel *chan, char digit)
337 {
338         return 0;
339 }
340
341 /*!
342  * \internal
343  * \brief ast_channel_tech send_digit_end callback
344  *
345  * This is here so that just in case a digit comes at a message channel
346  * that the Asterisk core doesn't waste any time trying to generate
347  * inband DTMF in audio.  It's a waste of resources.
348  */
349 static int chan_msg_send_digit_end(struct ast_channel *chan, char digit,
350                 unsigned int duration)
351 {
352         return 0;
353 }
354
355 static void msg_ds_destroy(void *data)
356 {
357         struct ast_msg *msg = data;
358
359         ao2_ref(msg, -1);
360 }
361
362 static int msg_data_hash_fn(const void *obj, const int flags)
363 {
364         const struct msg_data *data = obj;
365         return ast_str_case_hash(data->name);
366 }
367
368 static int msg_data_cmp_fn(void *obj, void *arg, int flags)
369 {
370         const struct msg_data *one = obj, *two = arg;
371         return !strcasecmp(one->name, two->name) ? CMP_MATCH | CMP_STOP : 0;
372 }
373
374 static void msg_data_destructor(void *obj)
375 {
376         struct msg_data *data = obj;
377         ast_string_field_free_memory(data);
378 }
379
380 static void msg_destructor(void *obj)
381 {
382         struct ast_msg *msg = obj;
383
384         ast_free(msg->to);
385         msg->to = NULL;
386
387         ast_free(msg->from);
388         msg->from = NULL;
389
390         ast_free(msg->body);
391         msg->body = NULL;
392
393         ast_free(msg->context);
394         msg->context = NULL;
395
396         ast_free(msg->exten);
397         msg->exten = NULL;
398
399         ao2_ref(msg->vars, -1);
400 }
401
402 struct ast_msg *ast_msg_alloc(void)
403 {
404         struct ast_msg *msg;
405
406         if (!(msg = ao2_alloc(sizeof(*msg), msg_destructor))) {
407                 return NULL;
408         }
409
410         if (!(msg->to = ast_str_create(32))) {
411                 ao2_ref(msg, -1);
412                 return NULL;
413         }
414
415         if (!(msg->from = ast_str_create(32))) {
416                 ao2_ref(msg, -1);
417                 return NULL;
418         }
419
420         if (!(msg->body = ast_str_create(128))) {
421                 ao2_ref(msg, -1);
422                 return NULL;
423         }
424
425         if (!(msg->context = ast_str_create(16))) {
426                 ao2_ref(msg, -1);
427                 return NULL;
428         }
429
430         if (!(msg->exten = ast_str_create(16))) {
431                 ao2_ref(msg, -1);
432                 return NULL;
433         }
434
435         if (!(msg->vars = ao2_container_alloc(1, msg_data_hash_fn, msg_data_cmp_fn))) {
436                 ao2_ref(msg, -1);
437                 return NULL;
438         }
439
440         ast_str_set(&msg->context, 0, "default");
441
442         return msg;
443 }
444
445 struct ast_msg *ast_msg_ref(struct ast_msg *msg)
446 {
447         ao2_ref(msg, 1);
448         return msg;
449 }
450
451 struct ast_msg *ast_msg_destroy(struct ast_msg *msg)
452 {
453         ao2_ref(msg, -1);
454
455         return NULL;
456 }
457
458 int ast_msg_set_to(struct ast_msg *msg, const char *fmt, ...)
459 {
460         va_list ap;
461         int res;
462
463         va_start(ap, fmt);
464         res = ast_str_set_va(&msg->to, 0, fmt, ap);
465         va_end(ap);
466
467         return res < 0 ? -1 : 0;
468 }
469
470 int ast_msg_set_from(struct ast_msg *msg, const char *fmt, ...)
471 {
472         va_list ap;
473         int res;
474
475         va_start(ap, fmt);
476         res = ast_str_set_va(&msg->from, 0, fmt, ap);
477         va_end(ap);
478
479         return res < 0 ? -1 : 0;
480 }
481
482 int ast_msg_set_body(struct ast_msg *msg, const char *fmt, ...)
483 {
484         va_list ap;
485         int res;
486
487         va_start(ap, fmt);
488         res = ast_str_set_va(&msg->body, 0, fmt, ap);
489         va_end(ap);
490
491         return res < 0 ? -1 : 0;
492 }
493
494 int ast_msg_set_context(struct ast_msg *msg, const char *fmt, ...)
495 {
496         va_list ap;
497         int res;
498
499         va_start(ap, fmt);
500         res = ast_str_set_va(&msg->context, 0, fmt, ap);
501         va_end(ap);
502
503         return res < 0 ? -1 : 0;
504 }
505
506 int ast_msg_set_exten(struct ast_msg *msg, const char *fmt, ...)
507 {
508         va_list ap;
509         int res;
510
511         va_start(ap, fmt);
512         res = ast_str_set_va(&msg->exten, 0, fmt, ap);
513         va_end(ap);
514
515         return res < 0 ? -1 : 0;
516 }
517
518 const char *ast_msg_get_body(const struct ast_msg *msg)
519 {
520         return ast_str_buffer(msg->body);
521 }
522
523 static struct msg_data *msg_data_alloc(void)
524 {
525         struct msg_data *data;
526
527         if (!(data = ao2_alloc(sizeof(*data), msg_data_destructor))) {
528                 return NULL;
529         }
530
531         if (ast_string_field_init(data, 32)) {
532                 ao2_ref(data, -1);
533                 return NULL;
534         }
535
536         return data;
537 }
538
539 static struct msg_data *msg_data_find(struct ao2_container *vars, const char *name)
540 {
541         struct msg_data tmp = {
542                 .name = name,
543         };
544         return ao2_find(vars, &tmp, OBJ_POINTER);
545 }
546
547 static int msg_set_var_full(struct ast_msg *msg, const char *name, const char *value, unsigned int outbound)
548 {
549         struct msg_data *data;
550
551         if (!(data = msg_data_find(msg->vars, name))) {
552                 if (ast_strlen_zero(value)) {
553                         return 0;
554                 }
555                 if (!(data = msg_data_alloc())) {
556                         return -1;
557                 };
558
559                 ast_string_field_set(data, name, name);
560                 ast_string_field_set(data, value, value);
561                 data->send = outbound;
562                 ao2_link(msg->vars, data);
563         } else {
564                 if (ast_strlen_zero(value)) {
565                         ao2_unlink(msg->vars, data);
566                 } else {
567                         ast_string_field_set(data, value, value);
568                         data->send = outbound;
569                 }
570         }
571
572         ao2_ref(data, -1);
573
574         return 0;
575 }
576
577 int ast_msg_set_var_outbound(struct ast_msg *msg, const char *name, const char *value)
578 {
579         return msg_set_var_full(msg, name, value, 1);
580 }
581
582 int ast_msg_set_var(struct ast_msg *msg, const char *name, const char *value)
583 {
584         return msg_set_var_full(msg, name, value, 0);
585 }
586
587 const char *ast_msg_get_var(struct ast_msg *msg, const char *name)
588 {
589         struct msg_data *data;
590         const char *val = NULL;
591
592         if (!(data = msg_data_find(msg->vars, name))) {
593                 return NULL;
594         }
595
596         /* Yep, this definitely looks like val would be a dangling pointer
597          * after the ref count is decremented.  As long as the message structure
598          * is used in a thread safe manner, this will not be the case though.
599          * The ast_msg holds a reference to this object in the msg->vars container. */
600         val = data->value;
601         ao2_ref(data, -1);
602
603         return val;
604 }
605
606 struct ast_msg_var_iterator {
607         struct ao2_iterator i;
608         struct msg_data *current_used;
609 };
610
611 struct ast_msg_var_iterator *ast_msg_var_iterator_init(const struct ast_msg *msg)
612 {
613         struct ast_msg_var_iterator *i;
614         if (!(i = ast_calloc(1, sizeof(*i)))) {
615                 return NULL;
616         }
617
618         i->i = ao2_iterator_init(msg->vars, 0);
619
620         return i;
621 }
622
623 int ast_msg_var_iterator_next(const struct ast_msg *msg, struct ast_msg_var_iterator *i, const char **name, const char **value)
624 {
625         struct msg_data *data;
626
627         /* Skip any that aren't marked for sending out */
628         while ((data = ao2_iterator_next(&i->i)) && !data->send) {
629                 ao2_ref(data, -1);
630         }
631
632         if (!data) {
633                 return 0;
634         }
635
636         if (data->send) {
637                 *name = data->name;
638                 *value = data->value;
639         }
640
641         /* Leave the refcount to be cleaned up by the caller with
642          * ast_msg_var_unref_current after they finish with the pointers to the data */
643         i->current_used = data;
644
645         return 1;
646 }
647
648 void ast_msg_var_unref_current(struct ast_msg_var_iterator *i) {
649         if (i->current_used) {
650                 ao2_ref(i->current_used, -1);
651         }
652         i->current_used = NULL;
653 }
654
655 void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *i)
656 {
657         ao2_iterator_destroy(&i->i);
658         ast_free(i);
659 }
660
661 static struct ast_channel *create_msg_q_chan(void)
662 {
663         struct ast_channel *chan;
664         struct ast_datastore *ds;
665
666         chan = ast_channel_alloc(1, AST_STATE_UP,
667                         NULL, NULL, NULL,
668                         NULL, NULL, NULL, 0,
669                         "%s", "Message/ast_msg_queue");
670
671         if (!chan) {
672                 return NULL;
673         }
674
675         ast_channel_unlink(chan);
676
677         ast_channel_tech_set(chan, &msg_chan_tech_hack);
678
679         if (!(ds = ast_datastore_alloc(&msg_datastore, NULL))) {
680                 ast_hangup(chan);
681                 return NULL;
682         }
683
684         ast_channel_lock(chan);
685         ast_channel_datastore_add(chan, ds);
686         ast_channel_unlock(chan);
687
688         return chan;
689 }
690
691 /*!
692  * \internal
693  * \brief Run the dialplan for message processing
694  *
695  * \pre The message has already been set up on the msg datastore
696  *      on this channel.
697  */
698 static void msg_route(struct ast_channel *chan, struct ast_msg *msg)
699 {
700         struct ast_pbx_args pbx_args;
701
702         ast_explicit_goto(chan, ast_str_buffer(msg->context), AS_OR(msg->exten, "s"), 1);
703
704         memset(&pbx_args, 0, sizeof(pbx_args));
705         pbx_args.no_hangup_chan = 1,
706         ast_pbx_run_args(chan, &pbx_args);
707 }
708
709 /*!
710  * \internal
711  * \brief Clean up ast_channel after each message
712  *
713  * Reset various bits of state after routing each message so the same ast_channel
714  * can just be reused.
715  */
716 static void chan_cleanup(struct ast_channel *chan)
717 {
718         struct ast_datastore *msg_ds, *ds;
719         struct varshead *headp;
720         struct ast_var_t *vardata;
721
722         ast_channel_lock(chan);
723
724         /*
725          * Remove the msg datastore.  Free its data but keep around the datastore
726          * object and just reuse it.
727          */
728         if ((msg_ds = ast_channel_datastore_find(chan, &msg_datastore, NULL)) && msg_ds->data) {
729                 ast_channel_datastore_remove(chan, msg_ds);
730                 ao2_ref(msg_ds->data, -1);
731                 msg_ds->data = NULL;
732         }
733
734         /*
735          * Destroy all other datastores.
736          */
737         while ((ds = AST_LIST_REMOVE_HEAD(ast_channel_datastores(chan), entry))) {
738                 ast_datastore_free(ds);
739         }
740
741         /*
742          * Destroy all channel variables.
743          */
744         headp = ast_channel_varshead(chan);
745         while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
746                 ast_var_delete(vardata);
747         }
748
749         /*
750          * Restore msg datastore.
751          */
752         if (msg_ds) {
753                 ast_channel_datastore_add(chan, msg_ds);
754         }
755
756         ast_channel_unlock(chan);
757 }
758
759 AST_THREADSTORAGE(msg_q_chan);
760
761 /*!
762  * \internal
763  * \brief Message queue task processor callback
764  *
765  * \retval 0 success
766  * \retval -1 failure
767  *
768  * \note Even though this returns a value, the taskprocessor code ignores the value.
769  */
770 static int msg_q_cb(void *data)
771 {
772         struct ast_msg *msg = data;
773         struct ast_channel **chan_p, *chan;
774         struct ast_datastore *ds;
775
776         if (!(chan_p = ast_threadstorage_get(&msg_q_chan, sizeof(struct ast_channel *)))) {
777                 return -1;
778         }
779         if (!*chan_p) {
780                 if (!(*chan_p = create_msg_q_chan())) {
781                         return -1;
782                 }
783         }
784         chan = *chan_p;
785
786         ast_channel_lock(chan);
787         if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
788                 ast_channel_unlock(chan);
789                 return -1;
790         }
791         ao2_ref(msg, +1);
792         ds->data = msg;
793         ast_channel_unlock(chan);
794
795         msg_route(chan, msg);
796         chan_cleanup(chan);
797
798         ao2_ref(msg, -1);
799
800         return 0;
801 }
802
803 int ast_msg_queue(struct ast_msg *msg)
804 {
805         int res;
806
807         res = ast_taskprocessor_push(msg_q_tp, msg_q_cb, msg);
808         if (res == -1) {
809                 ao2_ref(msg, -1);
810         }
811
812         return res;
813 }
814
815 /*!
816  * \internal
817  * \brief Find or create a message datastore on a channel
818  *
819  * \pre chan is locked
820  *
821  * \param chan the relevant channel
822  *
823  * \return the channel's message datastore, or NULL on error
824  */
825 static struct ast_datastore *msg_datastore_find_or_create(struct ast_channel *chan)
826 {
827         struct ast_datastore *ds;
828
829         if ((ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
830                 return ds;
831         }
832
833         if (!(ds = ast_datastore_alloc(&msg_datastore, NULL))) {
834                 return NULL;
835         }
836
837         if (!(ds->data = ast_msg_alloc())) {
838                 ast_datastore_free(ds);
839                 return NULL;
840         }
841
842         ast_channel_datastore_add(chan, ds);
843
844         return ds;
845 }
846
847 static int msg_func_read(struct ast_channel *chan, const char *function,
848                 char *data, char *buf, size_t len)
849 {
850         struct ast_datastore *ds;
851         struct ast_msg *msg;
852
853         ast_channel_lock(chan);
854
855         if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
856                 ast_channel_unlock(chan);
857                 ast_log(LOG_ERROR, "No MESSAGE data found on the channel to read.\n");
858                 return -1;
859         }
860
861         msg = ds->data;
862         ao2_ref(msg, +1);
863         ast_channel_unlock(chan);
864
865         ao2_lock(msg);
866
867         if (!strcasecmp(data, "to")) {
868                 ast_copy_string(buf, ast_str_buffer(msg->to), len);
869         } else if (!strcasecmp(data, "from")) {
870                 ast_copy_string(buf, ast_str_buffer(msg->from), len);
871         } else if (!strcasecmp(data, "body")) {
872                 ast_copy_string(buf, ast_msg_get_body(msg), len);
873         } else {
874                 ast_log(LOG_WARNING, "Invalid argument to MESSAGE(): '%s'\n", data);
875         }
876
877         ao2_unlock(msg);
878         ao2_ref(msg, -1);
879
880         return 0;
881 }
882
883 static int msg_func_write(struct ast_channel *chan, const char *function,
884                 char *data, const char *value)
885 {
886         struct ast_datastore *ds;
887         struct ast_msg *msg;
888
889         ast_channel_lock(chan);
890
891         if (!(ds = msg_datastore_find_or_create(chan))) {
892                 ast_channel_unlock(chan);
893                 return -1;
894         }
895
896         msg = ds->data;
897         ao2_ref(msg, +1);
898         ast_channel_unlock(chan);
899
900         ao2_lock(msg);
901
902         if (!strcasecmp(data, "to")) {
903                 ast_msg_set_to(msg, "%s", value);
904         } else if (!strcasecmp(data, "from")) {
905                 ast_msg_set_from(msg, "%s", value);
906         } else if (!strcasecmp(data, "body")) {
907                 ast_msg_set_body(msg, "%s", value);
908         } else if (!strcasecmp(data, "custom_data")) {
909                 int outbound = -1;
910                 if (!strcasecmp(value, "mark_all_outbound")) {
911                         outbound = 1;
912                 } else if (!strcasecmp(value, "clear_all_outbound")) {
913                         outbound = 0;
914                 } else {
915                         ast_log(LOG_WARNING, "'%s' is not a valid value for custom_data\n", value);
916                 }
917
918                 if (outbound != -1) {
919                         struct msg_data *hdr_data;
920                         struct ao2_iterator iter = ao2_iterator_init(msg->vars, 0);
921
922                         while ((hdr_data = ao2_iterator_next(&iter))) {
923                                 hdr_data->send = outbound;
924                                 ao2_ref(hdr_data, -1);
925                         }
926                         ao2_iterator_destroy(&iter);
927                 }
928         } else {
929                 ast_log(LOG_WARNING, "'%s' is not a valid write argument.\n", data);
930         }
931
932         ao2_unlock(msg);
933         ao2_ref(msg, -1);
934
935         return 0;
936 }
937
938 static int msg_data_func_read(struct ast_channel *chan, const char *function,
939                 char *data, char *buf, size_t len)
940 {
941         struct ast_datastore *ds;
942         struct ast_msg *msg;
943         const char *val;
944
945         ast_channel_lock(chan);
946
947         if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
948                 ast_channel_unlock(chan);
949                 ast_log(LOG_ERROR, "No MESSAGE data found on the channel to read.\n");
950                 return -1;
951         }
952
953         msg = ds->data;
954         ao2_ref(msg, +1);
955         ast_channel_unlock(chan);
956
957         ao2_lock(msg);
958
959         if ((val = ast_msg_get_var(msg, data))) {
960                 ast_copy_string(buf, val, len);
961         }
962
963         ao2_unlock(msg);
964         ao2_ref(msg, -1);
965
966         return 0;
967 }
968
969 static int msg_data_func_write(struct ast_channel *chan, const char *function,
970                 char *data, const char *value)
971 {
972         struct ast_datastore *ds;
973         struct ast_msg *msg;
974
975         ast_channel_lock(chan);
976
977         if (!(ds = msg_datastore_find_or_create(chan))) {
978                 ast_channel_unlock(chan);
979                 return -1;
980         }
981
982         msg = ds->data;
983         ao2_ref(msg, +1);
984         ast_channel_unlock(chan);
985
986         ao2_lock(msg);
987
988         ast_msg_set_var_outbound(msg, data, value);
989
990         ao2_unlock(msg);
991         ao2_ref(msg, -1);
992
993         return 0;
994 }
995 static int msg_tech_hash(const void *obj, const int flags)
996 {
997         struct ast_msg_tech_holder *tech_holder = (struct ast_msg_tech_holder *) obj;
998         int res = 0;
999
1000         ast_rwlock_rdlock(&tech_holder->tech_lock);
1001         if (tech_holder->tech) {
1002                 res = ast_str_case_hash(tech_holder->tech->name);
1003         }
1004         ast_rwlock_unlock(&tech_holder->tech_lock);
1005
1006         return res;
1007 }
1008
1009 static int msg_tech_cmp(void *obj, void *arg, int flags)
1010 {
1011         struct ast_msg_tech_holder *tech_holder = obj;
1012         const struct ast_msg_tech_holder *tech_holder2 = arg;
1013         int res = 1;
1014
1015         ast_rwlock_rdlock(&tech_holder->tech_lock);
1016         /*
1017          * tech_holder2 is a temporary fake tech_holder.
1018          */
1019         if (tech_holder->tech) {
1020                 res = strcasecmp(tech_holder->tech->name, tech_holder2->tech->name) ? 0 : CMP_MATCH | CMP_STOP;
1021         }
1022         ast_rwlock_unlock(&tech_holder->tech_lock);
1023
1024         return res;
1025 }
1026
1027 /*!
1028  * \internal
1029  * \brief MessageSend() application
1030  */
1031 static int msg_send_exec(struct ast_channel *chan, const char *data)
1032 {
1033         struct ast_datastore *ds;
1034         struct ast_msg *msg;
1035         char *tech_name;
1036         struct ast_msg_tech_holder *tech_holder = NULL;
1037         char *parse;
1038         int res = -1;
1039         AST_DECLARE_APP_ARGS(args,
1040                 AST_APP_ARG(to);
1041                 AST_APP_ARG(from);
1042         );
1043
1044         if (ast_strlen_zero(data)) {
1045                 ast_log(LOG_WARNING, "An argument is required to MessageSend()\n");
1046                 pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_URI");
1047                 return 0;
1048         }
1049
1050         parse = ast_strdupa(data);
1051         AST_STANDARD_APP_ARGS(args, parse);
1052
1053         if (ast_strlen_zero(args.to)) {
1054                 ast_log(LOG_WARNING, "A 'to' URI is required for MessageSend()\n");
1055                 pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_URI");
1056                 return 0;
1057         }
1058
1059         ast_channel_lock(chan);
1060
1061         if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
1062                 ast_channel_unlock(chan);
1063                 ast_log(LOG_WARNING, "No message data found on channel to send.\n");
1064                 pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "FAILURE");
1065                 return 0;
1066         }
1067
1068         msg = ds->data;
1069         ao2_ref(msg, +1);
1070         ast_channel_unlock(chan);
1071
1072         tech_name = ast_strdupa(args.to);
1073         tech_name = strsep(&tech_name, ":");
1074
1075         {
1076                 struct ast_msg_tech tmp_msg_tech = {
1077                         .name = tech_name,
1078                 };
1079                 struct ast_msg_tech_holder tmp_tech_holder = {
1080                         .tech = &tmp_msg_tech,
1081                 };
1082
1083                 tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER);
1084         }
1085
1086         if (!tech_holder) {
1087                 ast_log(LOG_WARNING, "No message technology '%s' found.\n", tech_name);
1088                 pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_PROTOCOL");
1089                 goto exit_cleanup;
1090         }
1091
1092         /*
1093          * The message lock is held here to safely allow the technology
1094          * implementation to access the message fields without worrying
1095          * that they could change.
1096          */
1097         ao2_lock(msg);
1098         ast_rwlock_rdlock(&tech_holder->tech_lock);
1099         if (tech_holder->tech) {
1100                 res = tech_holder->tech->msg_send(msg, S_OR(args.to, ""),
1101                                                         S_OR(args.from, ""));
1102         }
1103         ast_rwlock_unlock(&tech_holder->tech_lock);
1104         ao2_unlock(msg);
1105
1106         pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", res ? "FAILURE" : "SUCCESS");
1107
1108 exit_cleanup:
1109         if (tech_holder) {
1110                 ao2_ref(tech_holder, -1);
1111                 tech_holder = NULL;
1112         }
1113
1114         ao2_ref(msg, -1);
1115
1116         return 0;
1117 }
1118
1119 static int action_messagesend(struct mansession *s, const struct message *m)
1120 {
1121         const char *to = ast_strdupa(astman_get_header(m, "To"));
1122         const char *from = astman_get_header(m, "From");
1123         const char *body = astman_get_header(m, "Body");
1124         const char *base64body = astman_get_header(m, "Base64Body");
1125         char base64decoded[1301] = { 0, };
1126         char *tech_name = NULL;
1127         struct ast_variable *vars = NULL;
1128         struct ast_variable *data = NULL;
1129         struct ast_msg_tech_holder *tech_holder = NULL;
1130         struct ast_msg *msg;
1131         int res = -1;
1132
1133         if (ast_strlen_zero(to)) {
1134                 astman_send_error(s, m, "No 'To' address specified.");
1135                 return -1;
1136         }
1137
1138         if (!ast_strlen_zero(base64body)) {
1139                 ast_base64decode((unsigned char *) base64decoded, base64body, sizeof(base64decoded) - 1);
1140                 body = base64decoded;
1141         }
1142
1143         tech_name = ast_strdupa(to);
1144         tech_name = strsep(&tech_name, ":");
1145         {
1146                 struct ast_msg_tech tmp_msg_tech = {
1147                         .name = tech_name,
1148                 };
1149                 struct ast_msg_tech_holder tmp_tech_holder = {
1150                         .tech = &tmp_msg_tech,
1151                 };
1152
1153                 tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER);
1154         }
1155
1156         if (!tech_holder) {
1157                 astman_send_error(s, m, "Message technology not found.");
1158                 return -1;
1159         }
1160
1161         if (!(msg = ast_msg_alloc())) {
1162                 ao2_ref(tech_holder, -1);
1163                 astman_send_error(s, m, "Internal failure\n");
1164                 return -1;
1165         }
1166
1167         data = astman_get_variables(m);
1168         for (vars = data; vars; vars = vars->next) {
1169                 ast_msg_set_var_outbound(msg, vars->name, vars->value);
1170         }
1171
1172         ast_msg_set_body(msg, "%s", body);
1173
1174         ast_rwlock_rdlock(&tech_holder->tech_lock);
1175         if (tech_holder->tech) {
1176                 res = tech_holder->tech->msg_send(msg, S_OR(to, ""), S_OR(from, ""));
1177         }
1178         ast_rwlock_unlock(&tech_holder->tech_lock);
1179
1180         ast_variables_destroy(vars);
1181         ao2_ref(tech_holder, -1);
1182         ao2_ref(msg, -1);
1183
1184         if (res) {
1185                 astman_send_error(s, m, "Message failed to send.");
1186         } else {
1187                 astman_send_ack(s, m, "Message successfully sent");
1188         }
1189         return res;
1190 }
1191
1192 int ast_msg_send(struct ast_msg *msg, const char *to, const char *from)
1193 {
1194         char *tech_name = NULL;
1195         struct ast_msg_tech_holder *tech_holder = NULL;
1196         int res = -1;
1197
1198         if (ast_strlen_zero(to)) {
1199                 ao2_ref(msg, -1);
1200                 return -1;
1201         }
1202
1203         tech_name = ast_strdupa(to);
1204         tech_name = strsep(&tech_name, ":");
1205         {
1206                 struct ast_msg_tech tmp_msg_tech = {
1207                         .name = tech_name,
1208                 };
1209                 struct ast_msg_tech_holder tmp_tech_holder = {
1210                         .tech = &tmp_msg_tech,
1211                 };
1212
1213                 tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER);
1214         }
1215
1216         if (!tech_holder) {
1217                 ao2_ref(msg, -1);
1218                 return -1;
1219         }
1220
1221         ast_rwlock_rdlock(&tech_holder->tech_lock);
1222         if (tech_holder->tech) {
1223                 res = tech_holder->tech->msg_send(msg, S_OR(to, ""), S_OR(from, ""));
1224         }
1225         ast_rwlock_unlock(&tech_holder->tech_lock);
1226
1227         ao2_ref(tech_holder, -1);
1228         ao2_ref(msg, -1);
1229
1230         return res;
1231 }
1232
1233 int ast_msg_tech_register(const struct ast_msg_tech *tech)
1234 {
1235         struct ast_msg_tech_holder tmp_tech_holder = {
1236                 .tech = tech,
1237         };
1238         struct ast_msg_tech_holder *tech_holder;
1239
1240         if ((tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER))) {
1241                 ao2_ref(tech_holder, -1);
1242                 ast_log(LOG_ERROR, "Message technology already registered for '%s'\n",
1243                                 tech->name);
1244                 return -1;
1245         }
1246
1247         if (!(tech_holder = ao2_alloc(sizeof(*tech_holder), NULL))) {
1248                 return -1;
1249         }
1250
1251         ast_rwlock_init(&tech_holder->tech_lock);
1252         tech_holder->tech = tech;
1253
1254         ao2_link(msg_techs, tech_holder);
1255
1256         ao2_ref(tech_holder, -1);
1257         tech_holder = NULL;
1258
1259         ast_verb(3, "Message technology handler '%s' registered.\n", tech->name);
1260
1261         return 0;
1262 }
1263
1264 int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
1265 {
1266         struct ast_msg_tech_holder tmp_tech_holder = {
1267                 .tech = tech,
1268         };
1269         struct ast_msg_tech_holder *tech_holder;
1270
1271         tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER | OBJ_UNLINK);
1272
1273         if (!tech_holder) {
1274                 ast_log(LOG_ERROR, "No '%s' message technology found.\n", tech->name);
1275                 return -1;
1276         }
1277
1278         ast_rwlock_wrlock(&tech_holder->tech_lock);
1279         tech_holder->tech = NULL;
1280         ast_rwlock_unlock(&tech_holder->tech_lock);
1281
1282         ao2_ref(tech_holder, -1);
1283         tech_holder = NULL;
1284
1285         ast_verb(3, "Message technology handler '%s' unregistered.\n", tech->name);
1286
1287         return 0;
1288 }
1289
1290 /*
1291  * \internal
1292  * \brief Initialize stuff during Asterisk startup.
1293  *
1294  * Cleanup isn't a big deal in this function.  If we return non-zero,
1295  * Asterisk is going to exit.
1296  *
1297  * \retval 0 success
1298  * \retval non-zero failure
1299  */
1300 int ast_msg_init(void)
1301 {
1302         int res;
1303
1304         msg_q_tp = ast_taskprocessor_get("ast_msg_queue", TPS_REF_DEFAULT);
1305         if (!msg_q_tp) {
1306                 return -1;
1307         }
1308
1309         msg_techs = ao2_container_alloc(17, msg_tech_hash, msg_tech_cmp);
1310         if (!msg_techs) {
1311                 return -1;
1312         }
1313
1314         res = __ast_custom_function_register(&msg_function, NULL);
1315         res |= __ast_custom_function_register(&msg_data_function, NULL);
1316         res |= ast_register_application2(app_msg_send, msg_send_exec, NULL, NULL, NULL);
1317         res |= ast_manager_register_xml_core("MessageSend", EVENT_FLAG_MESSAGE, action_messagesend);
1318
1319         return res;
1320 }