00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413139 $")
00033
00034 #include "asterisk/_private.h"
00035
00036 #include "asterisk/module.h"
00037 #include "asterisk/datastore.h"
00038 #include "asterisk/pbx.h"
00039 #include "asterisk/manager.h"
00040 #include "asterisk/strings.h"
00041 #include "asterisk/astobj2.h"
00042 #include "asterisk/app.h"
00043 #include "asterisk/taskprocessor.h"
00044 #include "asterisk/message.h"
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 struct msg_data {
00196 AST_DECLARE_STRING_FIELDS(
00197 AST_STRING_FIELD(name);
00198 AST_STRING_FIELD(value);
00199 );
00200 unsigned int send:1;
00201 };
00202
00203 AST_LIST_HEAD_NOLOCK(outhead, msg_data);
00204
00205
00206
00207
00208
00209
00210 struct ast_msg {
00211 struct ast_str *to;
00212 struct ast_str *from;
00213 struct ast_str *body;
00214 struct ast_str *context;
00215 struct ast_str *exten;
00216 struct ao2_container *vars;
00217 };
00218
00219 struct ast_msg_tech_holder {
00220 const struct ast_msg_tech *tech;
00221
00222
00223
00224
00225
00226
00227 ast_rwlock_t tech_lock;
00228 };
00229
00230 static struct ao2_container *msg_techs;
00231
00232 static struct ast_taskprocessor *msg_q_tp;
00233
00234 static const char app_msg_send[] = "MessageSend";
00235
00236 static void msg_ds_destroy(void *data);
00237
00238 static const struct ast_datastore_info msg_datastore = {
00239 .type = "message",
00240 .destroy = msg_ds_destroy,
00241 };
00242
00243 static int msg_func_read(struct ast_channel *chan, const char *function,
00244 char *data, char *buf, size_t len);
00245 static int msg_func_write(struct ast_channel *chan, const char *function,
00246 char *data, const char *value);
00247
00248 static struct ast_custom_function msg_function = {
00249 .name = "MESSAGE",
00250 .read = msg_func_read,
00251 .write = msg_func_write,
00252 };
00253
00254 static int msg_data_func_read(struct ast_channel *chan, const char *function,
00255 char *data, char *buf, size_t len);
00256 static int msg_data_func_write(struct ast_channel *chan, const char *function,
00257 char *data, const char *value);
00258
00259 static struct ast_custom_function msg_data_function = {
00260 .name = "MESSAGE_DATA",
00261 .read = msg_data_func_read,
00262 .write = msg_data_func_write,
00263 };
00264
00265 static struct ast_frame *chan_msg_read(struct ast_channel *chan);
00266 static int chan_msg_write(struct ast_channel *chan, struct ast_frame *fr);
00267 static int chan_msg_indicate(struct ast_channel *chan, int condition,
00268 const void *data, size_t datalen);
00269 static int chan_msg_send_digit_begin(struct ast_channel *chan, char digit);
00270 static int chan_msg_send_digit_end(struct ast_channel *chan, char digit,
00271 unsigned int duration);
00272
00273
00274
00275
00276
00277
00278
00279
00280 static const struct ast_channel_tech msg_chan_tech_hack = {
00281 .type = "Message",
00282 .description = "Internal Text Message Processing",
00283 .read = chan_msg_read,
00284 .write = chan_msg_write,
00285 .indicate = chan_msg_indicate,
00286 .send_digit_begin = chan_msg_send_digit_begin,
00287 .send_digit_end = chan_msg_send_digit_end,
00288 };
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 static struct ast_frame *chan_msg_read(struct ast_channel *chan)
00299 {
00300 return &ast_null_frame;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309 static int chan_msg_write(struct ast_channel *chan, struct ast_frame *fr)
00310 {
00311 return 0;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 static int chan_msg_indicate(struct ast_channel *chan, int condition,
00325 const void *data, size_t datalen)
00326 {
00327 return 0;
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 static int chan_msg_send_digit_begin(struct ast_channel *chan, char digit)
00339 {
00340 return 0;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 static int chan_msg_send_digit_end(struct ast_channel *chan, char digit,
00352 unsigned int duration)
00353 {
00354 return 0;
00355 }
00356
00357 static void msg_ds_destroy(void *data)
00358 {
00359 struct ast_msg *msg = data;
00360
00361 ao2_ref(msg, -1);
00362 }
00363
00364 static int msg_data_hash_fn(const void *obj, const int flags)
00365 {
00366 const struct msg_data *data = obj;
00367 return ast_str_case_hash(data->name);
00368 }
00369
00370 static int msg_data_cmp_fn(void *obj, void *arg, int flags)
00371 {
00372 const struct msg_data *one = obj, *two = arg;
00373 return !strcasecmp(one->name, two->name) ? CMP_MATCH | CMP_STOP : 0;
00374 }
00375
00376 static void msg_data_destructor(void *obj)
00377 {
00378 struct msg_data *data = obj;
00379 ast_string_field_free_memory(data);
00380 }
00381
00382 static void msg_destructor(void *obj)
00383 {
00384 struct ast_msg *msg = obj;
00385
00386 ast_free(msg->to);
00387 msg->to = NULL;
00388
00389 ast_free(msg->from);
00390 msg->from = NULL;
00391
00392 ast_free(msg->body);
00393 msg->body = NULL;
00394
00395 ast_free(msg->context);
00396 msg->context = NULL;
00397
00398 ast_free(msg->exten);
00399 msg->exten = NULL;
00400
00401 ao2_ref(msg->vars, -1);
00402 }
00403
00404 struct ast_msg *ast_msg_alloc(void)
00405 {
00406 struct ast_msg *msg;
00407
00408 if (!(msg = ao2_alloc(sizeof(*msg), msg_destructor))) {
00409 return NULL;
00410 }
00411
00412 if (!(msg->to = ast_str_create(32))) {
00413 ao2_ref(msg, -1);
00414 return NULL;
00415 }
00416
00417 if (!(msg->from = ast_str_create(32))) {
00418 ao2_ref(msg, -1);
00419 return NULL;
00420 }
00421
00422 if (!(msg->body = ast_str_create(128))) {
00423 ao2_ref(msg, -1);
00424 return NULL;
00425 }
00426
00427 if (!(msg->context = ast_str_create(16))) {
00428 ao2_ref(msg, -1);
00429 return NULL;
00430 }
00431
00432 if (!(msg->exten = ast_str_create(16))) {
00433 ao2_ref(msg, -1);
00434 return NULL;
00435 }
00436
00437 if (!(msg->vars = ao2_container_alloc(1, msg_data_hash_fn, msg_data_cmp_fn))) {
00438 ao2_ref(msg, -1);
00439 return NULL;
00440 }
00441
00442 ast_str_set(&msg->context, 0, "default");
00443
00444 return msg;
00445 }
00446
00447 struct ast_msg *ast_msg_ref(struct ast_msg *msg)
00448 {
00449 ao2_ref(msg, 1);
00450 return msg;
00451 }
00452
00453 struct ast_msg *ast_msg_destroy(struct ast_msg *msg)
00454 {
00455 ao2_ref(msg, -1);
00456
00457 return NULL;
00458 }
00459
00460 int ast_msg_set_to(struct ast_msg *msg, const char *fmt, ...)
00461 {
00462 va_list ap;
00463 int res;
00464
00465 va_start(ap, fmt);
00466 res = ast_str_set_va(&msg->to, 0, fmt, ap);
00467 va_end(ap);
00468
00469 return res < 0 ? -1 : 0;
00470 }
00471
00472 int ast_msg_set_from(struct ast_msg *msg, const char *fmt, ...)
00473 {
00474 va_list ap;
00475 int res;
00476
00477 va_start(ap, fmt);
00478 res = ast_str_set_va(&msg->from, 0, fmt, ap);
00479 va_end(ap);
00480
00481 return res < 0 ? -1 : 0;
00482 }
00483
00484 int ast_msg_set_body(struct ast_msg *msg, const char *fmt, ...)
00485 {
00486 va_list ap;
00487 int res;
00488
00489 va_start(ap, fmt);
00490 res = ast_str_set_va(&msg->body, 0, fmt, ap);
00491 va_end(ap);
00492
00493 return res < 0 ? -1 : 0;
00494 }
00495
00496 int ast_msg_set_context(struct ast_msg *msg, const char *fmt, ...)
00497 {
00498 va_list ap;
00499 int res;
00500
00501 va_start(ap, fmt);
00502 res = ast_str_set_va(&msg->context, 0, fmt, ap);
00503 va_end(ap);
00504
00505 return res < 0 ? -1 : 0;
00506 }
00507
00508 int ast_msg_set_exten(struct ast_msg *msg, const char *fmt, ...)
00509 {
00510 va_list ap;
00511 int res;
00512
00513 va_start(ap, fmt);
00514 res = ast_str_set_va(&msg->exten, 0, fmt, ap);
00515 va_end(ap);
00516
00517 return res < 0 ? -1 : 0;
00518 }
00519
00520 const char *ast_msg_get_body(const struct ast_msg *msg)
00521 {
00522 return ast_str_buffer(msg->body);
00523 }
00524
00525 static struct msg_data *msg_data_alloc(void)
00526 {
00527 struct msg_data *data;
00528
00529 if (!(data = ao2_alloc(sizeof(*data), msg_data_destructor))) {
00530 return NULL;
00531 }
00532
00533 if (ast_string_field_init(data, 32)) {
00534 ao2_ref(data, -1);
00535 return NULL;
00536 }
00537
00538 return data;
00539 }
00540
00541 static struct msg_data *msg_data_find(struct ao2_container *vars, const char *name)
00542 {
00543 struct msg_data tmp = {
00544 .name = name,
00545 };
00546 return ao2_find(vars, &tmp, OBJ_POINTER);
00547 }
00548
00549 static int msg_set_var_full(struct ast_msg *msg, const char *name, const char *value, unsigned int outbound)
00550 {
00551 struct msg_data *data;
00552
00553 if (!(data = msg_data_find(msg->vars, name))) {
00554 if (ast_strlen_zero(value)) {
00555 return 0;
00556 }
00557 if (!(data = msg_data_alloc())) {
00558 return -1;
00559 };
00560
00561 ast_string_field_set(data, name, name);
00562 ast_string_field_set(data, value, value);
00563 data->send = outbound;
00564 ao2_link(msg->vars, data);
00565 } else {
00566 if (ast_strlen_zero(value)) {
00567 ao2_unlink(msg->vars, data);
00568 } else {
00569 ast_string_field_set(data, value, value);
00570 data->send = outbound;
00571 }
00572 }
00573
00574 ao2_ref(data, -1);
00575
00576 return 0;
00577 }
00578
00579 int ast_msg_set_var_outbound(struct ast_msg *msg, const char *name, const char *value)
00580 {
00581 return msg_set_var_full(msg, name, value, 1);
00582 }
00583
00584 int ast_msg_set_var(struct ast_msg *msg, const char *name, const char *value)
00585 {
00586 return msg_set_var_full(msg, name, value, 0);
00587 }
00588
00589 const char *ast_msg_get_var(struct ast_msg *msg, const char *name)
00590 {
00591 struct msg_data *data;
00592 const char *val = NULL;
00593
00594 if (!(data = msg_data_find(msg->vars, name))) {
00595 return NULL;
00596 }
00597
00598
00599
00600
00601
00602 val = data->value;
00603 ao2_ref(data, -1);
00604
00605 return val;
00606 }
00607
00608 struct ast_msg_var_iterator {
00609 struct ao2_iterator iter;
00610 struct msg_data *current_used;
00611 };
00612
00613 struct ast_msg_var_iterator *ast_msg_var_iterator_init(const struct ast_msg *msg)
00614 {
00615 struct ast_msg_var_iterator *iter;
00616
00617 iter = ast_calloc(1, sizeof(*iter));
00618 if (!iter) {
00619 return NULL;
00620 }
00621
00622 iter->iter = ao2_iterator_init(msg->vars, 0);
00623
00624 return iter;
00625 }
00626
00627 int ast_msg_var_iterator_next(const struct ast_msg *msg, struct ast_msg_var_iterator *iter, const char **name, const char **value)
00628 {
00629 struct msg_data *data;
00630
00631 if (!iter) {
00632 return 0;
00633 }
00634
00635
00636 while ((data = ao2_iterator_next(&iter->iter)) && !data->send) {
00637 ao2_ref(data, -1);
00638 }
00639
00640 if (!data) {
00641 return 0;
00642 }
00643
00644 if (data->send) {
00645 *name = data->name;
00646 *value = data->value;
00647 }
00648
00649
00650
00651 iter->current_used = data;
00652
00653 return 1;
00654 }
00655
00656 void ast_msg_var_unref_current(struct ast_msg_var_iterator *iter)
00657 {
00658 ao2_cleanup(iter->current_used);
00659 iter->current_used = NULL;
00660 }
00661
00662 void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *iter)
00663 {
00664 if (iter) {
00665 ao2_iterator_destroy(&iter->iter);
00666 ast_msg_var_unref_current(iter);
00667 ast_free(iter);
00668 }
00669 }
00670
00671 static struct ast_channel *create_msg_q_chan(void)
00672 {
00673 struct ast_channel *chan;
00674 struct ast_datastore *ds;
00675
00676 chan = ast_channel_alloc(1, AST_STATE_UP,
00677 NULL, NULL, NULL,
00678 NULL, NULL, NULL, 0,
00679 "%s", "Message/ast_msg_queue");
00680
00681 if (!chan) {
00682 return NULL;
00683 }
00684
00685 ast_channel_unlink(chan);
00686
00687 ast_channel_tech_set(chan, &msg_chan_tech_hack);
00688
00689 if (!(ds = ast_datastore_alloc(&msg_datastore, NULL))) {
00690 ast_hangup(chan);
00691 return NULL;
00692 }
00693
00694 ast_channel_lock(chan);
00695 ast_channel_datastore_add(chan, ds);
00696 ast_channel_unlock(chan);
00697
00698 return chan;
00699 }
00700
00701
00702
00703
00704
00705
00706
00707
00708 static void msg_route(struct ast_channel *chan, struct ast_msg *msg)
00709 {
00710 struct ast_pbx_args pbx_args;
00711
00712 ast_explicit_goto(chan, ast_str_buffer(msg->context), AS_OR(msg->exten, "s"), 1);
00713
00714 memset(&pbx_args, 0, sizeof(pbx_args));
00715 pbx_args.no_hangup_chan = 1,
00716 ast_pbx_run_args(chan, &pbx_args);
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726 static void chan_cleanup(struct ast_channel *chan)
00727 {
00728 struct ast_datastore *msg_ds, *ds;
00729 struct varshead *headp;
00730 struct ast_var_t *vardata;
00731
00732 ast_channel_lock(chan);
00733
00734
00735
00736
00737
00738 if ((msg_ds = ast_channel_datastore_find(chan, &msg_datastore, NULL)) && msg_ds->data) {
00739 ast_channel_datastore_remove(chan, msg_ds);
00740 ao2_ref(msg_ds->data, -1);
00741 msg_ds->data = NULL;
00742 }
00743
00744
00745
00746
00747 while ((ds = AST_LIST_REMOVE_HEAD(ast_channel_datastores(chan), entry))) {
00748 ast_datastore_free(ds);
00749 }
00750
00751
00752
00753
00754 headp = ast_channel_varshead(chan);
00755 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
00756 ast_var_delete(vardata);
00757 }
00758
00759
00760
00761
00762 if (msg_ds) {
00763 ast_channel_datastore_add(chan, msg_ds);
00764 }
00765
00766
00767
00768 ast_channel_clear_softhangup(chan, AST_SOFTHANGUP_ALL);
00769
00770 ast_channel_unlock(chan);
00771 }
00772
00773 static void destroy_msg_q_chan(void *data)
00774 {
00775 struct ast_channel **chan = data;
00776
00777 if (!*chan) {
00778 return;
00779 }
00780
00781 ast_channel_release(*chan);
00782 }
00783
00784 AST_THREADSTORAGE_CUSTOM(msg_q_chan, NULL, destroy_msg_q_chan);
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 static int msg_q_cb(void *data)
00796 {
00797 struct ast_msg *msg = data;
00798 struct ast_channel **chan_p, *chan;
00799 struct ast_datastore *ds;
00800
00801 if (!(chan_p = ast_threadstorage_get(&msg_q_chan, sizeof(struct ast_channel *)))) {
00802 return -1;
00803 }
00804 if (!*chan_p) {
00805 if (!(*chan_p = create_msg_q_chan())) {
00806 return -1;
00807 }
00808 }
00809 chan = *chan_p;
00810
00811 ast_channel_lock(chan);
00812 if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
00813 ast_channel_unlock(chan);
00814 return -1;
00815 }
00816 ao2_ref(msg, +1);
00817 ds->data = msg;
00818 ast_channel_unlock(chan);
00819
00820 msg_route(chan, msg);
00821 chan_cleanup(chan);
00822
00823 ao2_ref(msg, -1);
00824
00825 return 0;
00826 }
00827
00828 int ast_msg_queue(struct ast_msg *msg)
00829 {
00830 int res;
00831
00832 res = ast_taskprocessor_push(msg_q_tp, msg_q_cb, msg);
00833 if (res == -1) {
00834 ao2_ref(msg, -1);
00835 }
00836
00837 return res;
00838 }
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850 static struct ast_datastore *msg_datastore_find_or_create(struct ast_channel *chan)
00851 {
00852 struct ast_datastore *ds;
00853
00854 if ((ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
00855 return ds;
00856 }
00857
00858 if (!(ds = ast_datastore_alloc(&msg_datastore, NULL))) {
00859 return NULL;
00860 }
00861
00862 if (!(ds->data = ast_msg_alloc())) {
00863 ast_datastore_free(ds);
00864 return NULL;
00865 }
00866
00867 ast_channel_datastore_add(chan, ds);
00868
00869 return ds;
00870 }
00871
00872 static int msg_func_read(struct ast_channel *chan, const char *function,
00873 char *data, char *buf, size_t len)
00874 {
00875 struct ast_datastore *ds;
00876 struct ast_msg *msg;
00877
00878 if (!chan) {
00879 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
00880 return -1;
00881 }
00882
00883 ast_channel_lock(chan);
00884
00885 if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
00886 ast_channel_unlock(chan);
00887 ast_log(LOG_ERROR, "No MESSAGE data found on the channel to read.\n");
00888 return -1;
00889 }
00890
00891 msg = ds->data;
00892 ao2_ref(msg, +1);
00893 ast_channel_unlock(chan);
00894
00895 ao2_lock(msg);
00896
00897 if (!strcasecmp(data, "to")) {
00898 ast_copy_string(buf, ast_str_buffer(msg->to), len);
00899 } else if (!strcasecmp(data, "from")) {
00900 ast_copy_string(buf, ast_str_buffer(msg->from), len);
00901 } else if (!strcasecmp(data, "body")) {
00902 ast_copy_string(buf, ast_msg_get_body(msg), len);
00903 } else {
00904 ast_log(LOG_WARNING, "Invalid argument to MESSAGE(): '%s'\n", data);
00905 }
00906
00907 ao2_unlock(msg);
00908 ao2_ref(msg, -1);
00909
00910 return 0;
00911 }
00912
00913 static int msg_func_write(struct ast_channel *chan, const char *function,
00914 char *data, const char *value)
00915 {
00916 struct ast_datastore *ds;
00917 struct ast_msg *msg;
00918
00919 if (!chan) {
00920 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
00921 return -1;
00922 }
00923
00924 ast_channel_lock(chan);
00925
00926 if (!(ds = msg_datastore_find_or_create(chan))) {
00927 ast_channel_unlock(chan);
00928 return -1;
00929 }
00930
00931 msg = ds->data;
00932 ao2_ref(msg, +1);
00933 ast_channel_unlock(chan);
00934
00935 ao2_lock(msg);
00936
00937 if (!strcasecmp(data, "to")) {
00938 ast_msg_set_to(msg, "%s", value);
00939 } else if (!strcasecmp(data, "from")) {
00940 ast_msg_set_from(msg, "%s", value);
00941 } else if (!strcasecmp(data, "body")) {
00942 ast_msg_set_body(msg, "%s", value);
00943 } else if (!strcasecmp(data, "custom_data")) {
00944 int outbound = -1;
00945 if (!strcasecmp(value, "mark_all_outbound")) {
00946 outbound = 1;
00947 } else if (!strcasecmp(value, "clear_all_outbound")) {
00948 outbound = 0;
00949 } else {
00950 ast_log(LOG_WARNING, "'%s' is not a valid value for custom_data\n", value);
00951 }
00952
00953 if (outbound != -1) {
00954 struct msg_data *hdr_data;
00955 struct ao2_iterator iter = ao2_iterator_init(msg->vars, 0);
00956
00957 while ((hdr_data = ao2_iterator_next(&iter))) {
00958 hdr_data->send = outbound;
00959 ao2_ref(hdr_data, -1);
00960 }
00961 ao2_iterator_destroy(&iter);
00962 }
00963 } else {
00964 ast_log(LOG_WARNING, "'%s' is not a valid write argument.\n", data);
00965 }
00966
00967 ao2_unlock(msg);
00968 ao2_ref(msg, -1);
00969
00970 return 0;
00971 }
00972
00973 static int msg_data_func_read(struct ast_channel *chan, const char *function,
00974 char *data, char *buf, size_t len)
00975 {
00976 struct ast_datastore *ds;
00977 struct ast_msg *msg;
00978 const char *val;
00979
00980 if (!chan) {
00981 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
00982 return -1;
00983 }
00984
00985 ast_channel_lock(chan);
00986
00987 if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
00988 ast_channel_unlock(chan);
00989 ast_log(LOG_ERROR, "No MESSAGE data found on the channel to read.\n");
00990 return -1;
00991 }
00992
00993 msg = ds->data;
00994 ao2_ref(msg, +1);
00995 ast_channel_unlock(chan);
00996
00997 ao2_lock(msg);
00998
00999 if ((val = ast_msg_get_var(msg, data))) {
01000 ast_copy_string(buf, val, len);
01001 }
01002
01003 ao2_unlock(msg);
01004 ao2_ref(msg, -1);
01005
01006 return 0;
01007 }
01008
01009 static int msg_data_func_write(struct ast_channel *chan, const char *function,
01010 char *data, const char *value)
01011 {
01012 struct ast_datastore *ds;
01013 struct ast_msg *msg;
01014
01015 if (!chan) {
01016 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
01017 return -1;
01018 }
01019
01020 ast_channel_lock(chan);
01021
01022 if (!(ds = msg_datastore_find_or_create(chan))) {
01023 ast_channel_unlock(chan);
01024 return -1;
01025 }
01026
01027 msg = ds->data;
01028 ao2_ref(msg, +1);
01029 ast_channel_unlock(chan);
01030
01031 ao2_lock(msg);
01032
01033 ast_msg_set_var_outbound(msg, data, value);
01034
01035 ao2_unlock(msg);
01036 ao2_ref(msg, -1);
01037
01038 return 0;
01039 }
01040 static int msg_tech_hash(const void *obj, const int flags)
01041 {
01042 struct ast_msg_tech_holder *tech_holder = (struct ast_msg_tech_holder *) obj;
01043 int res = 0;
01044
01045 ast_rwlock_rdlock(&tech_holder->tech_lock);
01046 if (tech_holder->tech) {
01047 res = ast_str_case_hash(tech_holder->tech->name);
01048 }
01049 ast_rwlock_unlock(&tech_holder->tech_lock);
01050
01051 return res;
01052 }
01053
01054 static int msg_tech_cmp(void *obj, void *arg, int flags)
01055 {
01056 struct ast_msg_tech_holder *tech_holder = obj;
01057 const struct ast_msg_tech_holder *tech_holder2 = arg;
01058 int res = 1;
01059
01060 ast_rwlock_rdlock(&tech_holder->tech_lock);
01061
01062
01063
01064 if (tech_holder->tech) {
01065 res = strcasecmp(tech_holder->tech->name, tech_holder2->tech->name) ? 0 : CMP_MATCH | CMP_STOP;
01066 }
01067 ast_rwlock_unlock(&tech_holder->tech_lock);
01068
01069 return res;
01070 }
01071
01072 static struct ast_msg_tech_holder *msg_find_by_tech(const struct ast_msg_tech *msg_tech, int ao2_flags)
01073 {
01074 struct ast_msg_tech_holder *tech_holder;
01075 struct ast_msg_tech_holder tmp_tech_holder = {
01076 .tech = msg_tech,
01077 };
01078
01079 ast_rwlock_init(&tmp_tech_holder.tech_lock);
01080 tech_holder = ao2_find(msg_techs, &tmp_tech_holder, ao2_flags);
01081 ast_rwlock_destroy(&tmp_tech_holder.tech_lock);
01082 return tech_holder;
01083 }
01084
01085 static struct ast_msg_tech_holder *msg_find_by_tech_name(const char *tech_name, int ao2_flags)
01086 {
01087 struct ast_msg_tech tmp_msg_tech = {
01088 .name = tech_name,
01089 };
01090 return msg_find_by_tech(&tmp_msg_tech, ao2_flags);
01091 }
01092
01093
01094
01095
01096
01097 static int msg_send_exec(struct ast_channel *chan, const char *data)
01098 {
01099 struct ast_datastore *ds;
01100 struct ast_msg *msg;
01101 char *tech_name;
01102 struct ast_msg_tech_holder *tech_holder = NULL;
01103 char *parse;
01104 int res = -1;
01105 AST_DECLARE_APP_ARGS(args,
01106 AST_APP_ARG(to);
01107 AST_APP_ARG(from);
01108 );
01109
01110 if (ast_strlen_zero(data)) {
01111 ast_log(LOG_WARNING, "An argument is required to MessageSend()\n");
01112 pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_URI");
01113 return 0;
01114 }
01115
01116 parse = ast_strdupa(data);
01117 AST_STANDARD_APP_ARGS(args, parse);
01118
01119 if (ast_strlen_zero(args.to)) {
01120 ast_log(LOG_WARNING, "A 'to' URI is required for MessageSend()\n");
01121 pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_URI");
01122 return 0;
01123 }
01124
01125 ast_channel_lock(chan);
01126
01127 if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
01128 ast_channel_unlock(chan);
01129 ast_log(LOG_WARNING, "No message data found on channel to send.\n");
01130 pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "FAILURE");
01131 return 0;
01132 }
01133
01134 msg = ds->data;
01135 ao2_ref(msg, +1);
01136 ast_channel_unlock(chan);
01137
01138 tech_name = ast_strdupa(args.to);
01139 tech_name = strsep(&tech_name, ":");
01140
01141 tech_holder = msg_find_by_tech_name(tech_name, OBJ_POINTER);
01142
01143 if (!tech_holder) {
01144 ast_log(LOG_WARNING, "No message technology '%s' found.\n", tech_name);
01145 pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_PROTOCOL");
01146 goto exit_cleanup;
01147 }
01148
01149
01150
01151
01152
01153
01154 ao2_lock(msg);
01155 ast_rwlock_rdlock(&tech_holder->tech_lock);
01156 if (tech_holder->tech) {
01157 res = tech_holder->tech->msg_send(msg, S_OR(args.to, ""),
01158 S_OR(args.from, ""));
01159 }
01160 ast_rwlock_unlock(&tech_holder->tech_lock);
01161 ao2_unlock(msg);
01162
01163 pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", res ? "FAILURE" : "SUCCESS");
01164
01165 exit_cleanup:
01166 if (tech_holder) {
01167 ao2_ref(tech_holder, -1);
01168 tech_holder = NULL;
01169 }
01170
01171 ao2_ref(msg, -1);
01172
01173 return 0;
01174 }
01175
01176 static int action_messagesend(struct mansession *s, const struct message *m)
01177 {
01178 const char *to = ast_strdupa(astman_get_header(m, "To"));
01179 const char *from = astman_get_header(m, "From");
01180 const char *body = astman_get_header(m, "Body");
01181 const char *base64body = astman_get_header(m, "Base64Body");
01182 char base64decoded[1301] = { 0, };
01183 char *tech_name = NULL;
01184 struct ast_variable *vars = NULL;
01185 struct ast_variable *data = NULL;
01186 struct ast_msg_tech_holder *tech_holder = NULL;
01187 struct ast_msg *msg;
01188 int res = -1;
01189
01190 if (ast_strlen_zero(to)) {
01191 astman_send_error(s, m, "No 'To' address specified.");
01192 return -1;
01193 }
01194
01195 if (!ast_strlen_zero(base64body)) {
01196 ast_base64decode((unsigned char *) base64decoded, base64body, sizeof(base64decoded) - 1);
01197 body = base64decoded;
01198 }
01199
01200 tech_name = ast_strdupa(to);
01201 tech_name = strsep(&tech_name, ":");
01202
01203 tech_holder = msg_find_by_tech_name(tech_name, OBJ_POINTER);
01204
01205 if (!tech_holder) {
01206 astman_send_error(s, m, "Message technology not found.");
01207 return -1;
01208 }
01209
01210 if (!(msg = ast_msg_alloc())) {
01211 ao2_ref(tech_holder, -1);
01212 astman_send_error(s, m, "Internal failure\n");
01213 return -1;
01214 }
01215
01216 data = astman_get_variables(m);
01217 for (vars = data; vars; vars = vars->next) {
01218 ast_msg_set_var_outbound(msg, vars->name, vars->value);
01219 }
01220
01221 ast_msg_set_body(msg, "%s", body);
01222
01223 ast_rwlock_rdlock(&tech_holder->tech_lock);
01224 if (tech_holder->tech) {
01225 res = tech_holder->tech->msg_send(msg, S_OR(to, ""), S_OR(from, ""));
01226 }
01227 ast_rwlock_unlock(&tech_holder->tech_lock);
01228
01229 ast_variables_destroy(vars);
01230 ao2_ref(tech_holder, -1);
01231 ao2_ref(msg, -1);
01232
01233 if (res) {
01234 astman_send_error(s, m, "Message failed to send.");
01235 } else {
01236 astman_send_ack(s, m, "Message successfully sent");
01237 }
01238 return res;
01239 }
01240
01241 int ast_msg_send(struct ast_msg *msg, const char *to, const char *from)
01242 {
01243 char *tech_name = NULL;
01244 struct ast_msg_tech_holder *tech_holder = NULL;
01245 int res = -1;
01246
01247 if (ast_strlen_zero(to)) {
01248 ao2_ref(msg, -1);
01249 return -1;
01250 }
01251
01252 tech_name = ast_strdupa(to);
01253 tech_name = strsep(&tech_name, ":");
01254
01255 tech_holder = msg_find_by_tech_name(tech_name, OBJ_POINTER);
01256
01257 if (!tech_holder) {
01258 ao2_ref(msg, -1);
01259 return -1;
01260 }
01261
01262 ast_rwlock_rdlock(&tech_holder->tech_lock);
01263 if (tech_holder->tech) {
01264 res = tech_holder->tech->msg_send(msg, S_OR(to, ""), S_OR(from, ""));
01265 }
01266 ast_rwlock_unlock(&tech_holder->tech_lock);
01267
01268 ao2_ref(tech_holder, -1);
01269 ao2_ref(msg, -1);
01270
01271 return res;
01272 }
01273
01274 int ast_msg_tech_register(const struct ast_msg_tech *tech)
01275 {
01276 struct ast_msg_tech_holder *tech_holder;
01277
01278 if ((tech_holder = msg_find_by_tech(tech, OBJ_POINTER))) {
01279 ao2_ref(tech_holder, -1);
01280 ast_log(LOG_ERROR, "Message technology already registered for '%s'\n",
01281 tech->name);
01282 return -1;
01283 }
01284
01285 if (!(tech_holder = ao2_alloc(sizeof(*tech_holder), NULL))) {
01286 return -1;
01287 }
01288
01289 ast_rwlock_init(&tech_holder->tech_lock);
01290 tech_holder->tech = tech;
01291
01292 ao2_link(msg_techs, tech_holder);
01293
01294 ao2_ref(tech_holder, -1);
01295 tech_holder = NULL;
01296
01297 ast_verb(3, "Message technology handler '%s' registered.\n", tech->name);
01298
01299 return 0;
01300 }
01301
01302 int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
01303 {
01304 struct ast_msg_tech_holder *tech_holder;
01305
01306 tech_holder = msg_find_by_tech(tech, OBJ_POINTER | OBJ_UNLINK);
01307
01308 if (!tech_holder) {
01309 ast_log(LOG_ERROR, "No '%s' message technology found.\n", tech->name);
01310 return -1;
01311 }
01312
01313 ast_rwlock_wrlock(&tech_holder->tech_lock);
01314 tech_holder->tech = NULL;
01315 ast_rwlock_unlock(&tech_holder->tech_lock);
01316
01317 ao2_ref(tech_holder, -1);
01318 tech_holder = NULL;
01319
01320 ast_verb(3, "Message technology handler '%s' unregistered.\n", tech->name);
01321
01322 return 0;
01323 }
01324
01325 void ast_msg_shutdown(void)
01326 {
01327 if (msg_q_tp) {
01328 msg_q_tp = ast_taskprocessor_unreference(msg_q_tp);
01329 }
01330 }
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340 static void message_shutdown(void)
01341 {
01342 ast_custom_function_unregister(&msg_function);
01343 ast_custom_function_unregister(&msg_data_function);
01344 ast_unregister_application(app_msg_send);
01345 ast_manager_unregister("MessageSend");
01346
01347 if (msg_techs) {
01348 ao2_ref(msg_techs, -1);
01349 msg_techs = NULL;
01350 }
01351 }
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363 int ast_msg_init(void)
01364 {
01365 int res;
01366
01367 msg_q_tp = ast_taskprocessor_get("ast_msg_queue", TPS_REF_DEFAULT);
01368 if (!msg_q_tp) {
01369 return -1;
01370 }
01371
01372 msg_techs = ao2_container_alloc(17, msg_tech_hash, msg_tech_cmp);
01373 if (!msg_techs) {
01374 return -1;
01375 }
01376
01377 res = __ast_custom_function_register(&msg_function, NULL);
01378 res |= __ast_custom_function_register(&msg_data_function, NULL);
01379 res |= ast_register_application2(app_msg_send, msg_send_exec, NULL, NULL, NULL);
01380 res |= ast_manager_register_xml_core("MessageSend", EVENT_FLAG_MESSAGE, action_messagesend);
01381
01382 ast_register_atexit(message_shutdown);
01383
01384 return res;
01385 }