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 #include "asterisk.h"
00029
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00031
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 #include <iksemel.h>
00035
00036 #include "asterisk/channel.h"
00037 #include "asterisk/jabber.h"
00038 #include "asterisk/file.h"
00039 #include "asterisk/config.h"
00040 #include "asterisk/callerid.h"
00041 #include "asterisk/lock.h"
00042 #include "asterisk/logger.h"
00043 #include "asterisk/options.h"
00044 #include "asterisk/cli.h"
00045 #include "asterisk/app.h"
00046 #include "asterisk/pbx.h"
00047 #include "asterisk/md5.h"
00048 #include "asterisk/acl.h"
00049 #include "asterisk/utils.h"
00050 #include "asterisk/module.h"
00051 #include "asterisk/astobj.h"
00052 #include "asterisk/astdb.h"
00053 #include "asterisk/manager.h"
00054
00055 #define JABBER_CONFIG "jabber.conf"
00056
00057
00058 static int aji_highest_bit(int number);
00059 static void aji_buddy_destroy(struct aji_buddy *obj);
00060 static void aji_client_destroy(struct aji_client *obj);
00061 static int aji_send_exec(struct ast_channel *chan, void *data);
00062 static int aji_status_exec(struct ast_channel *chan, void *data);
00063 static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming);
00064 static int aji_act_hook(void *data, int type, iks *node);
00065 static void aji_handle_iq(struct aji_client *client, iks *node);
00066 static void aji_handle_message(struct aji_client *client, ikspak *pak);
00067 static void aji_handle_presence(struct aji_client *client, ikspak *pak);
00068 static void aji_handle_subscribe(struct aji_client *client, ikspak *pak);
00069 static void *aji_recv_loop(void *data);
00070 static int aji_component_initialize(struct aji_client *client);
00071 static int aji_client_initialize(struct aji_client *client);
00072 static int aji_client_connect(void *data, ikspak *pak);
00073 static void aji_set_presence(struct aji_client *client, char *to, char *from, int level, char *desc);
00074 static int aji_do_debug(int fd, int argc, char *argv[]);
00075 static int aji_do_reload(int fd, int argc, char *argv[]);
00076 static int aji_no_debug(int fd, int argc, char *argv[]);
00077 static int aji_test(int fd, int argc, char *argv[]);
00078 static int aji_show_clients(int fd, int argc, char *argv[]);
00079 static int aji_create_client(char *label, struct ast_variable *var, int debug);
00080 static int aji_create_buddy(char *label, struct aji_client *client);
00081 static int aji_reload(void);
00082 static int aji_load_config(void);
00083 static void aji_pruneregister(struct aji_client *client);
00084 static int aji_filter_roster(void *data, ikspak *pak);
00085 static int aji_get_roster(struct aji_client *client);
00086 static int aji_client_info_handler(void *data, ikspak *pak);
00087 static int aji_dinfo_handler(void *data, ikspak *pak);
00088 static int aji_ditems_handler(void *data, ikspak *pak);
00089 static int aji_register_query_handler(void *data, ikspak *pak);
00090 static int aji_register_approve_handler(void *data, ikspak *pak);
00091 static int aji_reconnect(struct aji_client *client);
00092 static iks *jabber_make_auth(iksid * id, const char *pass, const char *sid);
00093
00094
00095
00096
00097
00098
00099
00100 static char debug_usage[] =
00101 "Usage: jabber debug\n"
00102 " Enables dumping of Jabber packets for debugging purposes.\n";
00103
00104 static char no_debug_usage[] =
00105 "Usage: jabber debug off\n"
00106 " Disables dumping of Jabber packets for debugging purposes.\n";
00107
00108 static char reload_usage[] =
00109 "Usage: jabber reload\n"
00110 " Enables reloading of Jabber module.\n";
00111
00112 static char test_usage[] =
00113 "Usage: jabber test [client]\n"
00114 " Sends test message for debugging purposes. A specific client\n"
00115 " as configured in jabber.conf can be optionally specified.\n";
00116
00117 static struct ast_cli_entry aji_cli[] = {
00118 { { "jabber", "debug", NULL},
00119 aji_do_debug, "Enable Jabber debugging",
00120 debug_usage },
00121
00122 { { "jabber", "reload", NULL},
00123 aji_do_reload, "Reload Jabber configuration",
00124 reload_usage },
00125
00126 { { "jabber", "show", "connected", NULL},
00127 aji_show_clients, "Show state of clients and components",
00128 debug_usage },
00129
00130 { { "jabber", "debug", "off", NULL},
00131 aji_no_debug, "Disable Jabber debug",
00132 no_debug_usage },
00133
00134 { { "jabber", "test", NULL},
00135 aji_test, "Shows roster, but is generally used for mog's debugging.",
00136 test_usage },
00137 };
00138
00139 static char *app_ajisend = "JabberSend";
00140
00141 static char *ajisend_synopsis = "JabberSend(jabber,screenname,message)";
00142
00143 static char *ajisend_descrip =
00144 "JabberSend(Jabber,ScreenName,Message)\n"
00145 " Jabber - Client or transport Asterisk uses to connect to Jabber\n"
00146 " ScreenName - User Name to message.\n"
00147 " Message - Message to be sent to the buddy\n";
00148
00149 static char *app_ajistatus = "JabberStatus";
00150
00151 static char *ajistatus_synopsis = "JabberStatus(Jabber,ScreenName,Variable)";
00152
00153 static char *ajistatus_descrip =
00154 "JabberStatus(Jabber,ScreenName,Variable)\n"
00155 " Jabber - Client or transport Asterisk uses to connect to Jabber\n"
00156 " ScreenName - User Name to retrieve status from.\n"
00157 " Variable - Variable to store presence in will be 1-6.\n"
00158 " In order, Online, Chatty, Away, XAway, DND, Offline\n"
00159 " If not in roster variable will = 7\n";
00160
00161 struct aji_client_container clients;
00162
00163 struct aji_capabilities *capabilities;
00164
00165
00166 static struct ast_flags globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER };
00167
00168
00169
00170
00171
00172
00173 static void aji_client_destroy(struct aji_client *obj)
00174 {
00175 struct aji_message *tmp;
00176 ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, aji_buddy_destroy);
00177 ASTOBJ_CONTAINER_DESTROY(&obj->buddies);
00178 iks_filter_delete(obj->f);
00179 iks_parser_delete(obj->p);
00180 iks_stack_delete(obj->stack);
00181 AST_LIST_LOCK(&obj->messages);
00182 while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) {
00183 if (tmp->from)
00184 free(tmp->from);
00185 if (tmp->message)
00186 free(tmp->message);
00187 }
00188 AST_LIST_HEAD_DESTROY(&obj->messages);
00189 free(obj);
00190 }
00191
00192
00193
00194
00195
00196
00197 static void aji_buddy_destroy(struct aji_buddy *obj)
00198 {
00199 struct aji_resource *tmp;
00200
00201 while ((tmp = obj->resources)) {
00202 obj->resources = obj->resources->next;
00203 free(tmp->description);
00204 free(tmp);
00205 }
00206
00207 free(obj);
00208 }
00209
00210 static struct aji_version *aji_find_version(char *node, char *version, ikspak *pak)
00211 {
00212 struct aji_capabilities *list = NULL;
00213 struct aji_version *res = NULL;
00214
00215 list = capabilities;
00216
00217 if(!node)
00218 node = pak->from->full;
00219 if(!version)
00220 version = "none supplied.";
00221 while(list) {
00222 if(!strcasecmp(list->node, node)) {
00223 res = list->versions;
00224 while(res) {
00225 if(!strcasecmp(res->version, version))
00226 return res;
00227 res = res->next;
00228 }
00229 if(!res) {
00230 res = (struct aji_version *)malloc(sizeof(struct aji_version));
00231 if(!res) {
00232 ast_log(LOG_ERROR, "Out of memory!\n");
00233 return NULL;
00234 }
00235 res->jingle = 0;
00236 res->parent = list;
00237 ast_copy_string(res->version, version, sizeof(res->version));
00238 res->next = list->versions;
00239 list->versions = res;
00240 return res;
00241 }
00242 }
00243 list = list->next;
00244 }
00245 if(!list) {
00246 list = (struct aji_capabilities *)malloc(sizeof(struct aji_capabilities));
00247 if(!list) {
00248 ast_log(LOG_ERROR, "Out of memory!\n");
00249 return NULL;
00250 }
00251 res = (struct aji_version *)malloc(sizeof(struct aji_version));
00252 if(!res) {
00253 ast_log(LOG_ERROR, "Out of memory!\n");
00254 return NULL;
00255 }
00256 ast_copy_string(list->node, node, sizeof(list->node));
00257 ast_copy_string(res->version, version, sizeof(res->version));
00258 res->jingle = 0;
00259 res->parent = list;
00260 res->next = list->versions;
00261 list->versions = res;
00262 list->next = capabilities;
00263 capabilities = list;
00264 }
00265 return res;
00266 }
00267
00268 static struct aji_resource *aji_find_resource(struct aji_buddy *buddy, char *name)
00269 {
00270 struct aji_resource *res = NULL;
00271 if (!buddy || !name)
00272 return res;
00273 res = buddy->resources;
00274 while (res) {
00275 if (!strcasecmp(res->resource, name)) {
00276 break;
00277 }
00278 res = res->next;
00279 }
00280 return res;
00281 }
00282
00283 static int gtalk_yuck(iks *node)
00284 {
00285 if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps"))
00286 return 1;
00287 return 0;
00288 }
00289
00290
00291
00292
00293
00294
00295 static int aji_highest_bit(int number)
00296 {
00297 int x = sizeof(number) * 8 - 1;
00298 if (!number)
00299 return 0;
00300 for (; x > 0; x--) {
00301 if (number & (1 << x))
00302 break;
00303 }
00304 return (1 << x);
00305 }
00306
00307 static iks *jabber_make_auth(iksid * id, const char *pass, const char *sid)
00308 {
00309 iks *x, *y;
00310 x = iks_new("iq");
00311 iks_insert_attrib(x, "type", "set");
00312 y = iks_insert(x, "query");
00313 iks_insert_attrib(y, "xmlns", IKS_NS_AUTH);
00314 iks_insert_cdata(iks_insert(y, "username"), id->user, 0);
00315 iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0);
00316 if (sid) {
00317 char buf[41];
00318 char sidpass[100];
00319 snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass);
00320 ast_sha1_hash(buf, sidpass);
00321 iks_insert_cdata(iks_insert(y, "digest"), buf, 0);
00322 } else {
00323 iks_insert_cdata(iks_insert(y, "password"), pass, 0);
00324 }
00325 return x;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334 static int aji_status_exec(struct ast_channel *chan, void *data)
00335 {
00336 struct aji_client *client = NULL;
00337 struct aji_buddy *buddy = NULL;
00338 struct aji_resource *r = NULL;
00339 char *s = NULL, *sender = NULL, *jid = NULL, *screenname = NULL, *resource = NULL, *variable = NULL;
00340 int stat = 7;
00341 char status[2];
00342
00343 if (!data) {
00344 ast_log(LOG_ERROR, "This application requires arguments.\n");
00345 return 0;
00346 }
00347 s = ast_strdupa(data);
00348 if (s) {
00349 sender = strsep(&s, "|");
00350 if (sender && (sender[0] != '\0')) {
00351 jid = strsep(&s, "|");
00352 if (jid && (jid[0] != '\0')) {
00353 variable = s;
00354 } else {
00355 ast_log(LOG_ERROR, "Bad arguments\n");
00356 return -1;
00357 }
00358 }
00359 }
00360
00361 if(!strchr(jid, '/')) {
00362 resource = NULL;
00363 } else {
00364 screenname = strsep(&jid, "/");
00365 resource = jid;
00366 }
00367 client = ast_aji_get_client(sender);
00368 if (!client) {
00369 ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender);
00370 return -1;
00371 }
00372 if(!&client->buddies) {
00373 ast_log(LOG_WARNING, "No buddies for connection : %s\n", sender);
00374 return -1;
00375 }
00376 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, resource ? screenname: jid);
00377 if (!buddy) {
00378 ast_log(LOG_WARNING, "Could not find buddy in list : %s\n", resource ? screenname : jid);
00379 return -1;
00380 }
00381 r = aji_find_resource(buddy, resource);
00382 if(!r && buddy->resources)
00383 r = buddy->resources;
00384 if(!r)
00385 ast_log(LOG_NOTICE, "Resource %s of buddy %s not found \n", resource, screenname);
00386 else
00387 stat = r->status;
00388 sprintf(status, "%d", stat);
00389 pbx_builtin_setvar_helper(chan, variable, status);
00390 return 0;
00391 }
00392
00393
00394
00395
00396
00397
00398 static int aji_send_exec(struct ast_channel *chan, void *data)
00399 {
00400 struct aji_client *client = NULL;
00401
00402 char *s = NULL, *sender = NULL, *recipient = NULL, *message = NULL;
00403
00404 if (!data) {
00405 ast_log(LOG_ERROR, "This application requires arguments.\n");
00406 return 0;
00407 }
00408 s = ast_strdupa(data);
00409 if (s) {
00410 sender = strsep(&s, "|");
00411 if (sender && (sender[0] != '\0')) {
00412 recipient = strsep(&s, "|");
00413 if (recipient && (recipient[0] != '\0')) {
00414 message = s;
00415 } else {
00416 ast_log(LOG_ERROR, "Bad arguments: %s\n", (char *) data);
00417 return -1;
00418 }
00419 }
00420 }
00421 if (!(client = ast_aji_get_client(sender))) {
00422 ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender);
00423 return -1;
00424 }
00425 if (strchr(recipient, '@') && message)
00426 ast_aji_send(client, recipient, message);
00427 return 0;
00428 }
00429
00430
00431
00432
00433
00434 static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming)
00435 {
00436 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00437 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp);
00438
00439 if (client->debug) {
00440 if (is_incoming)
00441 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp);
00442 else {
00443 if( strlen(xmpp) == 1) {
00444 if(option_debug > 2 && xmpp[0] == ' ')
00445 ast_verbose("\nJABBER: Keep alive packet\n");
00446 } else
00447 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp);
00448 }
00449
00450 }
00451 ASTOBJ_UNREF(client, aji_client_destroy);
00452 }
00453
00454
00455
00456
00457
00458
00459 static int aji_act_hook(void *data, int type, iks *node)
00460 {
00461 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00462 ikspak *pak = NULL;
00463 iks *auth = NULL;
00464
00465 if(!node) {
00466 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n");
00467 ASTOBJ_UNREF(client, aji_client_destroy);
00468 return IKS_HOOK;
00469 }
00470
00471 pak = iks_packet(node);
00472
00473 if (!client->component) {
00474 switch (type) {
00475 case IKS_NODE_START:
00476 if (client->usetls && !iks_is_secure(client->p)) {
00477 if (iks_has_tls())
00478 iks_start_tls(client->p);
00479 else
00480 ast_log(LOG_ERROR, "gnuTLS not installed.\n");
00481 break;
00482 }
00483 if (!client->usesasl) {
00484 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);
00485 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id"));
00486 if (auth) {
00487 iks_insert_attrib(auth, "id", client->mid);
00488 iks_insert_attrib(auth, "to", client->jid->server);
00489 ast_aji_increment_mid(client->mid);
00490 iks_send(client->p, auth);
00491 iks_delete(auth);
00492 } else
00493 ast_log(LOG_ERROR, "Out of memory.\n");
00494 }
00495 break;
00496
00497 case IKS_NODE_NORMAL:
00498 {
00499 int features = 0;
00500 if (!strcmp("stream:features", iks_name(node))) {
00501 features = iks_stream_features(node);
00502 if (client->usesasl) {
00503 if (client->usetls && !iks_is_secure(client->p))
00504 break;
00505 if (client->authorized) {
00506 if (features & IKS_STREAM_BIND) {
00507 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);
00508 auth = iks_make_resource_bind(client->jid);
00509 if (auth) {
00510 iks_insert_attrib(auth, "id", client->mid);
00511 ast_aji_increment_mid(client->mid);
00512 iks_send(client->p, auth);
00513 iks_delete(auth);
00514 } else {
00515 ast_log(LOG_ERROR, "Out of memory.\n");
00516 break;
00517 }
00518 }
00519 if (features & IKS_STREAM_SESSION) {
00520 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);
00521 auth = iks_make_session();
00522 if (auth) {
00523 iks_insert_attrib(auth, "id", "auth");
00524 ast_aji_increment_mid(client->mid);
00525 iks_send(client->p, auth);
00526 iks_delete(auth);
00527 } else {
00528 ast_log(LOG_ERROR, "Out of memory.\n");
00529 }
00530 }
00531 } else {
00532 features = aji_highest_bit(features);
00533 if (features == IKS_STREAM_SASL_MD5)
00534 iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, client->jid->user, client->password);
00535 else {
00536 if (features == IKS_STREAM_SASL_PLAIN) {
00537 iks *x = NULL;
00538 x = iks_new("auth");
00539 if (x) {
00540 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL);
00541 int len = strlen(client->jid->user) + strlen(client->password) + 3;
00542
00543 char *s = ast_malloc(80 + len);
00544 char *base64 = ast_malloc(80 + len * 2);
00545 iks_insert_attrib(x, "mechanism", "PLAIN");
00546 sprintf(s, "%c%s%c%s", 0, client->jid->user, 0, client->password);
00547 ast_base64encode(base64, (const unsigned char *) s, len, len * 2);
00548 iks_insert_cdata(x, base64, 0);
00549 iks_send(client->p, x);
00550 iks_delete(x);
00551 if (base64)
00552 free(base64);
00553 if (s)
00554 free(s);
00555 } else {
00556 ast_log(LOG_ERROR, "Out of memory.\n");
00557 }
00558 }
00559 }
00560 }
00561 }
00562 } else if (!strcmp("failure", iks_name(node))) {
00563 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n");
00564 } else if (!strcmp("success", iks_name(node))) {
00565 client->authorized = 1;
00566 iks_send_header(client->p, client->jid->server);
00567 }
00568 break;
00569 }
00570 case IKS_NODE_ERROR:
00571 ast_log(LOG_ERROR, "JABBER: Node Error\n");
00572 ASTOBJ_UNREF(client, aji_client_destroy);
00573 return IKS_HOOK;
00574 break;
00575 case IKS_NODE_STOP:
00576 ast_log(LOG_WARNING, "JABBER: Disconnected\n");
00577 ASTOBJ_UNREF(client, aji_client_destroy);
00578 return IKS_HOOK;
00579 break;
00580 }
00581 } else if (client->state != AJI_CONNECTED && client->component) {
00582 switch (type) {
00583 case IKS_NODE_START:
00584 if (client->state == AJI_DISCONNECTED) {
00585 char secret[160], shasum[320], *handshake;
00586
00587 sprintf(secret, "%s%s", pak->id, client->password);
00588 ast_sha1_hash(shasum, secret);
00589 handshake = NULL;
00590 asprintf(&handshake, "<handshake>%s</handshake>", shasum);
00591 if (handshake) {
00592 iks_send_raw(client->p, handshake);
00593 free(handshake);
00594 handshake = NULL;
00595 }
00596 client->state = AJI_CONNECTING;
00597 if(iks_recv(client->p,1) == 2)
00598 client->state = AJI_CONNECTED;
00599 else
00600 ast_log(LOG_WARNING,"Jabber didn't seem to handshake, failed to authenicate.\n");
00601 break;
00602 }
00603 break;
00604
00605 case IKS_NODE_NORMAL:
00606 break;
00607
00608 case IKS_NODE_ERROR:
00609 ast_log(LOG_ERROR, "JABBER: Node Error\n");
00610 ASTOBJ_UNREF(client, aji_client_destroy);
00611 return IKS_HOOK;
00612
00613 case IKS_NODE_STOP:
00614 ast_log(LOG_WARNING, "JABBER: Disconnected\n");
00615 ASTOBJ_UNREF(client, aji_client_destroy);
00616 return IKS_HOOK;
00617 }
00618 }
00619
00620 switch (pak->type) {
00621 case IKS_PAK_NONE:
00622 if (option_debug)
00623 ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you NONE\n");
00624 break;
00625 case IKS_PAK_MESSAGE:
00626 aji_handle_message(client, pak);
00627 if (option_debug)
00628 ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you MESSAGE\n");
00629 break;
00630 case IKS_PAK_PRESENCE:
00631 aji_handle_presence(client, pak);
00632 if (option_debug)
00633 ast_log(LOG_DEBUG, "JABBER: I Do know how to handle presence!!\n");
00634 break;
00635 case IKS_PAK_S10N:
00636 aji_handle_subscribe(client, pak);
00637 if (option_debug)
00638 ast_log(LOG_DEBUG, "JABBER: I Dont know S10N subscribe!!\n");
00639 break;
00640 case IKS_PAK_IQ:
00641 if (option_debug)
00642 ast_log(LOG_DEBUG, "JABBER: I Dont have an IQ!!!\n");
00643 aji_handle_iq(client, node);
00644 break;
00645 default:
00646 if (option_debug)
00647 ast_log(LOG_DEBUG, "JABBER: I Dont know %i\n", pak->type);
00648 break;
00649 }
00650
00651 iks_filter_packet(client->f, pak);
00652
00653 if (node)
00654 iks_delete(node);
00655
00656 ASTOBJ_UNREF(client, aji_client_destroy);
00657 return IKS_OK;
00658 }
00659
00660 static int aji_register_approve_handler(void *data, ikspak *pak)
00661 {
00662 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00663 iks *iq = NULL, *presence = NULL, *x = NULL;
00664
00665 iq = iks_new("iq");
00666 presence = iks_new("presence");
00667 x = iks_new("x");
00668 if (client && iq && presence && x) {
00669 if (!iks_find(pak->query, "remove")) {
00670 iks_insert_attrib(iq, "from", client->jid->full);
00671 iks_insert_attrib(iq, "to", pak->from->full);
00672 iks_insert_attrib(iq, "id", pak->id);
00673 iks_insert_attrib(iq, "type", "result");
00674 iks_send(client->p, iq);
00675
00676 iks_insert_attrib(presence, "from", client->jid->full);
00677 iks_insert_attrib(presence, "to", pak->from->partial);
00678 iks_insert_attrib(presence, "id", client->mid);
00679 ast_aji_increment_mid(client->mid);
00680 iks_insert_attrib(presence, "type", "subscribe");
00681 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update");
00682 iks_insert_node(presence, x);
00683 iks_send(client->p, presence);
00684 }
00685 } else {
00686 ast_log(LOG_ERROR, "Out of memory.\n");
00687 }
00688
00689 if (iq)
00690 iks_delete(iq);
00691 if(presence)
00692 iks_delete(presence);
00693 if (x)
00694 iks_delete(x);
00695 ASTOBJ_UNREF(client, aji_client_destroy);
00696 return IKS_FILTER_EAT;
00697 }
00698
00699 static int aji_register_query_handler(void *data, ikspak *pak)
00700 {
00701 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00702 struct aji_buddy *buddy = NULL;
00703 char *node = NULL;
00704
00705 client = (struct aji_client *) data;
00706
00707 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00708 if (!buddy) {
00709 ast_verbose("Someone.... %s tried to register but they aren't allowed\n", pak->from->partial);
00710 iks *iq = NULL, *query = NULL, *error = NULL, *notacceptable = NULL;
00711 iq = iks_new("iq");
00712 query = iks_new("query");
00713 error = iks_new("error");
00714 notacceptable = iks_new("not-acceptable");
00715 if(iq && query && error && notacceptable) {
00716 iks_insert_attrib(iq, "type", "error");
00717 iks_insert_attrib(iq, "from", client->user);
00718 iks_insert_attrib(iq, "to", pak->from->full);
00719 iks_insert_attrib(iq, "id", pak->id);
00720 iks_insert_attrib(query, "xmlns", "jabber:iq:register");
00721 iks_insert_attrib(error, "code" , "406");
00722 iks_insert_attrib(error, "type", "modify");
00723 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
00724 iks_insert_node(iq, query);
00725 iks_insert_node(iq, error);
00726 iks_insert_node(error, notacceptable);
00727 iks_send(client->p, iq);
00728 } else {
00729 ast_log(LOG_ERROR, "Out of memory.\n");
00730 }
00731 if (iq)
00732 iks_delete(iq);
00733 if (query)
00734 iks_delete(query);
00735 if (error)
00736 iks_delete(error);
00737 if (notacceptable)
00738 iks_delete(notacceptable);
00739 } else if (!(node = iks_find_attrib(pak->query, "node"))) {
00740 iks *iq = NULL, *query = NULL, *instructions = NULL;
00741 char *explain = "Welcome to Asterisk - the Open Source PBX.\n";
00742 iq = iks_new("iq");
00743 query = iks_new("query");
00744 instructions = iks_new("instructions");
00745 if (iq && query && instructions && client) {
00746 iks_insert_attrib(iq, "from", client->user);
00747 iks_insert_attrib(iq, "to", pak->from->full);
00748 iks_insert_attrib(iq, "id", pak->id);
00749 iks_insert_attrib(iq, "type", "result");
00750 iks_insert_attrib(query, "xmlns", "jabber:iq:register");
00751 iks_insert_cdata(instructions, explain, 0);
00752 iks_insert_node(iq, query);
00753 iks_insert_node(query, instructions);
00754 iks_send(client->p, iq);
00755 } else {
00756 ast_log(LOG_ERROR, "Out of memory.\n");
00757 }
00758 if (iq)
00759 iks_delete(iq);
00760 if (query)
00761 iks_delete(query);
00762 if (instructions)
00763 iks_delete(instructions);
00764 }
00765 ASTOBJ_UNREF(client, aji_client_destroy);
00766 return IKS_FILTER_EAT;
00767 }
00768
00769 static int aji_ditems_handler(void *data, ikspak *pak)
00770 {
00771 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00772 char *node = NULL;
00773
00774 if (!(node = iks_find_attrib(pak->query, "node"))) {
00775 iks *iq = NULL, *query = NULL, *item = NULL;
00776 iq = iks_new("iq");
00777 query = iks_new("query");
00778 item = iks_new("item");
00779
00780 if (iq && query && item) {
00781 iks_insert_attrib(iq, "from", client->user);
00782 iks_insert_attrib(iq, "to", pak->from->full);
00783 iks_insert_attrib(iq, "id", pak->id);
00784 iks_insert_attrib(iq, "type", "result");
00785 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00786 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands");
00787 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands");
00788 iks_insert_attrib(item, "jid", client->user);
00789
00790 iks_insert_node(iq, query);
00791 iks_insert_node(query, item);
00792 iks_send(client->p, iq);
00793 } else {
00794 ast_log(LOG_ERROR, "Out of memory.\n");
00795 }
00796 if (iq)
00797 iks_delete(iq);
00798 if (query)
00799 iks_delete(query);
00800 if (item)
00801 iks_delete(item);
00802
00803 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) {
00804 iks *iq, *query, *confirm;
00805 iq = iks_new("iq");
00806 query = iks_new("query");
00807 confirm = iks_new("item");
00808 if (iq && query && confirm && client) {
00809 iks_insert_attrib(iq, "from", client->user);
00810 iks_insert_attrib(iq, "to", pak->from->full);
00811 iks_insert_attrib(iq, "id", pak->id);
00812 iks_insert_attrib(iq, "type", "result");
00813 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00814 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
00815 iks_insert_attrib(confirm, "node", "confirmaccount");
00816 iks_insert_attrib(confirm, "name", "Confirm AIM account");
00817 iks_insert_attrib(confirm, "jid", "blog.astjab.org");
00818
00819 iks_insert_node(iq, query);
00820 iks_insert_node(query, confirm);
00821 iks_send(client->p, iq);
00822 } else {
00823 ast_log(LOG_ERROR, "Out of memory.\n");
00824 }
00825 if (iq)
00826 iks_delete(iq);
00827 if (query)
00828 iks_delete(query);
00829 if (confirm)
00830 iks_delete(confirm);
00831
00832 } else if (!strcasecmp(node, "confirmaccount")) {
00833 iks *iq = NULL, *query = NULL, *feature = NULL;
00834
00835 iq = iks_new("iq");
00836 query = iks_new("query");
00837 feature = iks_new("feature");
00838
00839 if (iq && query && feature && client) {
00840 iks_insert_attrib(iq, "from", client->user);
00841 iks_insert_attrib(iq, "to", pak->from->full);
00842 iks_insert_attrib(iq, "id", pak->id);
00843 iks_insert_attrib(iq, "type", "result");
00844 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00845 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
00846 iks_insert_node(iq, query);
00847 iks_insert_node(query, feature);
00848 iks_send(client->p, iq);
00849 } else {
00850 ast_log(LOG_ERROR, "Out of memory.\n");
00851 }
00852 if (iq)
00853 iks_delete(iq);
00854 if (query)
00855 iks_delete(query);
00856 if (feature)
00857 iks_delete(feature);
00858 }
00859
00860 ASTOBJ_UNREF(client, aji_client_destroy);
00861 return IKS_FILTER_EAT;
00862
00863 }
00864
00865 static int aji_client_info_handler(void *data, ikspak *pak)
00866 {
00867 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00868 struct aji_resource *resource = NULL;
00869 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00870
00871 resource = aji_find_resource(buddy, pak->from->resource);
00872 if (pak->subtype == IKS_TYPE_RESULT) {
00873 if (!resource) {
00874 ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full);
00875 ASTOBJ_UNREF(client, aji_client_destroy);
00876 return IKS_FILTER_EAT;
00877 }
00878 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
00879 resource->cap->jingle = 1;
00880 } else
00881 resource->cap->jingle = 0;
00882 } else if (pak->subtype == IKS_TYPE_GET) {
00883 iks *iq, *disco, *ident, *google, *query;
00884 iq = iks_new("iq");
00885 query = iks_new("query");
00886 ident = iks_new("identity");
00887 disco = iks_new("feature");
00888 google = iks_new("feature");
00889 if (iq && ident && disco && google) {
00890 iks_insert_attrib(iq, "from", client->jid->full);
00891 iks_insert_attrib(iq, "to", pak->from->full);
00892 iks_insert_attrib(iq, "type", "result");
00893 iks_insert_attrib(iq, "id", pak->id);
00894 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
00895 iks_insert_attrib(ident, "category", "client");
00896 iks_insert_attrib(ident, "type", "pc");
00897 iks_insert_attrib(ident, "name", "asterisk");
00898 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info");
00899 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1");
00900 iks_insert_node(iq, query);
00901 iks_insert_node(query, ident);
00902 iks_insert_node(query, google);
00903 iks_insert_node(query, disco);
00904 iks_send(client->p, iq);
00905 } else
00906 ast_log(LOG_ERROR, "Out of Memory.\n");
00907 if (iq)
00908 iks_delete(iq);
00909 if (query)
00910 iks_delete(query);
00911 if (ident)
00912 iks_delete(ident);
00913 if (google)
00914 iks_delete(google);
00915 if (disco)
00916 iks_delete(disco);
00917 } else if (pak->subtype == IKS_TYPE_ERROR) {
00918 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full);
00919 }
00920 ASTOBJ_UNREF(client, aji_client_destroy);
00921 return IKS_FILTER_EAT;
00922 }
00923
00924 static int aji_dinfo_handler(void *data, ikspak *pak)
00925 {
00926 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00927 char *node = NULL;
00928 struct aji_resource *resource = NULL;
00929 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00930
00931 resource = aji_find_resource(buddy, pak->from->resource);
00932 if (pak->subtype == IKS_TYPE_ERROR) {
00933 ast_log(LOG_WARNING, "Recieved error from a client, turn on jabber debug!\n");
00934 return IKS_FILTER_EAT;
00935 }
00936 if (pak->subtype == IKS_TYPE_RESULT) {
00937 if (!resource) {
00938 ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full);
00939 ASTOBJ_UNREF(client, aji_client_destroy);
00940 return IKS_FILTER_EAT;
00941 }
00942 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
00943 resource->cap->jingle = 1;
00944 } else
00945 resource->cap->jingle = 0;
00946 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) {
00947 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search;
00948
00949 iq = iks_new("iq");
00950 query = iks_new("query");
00951 identity = iks_new("identity");
00952 disco = iks_new("feature");
00953 reg = iks_new("feature");
00954 commands = iks_new("feature");
00955 gateway = iks_new("feature");
00956 version = iks_new("feature");
00957 vcard = iks_new("feature");
00958 search = iks_new("feature");
00959
00960 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) {
00961 iks_insert_attrib(iq, "from", client->user);
00962 iks_insert_attrib(iq, "to", pak->from->full);
00963 iks_insert_attrib(iq, "id", pak->id);
00964 iks_insert_attrib(iq, "type", "result");
00965 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
00966 iks_insert_attrib(identity, "category", "gateway");
00967 iks_insert_attrib(identity, "type", "pstn");
00968 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX");
00969 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco");
00970 iks_insert_attrib(reg, "var", "jabber:iq:register");
00971 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands");
00972 iks_insert_attrib(gateway, "var", "jabber:iq:gateway");
00973 iks_insert_attrib(version, "var", "jabber:iq:version");
00974 iks_insert_attrib(vcard, "var", "vcard-temp");
00975 iks_insert_attrib(search, "var", "jabber:iq:search");
00976
00977 iks_insert_node(iq, query);
00978 iks_insert_node(query, identity);
00979 iks_insert_node(query, disco);
00980 iks_insert_node(query, reg);
00981 iks_insert_node(query, commands);
00982 iks_insert_node(query, gateway);
00983 iks_insert_node(query, version);
00984 iks_insert_node(query, vcard);
00985 iks_insert_node(query, search);
00986 iks_send(client->p, iq);
00987 } else {
00988 ast_log(LOG_ERROR, "Out of memory.\n");
00989 }
00990
00991 if (iq)
00992 iks_delete(iq);
00993 if (query)
00994 iks_delete(query);
00995 if (identity)
00996 iks_delete(identity);
00997 if (disco)
00998 iks_delete(disco);
00999 if (reg)
01000 iks_delete(reg);
01001 if (commands)
01002 iks_delete(commands);
01003 if (gateway)
01004 iks_delete(gateway);
01005 if (version)
01006 iks_delete(version);
01007 if (vcard)
01008 iks_delete(vcard);
01009 if (search)
01010 iks_delete(search);
01011
01012 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) {
01013 iks *iq, *query, *confirm;
01014 iq = iks_new("iq");
01015 query = iks_new("query");
01016 confirm = iks_new("item");
01017
01018 if (iq && query && confirm && client) {
01019 iks_insert_attrib(iq, "from", client->user);
01020 iks_insert_attrib(iq, "to", pak->from->full);
01021 iks_insert_attrib(iq, "id", pak->id);
01022 iks_insert_attrib(iq, "type", "result");
01023 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
01024 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
01025 iks_insert_attrib(confirm, "node", "confirmaccount");
01026 iks_insert_attrib(confirm, "name", "Confirm AIM account");
01027 iks_insert_attrib(confirm, "jid", client->user);
01028 iks_insert_node(iq, query);
01029 iks_insert_node(query, confirm);
01030 iks_send(client->p, iq);
01031 } else {
01032 ast_log(LOG_ERROR, "Out of memory.\n");
01033 }
01034 if (iq)
01035 iks_delete(iq);
01036 if (query)
01037 iks_delete(query);
01038 if (confirm)
01039 iks_delete(confirm);
01040
01041 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) {
01042 iks *iq, *query, *feature;
01043
01044 iq = iks_new("iq");
01045 query = iks_new("query");
01046 feature = iks_new("feature");
01047
01048 if (iq && query && feature && client) {
01049 iks_insert_attrib(iq, "from", client->user);
01050 iks_insert_attrib(iq, "to", pak->from->full);
01051 iks_insert_attrib(iq, "id", pak->id);
01052 iks_insert_attrib(iq, "type", "result");
01053 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
01054 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
01055 iks_insert_node(iq, query);
01056 iks_insert_node(query, feature);
01057 iks_send(client->p, iq);
01058 } else {
01059 ast_log(LOG_ERROR, "Out of memory.\n");
01060 }
01061 if (iq)
01062 iks_delete(iq);
01063 if (query)
01064 iks_delete(query);
01065 if (feature)
01066 iks_delete(feature);
01067 }
01068
01069 ASTOBJ_UNREF(client, aji_client_destroy);
01070 return IKS_FILTER_EAT;
01071 }
01072
01073
01074
01075
01076
01077
01078 static void aji_handle_iq(struct aji_client *client, iks *node)
01079 {
01080
01081 }
01082
01083
01084
01085
01086
01087
01088 static void aji_handle_message(struct aji_client *client, ikspak *pak)
01089 {
01090 struct aji_message *insert, *tmp;
01091 int flag = 0;
01092
01093 if (!(insert = ast_calloc(1, sizeof(struct aji_message))))
01094 return;
01095 time(&insert->arrived);
01096 if (iks_find_cdata(pak->x, "body"))
01097 insert->message = ast_strdup(iks_find_cdata(pak->x, "body"));
01098 if(pak->id)
01099 ast_copy_string(insert->id, pak->id, sizeof(insert->message));
01100 if (pak->from)
01101 insert->from = ast_strdup(pak->from->full);
01102 AST_LIST_LOCK(&client->messages);
01103 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) {
01104 if (flag) {
01105 AST_LIST_REMOVE_CURRENT(&client->messages, list);
01106 if (tmp->from)
01107 free(tmp->from);
01108 if (tmp->message)
01109 free(tmp->message);
01110 } else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) {
01111 flag = 1;
01112 AST_LIST_REMOVE_CURRENT(&client->messages, list);
01113 if (tmp->from)
01114 free(tmp->from);
01115 if (tmp->message)
01116 free(tmp->message);
01117 }
01118 }
01119 AST_LIST_TRAVERSE_SAFE_END;
01120 AST_LIST_INSERT_HEAD(&client->messages, insert, list);
01121 AST_LIST_UNLOCK(&client->messages);
01122 }
01123
01124 static void aji_handle_presence(struct aji_client *client, ikspak *pak)
01125 {
01126 int status, priority;
01127 struct aji_buddy *buddy;
01128 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL;
01129 char *ver, *node, *descrip, *type;
01130
01131 if(client->state != AJI_CONNECTED)
01132 aji_create_buddy(pak->from->partial, client);
01133
01134 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
01135 if (!buddy) {
01136 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial);
01137 return;
01138 }
01139 type = iks_find_attrib(pak->x, "type");
01140 if(client->component && type &&!strcasecmp("probe", type)) {
01141 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), 1, client->statusmessage);
01142 ast_verbose("what i was looking for \n");
01143 }
01144 ASTOBJ_WRLOCK(buddy);
01145 status = (pak->show) ? pak->show : 6;
01146 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0");
01147 tmp = buddy->resources;
01148 descrip = ast_strdup(iks_find_cdata(pak->x,"status"));
01149
01150 while (tmp) {
01151 if (!strcasecmp(tmp->resource, pak->from->resource)) {
01152 tmp->status = status;
01153 if (tmp->description) free(tmp->description);
01154 tmp->description = descrip;
01155 found = tmp;
01156 if (status == 6) {
01157 if (last && found->next) {
01158 last->next = found->next;
01159 } else if (!last) {
01160 if (found->next)
01161 buddy->resources = found->next;
01162 else
01163 buddy->resources = NULL;
01164 } else if (!found->next) {
01165 if (last)
01166 last->next = NULL;
01167 else
01168 buddy->resources = NULL;
01169 }
01170 free(found);
01171 found = NULL;
01172 break;
01173 }
01174 if (tmp->priority != priority) {
01175 found->priority = priority;
01176 if (!last && !found->next)
01177 break;
01178 if (last)
01179 last->next = found->next;
01180 else
01181 buddy->resources = found->next;
01182 last = NULL;
01183 tmp = buddy->resources;
01184 if (!buddy->resources)
01185 buddy->resources = found;
01186 while (tmp) {
01187 if (found->priority > tmp->priority) {
01188 if (last)
01189 last->next = found;
01190 found->next = tmp;
01191 if (!last)
01192 buddy->resources = found;
01193 break;
01194 }
01195 if (!tmp->next) {
01196 tmp->next = found;
01197 break;
01198 }
01199 last = tmp;
01200 tmp = tmp->next;
01201 }
01202 }
01203 break;
01204 }
01205 last = tmp;
01206 tmp = tmp->next;
01207 }
01208
01209 if (!found && status != 6) {
01210 found = (struct aji_resource *) malloc(sizeof(struct aji_resource));
01211 memset(found, 0, sizeof(struct aji_resource));
01212
01213 if (!found) {
01214 ast_log(LOG_ERROR, "Out of memory!\n");
01215 return;
01216 }
01217 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource));
01218 found->status = status;
01219 found->description = descrip;
01220 found->priority = priority;
01221 found->next = NULL;
01222 last = NULL;
01223 tmp = buddy->resources;
01224 while (tmp) {
01225 if (found->priority > tmp->priority) {
01226 if (last)
01227 last->next = found;
01228 found->next = tmp;
01229 if (!last)
01230 buddy->resources = found;
01231 break;
01232 }
01233 if (!tmp->next) {
01234 tmp->next = found;
01235 break;
01236 }
01237 last = tmp;
01238 tmp = tmp->next;
01239 }
01240 if (!tmp)
01241 buddy->resources = found;
01242 }
01243 ASTOBJ_UNLOCK(buddy);
01244 ASTOBJ_UNREF(buddy, aji_buddy_destroy);
01245
01246 node = iks_find_attrib(iks_find(pak->x, "c"), "node");
01247 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver");
01248
01249 if(status !=6 && !found->cap) {
01250 found->cap = aji_find_version(node, ver, pak);
01251 if(gtalk_yuck(pak->x))
01252 found->cap->jingle = 1;
01253 if(found->cap->jingle && option_debug > 4)
01254 ast_log(LOG_DEBUG,"Special case for google till they support discover.\n");
01255 else {
01256 iks *iq, *query;
01257 iq = iks_new("iq");
01258 query = iks_new("query");
01259 if(query && iq) {
01260 iks_insert_attrib(iq, "type", "get");
01261 iks_insert_attrib(iq, "to", pak->from->full);
01262 iks_insert_attrib(iq,"from",iks_find_attrib(pak->x,"to"));
01263 iks_insert_attrib(iq, "id", client->mid);
01264 ast_aji_increment_mid(client->mid);
01265 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
01266 iks_insert_node(iq, query);
01267 iks_send(client->p, iq);
01268
01269 } else
01270 ast_log(LOG_ERROR, "Out of memory.\n");
01271 if(query)
01272 iks_delete(query);
01273 if(iq)
01274 iks_delete(iq);
01275 }
01276 }
01277 if (option_verbose > 4) {
01278 switch (pak->subtype) {
01279 case IKS_TYPE_AVAILABLE:
01280 ast_verbose(VERBOSE_PREFIX_3 "JABBER: I am available ^_* %i\n", pak->subtype);
01281 break;
01282 case IKS_TYPE_UNAVAILABLE:
01283 ast_verbose(VERBOSE_PREFIX_3 "JABBER: I am unavailable ^_* %i\n", pak->subtype);
01284 break;
01285 default:
01286 ast_verbose(VERBOSE_PREFIX_3 "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype);
01287 }
01288 switch (pak->show) {
01289 case IKS_SHOW_UNAVAILABLE:
01290 ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01291 break;
01292 case IKS_SHOW_AVAILABLE:
01293 ast_verbose(VERBOSE_PREFIX_3 "JABBER: type is available\n");
01294 break;
01295 case IKS_SHOW_CHAT:
01296 ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01297 break;
01298 case IKS_SHOW_AWAY:
01299 ast_verbose(VERBOSE_PREFIX_3 "JABBER: type is away\n");
01300 break;
01301 case IKS_SHOW_XA:
01302 ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01303 break;
01304 case IKS_SHOW_DND:
01305 ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01306 break;
01307 default:
01308 ast_verbose(VERBOSE_PREFIX_3 "JABBER: Kinky! how did that happen %i\n", pak->show);
01309 }
01310 }
01311 }
01312
01313
01314
01315
01316
01317
01318 static void aji_handle_subscribe(struct aji_client *client, ikspak *pak)
01319 {
01320 if(pak->subtype == IKS_TYPE_SUBSCRIBE) {
01321 iks *presence = NULL, *status = NULL;
01322 presence = iks_new("presence");
01323 status = iks_new("status");
01324 if(presence && status) {
01325 iks_insert_attrib(presence, "type", "subscribed");
01326 iks_insert_attrib(presence, "to", pak->from->full);
01327 iks_insert_attrib(presence, "from", client->jid->full);
01328 if(pak->id)
01329 iks_insert_attrib(presence, "id", pak->id);
01330 iks_insert_cdata(status, "Asterisk has approved subscription", 0);
01331 iks_insert_node(presence, status);
01332 iks_send(client->p, presence);
01333 } else
01334 ast_log(LOG_ERROR, "Unable to allocate nodes\n");
01335 if(presence)
01336 iks_delete(presence);
01337 if(status)
01338 iks_delete(status);
01339 if(client->component)
01340 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), 1, client->statusmessage);
01341 }
01342 if (option_verbose > 4) {
01343 switch (pak->subtype) {
01344 case IKS_TYPE_SUBSCRIBE:
01345 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01346 break;
01347 case IKS_TYPE_SUBSCRIBED:
01348 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01349 break;
01350 case IKS_TYPE_UNSUBSCRIBE:
01351 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01352 break;
01353 case IKS_TYPE_UNSUBSCRIBED:
01354 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01355 break;
01356 default:
01357 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01358 break;
01359 }
01360 }
01361 }
01362
01363
01364
01365
01366
01367
01368 int ast_aji_send(struct aji_client *client, const char *address, const char *message)
01369 {
01370 int res = 0;
01371 iks *message_packet = NULL;
01372 if (client->state == AJI_CONNECTED) {
01373 message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message);
01374 if (message_packet) {
01375 iks_insert_attrib(message_packet, "from", client->jid->full);
01376 res = iks_send(client->p, message_packet);
01377 } else {
01378 ast_log(LOG_ERROR, "Out of memory.\n");
01379 }
01380 if (message_packet)
01381 iks_delete(message_packet);
01382 } else
01383 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n");
01384 return 1;
01385 }
01386
01387
01388
01389
01390
01391
01392 int ast_aji_create_chat(struct aji_client *client, char *room, char *server, char *topic)
01393 {
01394 int res = 0;
01395 iks *iq = NULL;
01396 iq = iks_new("iq");
01397 if (iq && client) {
01398 iks_insert_attrib(iq, "type", "get");
01399 iks_insert_attrib(iq, "to", server);
01400 iks_insert_attrib(iq, "id", client->mid);
01401 ast_aji_increment_mid(client->mid);
01402 iks_send(client->p, iq);
01403 } else
01404 ast_log(LOG_ERROR, "Out of memory.\n");
01405 return res;
01406 }
01407
01408
01409
01410
01411
01412
01413 int ast_aji_join_chat(struct aji_client *client, char *room)
01414 {
01415 int res = 0;
01416 iks *presence = NULL, *priority = NULL;
01417 presence = iks_new("presence");
01418 priority = iks_new("priority");
01419 if (presence && priority && client) {
01420 iks_insert_cdata(priority, "0", 1);
01421 iks_insert_attrib(presence, "to", room);
01422 iks_insert_node(presence, priority);
01423 res = iks_send(client->p, presence);
01424 iks_insert_cdata(priority, "5", 1);
01425 iks_insert_attrib(presence, "to", room);
01426 res = iks_send(client->p, presence);
01427 } else
01428 ast_log(LOG_ERROR, "Out of memory.\n");
01429 if (presence)
01430 iks_delete(presence);
01431 if (priority)
01432 iks_delete(priority);
01433 return res;
01434 }
01435
01436
01437
01438
01439
01440
01441 int ast_aji_invite_chat(struct aji_client *client, char *user, char *room, char *message)
01442 {
01443 int res = 0;
01444 iks *invite, *body, *namespace;
01445
01446 invite = iks_new("message");
01447 body = iks_new("body");
01448 namespace = iks_new("x");
01449 if (client && invite && body && namespace) {
01450 iks_insert_attrib(invite, "to", user);
01451 iks_insert_attrib(invite, "id", client->mid);
01452 ast_aji_increment_mid(client->mid);
01453 iks_insert_cdata(body, message, 0);
01454 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference");
01455 iks_insert_attrib(namespace, "jid", room);
01456 iks_insert_node(invite, body);
01457 iks_insert_node(invite, namespace);
01458 res = iks_send(client->p, invite);
01459 } else
01460 ast_log(LOG_ERROR, "Out of memory.\n");
01461 if (body)
01462 iks_delete(body);
01463 if (namespace)
01464 iks_delete(namespace);
01465 if (invite)
01466 iks_delete(invite);
01467 return res;
01468 }
01469
01470
01471
01472
01473
01474
01475
01476 static void *aji_recv_loop(void *data)
01477 {
01478 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01479 int res = IKS_HOOK;
01480 do {
01481 if (res != IKS_OK) {
01482 while(res != IKS_OK) {
01483 if(option_verbose > 3)
01484 ast_verbose("JABBER: reconnecting.\n");
01485 res = aji_reconnect(client);
01486 sleep(4);
01487 }
01488 }
01489
01490 res = iks_recv(client->p, 1);
01491 client->timeout--;
01492 if (res == IKS_HOOK)
01493 ast_log(LOG_WARNING, "JABBER: Got hook event.\n");
01494 else if (res == IKS_NET_TLSFAIL)
01495 ast_log(LOG_WARNING, "JABBER: Failure in TLS.\n");
01496 else if (client->timeout == 0 && client->state == AJI_CONNECTED) {
01497 res = iks_send_raw(client->p, " ");
01498 if(res == IKS_OK)
01499 client->timeout = 50;
01500 else
01501 ast_log(LOG_WARNING, "JABBER: Network Timeout\n");
01502 } else if (res == IKS_NET_RWERR)
01503 ast_log(LOG_WARNING, "JABBER: socket read error\n");
01504 } while (client);
01505 ASTOBJ_UNREF(client, aji_client_destroy);
01506 return 0;
01507 }
01508
01509
01510
01511
01512
01513
01514 void ast_aji_increment_mid(char *mid)
01515 {
01516 int i = 0;
01517
01518 for (i = strlen(mid) - 1; i >= 0; i--) {
01519 if (mid[i] != 'z') {
01520 mid[i] = mid[i] + 1;
01521 i = 0;
01522 } else
01523 mid[i] = 'a';
01524 }
01525 }
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621 static void aji_pruneregister(struct aji_client *client)
01622 {
01623 int res = 0;
01624 iks *removeiq = iks_new("iq");
01625 iks *removequery = iks_new("query");
01626 iks *removeitem = iks_new("item");
01627 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items");
01628
01629 if (client && removeiq && removequery && removeitem && send) {
01630 iks_insert_node(removeiq, removequery);
01631 iks_insert_node(removequery, removeitem);
01632 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01633 ASTOBJ_RDLOCK(iterator);
01634
01635
01636 if (ast_test_flag(iterator, AJI_AUTOPRUNE)) {
01637 res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name,
01638 "GoodBye your status is no longer needed by Asterisk the Open Source PBX"
01639 " so I am no longer subscribing to your presence.\n"));
01640 res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name,
01641 "GoodBye you are no longer in the asterisk config file so I am removing"
01642 " your access to my presence.\n"));
01643 iks_insert_attrib(removeiq, "from", client->jid->full);
01644 iks_insert_attrib(removeiq, "type", "set");
01645 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster");
01646 iks_insert_attrib(removeitem, "jid", iterator->name);
01647 iks_insert_attrib(removeitem, "subscription", "remove");
01648 res = iks_send(client->p, removeiq);
01649 } else if (ast_test_flag(iterator, AJI_AUTOREGISTER)) {
01650 res = iks_send(client->p, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name,
01651 "Greetings I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"));
01652 ast_clear_flag(iterator, AJI_AUTOREGISTER);
01653 }
01654 ASTOBJ_UNLOCK(iterator);
01655 });
01656 } else
01657 ast_log(LOG_ERROR, "Out of memory.\n");
01658 if (removeiq)
01659 iks_delete(removeiq);
01660 if (removequery)
01661 iks_delete(removequery);
01662 if (removeitem)
01663 iks_delete(removeitem);
01664 if (send)
01665 iks_delete(send);
01666 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, aji_buddy_destroy);
01667 }
01668
01669
01670
01671
01672
01673
01674 static int aji_filter_roster(void *data, ikspak *pak)
01675 {
01676 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01677 int flag = 0;
01678 iks *x = NULL;
01679 struct aji_buddy *buddy;
01680
01681 client->state = AJI_CONNECTED;
01682 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01683 ASTOBJ_RDLOCK(iterator);
01684 x = iks_child(pak->query);
01685 flag = 0;
01686 while (x) {
01687 if (!iks_strcmp(iks_name(x), "item")) {
01688 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) {
01689 flag = 1;
01690 ast_clear_flag(iterator, AJI_AUTOPRUNE | AJI_AUTOREGISTER);
01691 }
01692 }
01693 x = iks_next(x);
01694 }
01695 if (!flag)
01696 ast_copy_flags(iterator, client, AJI_AUTOREGISTER);
01697 if (x)
01698 iks_delete(x);
01699 ASTOBJ_UNLOCK(iterator);
01700 });
01701
01702 x = iks_child(pak->query);
01703 while (x) {
01704 flag = 0;
01705 if (iks_strcmp(iks_name(x), "item") == 0) {
01706 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01707 ASTOBJ_RDLOCK(iterator);
01708 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid")))
01709 flag = 1;
01710 ASTOBJ_UNLOCK(iterator);
01711 });
01712
01713 if (!flag) {
01714 buddy = (struct aji_buddy *) malloc(sizeof(struct aji_buddy));
01715 if (!buddy) {
01716 ast_log(LOG_WARNING, "Out of memory\n");
01717 return 0;
01718 }
01719 memset(buddy, 0, sizeof(struct aji_buddy));
01720 ASTOBJ_INIT(buddy);
01721 ASTOBJ_WRLOCK(buddy);
01722 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name));
01723 ast_clear_flag(buddy, AST_FLAGS_ALL);
01724 if(ast_test_flag(client, AJI_AUTOPRUNE)) {
01725 ast_set_flag(buddy, AJI_AUTOPRUNE);
01726 buddy->objflags |= ASTOBJ_FLAG_MARKED;
01727 } else
01728 ast_set_flag(buddy, AJI_AUTOREGISTER);
01729 ASTOBJ_UNLOCK(buddy);
01730 if (buddy) {
01731 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
01732 ASTOBJ_UNREF(buddy, aji_buddy_destroy);
01733 }
01734 }
01735 }
01736 x = iks_next(x);
01737 }
01738 if (x)
01739 iks_delete(x);
01740 aji_pruneregister(client);
01741
01742 ASTOBJ_UNREF(client, aji_client_destroy);
01743 return IKS_FILTER_EAT;
01744 }
01745
01746 static int aji_reconnect(struct aji_client *client)
01747 {
01748 int res = 0;
01749
01750 if (client->state)
01751 client->state = AJI_DISCONNECTED;
01752 client->timeout=50;
01753 if (client->p)
01754 iks_parser_reset(client->p);
01755 if (client->authorized)
01756 client->authorized = 0;
01757
01758 if(client->component)
01759 res = aji_component_initialize(client);
01760 else
01761 res = aji_client_initialize(client);
01762
01763 return res;
01764 }
01765
01766 static int aji_get_roster(struct aji_client *client)
01767 {
01768 iks *roster = NULL;
01769 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER);
01770 if(roster) {
01771 iks_insert_attrib(roster, "id", "roster");
01772 aji_set_presence(client, NULL, client->jid->full, 1, client->statusmessage);
01773 iks_send(client->p, roster);
01774 }
01775 if (roster)
01776 iks_delete(roster);
01777 return 1;
01778 }
01779
01780
01781
01782
01783
01784
01785 static int aji_client_connect(void *data, ikspak *pak)
01786 {
01787 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01788 int res = 0;
01789
01790 if (client) {
01791 if (client->state == AJI_DISCONNECTED) {
01792 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);
01793 client->state = AJI_CONNECTING;
01794 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid;
01795 iks_filter_remove_hook(client->f, aji_client_connect);
01796 if(!client->component)
01797 aji_get_roster(client);
01798 }
01799 } else
01800 ast_log(LOG_ERROR, "Out of memory.\n");
01801
01802 ASTOBJ_UNREF(client, aji_client_destroy);
01803 return res;
01804 }
01805
01806
01807
01808
01809
01810
01811 static int aji_client_initialize(struct aji_client *client)
01812 {
01813 int connected = 0;
01814
01815 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->jid->server);
01816
01817 if (connected == IKS_NET_NOCONN) {
01818 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
01819 return IKS_HOOK;
01820 } else if (connected == IKS_NET_NODNS) {
01821 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, S_OR(client->serverhost, client->jid->server));
01822 return IKS_HOOK;
01823 } else
01824 iks_recv(client->p, 30);
01825 return IKS_OK;
01826 }
01827
01828
01829
01830
01831
01832
01833 static int aji_component_initialize(struct aji_client *client)
01834 {
01835 int connected = 1;
01836 connected = iks_connect_via(client->p, client->jid->server, client->port, client->user);
01837 if (connected == IKS_NET_NOCONN) {
01838 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
01839 return IKS_HOOK;
01840 } else if (connected == IKS_NET_NODNS) {
01841 ast_log(LOG_ERROR, "JABBER ERROR: No DNS\n");
01842 return IKS_HOOK;
01843 } else if (!connected)
01844 iks_recv(client->p, 30);
01845 return IKS_OK;
01846 }
01847
01848
01849
01850
01851
01852
01853 int ast_aji_disconnect(struct aji_client *client)
01854 {
01855 if (client) {
01856 if (option_verbose > 3)
01857 ast_verbose(VERBOSE_PREFIX_3 "JABBER: Disconnecting\n");
01858 iks_disconnect(client->p);
01859 iks_parser_delete(client->p);
01860 ASTOBJ_UNREF(client, aji_client_destroy);
01861 }
01862
01863 return 1;
01864 }
01865
01866
01867
01868
01869
01870
01871 static void aji_set_presence(struct aji_client *client, char *to, char *from, int level, char *desc)
01872 {
01873 int res = 0;
01874 iks *presence = iks_make_pres(level, desc);
01875 iks *cnode = iks_new("c");
01876 iks *priority = iks_new("priority");
01877
01878 iks_insert_cdata(priority, "0", 1);
01879 if (presence && cnode && client) {
01880 if(to)
01881 iks_insert_attrib(presence, "to", to);
01882 if(from)
01883 iks_insert_attrib(presence, "from", from);
01884 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps");
01885 iks_insert_attrib(cnode, "ver", "asterisk-xmpp");
01886 iks_insert_attrib(cnode, "ext", "voice-v1");
01887 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps");
01888 iks_insert_node(presence, cnode);
01889 res = iks_send(client->p, presence);
01890 } else
01891 ast_log(LOG_ERROR, "Out of memory.\n");
01892 if (cnode)
01893 iks_delete(cnode);
01894 if (presence)
01895 iks_delete(presence);
01896 }
01897
01898
01899
01900
01901
01902
01903 static int aji_do_debug(int fd, int argc, char *argv[])
01904 {
01905 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01906 ASTOBJ_RDLOCK(iterator);
01907 iterator->debug = 1;
01908 ASTOBJ_UNLOCK(iterator);
01909 });
01910 ast_cli(fd, "Jabber Debugging Enabled.\n");
01911 return RESULT_SUCCESS;
01912 }
01913
01914
01915
01916
01917
01918
01919 static int aji_do_reload(int fd, int argc, char *argv[])
01920 {
01921 aji_reload();
01922 ast_cli(fd, "Jabber Reloaded.\n");
01923 return RESULT_SUCCESS;
01924 }
01925
01926
01927
01928
01929
01930
01931 static int aji_no_debug(int fd, int argc, char *argv[])
01932 {
01933 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01934 ASTOBJ_RDLOCK(iterator);
01935 iterator->debug = 0;
01936 ASTOBJ_UNLOCK(iterator);
01937 });
01938 ast_cli(fd, "Jabber Debugging Disabled.\n");
01939 return RESULT_SUCCESS;
01940 }
01941
01942
01943
01944
01945
01946
01947 static int aji_show_clients(int fd, int argc, char *argv[])
01948 {
01949 char *status;
01950 int count = 0;
01951 ast_cli(fd, "Jabber Users and their status:\n");
01952 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01953 ASTOBJ_RDLOCK(iterator);
01954 count++;
01955 switch (iterator->state) {
01956 case AJI_DISCONNECTED:
01957 status = "Disconnected";
01958 break;
01959 case AJI_CONNECTING:
01960 status = "Connecting";
01961 break;
01962 case AJI_CONNECTED:
01963 status = "Connected";
01964 break;
01965 default:
01966 status = "Unknown";
01967 }
01968 ast_cli(fd, " User: %s - %s\n", iterator->user, status);
01969 ASTOBJ_UNLOCK(iterator);
01970 });
01971 ast_cli(fd, "----\n");
01972 ast_cli(fd, " Number of users: %d\n", count);
01973 return RESULT_SUCCESS;
01974 }
01975
01976
01977
01978
01979
01980
01981 static int aji_test(int fd, int argc, char *argv[])
01982 {
01983 struct aji_client *client;
01984 struct aji_resource *resource;
01985 const char *name = "asterisk";
01986 struct aji_message *tmp;
01987
01988 if (argc > 3)
01989 return RESULT_SHOWUSAGE;
01990 else if (argc == 3)
01991 name = argv[2];
01992
01993 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) {
01994 ast_cli(fd, "Unable to find client '%s'!\n", name);
01995 return RESULT_FAILURE;
01996 }
01997
01998
01999 ast_aji_send(client, "mogorman@astjab.org", "blahblah");
02000 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
02001 ASTOBJ_RDLOCK(iterator);
02002 ast_verbose("User: %s\n", iterator->name);
02003 for (resource = iterator->resources; resource; resource = resource->next) {
02004 ast_verbose("Resource: %s\n", resource->resource);
02005 if(resource->cap) {
02006 ast_verbose(" client: %s\n", resource->cap->parent->node);
02007 ast_verbose(" version: %s\n", resource->cap->version);
02008 ast_verbose(" Jingle Capable: %d\n", resource->cap->jingle);
02009 }
02010 ast_verbose(" Priority: %d\n", resource->priority);
02011 ast_verbose(" Status: %d\n", resource->status);
02012 ast_verbose(" Message: %s\n", S_OR(resource->description,""));
02013 }
02014 ASTOBJ_UNLOCK(iterator);
02015 });
02016 ast_verbose("\nOooh a working message stack!\n");
02017 AST_LIST_LOCK(&client->messages);
02018 AST_LIST_TRAVERSE(&client->messages, tmp, list) {
02019 ast_verbose(" Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, ""));
02020 }
02021 AST_LIST_UNLOCK(&client->messages);
02022 ASTOBJ_UNREF(client, aji_client_destroy);
02023
02024 return RESULT_SUCCESS;
02025 }
02026
02027
02028
02029
02030
02031
02032 static int aji_create_client(char *label, struct ast_variable *var, int debug)
02033 {
02034 char *resource;
02035 struct aji_client *client = NULL;
02036 int flag = 0;
02037
02038 client = ASTOBJ_CONTAINER_FIND(&clients,label);
02039 if (!client) {
02040 flag = 1;
02041 client = (struct aji_client *) malloc(sizeof(struct aji_client));
02042 if (!client) {
02043 ast_log(LOG_ERROR, "Out of memory!\n");
02044 return 0;
02045 }
02046 memset(client, 0, sizeof(struct aji_client));
02047 ASTOBJ_INIT(client);
02048 ASTOBJ_WRLOCK(client);
02049 ASTOBJ_CONTAINER_INIT(&client->buddies);
02050 } else {
02051 ASTOBJ_WRLOCK(client);
02052 ASTOBJ_UNMARK(client);
02053 }
02054 ASTOBJ_CONTAINER_MARKALL(&client->buddies);
02055 ast_copy_string(client->name, label, sizeof(client->name));
02056 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid));
02057
02058 client->debug = debug;
02059 ast_copy_flags(client, &globalflags, AST_FLAGS_ALL);
02060 client->port = 5222;
02061 client->usetls = 1;
02062 client->usesasl = 1;
02063 client->forcessl = 0;
02064 client->keepalive = 1;
02065 client->timeout = 50;
02066 client->message_timeout = 100;
02067 AST_LIST_HEAD_INIT(&client->messages);
02068 client->component = 0;
02069 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage));
02070
02071 if (flag) {
02072 client->authorized = 0;
02073 client->state = AJI_DISCONNECTED;
02074 }
02075 while (var) {
02076 if (!strcasecmp(var->name, "username"))
02077 ast_copy_string(client->user, var->value, sizeof(client->user));
02078 else if (!strcasecmp(var->name, "serverhost"))
02079 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost));
02080 else if (!strcasecmp(var->name, "secret"))
02081 ast_copy_string(client->password, var->value, sizeof(client->password));
02082 else if (!strcasecmp(var->name, "statusmessage"))
02083 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage));
02084 else if (!strcasecmp(var->name, "port"))
02085 client->port = atoi(var->value);
02086 else if (!strcasecmp(var->name, "timeout"))
02087 client->message_timeout = atoi(var->value);
02088 else if (!strcasecmp(var->name, "debug"))
02089 client->debug = (ast_false(var->value)) ? 0 : 1;
02090 else if (!strcasecmp(var->name, "type")) {
02091 if (!strcasecmp(var->value, "component"))
02092 client->component = 1;
02093 } else if (!strcasecmp(var->name, "usetls")) {
02094 client->usetls = (ast_false(var->value)) ? 0 : 1;
02095 } else if (!strcasecmp(var->name, "usesasl")) {
02096 client->usesasl = (ast_false(var->value)) ? 0 : 1;
02097 } else if (!strcasecmp(var->name, "forceoldssl"))
02098 client->forcessl = (ast_false(var->value)) ? 0 : 1;
02099 else if (!strcasecmp(var->name, "keepalive"))
02100 client->keepalive = (ast_false(var->value)) ? 0 : 1;
02101 else if (!strcasecmp(var->name, "autoprune"))
02102 ast_set2_flag(client, ast_true(var->value), AJI_AUTOPRUNE);
02103 else if (!strcasecmp(var->name, "autoregister"))
02104 ast_set2_flag(client, ast_true(var->value), AJI_AUTOREGISTER);
02105 else if (!strcasecmp(var->name, "buddy"))
02106 aji_create_buddy(var->value, client);
02107
02108
02109
02110
02111 var = var->next;
02112 }
02113 if (!flag) {
02114 ASTOBJ_UNLOCK(client);
02115 ASTOBJ_UNREF(client, aji_client_destroy);
02116 return 1;
02117 }
02118 client->p = iks_stream_new(((client->component) ? "jabber:component:accept" : "jabber:client"), client, aji_act_hook);
02119 if (!client->p) {
02120 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name);
02121 return 0;
02122 }
02123 client->stack = iks_stack_new(8192, 8192);
02124 if (!client->stack) {
02125 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name);
02126 return 0;
02127 }
02128 client->f = iks_filter_new();
02129 if (!client->f) {
02130 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name);
02131 return 0;
02132 }
02133 if (!strchr(client->user, '/') && !client->component) {
02134 resource = NULL;
02135 asprintf(&resource, "%s/asterisk", client->user);
02136 if (resource) {
02137 client->jid = iks_id_new(client->stack, resource);
02138 free(resource);
02139 }
02140 } else
02141 client->jid = iks_id_new(client->stack, client->user);
02142 if (client->component) {
02143 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
02144 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE);
02145 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);
02146 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);
02147 } else {
02148 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
02149 }
02150 if (!strchr(client->user, '/') && !client->component) {
02151 resource = NULL;
02152 asprintf(&resource, "%s/asterisk", client->user);
02153 if (resource) {
02154 client->jid = iks_id_new(client->stack, resource);
02155 free(resource);
02156 }
02157 } else
02158 client->jid = iks_id_new(client->stack, client->user);
02159 iks_set_log_hook(client->p, aji_log_hook);
02160 ASTOBJ_UNLOCK(client);
02161 ASTOBJ_CONTAINER_LINK(&clients,client);
02162 return 1;
02163 }
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222 static int aji_create_buddy(char *label, struct aji_client *client)
02223 {
02224 struct aji_buddy *buddy = NULL;
02225 int flag = 0;
02226 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies,label);
02227 if (!buddy) {
02228 flag = 1;
02229 buddy = malloc(sizeof(struct aji_buddy));
02230 if(!buddy) {
02231 ast_log(LOG_WARNING, "Out of memory\n");
02232 return 0;
02233 }
02234 memset(buddy, 0, sizeof(struct aji_buddy));
02235 ASTOBJ_INIT(buddy);
02236 }
02237 ASTOBJ_WRLOCK(buddy);
02238 ast_copy_string(buddy->name, label, sizeof(buddy->name));
02239 ASTOBJ_UNLOCK(buddy);
02240 if(flag)
02241 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
02242 else {
02243 ASTOBJ_UNMARK(buddy);
02244 ASTOBJ_UNREF(buddy, aji_buddy_destroy);
02245 }
02246 return 1;
02247 }
02248
02249
02250
02251
02252
02253
02254 static int aji_load_config(void)
02255 {
02256 char *cat = NULL;
02257 int debug = 1;
02258 struct ast_config *cfg = NULL;
02259 struct ast_variable *var = NULL;
02260
02261 cfg = ast_config_load(JABBER_CONFIG);
02262 if (!cfg) {
02263 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG);
02264 return 0;
02265 }
02266
02267 cat = ast_category_browse(cfg, NULL);
02268 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
02269 if (!strcasecmp(var->name, "debug"))
02270 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1;
02271 else if (!strcasecmp(var->name, "autoprune"))
02272 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE);
02273 else if (!strcasecmp(var->name, "autoregister"))
02274 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER);
02275 }
02276
02277 while (cat) {
02278 if (strcasecmp(cat, "general")) {
02279 var = ast_variable_browse(cfg, cat);
02280 aji_create_client(cat, var, debug);
02281 }
02282 cat = ast_category_browse(cfg, cat);
02283 }
02284 return 1;
02285 }
02286
02287
02288
02289
02290
02291
02292 struct aji_client *ast_aji_get_client(const char *name)
02293 {
02294 struct aji_client *client = NULL;
02295
02296 client = ASTOBJ_CONTAINER_FIND(&clients, name);
02297 if (!client && !strchr(name, '@'))
02298 client = ASTOBJ_CONTAINER_FIND_FULL(&clients, name, user,,, strcasecmp);
02299 return client;
02300 }
02301
02302 struct aji_client_container *ast_aji_get_clients(void)
02303 {
02304 return &clients;
02305 }
02306
02307 static char mandescr_jabber_send[] =
02308 "Description: Sends a message to a Jabber Client.\n"
02309 "Variables: \n"
02310 " Jabber: Client or transport Asterisk uses to connect to JABBER.\n"
02311 " ScreenName: User Name to message.\n"
02312 " Message: Message to be sent to the buddy\n";
02313
02314
02315 static int manager_jabber_send(struct mansession *s, const struct message *m)
02316 {
02317 struct aji_client *client = NULL;
02318 const char *id = astman_get_header(m,"ActionID");
02319 const char *jabber = astman_get_header(m,"Jabber");
02320 const char *screenname = astman_get_header(m,"ScreenName");
02321 const char *message = astman_get_header(m,"Message");
02322
02323 if (ast_strlen_zero(jabber)) {
02324 astman_send_error(s, m, "No transport specified");
02325 return 0;
02326 }
02327 if (ast_strlen_zero(screenname)) {
02328 astman_send_error(s, m, "No ScreenName specified");
02329 return 0;
02330 }
02331 if (ast_strlen_zero(message)) {
02332 astman_send_error(s, m, "No Message specified");
02333 return 0;
02334 }
02335
02336 astman_send_ack(s, m, "Attempting to send Jabber Message");
02337 client = ast_aji_get_client(jabber);
02338 if (!client) {
02339 astman_send_error(s, m, "Could not find Sender");
02340 return 0;
02341 }
02342 if (strchr(screenname, '@') && message){
02343 ast_aji_send(client, screenname, message);
02344 if (!ast_strlen_zero(id))
02345 astman_append(s, "ActionID: %s\r\n",id);
02346 astman_append(s, "Response: Success\r\n");
02347 return 0;
02348 }
02349 if (!ast_strlen_zero(id))
02350 astman_append(s, "ActionID: %s\r\n",id);
02351 astman_append(s, "Response: Failure\r\n");
02352 return 0;
02353 }
02354
02355
02356 static int aji_reload()
02357 {
02358 ASTOBJ_CONTAINER_MARKALL(&clients);
02359 if (!aji_load_config()) {
02360 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n");
02361 return 0;
02362 }
02363 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy);
02364 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02365 ASTOBJ_RDLOCK(iterator);
02366 if(iterator->state == AJI_DISCONNECTED) {
02367 if (!iterator->thread)
02368 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator);
02369 } else if (iterator->state == AJI_CONNECTING)
02370 aji_get_roster(iterator);
02371 ASTOBJ_UNLOCK(iterator);
02372 });
02373
02374 return 1;
02375 }
02376
02377 static int unload_module(void)
02378 {
02379 ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
02380 ast_unregister_application(app_ajisend);
02381 ast_unregister_application(app_ajistatus);
02382 ast_manager_unregister("JabberSend");
02383 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02384 ASTOBJ_RDLOCK(iterator);
02385 if (option_verbose > 2)
02386 ast_verbose(VERBOSE_PREFIX_3 "JABBER: %s\n", iterator->name);
02387 iterator->state = AJI_DISCONNECTED;
02388 ast_aji_disconnect(iterator);
02389 pthread_join(iterator->thread, NULL);
02390 ASTOBJ_UNLOCK(iterator);
02391 });
02392
02393 ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy);
02394 ASTOBJ_CONTAINER_DESTROY(&clients);
02395
02396 ast_log(LOG_NOTICE, "res_jabber unloaded.\n");
02397 return 0;
02398 }
02399
02400 static int load_module(void)
02401 {
02402 ASTOBJ_CONTAINER_INIT(&clients);
02403 if(!aji_reload())
02404 return AST_MODULE_LOAD_DECLINE;
02405 ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send,
02406 "Sends a message to a Jabber Client", mandescr_jabber_send);
02407 ast_register_application(app_ajisend, aji_send_exec, ajisend_synopsis, ajisend_descrip);
02408 ast_register_application(app_ajistatus, aji_status_exec, ajistatus_synopsis, ajistatus_descrip);
02409 ast_cli_register_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
02410
02411 ast_log(LOG_NOTICE, "res_jabber.so loaded.\n");
02412 return 0;
02413 }
02414
02415 static int reload(void)
02416 {
02417 aji_reload();
02418 return 0;
02419 }
02420
02421 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "AJI - Asterisk Jabber Interface",
02422 .load = load_module,
02423 .unload = unload_module,
02424 .reload = reload,
02425 );