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
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "asterisk.h"
00042
00043 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 374338 $")
00044
00045 #include <ctype.h>
00046 #include <iksemel.h>
00047
00048 #include "asterisk/channel.h"
00049 #include "asterisk/jabber.h"
00050 #include "asterisk/file.h"
00051 #include "asterisk/config.h"
00052 #include "asterisk/callerid.h"
00053 #include "asterisk/lock.h"
00054 #include "asterisk/cli.h"
00055 #include "asterisk/app.h"
00056 #include "asterisk/pbx.h"
00057 #include "asterisk/md5.h"
00058 #include "asterisk/acl.h"
00059 #include "asterisk/utils.h"
00060 #include "asterisk/module.h"
00061 #include "asterisk/astobj.h"
00062 #include "asterisk/astdb.h"
00063 #include "asterisk/manager.h"
00064 #include "asterisk/event.h"
00065 #include "asterisk/devicestate.h"
00066 #include "asterisk/message.h"
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
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 #define JABBER_CONFIG "jabber.conf"
00289
00290
00291 static void aji_message_destroy(struct aji_message *obj);
00292 static int aji_is_secure(struct aji_client *client);
00293 #ifdef HAVE_OPENSSL
00294 static int aji_start_tls(struct aji_client *client);
00295 static int aji_tls_handshake(struct aji_client *client);
00296 #endif
00297 static int aji_io_recv(struct aji_client *client, char *buffer, size_t buf_len, int timeout);
00298 static int aji_recv(struct aji_client *client, int timeout);
00299 static int aji_send_header(struct aji_client *client, const char *to);
00300 static int aji_send_raw(struct aji_client *client, const char *xmlstr);
00301 static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming);
00302 static int aji_start_sasl(struct aji_client *client, enum ikssasltype type, char *username, char *pass);
00303 static int aji_act_hook(void *data, int type, iks *node);
00304 static void aji_handle_iq(struct aji_client *client, iks *node);
00305 static void aji_handle_message(struct aji_client *client, ikspak *pak);
00306 static void aji_handle_presence(struct aji_client *client, ikspak *pak);
00307 static void aji_handle_subscribe(struct aji_client *client, ikspak *pak);
00308 static int aji_send_raw_chat(struct aji_client *client, int groupchat, const char *nick, const char *address, const char *message);
00309 static void *aji_recv_loop(void *data);
00310 static int aji_initialize(struct aji_client *client);
00311 static int aji_client_connect(void *data, ikspak *pak);
00312 static void aji_set_presence(struct aji_client *client, char *to, char *from, int level, char *desc);
00313 static int aji_set_group_presence(struct aji_client *client, char *room, int level, char *nick, char *desc);
00314 static char *aji_do_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
00315 static char *aji_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
00316 static char *aji_show_clients(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
00317 static char *aji_show_buddies(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
00318 static int aji_create_client(char *label, struct ast_variable *var, int debug);
00319 static int aji_create_buddy(char *label, struct aji_client *client);
00320 static int aji_reload(int reload);
00321 static int aji_load_config(int reload);
00322 static void aji_pruneregister(struct aji_client *client);
00323 static int aji_filter_roster(void *data, ikspak *pak);
00324 static int aji_get_roster(struct aji_client *client);
00325 static int aji_client_info_handler(void *data, ikspak *pak);
00326 static int aji_dinfo_handler(void *data, ikspak *pak);
00327 static int aji_ditems_handler(void *data, ikspak *pak);
00328 static int aji_register_query_handler(void *data, ikspak *pak);
00329 static int aji_register_approve_handler(void *data, ikspak *pak);
00330 static int aji_reconnect(struct aji_client *client);
00331 static char *aji_cli_create_collection(struct ast_cli_entry *e, int cmd,
00332 struct ast_cli_args *a);
00333 static char *aji_cli_list_pubsub_nodes(struct ast_cli_entry *e, int cmd,
00334 struct ast_cli_args *a);
00335 static char *aji_cli_delete_pubsub_node(struct ast_cli_entry *e, int cmd, struct
00336 ast_cli_args *a);
00337 static char *aji_cli_purge_pubsub_nodes(struct ast_cli_entry *e, int cmd, struct
00338 ast_cli_args *a);
00339 static iks *jabber_make_auth(iksid * id, const char *pass, const char *sid);
00340 static int aji_receive_node_list(void *data, ikspak* pak);
00341 static void aji_init_event_distribution(struct aji_client *client);
00342 static iks* aji_create_pubsub_node(struct aji_client *client, const char *node_type,
00343 const char *name, const char *collection_name);
00344 static iks* aji_build_node_config(iks *pubsub, const char *node_type,
00345 const char *collection_name);
00346 static void aji_create_pubsub_collection(struct aji_client *client,
00347 const char *collection_name);
00348 static void aji_create_pubsub_leaf(struct aji_client *client, const char *collection_name,
00349 const char *leaf_name);
00350 static char *aji_cli_create_leafnode(struct ast_cli_entry *e, int cmd,
00351 struct ast_cli_args *a);
00352 static void aji_create_affiliations(struct aji_client *client, const char *node);
00353 static iks* aji_pubsub_iq_create(struct aji_client *client, const char *type);
00354 static void aji_publish_device_state(struct aji_client *client, const char * device,
00355 const char *device_state);
00356 static int aji_handle_pubsub_error(void *data, ikspak *pak);
00357 static int aji_handle_pubsub_event(void *data, ikspak *pak);
00358 static void aji_pubsub_subscribe(struct aji_client *client, const char *node);
00359 static void aji_delete_pubsub_node(struct aji_client *client, const char *node_name);
00360 static iks* aji_build_node_request(struct aji_client *client, const char *collection);
00361 static int aji_delete_node_list(void *data, ikspak* pak);
00362 static void aji_pubsub_purge_nodes(struct aji_client *client,
00363 const char* collection_name);
00364 static void aji_publish_mwi(struct aji_client *client, const char *mailbox,
00365 const char *context, const char *oldmsgs, const char *newmsgs);
00366 static void aji_devstate_cb(const struct ast_event *ast_event, void *data);
00367 static void aji_mwi_cb(const struct ast_event *ast_event, void *data);
00368 static iks* aji_build_publish_skeleton(struct aji_client *client, const char *node,
00369 const char *event_type);
00370
00371
00372
00373
00374
00375
00376
00377 static int msg_send_cb(const struct ast_msg *msg, const char *to, const char *from);
00378
00379 static const struct ast_msg_tech msg_tech = {
00380 .name = "xmpp",
00381 .msg_send = msg_send_cb,
00382 };
00383
00384 static struct ast_cli_entry aji_cli[] = {
00385 AST_CLI_DEFINE(aji_do_set_debug, "Enable/Disable Jabber debug"),
00386 AST_CLI_DEFINE(aji_do_reload, "Reload Jabber configuration"),
00387 AST_CLI_DEFINE(aji_show_clients, "Show state of clients and components"),
00388 AST_CLI_DEFINE(aji_show_buddies, "Show buddy lists of our clients"),
00389 AST_CLI_DEFINE(aji_cli_create_collection, "Creates a PubSub node collection."),
00390 AST_CLI_DEFINE(aji_cli_list_pubsub_nodes, "Lists PubSub nodes"),
00391 AST_CLI_DEFINE(aji_cli_create_leafnode, "Creates a PubSub leaf node"),
00392 AST_CLI_DEFINE(aji_cli_delete_pubsub_node, "Deletes a PubSub node"),
00393 AST_CLI_DEFINE(aji_cli_purge_pubsub_nodes, "Purges PubSub nodes"),
00394 };
00395
00396 static char *app_ajisend = "JabberSend";
00397 static char *app_ajisendgroup = "JabberSendGroup";
00398 static char *app_ajistatus = "JabberStatus";
00399 static char *app_ajijoin = "JabberJoin";
00400 static char *app_ajileave = "JabberLeave";
00401
00402 static struct aji_client_container clients;
00403 static struct aji_capabilities *capabilities = NULL;
00404 static struct ast_event_sub *mwi_sub = NULL;
00405 static struct ast_event_sub *device_state_sub = NULL;
00406 static ast_cond_t message_received_condition;
00407 static ast_mutex_t messagelock;
00408
00409
00410 static struct ast_flags globalflags = { AJI_AUTOREGISTER | AJI_AUTOACCEPT };
00411
00412
00413 static struct ast_flags pubsubflags = { 0 };
00414
00415
00416
00417
00418
00419
00420 void ast_aji_client_destroy(struct aji_client *obj)
00421 {
00422 struct aji_message *tmp;
00423 ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, ast_aji_buddy_destroy);
00424 ASTOBJ_CONTAINER_DESTROY(&obj->buddies);
00425 iks_filter_delete(obj->f);
00426 iks_parser_delete(obj->p);
00427 iks_stack_delete(obj->stack);
00428 AST_LIST_LOCK(&obj->messages);
00429 while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) {
00430 aji_message_destroy(tmp);
00431 }
00432 AST_LIST_HEAD_DESTROY(&obj->messages);
00433 ast_free(obj);
00434 }
00435
00436
00437
00438
00439
00440
00441
00442 void ast_aji_buddy_destroy(struct aji_buddy *obj)
00443 {
00444 struct aji_resource *tmp;
00445
00446 while ((tmp = obj->resources)) {
00447 obj->resources = obj->resources->next;
00448 ast_free(tmp->description);
00449 ast_free(tmp);
00450 }
00451
00452 ast_free(obj);
00453 }
00454
00455
00456
00457
00458
00459
00460
00461 static void aji_message_destroy(struct aji_message *obj)
00462 {
00463 if (obj->from) {
00464 ast_free(obj->from);
00465 }
00466 if (obj->message) {
00467 ast_free(obj->message);
00468 }
00469 ast_free(obj);
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 static struct aji_version *aji_find_version(char *node, char *version, ikspak *pak)
00483 {
00484 struct aji_capabilities *list = NULL;
00485 struct aji_version *res = NULL;
00486
00487 list = capabilities;
00488
00489 if (!node) {
00490 node = pak->from->full;
00491 }
00492 if (!version) {
00493 version = "none supplied.";
00494 }
00495 while (list) {
00496 if (!strcasecmp(list->node, node)) {
00497 res = list->versions;
00498 while(res) {
00499 if (!strcasecmp(res->version, version)) {
00500 return res;
00501 }
00502 res = res->next;
00503 }
00504
00505
00506 if (!res) {
00507 res = ast_malloc(sizeof(*res));
00508 if (!res) {
00509 ast_log(LOG_ERROR, "Out of memory!\n");
00510 return NULL;
00511 }
00512 res->jingle = 0;
00513 res->parent = list;
00514 ast_copy_string(res->version, version, sizeof(res->version));
00515 res->next = list->versions;
00516 list->versions = res;
00517 return res;
00518 }
00519 }
00520 list = list->next;
00521 }
00522
00523 if (!list) {
00524 list = ast_malloc(sizeof(*list));
00525 if (!list) {
00526 ast_log(LOG_ERROR, "Out of memory!\n");
00527 return NULL;
00528 }
00529 res = ast_malloc(sizeof(*res));
00530 if (!res) {
00531 ast_log(LOG_ERROR, "Out of memory!\n");
00532 ast_free(list);
00533 return NULL;
00534 }
00535 ast_copy_string(list->node, node, sizeof(list->node));
00536 ast_copy_string(res->version, version, sizeof(res->version));
00537 res->jingle = 0;
00538 res->parent = list;
00539 res->next = NULL;
00540 list->versions = res;
00541 list->next = capabilities;
00542 capabilities = list;
00543 }
00544 return res;
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554 static struct aji_resource *aji_find_resource(struct aji_buddy *buddy, char *name)
00555 {
00556 struct aji_resource *res = NULL;
00557 if (!buddy || !name) {
00558 return res;
00559 }
00560 res = buddy->resources;
00561 while (res) {
00562 if (!strcasecmp(res->resource, name)) {
00563 break;
00564 }
00565 res = res->next;
00566 }
00567 return res;
00568 }
00569
00570
00571
00572
00573
00574
00575
00576 static int gtalk_yuck(iks *node)
00577 {
00578 if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps")) {
00579 ast_debug(1, "Found resource with Googletalk voice capabilities\n");
00580 return 1;
00581 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 camera-v1 video-v1 voice-v1")) {
00582 ast_debug(1, "Found resource with Gmail voice/video chat capabilities\n");
00583 return 1;
00584 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 video-v1 voice-v1")) {
00585 ast_debug(1, "Found resource with Gmail voice/video chat capabilities (no camera)\n");
00586 return 1;
00587 }
00588
00589 return 0;
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 static iks *jabber_make_auth(iksid * id, const char *pass, const char *sid)
00601 {
00602 iks *x, *y;
00603 x = iks_new("iq");
00604 iks_insert_attrib(x, "type", "set");
00605 y = iks_insert(x, "query");
00606 iks_insert_attrib(y, "xmlns", IKS_NS_AUTH);
00607 iks_insert_cdata(iks_insert(y, "username"), id->user, 0);
00608 iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0);
00609 if (sid) {
00610 char buf[41];
00611 char sidpass[100];
00612 snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass);
00613 ast_sha1_hash(buf, sidpass);
00614 iks_insert_cdata(iks_insert(y, "digest"), buf, 0);
00615 } else {
00616 iks_insert_cdata(iks_insert(y, "password"), pass, 0);
00617 }
00618 return x;
00619 }
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 static int aji_status_exec(struct ast_channel *chan, const char *data)
00631 {
00632 struct aji_client *client = NULL;
00633 struct aji_buddy *buddy = NULL;
00634 struct aji_resource *r = NULL;
00635 char *s = NULL;
00636 int stat = 7;
00637 char status[2];
00638 static int deprecation_warning = 0;
00639 AST_DECLARE_APP_ARGS(args,
00640 AST_APP_ARG(sender);
00641 AST_APP_ARG(jid);
00642 AST_APP_ARG(variable);
00643 );
00644 AST_DECLARE_APP_ARGS(jid,
00645 AST_APP_ARG(screenname);
00646 AST_APP_ARG(resource);
00647 );
00648
00649 if (deprecation_warning++ % 10 == 0) {
00650 ast_log(LOG_WARNING, "JabberStatus is deprecated. Please use the JABBER_STATUS dialplan function in the future.\n");
00651 }
00652
00653 if (!data) {
00654 ast_log(LOG_ERROR, "Usage: JabberStatus(<sender>,<jid>[/<resource>],<varname>\n");
00655 return 0;
00656 }
00657 s = ast_strdupa(data);
00658 AST_STANDARD_APP_ARGS(args, s);
00659
00660 if (args.argc != 3) {
00661 ast_log(LOG_ERROR, "JabberStatus() requires 3 arguments.\n");
00662 return -1;
00663 }
00664
00665 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/');
00666 if (jid.argc < 1 || jid.argc > 2) {
00667 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid);
00668 return -1;
00669 }
00670
00671 if (!(client = ast_aji_get_client(args.sender))) {
00672 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender);
00673 return -1;
00674 }
00675 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname);
00676 if (!buddy) {
00677 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname);
00678 ASTOBJ_UNREF(client, ast_aji_client_destroy);
00679 return -1;
00680 }
00681 r = aji_find_resource(buddy, jid.resource);
00682 if (!r && buddy->resources) {
00683 r = buddy->resources;
00684 }
00685 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
00686 ASTOBJ_UNREF(client, ast_aji_client_destroy);
00687 if (!r) {
00688 ast_log(LOG_NOTICE, "Resource '%s' of buddy '%s' was not found\n", jid.resource, jid.screenname);
00689 } else {
00690 stat = r->status;
00691 }
00692 snprintf(status, sizeof(status), "%d", stat);
00693 pbx_builtin_setvar_helper(chan, args.variable, status);
00694 return 0;
00695 }
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 static int acf_jabberstatus_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
00707 {
00708 struct aji_client *client = NULL;
00709 struct aji_buddy *buddy = NULL;
00710 struct aji_resource *r = NULL;
00711 int stat = 7;
00712 AST_DECLARE_APP_ARGS(args,
00713 AST_APP_ARG(sender);
00714 AST_APP_ARG(jid);
00715 );
00716 AST_DECLARE_APP_ARGS(jid,
00717 AST_APP_ARG(screenname);
00718 AST_APP_ARG(resource);
00719 );
00720
00721 if (!data) {
00722 ast_log(LOG_ERROR, "Usage: JABBER_STATUS(<sender>,<jid>[/<resource>])\n");
00723 return 0;
00724 }
00725 AST_STANDARD_APP_ARGS(args, data);
00726
00727 if (args.argc != 2) {
00728 ast_log(LOG_ERROR, "JABBER_STATUS requires 2 arguments: sender and jid.\n");
00729 return -1;
00730 }
00731
00732 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/');
00733 if (jid.argc < 1 || jid.argc > 2) {
00734 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid);
00735 return -1;
00736 }
00737
00738 if (!(client = ast_aji_get_client(args.sender))) {
00739 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender);
00740 return -1;
00741 }
00742 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname);
00743 if (!buddy) {
00744 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname);
00745 ASTOBJ_UNREF(client, ast_aji_client_destroy);
00746 return -1;
00747 }
00748 r = aji_find_resource(buddy, jid.resource);
00749 if (!r && buddy->resources) {
00750 r = buddy->resources;
00751 }
00752 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
00753 ASTOBJ_UNREF(client, ast_aji_client_destroy);
00754 if (!r) {
00755 ast_log(LOG_NOTICE, "Resource %s of buddy %s was not found.\n", jid.resource, jid.screenname);
00756 } else {
00757 stat = r->status;
00758 }
00759 snprintf(buf, buflen, "%d", stat);
00760 return 0;
00761 }
00762
00763 static struct ast_custom_function jabberstatus_function = {
00764 .name = "JABBER_STATUS",
00765 .read = acf_jabberstatus_read,
00766 };
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777 static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
00778 {
00779 char *aux = NULL, *parse = NULL;
00780 int timeout;
00781 int jidlen, resourcelen;
00782 struct timeval start;
00783 long diff = 0;
00784 struct aji_client *client = NULL;
00785 int found = 0;
00786 struct aji_message *tmp = NULL;
00787 AST_DECLARE_APP_ARGS(args,
00788 AST_APP_ARG(account);
00789 AST_APP_ARG(jid);
00790 AST_APP_ARG(timeout);
00791 );
00792 AST_DECLARE_APP_ARGS(jid,
00793 AST_APP_ARG(screenname);
00794 AST_APP_ARG(resource);
00795 );
00796
00797 if (ast_strlen_zero(data)) {
00798 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name);
00799 return -1;
00800 }
00801
00802 parse = ast_strdupa(data);
00803 AST_STANDARD_APP_ARGS(args, parse);
00804
00805 if (args.argc < 2 || args.argc > 3) {
00806 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name);
00807 return -1;
00808 }
00809
00810 parse = ast_strdupa(args.jid);
00811 AST_NONSTANDARD_APP_ARGS(jid, parse, '/');
00812 if (jid.argc < 1 || jid.argc > 2 || strlen(args.jid) > AJI_MAX_JIDLEN) {
00813 ast_log(LOG_WARNING, "Invalid JID : %s\n", parse);
00814 return -1;
00815 }
00816
00817 if (ast_strlen_zero(args.timeout)) {
00818 timeout = 20;
00819 } else {
00820 sscanf(args.timeout, "%d", &timeout);
00821 if (timeout <= 0) {
00822 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
00823 return -1;
00824 }
00825 }
00826
00827 jidlen = strlen(jid.screenname);
00828 resourcelen = ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource);
00829
00830 client = ast_aji_get_client(args.account);
00831 if (!client) {
00832 ast_log(LOG_WARNING, "Could not find client %s, exiting\n", args.account);
00833 return -1;
00834 }
00835
00836 ast_debug(3, "Waiting for an XMPP message from %s\n", args.jid);
00837
00838 start = ast_tvnow();
00839
00840 if (ast_autoservice_start(chan) < 0) {
00841 ast_log(LOG_WARNING, "Cannot start autoservice for channel %s\n", ast_channel_name(chan));
00842 ASTOBJ_UNREF(client, ast_aji_client_destroy);
00843 return -1;
00844 }
00845
00846
00847
00848 while (diff < timeout) {
00849 struct timespec ts = { 0, };
00850 struct timeval wait;
00851 int res;
00852
00853 wait = ast_tvadd(start, ast_tv(timeout, 0));
00854 ts.tv_sec = wait.tv_sec;
00855 ts.tv_nsec = wait.tv_usec * 1000;
00856
00857
00858 ast_mutex_lock(&messagelock);
00859 res = ast_cond_timedwait(&message_received_condition, &messagelock, &ts);
00860 ast_mutex_unlock(&messagelock);
00861 if (res == ETIMEDOUT) {
00862 ast_debug(3, "No message received from %s in %d seconds\n", args.jid, timeout);
00863 break;
00864 }
00865
00866 AST_LIST_LOCK(&client->messages);
00867 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) {
00868 if (jid.argc == 1) {
00869
00870 if (strncasecmp(jid.screenname, tmp->from, jidlen)) {
00871 continue;
00872 }
00873 } else {
00874
00875 char *resource = strchr(tmp->from, '/');
00876 if (!resource || strlen(resource) == 0) {
00877 ast_log(LOG_WARNING, "Remote JID has no resource : %s\n", tmp->from);
00878 if (strncasecmp(jid.screenname, tmp->from, jidlen)) {
00879 continue;
00880 }
00881 } else {
00882 resource ++;
00883 if (strncasecmp(jid.screenname, tmp->from, jidlen) || strncmp(jid.resource, resource, resourcelen)) {
00884 continue;
00885 }
00886 }
00887 }
00888
00889 if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) {
00890 ast_debug(3, "Found old message from %s, deleting it\n", tmp->from);
00891 AST_LIST_REMOVE_CURRENT(list);
00892 aji_message_destroy(tmp);
00893 continue;
00894 }
00895 found = 1;
00896 aux = ast_strdupa(tmp->message);
00897 AST_LIST_REMOVE_CURRENT(list);
00898 aji_message_destroy(tmp);
00899 break;
00900 }
00901 AST_LIST_TRAVERSE_SAFE_END;
00902 AST_LIST_UNLOCK(&client->messages);
00903 if (found) {
00904 break;
00905 }
00906
00907
00908 diff = ast_tvdiff_ms(ast_tvnow(), start);
00909 }
00910
00911 ASTOBJ_UNREF(client, ast_aji_client_destroy);
00912 if (ast_autoservice_stop(chan) < 0) {
00913 ast_log(LOG_WARNING, "Cannot stop autoservice for channel %s\n", ast_channel_name(chan));
00914 }
00915
00916
00917 if (!found) {
00918 ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid);
00919 return -1;
00920 }
00921 ast_copy_string(buf, aux, buflen);
00922
00923 return 0;
00924 }
00925
00926 static struct ast_custom_function jabberreceive_function = {
00927 .name = "JABBER_RECEIVE",
00928 .read = acf_jabberreceive_read,
00929 };
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940 static int delete_old_messages(struct aji_client *client, char *from)
00941 {
00942 int deleted = 0;
00943 int isold = 0;
00944 struct aji_message *tmp = NULL;
00945 if (!client) {
00946 ast_log(LOG_ERROR, "Cannot find our XMPP client\n");
00947 return -1;
00948 }
00949
00950
00951 AST_LIST_LOCK(&client->messages);
00952 if (AST_LIST_EMPTY(&client->messages)) {
00953 AST_LIST_UNLOCK(&client->messages);
00954 return 0;
00955 }
00956
00957 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) {
00958 if (isold) {
00959 if (!from || !strncasecmp(from, tmp->from, strlen(from))) {
00960 AST_LIST_REMOVE_CURRENT(list);
00961 aji_message_destroy(tmp);
00962 deleted ++;
00963 }
00964 } else if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) {
00965 isold = 1;
00966 if (!from || !strncasecmp(from, tmp->from, strlen(from))) {
00967 AST_LIST_REMOVE_CURRENT(list);
00968 aji_message_destroy(tmp);
00969 deleted ++;
00970 }
00971 }
00972 }
00973 AST_LIST_TRAVERSE_SAFE_END;
00974 AST_LIST_UNLOCK(&client->messages);
00975
00976 return deleted;
00977 }
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987 static int delete_old_messages_all(struct aji_client *client)
00988 {
00989 return delete_old_messages(client, NULL);
00990 }
00991
00992
00993
00994
00995
00996
00997
00998
00999 static int aji_join_exec(struct ast_channel *chan, const char *data)
01000 {
01001 struct aji_client *client = NULL;
01002 char *s;
01003 char nick[AJI_MAX_RESJIDLEN];
01004
01005 AST_DECLARE_APP_ARGS(args,
01006 AST_APP_ARG(sender);
01007 AST_APP_ARG(jid);
01008 AST_APP_ARG(nick);
01009 );
01010
01011 if (!data) {
01012 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin);
01013 return -1;
01014 }
01015 s = ast_strdupa(data);
01016
01017 AST_STANDARD_APP_ARGS(args, s);
01018 if (args.argc < 2 || args.argc > 3) {
01019 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin);
01020 return -1;
01021 }
01022
01023 if (strchr(args.jid, '/')) {
01024 ast_log(LOG_ERROR, "Invalid room name : resource must not be appended\n");
01025 return -1;
01026 }
01027
01028 if (!(client = ast_aji_get_client(args.sender))) {
01029 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
01030 return -1;
01031 }
01032
01033 if (!ast_strlen_zero(args.nick)) {
01034 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick);
01035 } else {
01036 if (client->component) {
01037 sprintf(nick, "asterisk");
01038 } else {
01039 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user);
01040 }
01041 }
01042
01043 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) {
01044 ast_aji_join_chat(client, args.jid, nick);
01045 } else {
01046 ast_log(LOG_ERROR, "Problem with specified jid of '%s'\n", args.jid);
01047 }
01048
01049 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01050 return 0;
01051 }
01052
01053
01054
01055
01056
01057
01058
01059
01060 static int aji_leave_exec(struct ast_channel *chan, const char *data)
01061 {
01062 struct aji_client *client = NULL;
01063 char *s;
01064 char nick[AJI_MAX_RESJIDLEN];
01065 AST_DECLARE_APP_ARGS(args,
01066 AST_APP_ARG(sender);
01067 AST_APP_ARG(jid);
01068 AST_APP_ARG(nick);
01069 );
01070
01071 if (!data) {
01072 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave);
01073 return -1;
01074 }
01075 s = ast_strdupa(data);
01076
01077 AST_STANDARD_APP_ARGS(args, s);
01078 if (args.argc < 2 || args.argc > 3) {
01079 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave);
01080 return -1;
01081 }
01082
01083 if (strchr(args.jid, '/')) {
01084 ast_log(LOG_ERROR, "Invalid room name, resource must not be appended\n");
01085 return -1;
01086 }
01087
01088 if (!(client = ast_aji_get_client(args.sender))) {
01089 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
01090 return -1;
01091 }
01092
01093 if (!ast_strlen_zero(args.nick)) {
01094 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick);
01095 } else {
01096 if (client->component) {
01097 sprintf(nick, "asterisk");
01098 } else {
01099 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user);
01100 }
01101 }
01102
01103 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) {
01104 ast_aji_leave_chat(client, args.jid, nick);
01105 }
01106 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01107 return 0;
01108 }
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118 static int aji_send_exec(struct ast_channel *chan, const char *data)
01119 {
01120 struct aji_client *client = NULL;
01121 char *s;
01122 AST_DECLARE_APP_ARGS(args,
01123 AST_APP_ARG(sender);
01124 AST_APP_ARG(recipient);
01125 AST_APP_ARG(message);
01126 );
01127
01128 if (!data) {
01129 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend);
01130 return -1;
01131 }
01132 s = ast_strdupa(data);
01133
01134 AST_STANDARD_APP_ARGS(args, s);
01135 if (args.argc < 3) {
01136 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend);
01137 return -1;
01138 }
01139
01140 if (!(client = ast_aji_get_client(args.sender))) {
01141 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender);
01142 return -1;
01143 }
01144 if (strchr(args.recipient, '@') && !ast_strlen_zero(args.message)) {
01145 ast_aji_send_chat(client, args.recipient, args.message);
01146 }
01147 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01148 return 0;
01149 }
01150
01151 static int msg_send_cb(const struct ast_msg *msg, const char *to, const char *from)
01152 {
01153 struct aji_client *client;
01154 char *sender;
01155 char *dest;
01156 int res;
01157
01158 sender = ast_strdupa(from);
01159 strsep(&sender, ":");
01160 dest = ast_strdupa(to);
01161 strsep(&dest, ":");
01162
01163 if (ast_strlen_zero(sender)) {
01164 ast_log(LOG_ERROR, "MESSAGE(from) of '%s' invalid for xmpp\n", from);
01165 return -1;
01166 }
01167
01168 if (!(client = ast_aji_get_client(sender))) {
01169 ast_log(LOG_WARNING, "Could not finder account to send from as '%s'\n", sender);
01170 return -1;
01171 }
01172
01173 ast_debug(1, "Sending message to '%s' from '%s'\n", dest, client->name);
01174
01175 res = ast_aji_send_chat(client, dest, ast_msg_get_body(msg));
01176 if (res != IKS_OK) {
01177 ast_log(LOG_WARNING, "Failed to send xmpp message (%d).\n", res);
01178 }
01179
01180 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01181 return res == IKS_OK ? 0 : -1;
01182 }
01183
01184
01185
01186
01187
01188
01189
01190
01191 static int aji_sendgroup_exec(struct ast_channel *chan, const char *data)
01192 {
01193 struct aji_client *client = NULL;
01194 char *s;
01195 char nick[AJI_MAX_RESJIDLEN];
01196 int res = 0;
01197 AST_DECLARE_APP_ARGS(args,
01198 AST_APP_ARG(sender);
01199 AST_APP_ARG(groupchat);
01200 AST_APP_ARG(message);
01201 AST_APP_ARG(nick);
01202 );
01203
01204 if (!data) {
01205 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup);
01206 return -1;
01207 }
01208 s = ast_strdupa(data);
01209
01210 AST_STANDARD_APP_ARGS(args, s);
01211 if (args.argc < 3 || args.argc > 4) {
01212 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup);
01213 return -1;
01214 }
01215
01216 if (!(client = ast_aji_get_client(args.sender))) {
01217 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
01218 return -1;
01219 }
01220
01221 if (ast_strlen_zero(args.nick) || args.argc == 3) {
01222 if (client->component) {
01223 sprintf(nick, "asterisk");
01224 } else {
01225 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user);
01226 }
01227 } else {
01228 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick);
01229 }
01230
01231 if (strchr(args.groupchat, '@') && !ast_strlen_zero(args.message)) {
01232 res = ast_aji_send_groupchat(client, nick, args.groupchat, args.message);
01233 }
01234
01235 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01236 if (res != IKS_OK) {
01237 return -1;
01238 }
01239 return 0;
01240 }
01241
01242
01243
01244
01245
01246
01247 static int aji_is_secure(struct aji_client *client)
01248 {
01249 #ifdef HAVE_OPENSSL
01250 return client->stream_flags & SECURE;
01251 #else
01252 return 0;
01253 #endif
01254 }
01255
01256 #ifdef HAVE_OPENSSL
01257
01258
01259
01260
01261
01262
01263
01264 static int aji_start_tls(struct aji_client *client)
01265 {
01266 int ret;
01267
01268
01269 if ((ret = iks_send_raw(client->p, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"))) {
01270 return ret;
01271 }
01272
01273 client->stream_flags |= TRY_SECURE;
01274 return IKS_OK;
01275 }
01276
01277
01278
01279
01280
01281
01282
01283 static int aji_tls_handshake(struct aji_client *client)
01284 {
01285 int sock;
01286
01287 ast_debug(1, "Starting TLS handshake\n");
01288
01289
01290 client->ssl_method = SSLv3_method();
01291 if (!(client->ssl_context = SSL_CTX_new((SSL_METHOD *) client->ssl_method))) {
01292 return IKS_NET_TLSFAIL;
01293 }
01294
01295
01296 if (!(client->ssl_session = SSL_new(client->ssl_context))) {
01297 return IKS_NET_TLSFAIL;
01298 }
01299
01300
01301 sock = iks_fd(client->p);
01302 if (!SSL_set_fd(client->ssl_session, sock)) {
01303 return IKS_NET_TLSFAIL;
01304 }
01305
01306
01307 if (!SSL_connect(client->ssl_session)) {
01308 return IKS_NET_TLSFAIL;
01309 }
01310
01311 client->stream_flags &= (~TRY_SECURE);
01312 client->stream_flags |= SECURE;
01313
01314
01315 if (aji_send_header(client, client->jid->server) != IKS_OK) {
01316 return IKS_NET_TLSFAIL;
01317 }
01318
01319 ast_debug(1, "TLS started with server\n");
01320
01321 return IKS_OK;
01322 }
01323 #endif
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336 static int aji_io_recv(struct aji_client *client, char *buffer, size_t buf_len, int timeout)
01337 {
01338 struct pollfd pfd = { .events = POLLIN };
01339 int len, res;
01340
01341 #ifdef HAVE_OPENSSL
01342 if (aji_is_secure(client)) {
01343 pfd.fd = SSL_get_fd(client->ssl_session);
01344 if (pfd.fd < 0) {
01345 return -1;
01346 }
01347 } else
01348 #endif
01349 pfd.fd = iks_fd(client->p);
01350
01351 res = ast_poll(&pfd, 1, timeout > 0 ? timeout * 1000 : -1);
01352 if (res > 0) {
01353 #ifdef HAVE_OPENSSL
01354 if (aji_is_secure(client)) {
01355 len = SSL_read(client->ssl_session, buffer, buf_len);
01356 } else
01357 #endif
01358 len = recv(pfd.fd, buffer, buf_len, 0);
01359
01360 if (len > 0) {
01361 return len;
01362 } else if (len <= 0) {
01363 return -1;
01364 }
01365 }
01366 return res;
01367 }
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381 static int aji_recv (struct aji_client *client, int timeout)
01382 {
01383 int len, ret;
01384 char buf[NET_IO_BUF_SIZE - 1];
01385 char newbuf[NET_IO_BUF_SIZE - 1];
01386 int pos = 0;
01387 int newbufpos = 0;
01388 unsigned char c;
01389
01390 memset(buf, 0, sizeof(buf));
01391 memset(newbuf, 0, sizeof(newbuf));
01392
01393 while (1) {
01394 len = aji_io_recv(client, buf, NET_IO_BUF_SIZE - 2, timeout);
01395 if (len < 0) return IKS_NET_RWERR;
01396 if (len == 0) return IKS_NET_EXPIRED;
01397 buf[len] = '\0';
01398
01399
01400
01401
01402 while (pos < len) {
01403 c = buf[pos];
01404
01405
01406 if (c == '>') {
01407 while (isspace(buf[pos+1])) {
01408 pos++;
01409 }
01410 }
01411 newbuf[newbufpos] = c;
01412 newbufpos ++;
01413 pos++;
01414 }
01415 pos = 0;
01416 newbufpos = 0;
01417
01418
01419
01420 aji_log_hook(client, buf, len, 1);
01421
01422
01423
01424 ret = iks_parse(client->p, newbuf, 0, 0);
01425 memset(newbuf, 0, sizeof(newbuf));
01426
01427 switch (ret) {
01428 case IKS_NOMEM:
01429 ast_log(LOG_WARNING, "Parsing failure: Out of memory.\n");
01430 break;
01431 case IKS_BADXML:
01432 ast_log(LOG_WARNING, "Parsing failure: Invalid XML.\n");
01433 break;
01434 case IKS_HOOK:
01435 ast_log(LOG_WARNING, "Parsing failure: Hook returned an error.\n");
01436 break;
01437 }
01438 if (ret != IKS_OK) {
01439 return ret;
01440 }
01441 ast_debug(3, "XML parsing successful\n");
01442 }
01443 return IKS_OK;
01444 }
01445
01446
01447
01448
01449
01450
01451
01452
01453 static int aji_send_header(struct aji_client *client, const char *to)
01454 {
01455 char *msg;
01456 int len, err;
01457
01458 len = 91 + strlen(client->name_space) + 6 + strlen(to) + 16 + 1;
01459 msg = iks_malloc(len);
01460 if (!msg)
01461 return IKS_NOMEM;
01462 sprintf(msg, "<?xml version='1.0'?>"
01463 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='"
01464 "%s' to='%s' version='1.0'>", client->name_space, to);
01465 err = aji_send_raw(client, msg);
01466 iks_free(msg);
01467 if (err != IKS_OK)
01468 return err;
01469
01470 return IKS_OK;
01471 }
01472
01473
01474
01475
01476
01477
01478
01479 int ast_aji_send(struct aji_client *client, iks *x)
01480 {
01481 return aji_send_raw(client, iks_string(iks_stack(x), x));
01482 }
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493 static int aji_send_raw(struct aji_client *client, const char *xmlstr)
01494 {
01495 int ret;
01496 #ifdef HAVE_OPENSSL
01497 int len = strlen(xmlstr);
01498
01499 if (aji_is_secure(client)) {
01500 ret = SSL_write(client->ssl_session, xmlstr, len);
01501 if (ret) {
01502
01503
01504 aji_log_hook(client, xmlstr, len, 0);
01505 return IKS_OK;
01506 }
01507 }
01508 #endif
01509
01510
01511 ret = iks_send_raw(client->p, xmlstr);
01512 if (ret != IKS_OK) {
01513 return ret;
01514 }
01515
01516 return IKS_OK;
01517 }
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527 static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming)
01528 {
01529 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01530
01531 if (!ast_strlen_zero(xmpp)) {
01532 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp);
01533 }
01534
01535 if (client->debug) {
01536 if (is_incoming) {
01537 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp);
01538 } else {
01539 if (strlen(xmpp) == 1) {
01540 if (option_debug > 2 && xmpp[0] == ' ') {
01541 ast_verbose("\nJABBER: Keep alive packet\n");
01542 }
01543 } else {
01544 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp);
01545 }
01546 }
01547
01548 }
01549 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01550 }
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562 static int aji_start_sasl(struct aji_client *client, enum ikssasltype type, char *username, char *pass)
01563 {
01564 iks *x = NULL;
01565 int len;
01566 char *s;
01567 char *base64;
01568
01569
01570
01571
01572 if ((type & IKS_STREAM_SASL_MD5) && !aji_is_secure(client))
01573 return iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, username, pass);
01574 if (!(type & IKS_STREAM_SASL_PLAIN)) {
01575 ast_log(LOG_ERROR, "Server does not support SASL PLAIN authentication\n");
01576 return IKS_NET_NOTSUPP;
01577 }
01578
01579 x = iks_new("auth");
01580 if (!x) {
01581 ast_log(LOG_ERROR, "Out of memory.\n");
01582 return IKS_NET_NOTSUPP;
01583 }
01584
01585 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL);
01586 len = strlen(username) + strlen(pass) + 3;
01587 s = ast_alloca(len);
01588 base64 = ast_alloca((len + 2) * 4 / 3);
01589 iks_insert_attrib(x, "mechanism", "PLAIN");
01590 snprintf(s, len, "%c%s%c%s", 0, username, 0, pass);
01591
01592
01593
01594
01595
01596 ast_base64encode(base64, (const unsigned char *) s, len - 1, (len + 2) * 4 / 3);
01597 iks_insert_cdata(x, base64, 0);
01598 ast_aji_send(client, x);
01599 iks_delete(x);
01600
01601 return IKS_OK;
01602 }
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612 static int aji_act_hook(void *data, int type, iks *node)
01613 {
01614 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01615 ikspak *pak = NULL;
01616 iks *auth = NULL;
01617 int features = 0;
01618
01619 if (!node) {
01620 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n");
01621 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01622 return IKS_HOOK;
01623 }
01624
01625 if (client->state == AJI_DISCONNECTING) {
01626 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01627 return IKS_HOOK;
01628 }
01629
01630 pak = iks_packet(node);
01631
01632
01633
01634
01635 if (iks_has_children(node) && strchr(iks_name(iks_child(node)), ':')) {
01636 char *node_ns = NULL;
01637 char attr[AJI_MAX_ATTRLEN];
01638 char *node_name = iks_name(iks_child(node));
01639 char *aux = strchr(node_name, ':') + 1;
01640 snprintf(attr, strlen("xmlns:") + (strlen(node_name) - strlen(aux)), "xmlns:%s", node_name);
01641 node_ns = iks_find_attrib(iks_child(node), attr);
01642 if (node_ns) {
01643 pak->ns = node_ns;
01644 pak->query = iks_child(node);
01645 }
01646 }
01647
01648
01649 if (!client->component) {
01650 switch (type) {
01651 case IKS_NODE_START:
01652 if (client->usetls && !aji_is_secure(client)) {
01653 #ifndef HAVE_OPENSSL
01654 ast_log(LOG_ERROR, "TLS connection cannot be established. Please install OpenSSL and its development libraries on this system, or disable the TLS option in your configuration file\n");
01655 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01656 return IKS_HOOK;
01657 #else
01658 if (aji_start_tls(client) == IKS_NET_TLSFAIL) {
01659 ast_log(LOG_ERROR, "Could not start TLS\n");
01660 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01661 return IKS_HOOK;
01662 }
01663 break;
01664 #endif
01665 }
01666 if (!client->usesasl) {
01667 iks_filter_add_rule(client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, IKS_RULE_DONE);
01668 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id"));
01669 if (auth) {
01670 iks_insert_attrib(auth, "id", client->mid);
01671 iks_insert_attrib(auth, "to", client->jid->server);
01672 ast_aji_increment_mid(client->mid);
01673 ast_aji_send(client, auth);
01674 iks_delete(auth);
01675 } else {
01676 ast_log(LOG_ERROR, "Out of memory.\n");
01677 }
01678 }
01679 break;
01680
01681 case IKS_NODE_NORMAL:
01682 #ifdef HAVE_OPENSSL
01683 if (client->stream_flags & TRY_SECURE) {
01684 if (!strcmp("proceed", iks_name(node))) {
01685 return aji_tls_handshake(client);
01686 }
01687 }
01688 #endif
01689 if (!strcmp("stream:features", iks_name(node))) {
01690 features = iks_stream_features(node);
01691 if (client->usesasl) {
01692 if (client->usetls && !aji_is_secure(client)) {
01693 break;
01694 }
01695 if (client->authorized) {
01696 if (features & IKS_STREAM_BIND) {
01697 iks_filter_add_rule(client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_DONE);
01698 auth = iks_make_resource_bind(client->jid);
01699 if (auth) {
01700 iks_insert_attrib(auth, "id", client->mid);
01701 ast_aji_increment_mid(client->mid);
01702 ast_aji_send(client, auth);
01703 iks_delete(auth);
01704 } else {
01705 ast_log(LOG_ERROR, "Out of memory.\n");
01706 break;
01707 }
01708 }
01709 if (features & IKS_STREAM_SESSION) {
01710 iks_filter_add_rule (client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, "auth", IKS_RULE_DONE);
01711 auth = iks_make_session();
01712 if (auth) {
01713 iks_insert_attrib(auth, "id", "auth");
01714 ast_aji_increment_mid(client->mid);
01715 ast_aji_send(client, auth);
01716 iks_delete(auth);
01717 } else {
01718 ast_log(LOG_ERROR, "Out of memory.\n");
01719 }
01720 }
01721 } else {
01722 int ret;
01723 if (!client->jid->user) {
01724 ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full);
01725 break;
01726 }
01727
01728 ret = aji_start_sasl(client, features, client->jid->user, client->password);
01729 if (ret != IKS_OK) {
01730 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01731 return IKS_HOOK;
01732 }
01733 break;
01734 }
01735 }
01736 } else if (!strcmp("failure", iks_name(node))) {
01737 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n");
01738 } else if (!strcmp("success", iks_name(node))) {
01739 client->authorized = 1;
01740 aji_send_header(client, client->jid->server);
01741 }
01742 break;
01743 case IKS_NODE_ERROR:
01744 ast_log(LOG_ERROR, "JABBER: Node Error\n");
01745 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01746 return IKS_HOOK;
01747 break;
01748 case IKS_NODE_STOP:
01749 ast_log(LOG_WARNING, "JABBER: Disconnected\n");
01750 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01751 return IKS_HOOK;
01752 break;
01753 }
01754 } else if (client->state != AJI_CONNECTED && client->component) {
01755 switch (type) {
01756 case IKS_NODE_START:
01757 if (client->state == AJI_DISCONNECTED) {
01758 char secret[160], shasum[320], *handshake;
01759
01760 sprintf(secret, "%s%s", pak->id, client->password);
01761 ast_sha1_hash(shasum, secret);
01762 if (ast_asprintf(&handshake, "<handshake>%s</handshake>", shasum) >= 0) {
01763 aji_send_raw(client, handshake);
01764 ast_free(handshake);
01765 }
01766 client->state = AJI_CONNECTING;
01767 if (aji_recv(client, 1) == 2)
01768 client->state = AJI_CONNECTED;
01769 else
01770 ast_log(LOG_WARNING, "Jabber didn't seem to handshake, failed to authenticate.\n");
01771 break;
01772 }
01773 break;
01774
01775 case IKS_NODE_NORMAL:
01776 break;
01777
01778 case IKS_NODE_ERROR:
01779 ast_log(LOG_ERROR, "JABBER: Node Error\n");
01780 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01781 return IKS_HOOK;
01782
01783 case IKS_NODE_STOP:
01784 ast_log(LOG_WARNING, "JABBER: Disconnected\n");
01785 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01786 return IKS_HOOK;
01787 }
01788 }
01789
01790 switch (pak->type) {
01791 case IKS_PAK_NONE:
01792 ast_debug(1, "JABBER: I don't know what to do with paktype NONE.\n");
01793 break;
01794 case IKS_PAK_MESSAGE:
01795 aji_handle_message(client, pak);
01796 ast_debug(1, "JABBER: Handling paktype MESSAGE.\n");
01797 break;
01798 case IKS_PAK_PRESENCE:
01799 aji_handle_presence(client, pak);
01800 ast_debug(1, "JABBER: Handling paktype PRESENCE\n");
01801 break;
01802 case IKS_PAK_S10N:
01803 aji_handle_subscribe(client, pak);
01804 ast_debug(1, "JABBER: Handling paktype S10N\n");
01805 break;
01806 case IKS_PAK_IQ:
01807 ast_debug(1, "JABBER: Handling paktype IQ\n");
01808 aji_handle_iq(client, node);
01809 break;
01810 default:
01811 ast_debug(1, "JABBER: I don't know anything about paktype '%d'\n", pak->type);
01812 break;
01813 }
01814
01815 iks_filter_packet(client->f, pak);
01816
01817 if (node)
01818 iks_delete(node);
01819
01820 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01821 return IKS_OK;
01822 }
01823
01824
01825
01826
01827
01828
01829
01830 static int aji_register_approve_handler(void *data, ikspak *pak)
01831 {
01832 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01833 iks *iq = NULL, *presence = NULL, *x = NULL;
01834
01835 iq = iks_new("iq");
01836 presence = iks_new("presence");
01837 x = iks_new("x");
01838 if (client && iq && presence && x) {
01839 if (!iks_find(pak->query, "remove")) {
01840 iks_insert_attrib(iq, "from", client->jid->full);
01841 iks_insert_attrib(iq, "to", pak->from->full);
01842 iks_insert_attrib(iq, "id", pak->id);
01843 iks_insert_attrib(iq, "type", "result");
01844 ast_aji_send(client, iq);
01845
01846 iks_insert_attrib(presence, "from", client->jid->full);
01847 iks_insert_attrib(presence, "to", pak->from->partial);
01848 iks_insert_attrib(presence, "id", client->mid);
01849 ast_aji_increment_mid(client->mid);
01850 iks_insert_attrib(presence, "type", "subscribe");
01851 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update");
01852 iks_insert_node(presence, x);
01853 ast_aji_send(client, presence);
01854 }
01855 } else {
01856 ast_log(LOG_ERROR, "Out of memory.\n");
01857 }
01858
01859 iks_delete(iq);
01860 iks_delete(presence);
01861 iks_delete(x);
01862
01863 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01864 return IKS_FILTER_EAT;
01865 }
01866
01867
01868
01869
01870
01871
01872
01873 static int aji_register_query_handler(void *data, ikspak *pak)
01874 {
01875 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01876 struct aji_buddy *buddy = NULL;
01877 iks *iq = NULL, *query = NULL;
01878
01879 client = (struct aji_client *) data;
01880
01881 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
01882 if (!buddy) {
01883 iks *error = NULL, *notacceptable = NULL;
01884
01885 ast_log(LOG_ERROR, "Someone.... %s tried to register but they aren't allowed\n", pak->from->partial);
01886 iq = iks_new("iq");
01887 query = iks_new("query");
01888 error = iks_new("error");
01889 notacceptable = iks_new("not-acceptable");
01890 if (iq && query && error && notacceptable) {
01891 iks_insert_attrib(iq, "type", "error");
01892 iks_insert_attrib(iq, "from", client->user);
01893 iks_insert_attrib(iq, "to", pak->from->full);
01894 iks_insert_attrib(iq, "id", pak->id);
01895 iks_insert_attrib(query, "xmlns", "jabber:iq:register");
01896 iks_insert_attrib(error, "code" , "406");
01897 iks_insert_attrib(error, "type", "modify");
01898 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
01899 iks_insert_node(iq, query);
01900 iks_insert_node(iq, error);
01901 iks_insert_node(error, notacceptable);
01902 ast_aji_send(client, iq);
01903 } else {
01904 ast_log(LOG_ERROR, "Out of memory.\n");
01905 }
01906
01907 iks_delete(error);
01908 iks_delete(notacceptable);
01909 } else if (!iks_find_attrib(pak->query, "node")) {
01910 iks *instructions = NULL;
01911 char *explain = "Welcome to Asterisk - the Open Source PBX.\n";
01912 iq = iks_new("iq");
01913 query = iks_new("query");
01914 instructions = iks_new("instructions");
01915 if (iq && query && instructions && client) {
01916 iks_insert_attrib(iq, "from", client->user);
01917 iks_insert_attrib(iq, "to", pak->from->full);
01918 iks_insert_attrib(iq, "id", pak->id);
01919 iks_insert_attrib(iq, "type", "result");
01920 iks_insert_attrib(query, "xmlns", "jabber:iq:register");
01921 iks_insert_cdata(instructions, explain, 0);
01922 iks_insert_node(iq, query);
01923 iks_insert_node(query, instructions);
01924 ast_aji_send(client, iq);
01925 } else {
01926 ast_log(LOG_ERROR, "Out of memory.\n");
01927 }
01928
01929 iks_delete(instructions);
01930 }
01931 iks_delete(iq);
01932 iks_delete(query);
01933 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
01934 ASTOBJ_UNREF(client, ast_aji_client_destroy);
01935 return IKS_FILTER_EAT;
01936 }
01937
01938
01939
01940
01941
01942
01943
01944
01945 static int aji_ditems_handler(void *data, ikspak *pak)
01946 {
01947 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01948 char *node = NULL;
01949
01950 if (!(node = iks_find_attrib(pak->query, "node"))) {
01951 iks *iq = NULL, *query = NULL, *item = NULL;
01952 iq = iks_new("iq");
01953 query = iks_new("query");
01954 item = iks_new("item");
01955
01956 if (iq && query && item) {
01957 iks_insert_attrib(iq, "from", client->user);
01958 iks_insert_attrib(iq, "to", pak->from->full);
01959 iks_insert_attrib(iq, "id", pak->id);
01960 iks_insert_attrib(iq, "type", "result");
01961 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
01962 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands");
01963 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands");
01964 iks_insert_attrib(item, "jid", client->user);
01965
01966 iks_insert_node(iq, query);
01967 iks_insert_node(query, item);
01968 ast_aji_send(client, iq);
01969 } else {
01970 ast_log(LOG_ERROR, "Out of memory.\n");
01971 }
01972
01973 iks_delete(iq);
01974 iks_delete(query);
01975 iks_delete(item);
01976
01977 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) {
01978 iks *iq, *query, *confirm;
01979 iq = iks_new("iq");
01980 query = iks_new("query");
01981 confirm = iks_new("item");
01982 if (iq && query && confirm && client) {
01983 iks_insert_attrib(iq, "from", client->user);
01984 iks_insert_attrib(iq, "to", pak->from->full);
01985 iks_insert_attrib(iq, "id", pak->id);
01986 iks_insert_attrib(iq, "type", "result");
01987 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
01988 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
01989 iks_insert_attrib(confirm, "node", "confirmaccount");
01990 iks_insert_attrib(confirm, "name", "Confirm AIM account");
01991 iks_insert_attrib(confirm, "jid", "blog.astjab.org");
01992
01993 iks_insert_node(iq, query);
01994 iks_insert_node(query, confirm);
01995 ast_aji_send(client, iq);
01996 } else {
01997 ast_log(LOG_ERROR, "Out of memory.\n");
01998 }
01999
02000 iks_delete(iq);
02001 iks_delete(query);
02002 iks_delete(confirm);
02003
02004 } else if (!strcasecmp(node, "confirmaccount")) {
02005 iks *iq = NULL, *query = NULL, *feature = NULL;
02006
02007 iq = iks_new("iq");
02008 query = iks_new("query");
02009 feature = iks_new("feature");
02010
02011 if (iq && query && feature && client) {
02012 iks_insert_attrib(iq, "from", client->user);
02013 iks_insert_attrib(iq, "to", pak->from->full);
02014 iks_insert_attrib(iq, "id", pak->id);
02015 iks_insert_attrib(iq, "type", "result");
02016 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
02017 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
02018 iks_insert_node(iq, query);
02019 iks_insert_node(query, feature);
02020 ast_aji_send(client, iq);
02021 } else {
02022 ast_log(LOG_ERROR, "Out of memory.\n");
02023 }
02024
02025 iks_delete(iq);
02026 iks_delete(query);
02027 iks_delete(feature);
02028 }
02029
02030 ASTOBJ_UNREF(client, ast_aji_client_destroy);
02031 return IKS_FILTER_EAT;
02032
02033 }
02034
02035
02036
02037
02038
02039
02040
02041
02042 static int aji_client_info_handler(void *data, ikspak *pak)
02043 {
02044 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
02045 struct aji_resource *resource = NULL;
02046 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
02047
02048 if (!buddy) {
02049 ast_log(LOG_NOTICE, "JABBER: Received client info from unknown buddy: %s.\n", pak->from->full);
02050 ASTOBJ_UNREF(client, ast_aji_client_destroy);
02051 return IKS_FILTER_EAT;
02052 }
02053
02054 resource = aji_find_resource(buddy, pak->from->resource);
02055 if (pak->subtype == IKS_TYPE_RESULT) {
02056 if (!resource) {
02057 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full);
02058 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
02059 ASTOBJ_UNREF(client, ast_aji_client_destroy);
02060 return IKS_FILTER_EAT;
02061 }
02062 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
02063 resource->cap->jingle = 1;
02064 } else {
02065 resource->cap->jingle = 0;
02066 }
02067 } else if (pak->subtype == IKS_TYPE_GET) {
02068 iks *iq, *disco, *ident, *google, *query;
02069 iq = iks_new("iq");
02070 query = iks_new("query");
02071 ident = iks_new("identity");
02072 disco = iks_new("feature");
02073 google = iks_new("feature");
02074 if (iq && ident && disco && google) {
02075 iks_insert_attrib(iq, "from", client->jid->full);
02076 iks_insert_attrib(iq, "to", pak->from->full);
02077 iks_insert_attrib(iq, "type", "result");
02078 iks_insert_attrib(iq, "id", pak->id);
02079 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
02080 iks_insert_attrib(ident, "category", "client");
02081 iks_insert_attrib(ident, "type", "pc");
02082 iks_insert_attrib(ident, "name", "asterisk");
02083 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info");
02084 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1");
02085 iks_insert_node(iq, query);
02086 iks_insert_node(query, ident);
02087 iks_insert_node(query, google);
02088 iks_insert_node(query, disco);
02089 ast_aji_send(client, iq);
02090 } else {
02091 ast_log(LOG_ERROR, "Out of Memory.\n");
02092 }
02093
02094 iks_delete(iq);
02095 iks_delete(query);
02096 iks_delete(ident);
02097 iks_delete(google);
02098 iks_delete(disco);
02099 } else if (pak->subtype == IKS_TYPE_ERROR) {
02100 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full);
02101 }
02102 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
02103 ASTOBJ_UNREF(client, ast_aji_client_destroy);
02104 return IKS_FILTER_EAT;
02105 }
02106
02107
02108
02109
02110
02111
02112
02113
02114 static int aji_dinfo_handler(void *data, ikspak *pak)
02115 {
02116 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
02117 char *node = NULL;
02118 struct aji_resource *resource = NULL;
02119 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
02120
02121 if (!buddy) {
02122 ast_log(LOG_NOTICE, "JABBER: Received client info from unknown buddy: %s.\n", pak->from->full);
02123 ASTOBJ_UNREF(client, ast_aji_client_destroy);
02124 return IKS_FILTER_EAT;
02125 }
02126
02127 if (pak->subtype == IKS_TYPE_ERROR) {
02128 ast_log(LOG_WARNING, "Received error from a client, turn on jabber debug!\n");
02129 ASTOBJ_UNREF(client, ast_aji_client_destroy);
02130 return IKS_FILTER_EAT;
02131 }
02132 resource = aji_find_resource(buddy, pak->from->resource);
02133 if (pak->subtype == IKS_TYPE_RESULT) {
02134 if (!resource) {
02135 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full);
02136 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
02137 ASTOBJ_UNREF(client, ast_aji_client_destroy);
02138 return IKS_FILTER_EAT;
02139 }
02140 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
02141 resource->cap->jingle = 1;
02142 } else {
02143 resource->cap->jingle = 0;
02144 }
02145 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) {
02146 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search;
02147
02148 iq = iks_new("iq");
02149 query = iks_new("query");
02150 identity = iks_new("identity");
02151 disco = iks_new("feature");
02152 reg = iks_new("feature");
02153 commands = iks_new("feature");
02154 gateway = iks_new("feature");
02155 version = iks_new("feature");
02156 vcard = iks_new("feature");
02157 search = iks_new("feature");
02158 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) {
02159 iks_insert_attrib(iq, "from", client->user);
02160 iks_insert_attrib(iq, "to", pak->from->full);
02161 iks_insert_attrib(iq, "id", pak->id);
02162 iks_insert_attrib(iq, "type", "result");
02163 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
02164 iks_insert_attrib(identity, "category", "gateway");
02165 iks_insert_attrib(identity, "type", "pstn");
02166 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX");
02167 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco");
02168 iks_insert_attrib(reg, "var", "jabber:iq:register");
02169 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands");
02170 iks_insert_attrib(gateway, "var", "jabber:iq:gateway");
02171 iks_insert_attrib(version, "var", "jabber:iq:version");
02172 iks_insert_attrib(vcard, "var", "vcard-temp");
02173 iks_insert_attrib(search, "var", "jabber:iq:search");
02174
02175 iks_insert_node(iq, query);
02176 iks_insert_node(query, identity);
02177 iks_insert_node(query, disco);
02178 iks_insert_node(query, reg);
02179 iks_insert_node(query, commands);
02180 iks_insert_node(query, gateway);
02181 iks_insert_node(query, version);
02182 iks_insert_node(query, vcard);
02183 iks_insert_node(query, search);
02184 ast_aji_send(client, iq);
02185 } else {
02186 ast_log(LOG_ERROR, "Out of memory.\n");
02187 }
02188
02189 iks_delete(iq);
02190 iks_delete(query);
02191 iks_delete(identity);
02192 iks_delete(disco);
02193 iks_delete(reg);
02194 iks_delete(commands);
02195 iks_delete(gateway);
02196 iks_delete(version);
02197 iks_delete(vcard);
02198 iks_delete(search);
02199 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) {
02200 iks *iq, *query, *confirm;
02201 iq = iks_new("iq");
02202 query = iks_new("query");
02203 confirm = iks_new("item");
02204
02205 if (iq && query && confirm && client) {
02206 iks_insert_attrib(iq, "from", client->user);
02207 iks_insert_attrib(iq, "to", pak->from->full);
02208 iks_insert_attrib(iq, "id", pak->id);
02209 iks_insert_attrib(iq, "type", "result");
02210 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
02211 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
02212 iks_insert_attrib(confirm, "node", "confirmaccount");
02213 iks_insert_attrib(confirm, "name", "Confirm AIM account");
02214 iks_insert_attrib(confirm, "jid", client->user);
02215 iks_insert_node(iq, query);
02216 iks_insert_node(query, confirm);
02217 ast_aji_send(client, iq);
02218 } else {
02219 ast_log(LOG_ERROR, "Out of memory.\n");
02220 }
02221
02222 iks_delete(iq);
02223 iks_delete(query);
02224 iks_delete(confirm);
02225
02226 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) {
02227 iks *iq, *query, *feature;
02228
02229 iq = iks_new("iq");
02230 query = iks_new("query");
02231 feature = iks_new("feature");
02232
02233 if (iq && query && feature && client) {
02234 iks_insert_attrib(iq, "from", client->user);
02235 iks_insert_attrib(iq, "to", pak->from->full);
02236 iks_insert_attrib(iq, "id", pak->id);
02237 iks_insert_attrib(iq, "type", "result");
02238 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
02239 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
02240 iks_insert_node(iq, query);
02241 iks_insert_node(query, feature);
02242 ast_aji_send(client, iq);
02243 } else {
02244 ast_log(LOG_ERROR, "Out of memory.\n");
02245 }
02246
02247 iks_delete(iq);
02248 iks_delete(query);
02249 iks_delete(feature);
02250 }
02251
02252 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
02253 ASTOBJ_UNREF(client, ast_aji_client_destroy);
02254 return IKS_FILTER_EAT;
02255 }
02256
02257
02258
02259
02260
02261
02262
02263
02264 static void aji_handle_iq(struct aji_client *client, iks *node)
02265 {
02266
02267 }
02268
02269
02270
02271
02272
02273
02274
02275
02276 static void aji_handle_message(struct aji_client *client, ikspak *pak)
02277 {
02278 struct aji_message *insert;
02279 int deleted = 0;
02280 struct ast_msg *msg;
02281
02282 ast_debug(3, "client %s received a message\n", client->name);
02283
02284 if (!(insert = ast_calloc(1, sizeof(*insert)))) {
02285 return;
02286 }
02287
02288 insert->arrived = ast_tvnow();
02289
02290
02291 ast_mutex_lock(&messagelock);
02292 ast_cond_broadcast(&message_received_condition);
02293 ast_mutex_unlock(&messagelock);
02294
02295 if (iks_find_cdata(pak->x, "body")) {
02296 insert->message = ast_strdup(iks_find_cdata(pak->x, "body"));
02297 }
02298 if (pak->id) {
02299 ast_copy_string(insert->id, pak->id, sizeof(insert->id));
02300 }
02301 if (pak->from){
02302
02303 insert->from = ast_strdup(pak->from->full);
02304 if (!insert->from) {
02305 ast_free(insert);
02306 ast_log(LOG_ERROR, "Memory allocation failure\n");
02307 return;
02308 }
02309 ast_debug(3, "message comes from %s\n", insert->from);
02310 }
02311
02312 if (client->send_to_dialplan) {
02313 if ((msg = ast_msg_alloc())) {
02314 int res;
02315
02316 res = ast_msg_set_to(msg, "xmpp:%s", client->user);
02317 res |= ast_msg_set_from(msg, "xmpp:%s", insert->from);
02318 res |= ast_msg_set_body(msg, "%s", insert->message);
02319 res |= ast_msg_set_context(msg, "%s", client->context);
02320
02321 if (res) {
02322 ast_msg_destroy(msg);
02323 } else {
02324 ast_msg_queue(msg);
02325 }
02326
02327 msg = NULL;
02328 }
02329 }
02330
02331
02332
02333 deleted = delete_old_messages(client, pak->from->partial);
02334 ast_debug(3, "Deleted %d messages for client %s from JID %s\n", deleted, client->name, pak->from->partial);
02335 AST_LIST_LOCK(&client->messages);
02336 AST_LIST_INSERT_HEAD(&client->messages, insert, list);
02337 AST_LIST_UNLOCK(&client->messages);
02338 }
02339
02340
02341
02342
02343
02344
02345
02346 static void aji_handle_presence(struct aji_client *client, ikspak *pak)
02347 {
02348 int status, priority;
02349 struct aji_buddy *buddy;
02350 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL;
02351 char *ver, *node, *descrip, *type;
02352
02353 if (client->state != AJI_CONNECTED)
02354 aji_create_buddy(pak->from->partial, client);
02355
02356 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
02357 if (!buddy && pak->from->partial) {
02358
02359 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial))
02360 aji_create_buddy(pak->from->partial, client);
02361 else
02362 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial);
02363 return;
02364 }
02365 type = iks_find_attrib(pak->x, "type");
02366 if (client->component && type &&!strcasecmp("probe", type)) {
02367 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage);
02368 ast_verbose("what i was looking for \n");
02369 }
02370 ASTOBJ_WRLOCK(buddy);
02371 status = (pak->show) ? pak->show : 6;
02372 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0");
02373 tmp = buddy->resources;
02374 descrip = ast_strdup(iks_find_cdata(pak->x, "status"));
02375
02376 while (tmp && pak->from->resource) {
02377 if (!strcasecmp(tmp->resource, pak->from->resource)) {
02378 tmp->status = status;
02379 if (tmp->description) {
02380 ast_free(tmp->description);
02381 }
02382 tmp->description = descrip;
02383 found = tmp;
02384 if (status == 6) {
02385 if (last && found->next) {
02386 last->next = found->next;
02387 } else if (!last) {
02388 if (found->next) {
02389 buddy->resources = found->next;
02390 } else {
02391 buddy->resources = NULL;
02392 }
02393 } else if (!found->next) {
02394 if (last) {
02395 last->next = NULL;
02396 } else {
02397 buddy->resources = NULL;
02398 }
02399 }
02400 ast_free(found);
02401 found = NULL;
02402 break;
02403 }
02404
02405 if (tmp->priority != priority) {
02406 found->priority = priority;
02407 if (!last && !found->next) {
02408
02409
02410 break;
02411 }
02412
02413
02414 if (last) {
02415 last->next = found->next;
02416 } else {
02417 buddy->resources = found->next;
02418 }
02419
02420 last = NULL;
02421 tmp = buddy->resources;
02422 if (!buddy->resources) {
02423 buddy->resources = found;
02424 }
02425
02426 while (tmp) {
02427
02428
02429 if (found->priority > tmp->priority) {
02430 if (last) {
02431
02432 last->next = found;
02433 }
02434 found->next = tmp;
02435 if (!last) {
02436
02437 buddy->resources = found;
02438 }
02439 break;
02440 }
02441 if (!tmp->next) {
02442
02443 tmp->next = found;
02444 found->next = NULL;
02445 break;
02446 }
02447 last = tmp;
02448 tmp = tmp->next;
02449 }
02450 }
02451 break;
02452 }
02453 last = tmp;
02454 tmp = tmp->next;
02455 }
02456
02457
02458 if (!found && status != 6 && pak->from->resource) {
02459 found = ast_calloc(1, sizeof(*found));
02460
02461 if (!found) {
02462 ast_log(LOG_ERROR, "Out of memory!\n");
02463 ASTOBJ_UNLOCK(buddy);
02464 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
02465 return;
02466 }
02467 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource));
02468 found->status = status;
02469 found->description = descrip;
02470 found->priority = priority;
02471 found->next = NULL;
02472 last = NULL;
02473 tmp = buddy->resources;
02474 while (tmp) {
02475 if (found->priority > tmp->priority) {
02476 if (last) {
02477 last->next = found;
02478 }
02479 found->next = tmp;
02480 if (!last) {
02481 buddy->resources = found;
02482 }
02483 break;
02484 }
02485 if (!tmp->next) {
02486 tmp->next = found;
02487 break;
02488 }
02489 last = tmp;
02490 tmp = tmp->next;
02491 }
02492 if (!tmp) {
02493 buddy->resources = found;
02494 }
02495 }
02496
02497 ASTOBJ_UNLOCK(buddy);
02498 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
02499
02500 node = iks_find_attrib(iks_find(pak->x, "c"), "node");
02501 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver");
02502
02503
02504 if (!node && !ver) {
02505 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node");
02506 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver");
02507 }
02508
02509
02510 if (status != 6 && found && !found->cap) {
02511 found->cap = aji_find_version(node, ver, pak);
02512 if (gtalk_yuck(pak->x)) {
02513 found->cap->jingle = 1;
02514 }
02515 if (found->cap->jingle) {
02516 ast_debug(1, "Special case for google till they support discover.\n");
02517 } else {
02518 iks *iq, *query;
02519 iq = iks_new("iq");
02520 query = iks_new("query");
02521 if (query && iq) {
02522 iks_insert_attrib(iq, "type", "get");
02523 iks_insert_attrib(iq, "to", pak->from->full);
02524 iks_insert_attrib(iq, "from", client->jid->full);
02525 iks_insert_attrib(iq, "id", client->mid);
02526 ast_aji_increment_mid(client->mid);
02527 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
02528 iks_insert_node(iq, query);
02529 ast_aji_send(client, iq);
02530 } else {
02531 ast_log(LOG_ERROR, "Out of memory.\n");
02532 }
02533 iks_delete(query);
02534 iks_delete(iq);
02535 }
02536 }
02537 switch (pak->subtype) {
02538 case IKS_TYPE_AVAILABLE:
02539 ast_debug(3, "JABBER: I am available ^_* %i\n", pak->subtype);
02540 break;
02541 case IKS_TYPE_UNAVAILABLE:
02542 ast_debug(3, "JABBER: I am unavailable ^_* %i\n", pak->subtype);
02543 break;
02544 default:
02545 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype);
02546 }
02547 switch (pak->show) {
02548 case IKS_SHOW_UNAVAILABLE:
02549 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
02550 break;
02551 case IKS_SHOW_AVAILABLE:
02552 ast_debug(3, "JABBER: type is available\n");
02553 break;
02554 case IKS_SHOW_CHAT:
02555 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
02556 break;
02557 case IKS_SHOW_AWAY:
02558 ast_debug(3, "JABBER: type is away\n");
02559 break;
02560 case IKS_SHOW_XA:
02561 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
02562 break;
02563 case IKS_SHOW_DND:
02564 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
02565 break;
02566 default:
02567 ast_debug(3, "JABBER: Kinky! how did that happen %i\n", pak->show);
02568 }
02569
02570 if (found) {
02571 manager_event(EVENT_FLAG_USER, "JabberStatus",
02572 "Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d"
02573 "\r\nDescription: %s\r\n",
02574 client->name, pak->from->partial, found->resource, found->status,
02575 found->priority, S_OR(found->description, ""));
02576 } else {
02577 manager_event(EVENT_FLAG_USER, "JabberStatus",
02578 "Account: %s\r\nJID: %s\r\nStatus: %d\r\n",
02579 client->name, pak->from->partial, pak->show ? pak->show : IKS_SHOW_UNAVAILABLE);
02580 }
02581 }
02582
02583
02584
02585
02586
02587
02588
02589
02590 static void aji_handle_subscribe(struct aji_client *client, ikspak *pak)
02591 {
02592 iks *presence = NULL, *status = NULL;
02593 struct aji_buddy* buddy = NULL;
02594
02595 switch (pak->subtype) {
02596 case IKS_TYPE_SUBSCRIBE:
02597 if (ast_test_flag(&client->flags, AJI_AUTOACCEPT)) {
02598 presence = iks_new("presence");
02599 status = iks_new("status");
02600 if (presence && status) {
02601 iks_insert_attrib(presence, "type", "subscribed");
02602 iks_insert_attrib(presence, "to", pak->from->full);
02603 iks_insert_attrib(presence, "from", client->jid->full);
02604 if (pak->id)
02605 iks_insert_attrib(presence, "id", pak->id);
02606 iks_insert_cdata(status, "Asterisk has approved subscription", 0);
02607 iks_insert_node(presence, status);
02608 ast_aji_send(client, presence);
02609 } else {
02610 ast_log(LOG_ERROR, "Unable to allocate nodes\n");
02611 }
02612
02613 iks_delete(presence);
02614 iks_delete(status);
02615 }
02616
02617 if (client->component)
02618 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage);
02619 case IKS_TYPE_SUBSCRIBED:
02620 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
02621 if (!buddy && pak->from->partial) {
02622 aji_create_buddy(pak->from->partial, client);
02623 } else if (buddy) {
02624 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
02625 }
02626 default:
02627 ast_verb(5, "JABBER: This is a subcription of type %i\n", pak->subtype);
02628 }
02629 }
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639 int ast_aji_send_chat(struct aji_client *client, const char *address, const char *message)
02640 {
02641 return aji_send_raw_chat(client, 0, NULL, address, message);
02642 }
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653 int ast_aji_send_groupchat(struct aji_client *client, const char *nick, const char *address, const char *message) {
02654 return aji_send_raw_chat(client, 1, nick, address, message);
02655 }
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666 static int aji_send_raw_chat(struct aji_client *client, int groupchat, const char *nick, const char *address, const char *message)
02667 {
02668 int res = 0;
02669 iks *message_packet = NULL;
02670 char from[AJI_MAX_JIDLEN];
02671
02672 if (nick && client->component) {
02673 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick);
02674 } else {
02675 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full);
02676 }
02677
02678 if (client->state != AJI_CONNECTED) {
02679 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n");
02680 return -1;
02681 }
02682
02683 message_packet = iks_make_msg(groupchat ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message);
02684 if (!message_packet) {
02685 ast_log(LOG_ERROR, "Out of memory.\n");
02686 return -1;
02687 }
02688 iks_insert_attrib(message_packet, "from", from);
02689 res = ast_aji_send(client, message_packet);
02690 iks_delete(message_packet);
02691
02692 return res;
02693 }
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703 int ast_aji_create_chat(struct aji_client *client, char *room, char *server, char *topic)
02704 {
02705 int res = 0;
02706 iks *iq = NULL;
02707 iq = iks_new("iq");
02708
02709 if (iq && client) {
02710 iks_insert_attrib(iq, "type", "get");
02711 iks_insert_attrib(iq, "to", server);
02712 iks_insert_attrib(iq, "id", client->mid);
02713 ast_aji_increment_mid(client->mid);
02714 ast_aji_send(client, iq);
02715 } else {
02716 ast_log(LOG_ERROR, "Out of memory.\n");
02717 }
02718
02719 iks_delete(iq);
02720
02721 return res;
02722 }
02723
02724
02725
02726
02727
02728
02729
02730
02731 int ast_aji_join_chat(struct aji_client *client, char *room, char *nick)
02732 {
02733 return aji_set_group_presence(client, room, IKS_SHOW_AVAILABLE, nick, NULL);
02734 }
02735
02736
02737
02738
02739
02740
02741
02742
02743 int ast_aji_leave_chat(struct aji_client *client, char *room, char *nick)
02744 {
02745 return aji_set_group_presence(client, room, IKS_SHOW_UNAVAILABLE, nick, NULL);
02746 }
02747
02748
02749
02750
02751
02752
02753
02754
02755 int ast_aji_invite_chat(struct aji_client *client, char *user, char *room, char *message)
02756 {
02757 int res = 0;
02758 iks *invite, *body, *namespace;
02759
02760 invite = iks_new("message");
02761 body = iks_new("body");
02762 namespace = iks_new("x");
02763 if (client && invite && body && namespace) {
02764 iks_insert_attrib(invite, "to", user);
02765 iks_insert_attrib(invite, "id", client->mid);
02766 ast_aji_increment_mid(client->mid);
02767 iks_insert_cdata(body, message, 0);
02768 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference");
02769 iks_insert_attrib(namespace, "jid", room);
02770 iks_insert_node(invite, body);
02771 iks_insert_node(invite, namespace);
02772 res = ast_aji_send(client, invite);
02773 } else {
02774 ast_log(LOG_ERROR, "Out of memory.\n");
02775 }
02776
02777 iks_delete(body);
02778 iks_delete(namespace);
02779 iks_delete(invite);
02780
02781 return res;
02782 }
02783
02784
02785
02786
02787
02788
02789
02790 static void *aji_recv_loop(void *data)
02791 {
02792 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
02793 int res = IKS_HOOK;
02794
02795 while (res != IKS_OK) {
02796 ast_debug(3, "JABBER: Connecting.\n");
02797 res = aji_reconnect(client);
02798 sleep(4);
02799 }
02800
02801 do {
02802 if (res == IKS_NET_RWERR || client->timeout == 0) {
02803 while (res != IKS_OK) {
02804 ast_debug(3, "JABBER: reconnecting.\n");
02805 res = aji_reconnect(client);
02806 sleep(4);
02807 }
02808 }
02809
02810 res = aji_recv(client, 1);
02811
02812 if (client->state == AJI_DISCONNECTING) {
02813 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n");
02814 pthread_exit(NULL);
02815 }
02816
02817
02818
02819 if (res == IKS_NET_EXPIRED) {
02820 client->timeout--;
02821 delete_old_messages_all(client);
02822 }
02823 if (res == IKS_HOOK) {
02824 ast_log(LOG_WARNING, "JABBER: Got hook event.\n");
02825 } else if (res == IKS_NET_TLSFAIL) {
02826 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n");
02827 } else if (client->timeout == 0 && client->state == AJI_CONNECTED) {
02828 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK;
02829 if (res == IKS_OK) {
02830 client->timeout = 50;
02831 } else {
02832 ast_log(LOG_WARNING, "JABBER: Network Timeout\n");
02833 }
02834 } else if (res == IKS_NET_RWERR) {
02835 ast_log(LOG_WARNING, "JABBER: socket read error\n");
02836 }
02837 } while (client);
02838 ASTOBJ_UNREF(client, ast_aji_client_destroy);
02839 return 0;
02840 }
02841
02842
02843
02844
02845
02846
02847 void ast_aji_increment_mid(char *mid)
02848 {
02849 int i = 0;
02850
02851 for (i = strlen(mid) - 1; i >= 0; i--) {
02852 if (mid[i] != 'z') {
02853 mid[i] = mid[i] + 1;
02854 i = 0;
02855 } else
02856 mid[i] = 'a';
02857 }
02858 }
02859
02860 #if 0
02861
02862
02863
02864
02865
02866
02867 static int aji_register_transport(void *data, ikspak *pak)
02868 {
02869 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
02870 int res = 0;
02871 struct aji_buddy *buddy = NULL;
02872 iks *send = iks_make_iq(IKS_TYPE_GET, "jabber:iq:register");
02873
02874 if (client && send) {
02875 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
02876 ASTOBJ_RDLOCK(iterator);
02877 if (iterator->btype == AJI_TRANS) {
02878 buddy = iterator;
02879 }
02880 ASTOBJ_UNLOCK(iterator);
02881 });
02882 iks_filter_remove_hook(client->f, aji_register_transport);
02883 iks_filter_add_rule(client->f, aji_register_transport2, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_NS, IKS_NS_REGISTER, IKS_RULE_DONE);
02884 iks_insert_attrib(send, "to", buddy->host);
02885 iks_insert_attrib(send, "id", client->mid);
02886 ast_aji_increment_mid(client->mid);
02887 iks_insert_attrib(send, "from", client->user);
02888 res = ast_aji_send(client, send);
02889 } else
02890 ast_log(LOG_ERROR, "Out of memory.\n");
02891
02892 if (send)
02893 iks_delete(send);
02894 ASTOBJ_UNREF(client, ast_aji_client_destroy);
02895 return IKS_FILTER_EAT;
02896
02897 }
02898
02899
02900
02901
02902
02903
02904 static int aji_register_transport2(void *data, ikspak *pak)
02905 {
02906 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
02907 int res = 0;
02908 struct aji_buddy *buddy = NULL;
02909
02910 iks *regiq = iks_new("iq");
02911 iks *regquery = iks_new("query");
02912 iks *reguser = iks_new("username");
02913 iks *regpass = iks_new("password");
02914
02915 if (client && regquery && reguser && regpass && regiq) {
02916 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
02917 ASTOBJ_RDLOCK(iterator);
02918 if (iterator->btype == AJI_TRANS)
02919 buddy = iterator; ASTOBJ_UNLOCK(iterator);
02920 });
02921 iks_filter_remove_hook(client->f, aji_register_transport2);
02922 iks_insert_attrib(regiq, "to", buddy->host);
02923 iks_insert_attrib(regiq, "type", "set");
02924 iks_insert_attrib(regiq, "id", client->mid);
02925 ast_aji_increment_mid(client->mid);
02926 iks_insert_attrib(regiq, "from", client->user);
02927 iks_insert_attrib(regquery, "xmlns", "jabber:iq:register");
02928 iks_insert_cdata(reguser, buddy->user, 0);
02929 iks_insert_cdata(regpass, buddy->pass, 0);
02930 iks_insert_node(regiq, regquery);
02931 iks_insert_node(regquery, reguser);
02932 iks_insert_node(regquery, regpass);
02933 res = ast_aji_send(client, regiq);
02934 } else
02935 ast_log(LOG_ERROR, "Out of memory.\n");
02936 if (regiq)
02937 iks_delete(regiq);
02938 if (regquery)
02939 iks_delete(regquery);
02940 if (reguser)
02941 iks_delete(reguser);
02942 if (regpass)
02943 iks_delete(regpass);
02944 ASTOBJ_UNREF(client, ast_aji_client_destroy);
02945 return IKS_FILTER_EAT;
02946 }
02947 #endif
02948
02949
02950
02951
02952
02953
02954
02955
02956 static void aji_pruneregister(struct aji_client *client)
02957 {
02958 iks *removeiq = iks_new("iq");
02959 iks *removequery = iks_new("query");
02960 iks *removeitem = iks_new("item");
02961 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items");
02962 if (!client || !removeiq || !removequery || !removeitem || !send) {
02963 ast_log(LOG_ERROR, "Out of memory.\n");
02964 goto safeout;
02965 }
02966
02967 iks_insert_node(removeiq, removequery);
02968 iks_insert_node(removequery, removeitem);
02969 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
02970 ASTOBJ_RDLOCK(iterator);
02971
02972
02973 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) {
02974 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name,
02975 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX"
02976 " so I am no longer subscribing to your presence.\n"));
02977 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name,
02978 "GoodBye. You are no longer in the Asterisk config file so I am removing"
02979 " your access to my presence.\n"));
02980 iks_insert_attrib(removeiq, "from", client->jid->full);
02981 iks_insert_attrib(removeiq, "type", "set");
02982 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster");
02983 iks_insert_attrib(removeitem, "jid", iterator->name);
02984 iks_insert_attrib(removeitem, "subscription", "remove");
02985 ast_aji_send(client, removeiq);
02986 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) {
02987 ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name,
02988 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"));
02989 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER);
02990 }
02991 ASTOBJ_UNLOCK(iterator);
02992 });
02993
02994 safeout:
02995 iks_delete(removeiq);
02996 iks_delete(removequery);
02997 iks_delete(removeitem);
02998 iks_delete(send);
02999
03000 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, ast_aji_buddy_destroy);
03001 }
03002
03003
03004
03005
03006
03007
03008
03009
03010 static int aji_filter_roster(void *data, ikspak *pak)
03011 {
03012 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
03013 int flag = 0;
03014 iks *x = NULL;
03015 struct aji_buddy *buddy;
03016
03017 client->state = AJI_CONNECTED;
03018 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
03019 ASTOBJ_RDLOCK(iterator);
03020 x = iks_child(pak->query);
03021 flag = 0;
03022 while (x) {
03023 if (!iks_strcmp(iks_name(x), "item")) {
03024 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) {
03025 flag = 1;
03026 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER);
03027 }
03028 }
03029 x = iks_next(x);
03030 }
03031 if (!flag) {
03032 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER);
03033 }
03034 iks_delete(x);
03035
03036 ASTOBJ_UNLOCK(iterator);
03037 });
03038
03039 x = iks_child(pak->query);
03040 while (x) {
03041 flag = 0;
03042 if (iks_strcmp(iks_name(x), "item") == 0) {
03043 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
03044 ASTOBJ_RDLOCK(iterator);
03045 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid")))
03046 flag = 1;
03047 ASTOBJ_UNLOCK(iterator);
03048 });
03049
03050 if (flag) {
03051
03052 x = iks_next(x);
03053 continue;
03054 }
03055
03056 buddy = ast_calloc(1, sizeof(*buddy));
03057 if (!buddy) {
03058 ast_log(LOG_WARNING, "Out of memory\n");
03059 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03060 return 0;
03061 }
03062 ASTOBJ_INIT(buddy);
03063 ASTOBJ_WRLOCK(buddy);
03064 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name));
03065 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL);
03066 if (ast_test_flag(&client->flags, AJI_AUTOPRUNE)) {
03067 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE);
03068 ASTOBJ_MARK(buddy);
03069 } else if (ast_test_flag(&client->flags, AJI_AUTOREGISTER)) {
03070 if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) {
03071
03072
03073 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER);
03074 }
03075 }
03076 ASTOBJ_UNLOCK(buddy);
03077 if (buddy) {
03078 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
03079 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
03080 }
03081 }
03082 x = iks_next(x);
03083 }
03084
03085 iks_delete(x);
03086 aji_pruneregister(client);
03087
03088 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03089 return IKS_FILTER_EAT;
03090 }
03091
03092
03093
03094
03095
03096
03097
03098 static int aji_reconnect(struct aji_client *client)
03099 {
03100 int res = 0;
03101
03102 if (client->state) {
03103 client->state = AJI_DISCONNECTED;
03104 }
03105 client->timeout = 50;
03106 if (client->p) {
03107 iks_parser_reset(client->p);
03108 }
03109 if (client->authorized) {
03110 client->authorized = 0;
03111 }
03112
03113 res = aji_initialize(client);
03114
03115 return res;
03116 }
03117
03118
03119
03120
03121
03122
03123
03124 static int aji_get_roster(struct aji_client *client)
03125 {
03126 iks *roster = NULL;
03127 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER);
03128
03129 if (roster) {
03130 iks_insert_attrib(roster, "id", "roster");
03131 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage);
03132 ast_aji_send(client, roster);
03133 }
03134
03135 iks_delete(roster);
03136
03137 return 1;
03138 }
03139
03140
03141
03142
03143
03144
03145
03146
03147 static int aji_client_connect(void *data, ikspak *pak)
03148 {
03149 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
03150 int res = IKS_FILTER_PASS;
03151
03152 if (client) {
03153 if (client->state == AJI_DISCONNECTED) {
03154 iks_filter_add_rule(client->f, aji_filter_roster, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, "roster", IKS_RULE_DONE);
03155 client->state = AJI_CONNECTING;
03156 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid;
03157 if (!client->component) {
03158 aji_get_roster(client);
03159 }
03160 if (client->distribute_events) {
03161 aji_init_event_distribution(client);
03162 }
03163
03164 iks_filter_remove_hook(client->f, aji_client_connect);
03165
03166 res = IKS_FILTER_EAT;
03167 }
03168 } else {
03169 ast_log(LOG_ERROR, "Out of memory.\n");
03170 }
03171
03172 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03173 return res;
03174 }
03175
03176
03177
03178
03179
03180
03181
03182 static int aji_initialize(struct aji_client *client)
03183 {
03184 int connected = IKS_NET_NOCONN;
03185
03186 #ifdef HAVE_OPENSSL
03187
03188 client->stream_flags = 0;
03189 #endif
03190
03191 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server);
03192
03193 if (connected == IKS_NET_NOCONN) {
03194 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
03195 return IKS_HOOK;
03196 } else if (connected == IKS_NET_NODNS) {
03197 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name,
03198 S_OR(client->serverhost, client->jid->server));
03199 return IKS_HOOK;
03200 }
03201
03202 return IKS_OK;
03203 }
03204
03205
03206
03207
03208
03209
03210 int ast_aji_disconnect(struct aji_client *client)
03211 {
03212 if (client) {
03213 ast_verb(4, "JABBER: Disconnecting\n");
03214 #ifdef HAVE_OPENSSL
03215 if (client->stream_flags & SECURE) {
03216 SSL_shutdown(client->ssl_session);
03217 SSL_CTX_free(client->ssl_context);
03218 SSL_free(client->ssl_session);
03219 }
03220 #endif
03221 iks_disconnect(client->p);
03222 iks_parser_delete(client->p);
03223 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03224 }
03225
03226 return 1;
03227 }
03228
03229
03230
03231
03232
03233
03234
03235 static void aji_mwi_cb(const struct ast_event *ast_event, void *data)
03236 {
03237 const char *mailbox;
03238 const char *context;
03239 char oldmsgs[10];
03240 char newmsgs[10];
03241 struct aji_client *client;
03242 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID)))
03243 {
03244
03245 ast_debug(1, "Returning here\n");
03246 return;
03247 }
03248
03249 client = ASTOBJ_REF((struct aji_client *) data);
03250 mailbox = ast_event_get_ie_str(ast_event, AST_EVENT_IE_MAILBOX);
03251 context = ast_event_get_ie_str(ast_event, AST_EVENT_IE_CONTEXT);
03252 snprintf(oldmsgs, sizeof(oldmsgs), "%d",
03253 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_OLDMSGS));
03254 snprintf(newmsgs, sizeof(newmsgs), "%d",
03255 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_NEWMSGS));
03256 aji_publish_mwi(client, mailbox, context, oldmsgs, newmsgs);
03257 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03258
03259 }
03260
03261
03262
03263
03264
03265
03266 static void aji_devstate_cb(const struct ast_event *ast_event, void *data)
03267 {
03268 const char *device;
03269 const char *device_state;
03270 struct aji_client *client;
03271 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID)))
03272 {
03273
03274 ast_debug(1, "Returning here\n");
03275 return;
03276 }
03277
03278 client = ASTOBJ_REF((struct aji_client *) data);
03279 device = ast_event_get_ie_str(ast_event, AST_EVENT_IE_DEVICE);
03280 device_state = ast_devstate_str(ast_event_get_ie_uint(ast_event, AST_EVENT_IE_STATE));
03281 aji_publish_device_state(client, device, device_state);
03282 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03283 }
03284
03285
03286
03287
03288
03289
03290 static void aji_init_event_distribution(struct aji_client *client)
03291 {
03292 if (!mwi_sub) {
03293 mwi_sub = ast_event_subscribe(AST_EVENT_MWI, aji_mwi_cb, "aji_mwi_subscription",
03294 client, AST_EVENT_IE_END);
03295 }
03296 if (!device_state_sub) {
03297 if (ast_enable_distributed_devstate()) {
03298 return;
03299 }
03300 device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE,
03301 aji_devstate_cb, "aji_devstate_subscription", client, AST_EVENT_IE_END);
03302 ast_event_dump_cache(device_state_sub);
03303 }
03304
03305 aji_pubsub_subscribe(client, "device_state");
03306 aji_pubsub_subscribe(client, "message_waiting");
03307 iks_filter_add_rule(client->f, aji_handle_pubsub_event, client, IKS_RULE_TYPE,
03308 IKS_PAK_MESSAGE, IKS_RULE_FROM, client->pubsub_node, IKS_RULE_DONE);
03309 iks_filter_add_rule(client->f, aji_handle_pubsub_error, client, IKS_RULE_TYPE,
03310 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE);
03311
03312 }
03313
03314
03315
03316
03317
03318
03319
03320 static int aji_handle_pubsub_event(void *data, ikspak *pak)
03321 {
03322 char *item_id, *device_state, *context;
03323 int oldmsgs, newmsgs;
03324 iks *item, *item_content;
03325 struct ast_eid pubsub_eid;
03326 struct ast_event *event;
03327 item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item");
03328 if (!item) {
03329 ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n");
03330 return IKS_FILTER_EAT;
03331 }
03332 item_id = iks_find_attrib(item, "id");
03333 item_content = iks_child(item);
03334 ast_str_to_eid(&pubsub_eid, iks_find_attrib(item_content, "eid"));
03335 if (!ast_eid_cmp(&ast_eid_default, &pubsub_eid)) {
03336 ast_debug(1, "Returning here, eid of incoming event matches ours!\n");
03337 return IKS_FILTER_EAT;
03338 }
03339 if (!strcasecmp(iks_name(item_content), "state")) {
03340 device_state = iks_find_cdata(item, "state");
03341 if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE,
03342 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE,
03343 AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID,
03344 AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid),
03345 AST_EVENT_IE_END))) {
03346 return IKS_FILTER_EAT;
03347 }
03348 } else if (!strcasecmp(iks_name(item_content), "mailbox")) {
03349 context = strsep(&item_id, "@");
03350 sscanf(iks_find_cdata(item_content, "OLDMSGS"), "%10d", &oldmsgs);
03351 sscanf(iks_find_cdata(item_content, "NEWMSGS"), "%10d", &newmsgs);
03352 if (!(event = ast_event_new(AST_EVENT_MWI, AST_EVENT_IE_MAILBOX,
03353 AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_CONTEXT,
03354 AST_EVENT_IE_PLTYPE_STR, context, AST_EVENT_IE_OLDMSGS,
03355 AST_EVENT_IE_PLTYPE_UINT, oldmsgs, AST_EVENT_IE_NEWMSGS,
03356 AST_EVENT_IE_PLTYPE_UINT, newmsgs, AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW,
03357 &pubsub_eid, sizeof(pubsub_eid), AST_EVENT_IE_END))) {
03358 return IKS_FILTER_EAT;
03359 }
03360 } else {
03361 ast_debug(1, "Don't know how to handle PubSub event of type %s\n",
03362 iks_name(item_content));
03363 return IKS_FILTER_EAT;
03364 }
03365 ast_event_queue_and_cache(event);
03366 return IKS_FILTER_EAT;
03367 }
03368
03369
03370
03371
03372
03373
03374
03375 static void aji_create_affiliations(struct aji_client *client, const char *node)
03376 {
03377 iks *modify_affiliates = aji_pubsub_iq_create(client, "set");
03378 iks *pubsub, *affiliations, *affiliate;
03379 pubsub = iks_insert(modify_affiliates, "pubsub");
03380 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner");
03381 affiliations = iks_insert(pubsub, "affiliations");
03382 iks_insert_attrib(affiliations, "node", node);
03383 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
03384 ASTOBJ_RDLOCK(iterator);
03385 affiliate = iks_insert(affiliations, "affiliation");
03386 iks_insert_attrib(affiliate, "jid", iterator->name);
03387 iks_insert_attrib(affiliate, "affiliation", "owner");
03388 ASTOBJ_UNLOCK(iterator);
03389 });
03390 ast_aji_send(client, modify_affiliates);
03391 iks_delete(modify_affiliates);
03392 }
03393
03394
03395
03396
03397
03398
03399
03400 static void aji_pubsub_subscribe(struct aji_client *client, const char *node)
03401 {
03402 iks *request = aji_pubsub_iq_create(client, "set");
03403 iks *pubsub, *subscribe;
03404
03405 pubsub = iks_insert(request, "pubsub");
03406 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
03407 subscribe = iks_insert(pubsub, "subscribe");
03408 iks_insert_attrib(subscribe, "jid", client->jid->partial);
03409 iks_insert_attrib(subscribe, "node", node);
03410 if (ast_test_flag(&globalflags, AJI_XEP0248)) {
03411 iks *options, *x, *sub_options, *sub_type, *sub_depth;
03412 options = iks_insert(pubsub, "options");
03413 x = iks_insert(options, "x");
03414 iks_insert_attrib(x, "xmlns", "jabber:x:data");
03415 iks_insert_attrib(x, "type", "submit");
03416 sub_options = iks_insert(x, "field");
03417 iks_insert_attrib(sub_options, "var", "FORM_TYPE");
03418 iks_insert_attrib(sub_options, "type", "hidden");
03419 iks_insert_cdata(iks_insert(sub_options, "value"),
03420 "http://jabber.org/protocol/pubsub#subscribe_options", 51);
03421 sub_type = iks_insert(x, "field");
03422 iks_insert_attrib(sub_type, "var", "pubsub#subscription_type");
03423 iks_insert_cdata(iks_insert(sub_type, "value"), "items", 5);
03424 sub_depth = iks_insert(x, "field");
03425 iks_insert_attrib(sub_type, "var", "pubsub#subscription_depth");
03426 iks_insert_cdata(iks_insert(sub_depth, "value"), "all", 3);
03427 }
03428 ast_aji_send(client, request);
03429 iks_delete(request);
03430 }
03431
03432
03433
03434
03435
03436
03437
03438
03439 static iks* aji_build_publish_skeleton(struct aji_client *client, const char *node,
03440 const char *event_type)
03441 {
03442 iks *request = aji_pubsub_iq_create(client, "set");
03443 iks *pubsub, *publish, *item;
03444 pubsub = iks_insert(request, "pubsub");
03445 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
03446 publish = iks_insert(pubsub, "publish");
03447 if (ast_test_flag(&globalflags, AJI_XEP0248)) {
03448 iks_insert_attrib(publish, "node", node);
03449 } else {
03450 iks_insert_attrib(publish, "node", event_type);
03451 }
03452 item = iks_insert(publish, "item");
03453 iks_insert_attrib(item, "id", node);
03454 return item;
03455
03456 }
03457
03458
03459
03460
03461
03462
03463
03464
03465 static void aji_publish_device_state(struct aji_client *client, const char *device,
03466 const char *device_state)
03467 {
03468 iks *request = aji_build_publish_skeleton(client, device, "device_state");
03469 iks *state;
03470 char eid_str[20];
03471 if (ast_test_flag(&pubsubflags, AJI_PUBSUB_AUTOCREATE)) {
03472 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) {
03473 aji_create_pubsub_node(client, "leaf", device, "device_state");
03474 } else {
03475 aji_create_pubsub_node(client, NULL, device, NULL);
03476 }
03477 }
03478 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
03479 state = iks_insert(request, "state");
03480 iks_insert_attrib(state, "xmlns", "http://asterisk.org");
03481 iks_insert_attrib(state, "eid", eid_str);
03482 iks_insert_cdata(state, device_state, strlen(device_state));
03483 ast_aji_send(client, iks_root(request));
03484 iks_delete(request);
03485 }
03486
03487
03488
03489
03490
03491
03492
03493
03494
03495
03496 static void aji_publish_mwi(struct aji_client *client, const char *mailbox,
03497 const char *context, const char *oldmsgs, const char *newmsgs)
03498 {
03499 char full_mailbox[AST_MAX_EXTENSION+AST_MAX_CONTEXT];
03500 char eid_str[20];
03501 iks *mailbox_node, *request;
03502 snprintf(full_mailbox, sizeof(full_mailbox), "%s@%s", mailbox, context);
03503 request = aji_build_publish_skeleton(client, full_mailbox, "message_waiting");
03504 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
03505 mailbox_node = iks_insert(request, "mailbox");
03506 iks_insert_attrib(mailbox_node, "xmlns", "http://asterisk.org");
03507 iks_insert_attrib(mailbox_node, "eid", eid_str);
03508 iks_insert_cdata(iks_insert(mailbox_node, "NEWMSGS"), newmsgs, strlen(newmsgs));
03509 iks_insert_cdata(iks_insert(mailbox_node, "OLDMSGS"), oldmsgs, strlen(oldmsgs));
03510 ast_aji_send(client, iks_root(request));
03511 iks_delete(request);
03512 }
03513
03514
03515
03516
03517
03518
03519
03520 static iks* aji_pubsub_iq_create(struct aji_client *client, const char *type)
03521 {
03522 iks *request = iks_new("iq");
03523
03524 iks_insert_attrib(request, "to", client->pubsub_node);
03525 iks_insert_attrib(request, "from", client->jid->full);
03526 iks_insert_attrib(request, "type", type);
03527 ast_aji_increment_mid(client->mid);
03528 iks_insert_attrib(request, "id", client->mid);
03529 return request;
03530 }
03531
03532 static int aji_handle_pubsub_error(void *data, ikspak *pak)
03533 {
03534 char *node_name;
03535 char *error;
03536 int error_num;
03537 iks *orig_request;
03538 iks *orig_pubsub = iks_find(pak->x, "pubsub");
03539 struct aji_client *client;
03540 if (!orig_pubsub) {
03541 ast_log(LOG_ERROR, "Error isn't a PubSub error, why are we here?\n");
03542 return IKS_FILTER_EAT;
03543 }
03544 orig_request = iks_child(orig_pubsub);
03545 error = iks_find_attrib(iks_find(pak->x, "error"), "code");
03546 node_name = iks_find_attrib(orig_request, "node");
03547 if (!sscanf(error, "%30d", &error_num)) {
03548 return IKS_FILTER_EAT;
03549 }
03550 if (error_num > 399 && error_num < 500 && error_num != 404) {
03551 ast_log(LOG_ERROR,
03552 "Error performing operation on PubSub node %s, %s.\n", node_name, error);
03553 return IKS_FILTER_EAT;
03554 } else if (error_num > 499 && error_num < 600) {
03555 ast_log(LOG_ERROR, "PubSub Server error, %s\n", error);
03556 return IKS_FILTER_EAT;
03557 }
03558
03559 client = ASTOBJ_REF((struct aji_client *) data);
03560
03561 if (!strcasecmp(iks_name(orig_request), "publish")) {
03562 iks *request;
03563 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) {
03564 if (iks_find(iks_find(orig_request, "item"), "state")) {
03565 aji_create_pubsub_leaf(client, "device_state", node_name);
03566 } else if (iks_find(iks_find(orig_request, "item"), "mailbox")) {
03567 aji_create_pubsub_leaf(client, "message_waiting", node_name);
03568 }
03569 } else {
03570 aji_create_pubsub_node(client, NULL, node_name, NULL);
03571 }
03572 request = aji_pubsub_iq_create(client, "set");
03573 iks_insert_node(request, orig_pubsub);
03574 ast_aji_send(client, request);
03575 iks_delete(request);
03576 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03577 return IKS_FILTER_EAT;
03578 } else if (!strcasecmp(iks_name(orig_request), "subscribe")) {
03579 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) {
03580 aji_create_pubsub_collection(client, node_name);
03581 } else {
03582 aji_create_pubsub_node(client, NULL, node_name, NULL);
03583 }
03584 }
03585 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03586 return IKS_FILTER_EAT;
03587 }
03588
03589
03590
03591
03592
03593
03594
03595 static void aji_request_pubsub_nodes(struct aji_client *client, const char *collection)
03596 {
03597 iks *request = aji_build_node_request(client, collection);
03598
03599 iks_filter_add_rule(client->f, aji_receive_node_list, client, IKS_RULE_TYPE,
03600 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid,
03601 IKS_RULE_DONE);
03602 ast_aji_send(client, request);
03603 iks_delete(request);
03604
03605 }
03606
03607
03608
03609
03610
03611
03612
03613 static iks* aji_build_node_request(struct aji_client *client, const char *collection)
03614 {
03615 iks *request = aji_pubsub_iq_create(client, "get");
03616 iks *query;
03617 query = iks_insert(request, "query");
03618 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
03619 if (collection) {
03620 iks_insert_attrib(query, "node", collection);
03621 }
03622 return request;
03623 }
03624
03625
03626
03627
03628
03629
03630
03631 static int aji_receive_node_list(void *data, ikspak* pak)
03632 {
03633
03634 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
03635 iks *item = NULL;
03636 if (iks_has_children(pak->query)) {
03637 item = iks_first_tag(pak->query);
03638 ast_verbose("Connection %s: %s\nNode name: %s\n", client->name, client->jid->partial,
03639 iks_find_attrib(item, "node"));
03640 while ((item = iks_next_tag(item))) {
03641 ast_verbose("Node name: %s\n", iks_find_attrib(item, "node"));
03642 }
03643 }
03644 if (item) {
03645 iks_delete(item);
03646 }
03647 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03648 return IKS_FILTER_EAT;
03649 }
03650
03651
03652
03653
03654
03655
03656
03657
03658
03659 static char *aji_cli_list_pubsub_nodes(struct ast_cli_entry *e, int cmd, struct
03660 ast_cli_args *a)
03661 {
03662 struct aji_client *client;
03663 const char *name = NULL;
03664 const char *collection = NULL;
03665
03666 switch (cmd) {
03667 case CLI_INIT:
03668 e->command = "jabber list nodes";
03669 e->usage =
03670 "Usage: jabber list nodes <connection> [collection]\n"
03671 " Lists the user's nodes on the respective connection\n"
03672 " ([connection] as configured in jabber.conf.)\n";
03673 return NULL;
03674 case CLI_GENERATE:
03675 return NULL;
03676 }
03677
03678 if (a->argc > 5 || a->argc < 4) {
03679 return CLI_SHOWUSAGE;
03680 } else if (a->argc == 4 || a->argc == 5) {
03681 name = a->argv[3];
03682 }
03683 if (a->argc == 5) {
03684 collection = a->argv[4];
03685 }
03686 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) {
03687 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
03688 return CLI_FAILURE;
03689 }
03690
03691 ast_cli(a->fd, "Listing pubsub nodes.\n");
03692 aji_request_pubsub_nodes(client, collection);
03693 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03694 return CLI_SUCCESS;
03695 }
03696
03697
03698
03699
03700
03701
03702
03703
03704 static char *aji_cli_purge_pubsub_nodes(struct ast_cli_entry *e, int cmd, struct
03705 ast_cli_args *a)
03706 {
03707 struct aji_client *client;
03708 const char *name;
03709
03710 switch (cmd) {
03711 case CLI_INIT:
03712 e->command = "jabber purge nodes";
03713 e->usage =
03714 "Usage: jabber purge nodes <connection> <node>\n"
03715 " Purges nodes on PubSub server\n"
03716 " as configured in jabber.conf.\n";
03717 return NULL;
03718 case CLI_GENERATE:
03719 return NULL;
03720 }
03721
03722 if (a->argc != 5) {
03723 return CLI_SHOWUSAGE;
03724 }
03725 name = a->argv[3];
03726
03727 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) {
03728 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
03729 return CLI_FAILURE;
03730 }
03731 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) {
03732 aji_pubsub_purge_nodes(client, a->argv[4]);
03733 } else {
03734 aji_delete_pubsub_node(client, a->argv[4]);
03735 }
03736 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03737 return CLI_SUCCESS;
03738 }
03739
03740 static void aji_pubsub_purge_nodes(struct aji_client *client, const char* collection_name)
03741 {
03742 iks *request = aji_build_node_request(client, collection_name);
03743 ast_aji_send(client, request);
03744 iks_filter_add_rule(client->f, aji_delete_node_list, client, IKS_RULE_TYPE,
03745 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid,
03746 IKS_RULE_DONE);
03747 ast_aji_send(client, request);
03748 iks_delete(request);
03749 }
03750
03751
03752
03753
03754
03755
03756
03757 static int aji_delete_node_list(void *data, ikspak* pak)
03758 {
03759
03760 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
03761 iks *item = NULL;
03762 if (iks_has_children(pak->query)) {
03763 item = iks_first_tag(pak->query);
03764 ast_log(LOG_WARNING, "Connection: %s Node name: %s\n", client->jid->partial,
03765 iks_find_attrib(item, "node"));
03766 while ((item = iks_next_tag(item))) {
03767 aji_delete_pubsub_node(client, iks_find_attrib(item, "node"));
03768 }
03769 }
03770 if (item) {
03771 iks_delete(item);
03772 }
03773 return IKS_FILTER_EAT;
03774 }
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784 static char *aji_cli_delete_pubsub_node(struct ast_cli_entry *e, int cmd, struct
03785 ast_cli_args *a)
03786 {
03787 struct aji_client *client;
03788 const char *name;
03789
03790 switch (cmd) {
03791 case CLI_INIT:
03792 e->command = "jabber delete node";
03793 e->usage =
03794 "Usage: jabber delete node <connection> <node>\n"
03795 " Deletes a node on PubSub server\n"
03796 " as configured in jabber.conf.\n";
03797 return NULL;
03798 case CLI_GENERATE:
03799 return NULL;
03800 }
03801
03802 if (a->argc != 5) {
03803 return CLI_SHOWUSAGE;
03804 }
03805 name = a->argv[3];
03806
03807 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) {
03808 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
03809 return CLI_FAILURE;
03810 }
03811 aji_delete_pubsub_node(client, a->argv[4]);
03812 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03813 return CLI_SUCCESS;
03814 }
03815
03816
03817
03818
03819
03820
03821
03822 static void aji_delete_pubsub_node(struct aji_client *client, const char *node_name)
03823 {
03824 iks *request = aji_pubsub_iq_create(client, "set");
03825 iks *pubsub, *delete;
03826 pubsub = iks_insert(request, "pubsub");
03827 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner");
03828 delete = iks_insert(pubsub, "delete");
03829 iks_insert_attrib(delete, "node", node_name);
03830 ast_aji_send(client, request);
03831 }
03832
03833
03834
03835
03836
03837
03838
03839 static void aji_create_pubsub_collection(struct aji_client *client, const char
03840 *collection_name)
03841 {
03842 aji_create_pubsub_node(client, "collection", collection_name, NULL);
03843 }
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853 static void aji_create_pubsub_leaf(struct aji_client *client, const char *collection_name,
03854 const char *leaf_name)
03855 {
03856 aji_create_pubsub_node(client, "leaf", leaf_name, collection_name);
03857 }
03858
03859
03860
03861
03862
03863
03864
03865
03866
03867 static iks* aji_create_pubsub_node(struct aji_client *client, const char *node_type, const
03868 char *name, const char *collection_name)
03869 {
03870 iks *node = aji_pubsub_iq_create(client, "set");
03871 iks *pubsub, *create;
03872 pubsub = iks_insert(node, "pubsub");
03873 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
03874 create = iks_insert(pubsub, "create");
03875 iks_insert_attrib(create, "node", name);
03876 aji_build_node_config(pubsub, node_type, collection_name);
03877 ast_aji_send(client, node);
03878 aji_create_affiliations(client, name);
03879 iks_delete(node);
03880 return 0;
03881 }
03882
03883
03884
03885 static iks* aji_build_node_config(iks *pubsub, const char *node_type, const char *collection_name)
03886 {
03887 iks *configure, *x, *field_owner, *field_node_type, *field_node_config,
03888 *field_deliver_payload, *field_persist_items, *field_access_model,
03889 *field_pubsub_collection;
03890 configure = iks_insert(pubsub, "configure");
03891 x = iks_insert(configure, "x");
03892 iks_insert_attrib(x, "xmlns", "jabber:x:data");
03893 iks_insert_attrib(x, "type", "submit");
03894 field_owner = iks_insert(x, "field");
03895 iks_insert_attrib(field_owner, "var", "FORM_TYPE");
03896 iks_insert_attrib(field_owner, "type", "hidden");
03897 iks_insert_cdata(iks_insert(field_owner, "value"),
03898 "http://jabber.org/protocol/pubsub#owner", 39);
03899 if (node_type) {
03900 field_node_type = iks_insert(x, "field");
03901 iks_insert_attrib(field_node_type, "var", "pubsub#node_type");
03902 iks_insert_cdata(iks_insert(field_node_type, "value"), node_type, strlen(node_type));
03903 }
03904 field_node_config = iks_insert(x, "field");
03905 iks_insert_attrib(field_node_config, "var", "FORM_TYPE");
03906 iks_insert_attrib(field_node_config, "type", "hidden");
03907 iks_insert_cdata(iks_insert(field_node_config, "value"),
03908 "http://jabber.org/protocol/pubsub#node_config", 45);
03909 field_deliver_payload = iks_insert(x, "field");
03910 iks_insert_attrib(field_deliver_payload, "var", "pubsub#deliver_payloads");
03911 iks_insert_cdata(iks_insert(field_deliver_payload, "value"), "1", 1);
03912 field_persist_items = iks_insert(x, "field");
03913 iks_insert_attrib(field_persist_items, "var", "pubsub#persist_items");
03914 iks_insert_cdata(iks_insert(field_persist_items, "value"), "1", 1);
03915 field_access_model = iks_insert(x, "field");
03916 iks_insert_attrib(field_access_model, "var", "pubsub#access_model");
03917 iks_insert_cdata(iks_insert(field_access_model, "value"), "whitelist", 9);
03918 if (node_type && !strcasecmp(node_type, "leaf")) {
03919 field_pubsub_collection = iks_insert(x, "field");
03920 iks_insert_attrib(field_pubsub_collection, "var", "pubsub#collection");
03921 iks_insert_cdata(iks_insert(field_pubsub_collection, "value"), collection_name,
03922 strlen(collection_name));
03923 }
03924 return configure;
03925 }
03926
03927
03928
03929
03930
03931
03932
03933 static char *aji_cli_create_collection(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03934 {
03935 struct aji_client *client;
03936 const char *name;
03937 const char *collection_name;
03938
03939 switch (cmd) {
03940 case CLI_INIT:
03941 e->command = "jabber create collection";
03942 e->usage =
03943 "Usage: jabber create collection <connection> <collection>\n"
03944 " Creates a PubSub collection node using the account\n"
03945 " as configured in jabber.conf.\n";
03946 return NULL;
03947 case CLI_GENERATE:
03948 return NULL;
03949 }
03950
03951 if (a->argc != 5) {
03952 return CLI_SHOWUSAGE;
03953 }
03954 name = a->argv[3];
03955 collection_name = a->argv[4];
03956
03957 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) {
03958 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
03959 return CLI_FAILURE;
03960 }
03961
03962 ast_cli(a->fd, "Creating test PubSub node collection.\n");
03963 aji_create_pubsub_collection(client, collection_name);
03964 ASTOBJ_UNREF(client, ast_aji_client_destroy);
03965 return CLI_SUCCESS;
03966 }
03967
03968
03969
03970
03971
03972 static char *aji_cli_create_leafnode(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03973 {
03974 struct aji_client *client;
03975 const char *name;
03976 const char *collection_name;
03977 const char *leaf_name;
03978
03979 switch (cmd) {
03980 case CLI_INIT:
03981 e->command = "jabber create leaf";
03982 e->usage =
03983 "Usage: jabber create leaf <connection> <collection> <leaf>\n"
03984 " Creates a PubSub leaf node using the account\n"
03985 " as configured in jabber.conf.\n";
03986 return NULL;
03987 case CLI_GENERATE:
03988 return NULL;
03989 }
03990
03991 if (a->argc != 6) {
03992 return CLI_SHOWUSAGE;
03993 }
03994 name = a->argv[3];
03995 collection_name = a->argv[4];
03996 leaf_name = a->argv[5];
03997
03998 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) {
03999 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
04000 return CLI_FAILURE;
04001 }
04002
04003 ast_cli(a->fd, "Creating test PubSub node collection.\n");
04004 aji_create_pubsub_leaf(client, collection_name, leaf_name);
04005 ASTOBJ_UNREF(client, ast_aji_client_destroy);
04006 return CLI_SUCCESS;
04007 }
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018
04019
04020
04021 static void aji_set_presence(struct aji_client *client, char *to, char *from, int level, char *desc)
04022 {
04023 iks *presence = iks_make_pres(level, desc);
04024 iks *cnode = iks_new("c");
04025 iks *priority = iks_new("priority");
04026 char priorityS[10];
04027
04028 if (presence && cnode && client && priority) {
04029 if (to) {
04030 iks_insert_attrib(presence, "to", to);
04031 }
04032 if (from) {
04033 iks_insert_attrib(presence, "from", from);
04034 }
04035 snprintf(priorityS, sizeof(priorityS), "%d", client->priority);
04036 iks_insert_cdata(priority, priorityS, strlen(priorityS));
04037 iks_insert_node(presence, priority);
04038 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps");
04039 iks_insert_attrib(cnode, "ver", "asterisk-xmpp");
04040 iks_insert_attrib(cnode, "ext", "voice-v1");
04041 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps");
04042 iks_insert_node(presence, cnode);
04043 ast_aji_send(client, presence);
04044 } else {
04045 ast_log(LOG_ERROR, "Out of memory.\n");
04046 }
04047
04048 iks_delete(cnode);
04049 iks_delete(presence);
04050 iks_delete(priority);
04051 }
04052
04053
04054
04055
04056
04057
04058
04059
04060
04061
04062
04063 static int aji_set_group_presence(struct aji_client *client, char *room, int level, char *nick, char *desc)
04064 {
04065 int res = 0;
04066 iks *presence = NULL, *x = NULL;
04067 char from[AJI_MAX_JIDLEN];
04068 char roomid[AJI_MAX_JIDLEN];
04069
04070 presence = iks_make_pres(level, NULL);
04071 x = iks_new("x");
04072
04073 if (client->component) {
04074 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick);
04075 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick);
04076 } else {
04077 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full);
04078 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick ? nick : client->jid->user);
04079 }
04080
04081 if (!presence || !x || !client) {
04082 ast_log(LOG_ERROR, "Out of memory.\n");
04083 res = -1;
04084 goto safeout;
04085 } else {
04086 iks_insert_attrib(presence, "to", roomid);
04087 iks_insert_attrib(presence, "from", from);
04088 iks_insert_attrib(x, "xmlns", MUC_NS);
04089 iks_insert_node(presence, x);
04090 res = ast_aji_send(client, presence);
04091 }
04092
04093 safeout:
04094 iks_delete(presence);
04095 iks_delete(x);
04096 return res;
04097 }
04098
04099
04100
04101
04102
04103
04104 static char *aji_do_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04105 {
04106 switch (cmd) {
04107 case CLI_INIT:
04108 e->command = "jabber set debug {on|off}";
04109 e->usage =
04110 "Usage: jabber set debug {on|off}\n"
04111 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n";
04112 return NULL;
04113 case CLI_GENERATE:
04114 return NULL;
04115 }
04116
04117 if (a->argc != e->args) {
04118 return CLI_SHOWUSAGE;
04119 }
04120
04121 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
04122 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
04123 ASTOBJ_RDLOCK(iterator);
04124 iterator->debug = 1;
04125 ASTOBJ_UNLOCK(iterator);
04126 });
04127 ast_cli(a->fd, "Jabber Debugging Enabled.\n");
04128 return CLI_SUCCESS;
04129 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) {
04130 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
04131 ASTOBJ_RDLOCK(iterator);
04132 iterator->debug = 0;
04133 ASTOBJ_UNLOCK(iterator);
04134 });
04135 ast_cli(a->fd, "Jabber Debugging Disabled.\n");
04136 return CLI_SUCCESS;
04137 }
04138 return CLI_SHOWUSAGE;
04139 }
04140
04141
04142
04143
04144
04145
04146 static char *aji_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04147 {
04148 switch (cmd) {
04149 case CLI_INIT:
04150 e->command = "jabber reload";
04151 e->usage =
04152 "Usage: jabber reload\n"
04153 " Reloads the Jabber module.\n";
04154 return NULL;
04155 case CLI_GENERATE:
04156 return NULL;
04157 }
04158
04159 aji_reload(1);
04160 ast_cli(a->fd, "Jabber Reloaded.\n");
04161 return CLI_SUCCESS;
04162 }
04163
04164
04165
04166
04167
04168
04169 static char *aji_show_clients(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04170 {
04171 char *status;
04172 int count = 0;
04173
04174 switch (cmd) {
04175 case CLI_INIT:
04176 e->command = "jabber show connections";
04177 e->usage =
04178 "Usage: jabber show connections\n"
04179 " Shows state of client and component connections\n";
04180 return NULL;
04181 case CLI_GENERATE:
04182 return NULL;
04183 }
04184
04185 ast_cli(a->fd, "Jabber Users and their status:\n");
04186 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
04187 ASTOBJ_RDLOCK(iterator);
04188 count++;
04189 switch (iterator->state) {
04190 case AJI_DISCONNECTED:
04191 status = "Disconnected";
04192 break;
04193 case AJI_CONNECTING:
04194 status = "Connecting";
04195 break;
04196 case AJI_CONNECTED:
04197 status = "Connected";
04198 break;
04199 default:
04200 status = "Unknown";
04201 }
04202 ast_cli(a->fd, " [%s] %s - %s\n", iterator->name, iterator->user, status);
04203 ASTOBJ_UNLOCK(iterator);
04204 });
04205 ast_cli(a->fd, "----\n");
04206 ast_cli(a->fd, " Number of users: %d\n", count);
04207 return CLI_SUCCESS;
04208 }
04209
04210
04211
04212
04213
04214
04215 static char *aji_show_buddies(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04216 {
04217 struct aji_resource *resource;
04218 struct aji_client *client;
04219
04220 switch (cmd) {
04221 case CLI_INIT:
04222 e->command = "jabber show buddies";
04223 e->usage =
04224 "Usage: jabber show buddies\n"
04225 " Shows buddy lists of our clients\n";
04226 return NULL;
04227 case CLI_GENERATE:
04228 return NULL;
04229 }
04230
04231 ast_cli(a->fd, "Jabber buddy lists\n");
04232 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
04233 ast_cli(a->fd, "Client: %s\n", iterator->user);
04234 client = iterator;
04235 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
04236 ASTOBJ_RDLOCK(iterator);
04237 ast_cli(a->fd, "\tBuddy:\t%s\n", iterator->name);
04238 if (!iterator->resources)
04239 ast_cli(a->fd, "\t\tResource: None\n");
04240 for (resource = iterator->resources; resource; resource = resource->next) {
04241 ast_cli(a->fd, "\t\tResource: %s\n", resource->resource);
04242 if (resource->cap) {
04243 ast_cli(a->fd, "\t\t\tnode: %s\n", resource->cap->parent->node);
04244 ast_cli(a->fd, "\t\t\tversion: %s\n", resource->cap->version);
04245 ast_cli(a->fd, "\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no");
04246 }
04247 ast_cli(a->fd, "\t\tStatus: %d\n", resource->status);
04248 ast_cli(a->fd, "\t\tPriority: %d\n", resource->priority);
04249 }
04250 ASTOBJ_UNLOCK(iterator);
04251 });
04252 iterator = client;
04253 });
04254 return CLI_SUCCESS;
04255 }
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265 static int aji_create_client(char *label, struct ast_variable *var, int debug)
04266 {
04267 char *resource;
04268 struct aji_client *client = NULL;
04269 int flag = 0;
04270
04271 client = ASTOBJ_CONTAINER_FIND(&clients, label);
04272 if (!client) {
04273 flag = 1;
04274 client = ast_calloc(1, sizeof(*client));
04275 if (!client) {
04276 ast_log(LOG_ERROR, "Out of memory!\n");
04277 return 0;
04278 }
04279 ASTOBJ_INIT(client);
04280 ASTOBJ_WRLOCK(client);
04281 ASTOBJ_CONTAINER_INIT(&client->buddies);
04282 } else {
04283 ASTOBJ_WRLOCK(client);
04284 ASTOBJ_UNMARK(client);
04285 }
04286 ASTOBJ_CONTAINER_MARKALL(&client->buddies);
04287 ast_copy_string(client->name, label, sizeof(client->name));
04288 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid));
04289 ast_copy_string(client->context, "default", sizeof(client->context));
04290
04291
04292 client->debug = debug;
04293 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL);
04294 client->port = 5222;
04295 client->usetls = 1;
04296 client->usesasl = 1;
04297 client->forcessl = 0;
04298 client->keepalive = 1;
04299 client->timeout = 50;
04300 client->message_timeout = 5;
04301 client->distribute_events = 0;
04302 AST_LIST_HEAD_INIT(&client->messages);
04303 client->component = 0;
04304 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage));
04305 client->priority = 0;
04306 client->status = IKS_SHOW_AVAILABLE;
04307 client->send_to_dialplan = 0;
04308
04309 if (flag) {
04310 client->authorized = 0;
04311 client->state = AJI_DISCONNECTED;
04312 }
04313 while (var) {
04314 if (!strcasecmp(var->name, "username")) {
04315 ast_copy_string(client->user, var->value, sizeof(client->user));
04316 } else if (!strcasecmp(var->name, "serverhost")) {
04317 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost));
04318 } else if (!strcasecmp(var->name, "secret")) {
04319 ast_copy_string(client->password, var->value, sizeof(client->password));
04320 } else if (!strcasecmp(var->name, "statusmessage")) {
04321 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage));
04322 } else if (!strcasecmp(var->name, "port")) {
04323 client->port = atoi(var->value);
04324 } else if (!strcasecmp(var->name, "timeout")) {
04325 client->message_timeout = atoi(var->value);
04326 } else if (!strcasecmp(var->name, "debug")) {
04327 client->debug = (ast_false(var->value)) ? 0 : 1;
04328 } else if (!strcasecmp(var->name, "type")) {
04329 if (!strcasecmp(var->value, "component")) {
04330 client->component = 1;
04331 if (client->distribute_events) {
04332 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n");
04333 client->distribute_events = 0;
04334 }
04335 }
04336 } else if (!strcasecmp(var->name, "distribute_events")) {
04337 if (ast_true(var->value)) {
04338 if (client->component) {
04339 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n");
04340 } else {
04341 if (ast_test_flag(&pubsubflags, AJI_PUBSUB)) {
04342 ast_log(LOG_ERROR, "Only one connection can be configured for distributed events.\n");
04343 } else {
04344 ast_set_flag(&pubsubflags, AJI_PUBSUB);
04345 client->distribute_events = 1;
04346 }
04347 }
04348 }
04349 } else if (!strcasecmp(var->name, "pubsub_node")) {
04350 ast_copy_string(client->pubsub_node, var->value, sizeof(client->pubsub_node));
04351 } else if (!strcasecmp(var->name, "usetls")) {
04352 client->usetls = (ast_false(var->value)) ? 0 : 1;
04353 } else if (!strcasecmp(var->name, "usesasl")) {
04354 client->usesasl = (ast_false(var->value)) ? 0 : 1;
04355 } else if (!strcasecmp(var->name, "forceoldssl")) {
04356 client->forcessl = (ast_false(var->value)) ? 0 : 1;
04357 } else if (!strcasecmp(var->name, "keepalive")) {
04358 client->keepalive = (ast_false(var->value)) ? 0 : 1;
04359 } else if (!strcasecmp(var->name, "autoprune")) {
04360 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE);
04361 } else if (!strcasecmp(var->name, "autoregister")) {
04362 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER);
04363 } else if (!strcasecmp(var->name, "auth_policy")) {
04364 if (!strcasecmp(var->value, "accept")) {
04365 ast_set_flag(&client->flags, AJI_AUTOACCEPT);
04366 } else {
04367 ast_clear_flag(&client->flags, AJI_AUTOACCEPT);
04368 }
04369 } else if (!strcasecmp(var->name, "buddy")) {
04370 aji_create_buddy((char *)var->value, client);
04371 } else if (!strcasecmp(var->name, "priority")) {
04372 client->priority = atoi(var->value);
04373 } else if (!strcasecmp(var->name, "status")) {
04374 if (!strcasecmp(var->value, "unavailable")) {
04375 client->status = IKS_SHOW_UNAVAILABLE;
04376 } else if (!strcasecmp(var->value, "available")
04377 || !strcasecmp(var->value, "online")) {
04378 client->status = IKS_SHOW_AVAILABLE;
04379 } else if (!strcasecmp(var->value, "chat")
04380 || !strcasecmp(var->value, "chatty")) {
04381 client->status = IKS_SHOW_CHAT;
04382 } else if (!strcasecmp(var->value, "away")) {
04383 client->status = IKS_SHOW_AWAY;
04384 } else if (!strcasecmp(var->value, "xa")
04385 || !strcasecmp(var->value, "xaway")) {
04386 client->status = IKS_SHOW_XA;
04387 } else if (!strcasecmp(var->value, "dnd")) {
04388 client->status = IKS_SHOW_DND;
04389 } else if (!strcasecmp(var->value, "invisible")) {
04390 #ifdef IKS_SHOW_INVISIBLE
04391 client->status = IKS_SHOW_INVISIBLE;
04392 #else
04393 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n");
04394 client->status = IKS_SHOW_DND;
04395 #endif
04396 } else {
04397 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value);
04398 }
04399 } else if (!strcasecmp(var->name, "context")) {
04400 ast_copy_string(client->context, var->value, sizeof(client->context));
04401 } else if (!strcasecmp(var->name, "sendtodialplan")) {
04402 client->send_to_dialplan = ast_true(var->value) ? 1 : 0;
04403 }
04404
04405
04406
04407
04408 var = var->next;
04409 }
04410 if (!flag) {
04411 ASTOBJ_UNLOCK(client);
04412 ASTOBJ_UNREF(client, ast_aji_client_destroy);
04413 return 1;
04414 }
04415
04416 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space));
04417 client->p = iks_stream_new(client->name_space, client, aji_act_hook);
04418 if (!client->p) {
04419 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name);
04420 return 0;
04421 }
04422 client->stack = iks_stack_new(8192, 8192);
04423 if (!client->stack) {
04424 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name);
04425 return 0;
04426 }
04427 client->f = iks_filter_new();
04428 if (!client->f) {
04429 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name);
04430 return 0;
04431 }
04432 if (!strchr(client->user, '/') && !client->component) {
04433 if (ast_asprintf(&resource, "%s/asterisk", client->user) >= 0) {
04434 client->jid = iks_id_new(client->stack, resource);
04435 ast_free(resource);
04436 }
04437 } else {
04438 client->jid = iks_id_new(client->stack, client->user);
04439 }
04440 if (client->component) {
04441 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
04442 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE);
04443 iks_filter_add_rule(client->f, aji_register_query_handler, client, IKS_RULE_SUBTYPE, IKS_TYPE_GET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE);
04444 iks_filter_add_rule(client->f, aji_register_approve_handler, client, IKS_RULE_SUBTYPE, IKS_TYPE_SET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE);
04445 } else {
04446 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
04447 }
04448
04449 iks_set_log_hook(client->p, aji_log_hook);
04450 ASTOBJ_UNLOCK(client);
04451 ASTOBJ_CONTAINER_LINK(&clients, client);
04452 return 1;
04453 }
04454
04455
04456
04457 #if 0
04458
04459
04460
04461
04462
04463
04464 static int aji_create_transport(char *label, struct aji_client *client)
04465 {
04466 char *server = NULL, *buddyname = NULL, *user = NULL, *pass = NULL;
04467 struct aji_buddy *buddy = NULL;
04468 int needs_unref = 1;
04469
04470 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies,label);
04471 if (!buddy) {
04472 needs_unref = 0;
04473 buddy = ast_calloc(1, sizeof(*buddy));
04474 if (!buddy) {
04475 ast_log(LOG_WARNING, "Out of memory\n");
04476 return 0;
04477 }
04478 ASTOBJ_INIT(buddy);
04479 }
04480 ASTOBJ_WRLOCK(buddy);
04481 server = label;
04482 if ((buddyname = strchr(label, ','))) {
04483 *buddyname = '\0';
04484 buddyname++;
04485 if (buddyname && buddyname[0] != '\0') {
04486 if ((user = strchr(buddyname, ','))) {
04487 *user = '\0';
04488 user++;
04489 if (user && user[0] != '\0') {
04490 if ((pass = strchr(user, ','))) {
04491 *pass = '\0';
04492 pass++;
04493 ast_copy_string(buddy->pass, pass, sizeof(buddy->pass));
04494 ast_copy_string(buddy->user, user, sizeof(buddy->user));
04495 ast_copy_string(buddy->name, buddyname, sizeof(buddy->name));
04496 ast_copy_string(buddy->server, server, sizeof(buddy->server));
04497 if (needs_unref) {
04498 ASTOBJ_UNMARK(buddy);
04499 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
04500 }
04501 return 1;
04502 }
04503 }
04504 }
04505 }
04506 }
04507 ASTOBJ_UNLOCK(buddy);
04508 if (needs_unref) {
04509 ASTOBJ_UNMARK(buddy);
04510 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
04511 } else {
04512 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
04513 }
04514 return 0;
04515 }
04516 #endif
04517
04518
04519
04520
04521
04522
04523
04524
04525 static int aji_create_buddy(char *label, struct aji_client *client)
04526 {
04527 struct aji_buddy *buddy = NULL;
04528 int needs_unref = 1;
04529 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, label);
04530 if (!buddy) {
04531 needs_unref = 0;
04532 buddy = ast_calloc(1, sizeof(*buddy));
04533 if (!buddy) {
04534 ast_log(LOG_WARNING, "Out of memory\n");
04535 return 0;
04536 }
04537 ASTOBJ_INIT(buddy);
04538 }
04539 ASTOBJ_WRLOCK(buddy);
04540 ast_copy_string(buddy->name, label, sizeof(buddy->name));
04541 ASTOBJ_UNLOCK(buddy);
04542 if (needs_unref) {
04543 ASTOBJ_UNMARK(buddy);
04544 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
04545 } else {
04546 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
04547 }
04548 return 1;
04549 }
04550
04551
04552 static int aji_load_config(int reload)
04553 {
04554 char *cat = NULL;
04555 int debug = 0;
04556 struct ast_config *cfg = NULL;
04557 struct ast_variable *var = NULL;
04558 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
04559
04560 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
04561 return -1;
04562 }
04563
04564
04565 ast_set_flag(&globalflags, AJI_AUTOREGISTER | AJI_AUTOACCEPT);
04566
04567 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
04568 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG);
04569 return 0;
04570 }
04571
04572 cat = ast_category_browse(cfg, NULL);
04573 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
04574 if (!strcasecmp(var->name, "debug")) {
04575 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1;
04576 } else if (!strcasecmp(var->name, "autoprune")) {
04577 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE);
04578 } else if (!strcasecmp(var->name, "autoregister")) {
04579 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER);
04580 } else if (!strcasecmp(var->name, "collection_nodes")) {
04581 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_XEP0248);
04582 } else if (!strcasecmp(var->name, "pubsub_autocreate")) {
04583 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_PUBSUB_AUTOCREATE);
04584 } else if (!strcasecmp(var->name, "auth_policy")) {
04585 if (!strcasecmp(var->value, "accept")) {
04586 ast_set_flag(&globalflags, AJI_AUTOACCEPT);
04587 } else {
04588 ast_clear_flag(&globalflags, AJI_AUTOACCEPT);
04589 }
04590 }
04591 }
04592
04593 while (cat) {
04594 if (strcasecmp(cat, "general")) {
04595 var = ast_variable_browse(cfg, cat);
04596 aji_create_client(cat, var, debug);
04597 }
04598 cat = ast_category_browse(cfg, cat);
04599 }
04600 ast_config_destroy(cfg);
04601 return 1;
04602 }
04603
04604
04605
04606
04607
04608
04609
04610 struct aji_client *ast_aji_get_client(const char *name)
04611 {
04612 struct aji_client *client = NULL;
04613 char *aux = NULL;
04614
04615 client = ASTOBJ_CONTAINER_FIND(&clients, name);
04616 if (!client && strchr(name, '@')) {
04617 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
04618 aux = ast_strdupa(iterator->user);
04619 if (strchr(aux, '/')) {
04620
04621 aux = strsep(&aux, "/");
04622 }
04623 if (!strncasecmp(aux, name, strlen(aux))) {
04624 client = ASTOBJ_REF(iterator);
04625 }
04626 });
04627 }
04628
04629 return client;
04630 }
04631
04632 struct aji_client_container *ast_aji_get_clients(void)
04633 {
04634 return &clients;
04635 }
04636
04637
04638
04639
04640
04641
04642
04643
04644 static int manager_jabber_send(struct mansession *s, const struct message *m)
04645 {
04646 struct aji_client *client = NULL;
04647 const char *id = astman_get_header(m, "ActionID");
04648 const char *jabber = astman_get_header(m, "Jabber");
04649 const char *screenname = astman_get_header(m, "ScreenName");
04650 const char *message = astman_get_header(m, "Message");
04651
04652 if (ast_strlen_zero(jabber)) {
04653 astman_send_error(s, m, "No transport specified");
04654 return 0;
04655 }
04656 if (ast_strlen_zero(screenname)) {
04657 astman_send_error(s, m, "No ScreenName specified");
04658 return 0;
04659 }
04660 if (ast_strlen_zero(message)) {
04661 astman_send_error(s, m, "No Message specified");
04662 return 0;
04663 }
04664
04665 astman_send_ack(s, m, "Attempting to send Jabber Message");
04666 client = ast_aji_get_client(jabber);
04667 if (!client) {
04668 astman_send_error(s, m, "Could not find Sender");
04669 return 0;
04670 }
04671 if (strchr(screenname, '@') && message) {
04672 ast_aji_send_chat(client, screenname, message);
04673 astman_append(s, "Response: Success\r\n");
04674 } else {
04675 astman_append(s, "Response: Error\r\n");
04676 }
04677 ASTOBJ_UNREF(client, ast_aji_client_destroy);
04678 if (!ast_strlen_zero(id)) {
04679 astman_append(s, "ActionID: %s\r\n", id);
04680 }
04681 astman_append(s, "\r\n");
04682 return 0;
04683 }
04684
04685
04686
04687
04688
04689 static int aji_reload(int reload)
04690 {
04691 int res;
04692
04693 ASTOBJ_CONTAINER_MARKALL(&clients);
04694 if (!(res = aji_load_config(reload))) {
04695 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n");
04696 return 0;
04697 } else if (res == -1)
04698 return 1;
04699
04700 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, ast_aji_client_destroy);
04701 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
04702 ASTOBJ_RDLOCK(iterator);
04703 if (iterator->state == AJI_DISCONNECTED) {
04704 if (!iterator->thread)
04705 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator);
04706 } else if (iterator->state == AJI_CONNECTING) {
04707 aji_get_roster(iterator);
04708 if (iterator->distribute_events) {
04709 aji_init_event_distribution(iterator);
04710 }
04711 }
04712
04713 ASTOBJ_UNLOCK(iterator);
04714 });
04715
04716 return 1;
04717 }
04718
04719
04720
04721
04722
04723 static int unload_module(void)
04724 {
04725 ast_msg_tech_unregister(&msg_tech);
04726 ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli));
04727 ast_unregister_application(app_ajisend);
04728 ast_unregister_application(app_ajisendgroup);
04729 ast_unregister_application(app_ajistatus);
04730 ast_unregister_application(app_ajijoin);
04731 ast_unregister_application(app_ajileave);
04732 ast_manager_unregister("JabberSend");
04733 ast_custom_function_unregister(&jabberstatus_function);
04734 if (mwi_sub) {
04735 ast_event_unsubscribe(mwi_sub);
04736 }
04737 if (device_state_sub) {
04738 ast_event_unsubscribe(device_state_sub);
04739 }
04740 ast_custom_function_unregister(&jabberreceive_function);
04741
04742 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
04743 ASTOBJ_WRLOCK(iterator);
04744 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name);
04745 iterator->state = AJI_DISCONNECTING;
04746 ASTOBJ_UNLOCK(iterator);
04747 pthread_join(iterator->thread, NULL);
04748 ast_aji_disconnect(iterator);
04749 });
04750
04751 ASTOBJ_CONTAINER_DESTROYALL(&clients, ast_aji_client_destroy);
04752 ASTOBJ_CONTAINER_DESTROY(&clients);
04753
04754 ast_cond_destroy(&message_received_condition);
04755 ast_mutex_destroy(&messagelock);
04756
04757 return 0;
04758 }
04759
04760
04761
04762
04763
04764 static int load_module(void)
04765 {
04766 ASTOBJ_CONTAINER_INIT(&clients);
04767 if (!aji_reload(0))
04768 return AST_MODULE_LOAD_DECLINE;
04769 ast_manager_register_xml("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send);
04770 ast_register_application_xml(app_ajisend, aji_send_exec);
04771 ast_register_application_xml(app_ajisendgroup, aji_sendgroup_exec);
04772 ast_register_application_xml(app_ajistatus, aji_status_exec);
04773 ast_register_application_xml(app_ajijoin, aji_join_exec);
04774 ast_register_application_xml(app_ajileave, aji_leave_exec);
04775 ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli));
04776 ast_custom_function_register(&jabberstatus_function);
04777 ast_custom_function_register(&jabberreceive_function);
04778 ast_msg_tech_register(&msg_tech);
04779
04780 ast_mutex_init(&messagelock);
04781 ast_cond_init(&message_received_condition, NULL);
04782 return 0;
04783 }
04784
04785
04786
04787
04788
04789 static int reload(void)
04790 {
04791 aji_reload(1);
04792 return 0;
04793 }
04794
04795 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "AJI - Asterisk Jabber Interface",
04796 .load = load_module,
04797 .unload = unload_module,
04798 .reload = reload,
04799 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
04800 );