Fix up the AGI doc dump CLI command and update the AGI commands tex file to not
[asterisk/asterisk.git] / res / res_jabber.c
index 48c375c..78ff7d9 100644 (file)
 /*! \file
  * \brief A resource for interfacing asterisk directly as a client
  * or a component to a jabber compliant server.
+ *
+ * \extref Iksemel http://iksemel.jabberstudio.org/
+ *
+ * \todo If you unload this module, chan_gtalk/jingle will be dead. How do we handle that?
+ * \todo If you have TLS, you can't unload this module. See bug #9738. This needs to be fixed,
+ *       but the bug is in the unmantained Iksemel library
+ *
  */
 
 /*** MODULEINFO
        <depend>iksemel</depend>
+       <use>gnutls</use>
  ***/
 
 #include "asterisk.h"
@@ -54,8 +62,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #define JABBER_CONFIG "jabber.conf"
 
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
 /*-- Forward declarations */
-static int manager_jabber_send( struct mansession *s, struct message *m );
+static int aji_start_sasl(iksparser *prs, enum ikssasltype type, char *username, char *pass);
 static int aji_highest_bit(int number);
 static void aji_buddy_destroy(struct aji_buddy *obj);
 static void aji_client_destroy(struct aji_client *obj);
@@ -68,10 +84,9 @@ static void aji_handle_message(struct aji_client *client, ikspak *pak);
 static void aji_handle_presence(struct aji_client *client, ikspak *pak);
 static void aji_handle_subscribe(struct aji_client *client, ikspak *pak);
 static void *aji_recv_loop(void *data);
-static int aji_component_initialize(struct aji_client *client);
-static int aji_client_initialize(struct aji_client *client);
+static int aji_initialize(struct aji_client *client);
 static int aji_client_connect(void *data, ikspak *pak);
-static void aji_set_presence(struct aji_client *client, char *user, int level, char *desc);
+static void aji_set_presence(struct aji_client *client, char *to, char *from, int level, char *desc);
 static int aji_do_debug(int fd, int argc, char *argv[]);
 static int aji_do_reload(int fd, int argc, char *argv[]);
 static int aji_no_debug(int fd, int argc, char *argv[]);
@@ -79,12 +94,9 @@ static int aji_test(int fd, int argc, char *argv[]);
 static int aji_show_clients(int fd, int argc, char *argv[]);
 static int aji_create_client(char *label, struct ast_variable *var, int debug);
 static int aji_create_buddy(char *label, struct aji_client *client);
-static int aji_create_transport(char *label, struct aji_client *client);
-static void aji_reload(void);
+static int aji_reload(void);
 static int aji_load_config(void);
 static void aji_pruneregister(struct aji_client *client);
-static int aji_register_transport(void *data, ikspak *pak);
-static int aji_register_transport2(void *data, ikspak *pak);
 static int aji_filter_roster(void *data, ikspak *pak);
 static int aji_get_roster(struct aji_client *client);
 static int aji_client_info_handler(void *data, ikspak *pak);
@@ -94,40 +106,58 @@ static int aji_register_query_handler(void *data, ikspak *pak);
 static int aji_register_approve_handler(void *data, ikspak *pak);
 static int aji_reconnect(struct aji_client *client);
 static iks *jabber_make_auth(iksid * id, const char *pass, const char *sid);
+/* No transports in this version */
+/*
+static int aji_create_transport(char *label, struct aji_client *client);
+static int aji_register_transport(void *data, ikspak *pak);
+static int aji_register_transport2(void *data, ikspak *pak);
+*/
 
-static char debug_usage[] = 
+static const char debug_usage[] = 
 "Usage: jabber debug\n" 
 "       Enables dumping of Jabber packets for debugging purposes.\n";
 
-static char no_debug_usage[] = 
-"Usage: jabber no debug\n" 
+static const char no_debug_usage[] = 
+"Usage: jabber debug off\n" 
 "       Disables dumping of Jabber packets for debugging purposes.\n";
 
-static char reload_usage[] = 
+static const char reload_usage[] = 
 "Usage: jabber reload\n" 
 "       Enables reloading of Jabber module.\n";
 
-static char test_usage[] = 
+static const char test_usage[] = 
 "Usage: jabber test [client]\n" 
 "       Sends test message for debugging purposes.  A specific client\n"
 "       as configured in jabber.conf can be optionally specified.\n";
 
 static struct ast_cli_entry aji_cli[] = {
-       {{ "jabber", "debug", NULL}, aji_do_debug, "Enable Jabber debugging", debug_usage },
-       {{ "jabber", "reload", NULL}, aji_do_reload, "Enable Jabber debugging", reload_usage },
-       {{ "jabber", "show", "connected", NULL}, aji_show_clients, "Show state of clients and components", debug_usage },
-       {{ "jabber", "no", "debug", NULL}, aji_no_debug, "Disable Jabber debug", no_debug_usage },
-       {{ "jabber", "test", NULL}, aji_test, "Shows roster, but is genearlly used for mog's debugging.", test_usage },
- };
+       { { "jabber", "debug", NULL},
+       aji_do_debug, "Enable Jabber debugging",
+       debug_usage },
+
+       { { "jabber", "reload", NULL},
+       aji_do_reload, "Reload Jabber configuration",
+       reload_usage },
+
+       { { "jabber", "show", "connected", NULL},
+       aji_show_clients, "Show state of clients and components",
+       debug_usage },
 
-static const char *tdesc = "AJI - Asterisk Jabber Interface";
+       { { "jabber", "debug", "off", NULL},
+       aji_no_debug, "Disable Jabber debug",
+       no_debug_usage },
+
+       { { "jabber", "test", NULL},
+       aji_test, "Shows roster, but is generally used for mog's debugging.",
+       test_usage },
+};
 
 static char *app_ajisend = "JabberSend";
 
 static char *ajisend_synopsis = "JabberSend(jabber,screenname,message)";
 
 static char *ajisend_descrip =
-"JabberRSend(Jabber,ScreenName,Message)\n"
+"JabberSend(Jabber,ScreenName,Message)\n"
 "  Jabber - Client or transport Asterisk uses to connect to Jabber\n" 
 "  ScreenName - User Name to message.\n" 
 "  Message - Message to be sent to the buddy\n";
@@ -145,15 +175,15 @@ static char *ajistatus_descrip =
 "             If not in roster variable will = 7\n";
 
 struct aji_client_container clients;
-
-struct aji_capabilities *capabilities;
+struct aji_capabilities *capabilities = NULL;
 
 /*! \brief Global flags, initialized to default values */
 static struct ast_flags globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER };
+static int tls_initialized = FALSE;
 
 /*!
  * \brief Deletes the aji_client data structure.
- * \param obj is the structure we will delete.
+ * \param obj aji_client The structure we will delete.
  * \return void.
  */
 static void aji_client_destroy(struct aji_client *obj)
@@ -167,17 +197,17 @@ static void aji_client_destroy(struct aji_client *obj)
        AST_LIST_LOCK(&obj->messages);
        while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) {
                if (tmp->from)
-                       free(tmp->from);
+                       ast_free(tmp->from);
                if (tmp->message)
-                       free(tmp->message);
+                       ast_free(tmp->message);
        }
        AST_LIST_HEAD_DESTROY(&obj->messages);
-       free(obj);
+       ast_free(obj);
 }
 
 /*!
  * \brief Deletes the aji_buddy data structure.
- * \param obj is the structure we will delete.
+ * \param obj aji_buddy The structure we will delete.
  * \return void.
  */
 static void aji_buddy_destroy(struct aji_buddy *obj)
@@ -186,13 +216,22 @@ static void aji_buddy_destroy(struct aji_buddy *obj)
 
        while ((tmp = obj->resources)) {
                obj->resources = obj->resources->next;
-               free(tmp->description);
-               free(tmp);
+               ast_free(tmp->description);
+               ast_free(tmp);
        }
 
-       free(obj);
+       ast_free(obj);
 }
 
+/*!
+ * \brief Find version in XML stream and populate our capabilities list
+ * \param node the node attribute in the caps element we'll look for or add to 
+ * our list
+ * \param version the version attribute in the caps element we'll look for or 
+ * add to our list
+ * \param pak struct The XML stanza we're processing
+ * \return a pointer to the added or found aji_version structure
+ */ 
 static struct aji_version *aji_find_version(char *node, char *version, ikspak *pak)
 {
        struct aji_capabilities *list = NULL;
@@ -212,8 +251,10 @@ static struct aji_version *aji_find_version(char *node, char *version, ikspak *p
                                         return res;
                                 res = res->next;
                        }
+                       /* Specified version not found. Let's add it to 
+                          this node in our capabilities list */
                        if(!res) {
-                               res = (struct aji_version *)malloc(sizeof(struct aji_version));
+                               res = ast_malloc(sizeof(*res));
                                if(!res) {
                                        ast_log(LOG_ERROR, "Out of memory!\n");
                                        return NULL;
@@ -228,13 +269,14 @@ static struct aji_version *aji_find_version(char *node, char *version, ikspak *p
                }
                list = list->next;
        }
+       /* Specified node not found. Let's add it our capabilities list */
        if(!list) {
-               list = (struct aji_capabilities *)malloc(sizeof(struct aji_capabilities));
+               list = ast_malloc(sizeof(*list));
                if(!list) {
                        ast_log(LOG_ERROR, "Out of memory!\n");
                        return NULL;
                }
-               res = (struct aji_version *)malloc(sizeof(struct aji_version));
+               res = ast_malloc(sizeof(*res));
                if(!res) {
                        ast_log(LOG_ERROR, "Out of memory!\n");
                        return NULL;
@@ -243,22 +285,27 @@ static struct aji_version *aji_find_version(char *node, char *version, ikspak *p
                ast_copy_string(res->version, version, sizeof(res->version));
                res->jingle = 0;
                res->parent = list;
-               res->next = list->versions;
+               res->next = NULL;
                list->versions = res;
                list->next = capabilities;
                capabilities = list;
        }
        return res;
 }
-
-static struct aji_resource *aji_find_resource(struct aji_buddy *buddy, char *rname)
+/*!
+ * \brief Find the aji_resource we want
+ * \param buddy aji_buddy A buddy
+ * \param name 
+ * \return aji_resource object
+*/
+static struct aji_resource *aji_find_resource(struct aji_buddy *buddy, char *name)
 {
        struct aji_resource *res = NULL;
-       if (!buddy || !rname)
+       if (!buddy || !name)
                return res;
        res = buddy->resources;
        while (res) {
-               if (!strcasecmp(res->resource, rname)) {
+               if (!strcasecmp(res->resource, name)) {
                        break;
                }
                res = res->next;
@@ -266,6 +313,11 @@ static struct aji_resource *aji_find_resource(struct aji_buddy *buddy, char *rna
        return res;
 }
 
+/*!
+ * \brief Jabber GTalk function
+ * \param node iks
+ * \return 1 on success, 0 on failure.
+*/
 static int gtalk_yuck(iks *node)
 {
        if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps"))
@@ -275,7 +327,7 @@ static int gtalk_yuck(iks *node)
 
 /*!
  * \brief Detects the highest bit in a number.
- * \param Number you want to have evaluated.
+ * \param number  Number you want to have evaluated.
  * \return the highest power of 2 that can go into the number.
  */
 static int aji_highest_bit(int number)
@@ -290,6 +342,13 @@ static int aji_highest_bit(int number)
        return (1 << x);
 }
 
+/*!
+ * \brief Setup the authentication struct
+ * \param id iksid 
+ * \param pass password
+ * \param sid
+ * \return x iks
+*/
 static iks *jabber_make_auth(iksid * id, const char *pass, const char *sid)
 {
        iks *x, *y;
@@ -314,8 +373,9 @@ static iks *jabber_make_auth(iksid * id, const char *pass, const char *sid)
 /*!
  * \brief Dial plan function status(). puts the status of watched user 
    into a channel variable.
- * \param channel, and username,watched user, status var
- * \return 0.
+ * \param chan ast_channel
+ * \param data
+ * \return 0 on success, -1 on error
  */
 static int aji_status_exec(struct ast_channel *chan, void *data)
 {
@@ -325,23 +385,23 @@ static int aji_status_exec(struct ast_channel *chan, void *data)
        char *s = NULL, *sender = NULL, *jid = NULL, *screenname = NULL, *resource = NULL, *variable = NULL;
        int stat = 7;
        char status[2];
-       if (data) {
-               s = ast_strdupa((char *) data);
-               if (s) {
-                       sender = strsep(&s, "|");
-                       if (sender && (sender[0] != '\0')) {
-                               jid = strsep(&s, "|");
-                               if (jid && (jid[0] != '\0')) {
-                                       variable = s;
-                               } else {
-                                       ast_log(LOG_ERROR, "Bad arguments\n");
-                                       return -1;
-                               }
+
+       if (!data) {
+               ast_log(LOG_ERROR, "This application requires arguments.\n");
+               return 0;
+       }
+       s = ast_strdupa(data);
+       if (s) {
+               sender = strsep(&s, "|");
+               if (sender && (sender[0] != '\0')) {
+                       jid = strsep(&s, "|");
+                       if (jid && (jid[0] != '\0')) {
+                               variable = s;
+                       } else {
+                               ast_log(LOG_ERROR, "Bad arguments\n");
+                               return -1;
                        }
                }
-       } else {
-               ast_log(LOG_ERROR, "Out of memory\n");
-               return -1;
        }
 
        if(!strchr(jid, '/')) {
@@ -352,26 +412,25 @@ static int aji_status_exec(struct ast_channel *chan, void *data)
        }
        client = ast_aji_get_client(sender);
        if (!client) {
-               ast_log(LOG_WARNING, "Could not find Connection.\n");
+               ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender);
                return -1;
        }
        if(!&client->buddies) {
-               ast_log(LOG_WARNING, "No buddies for connection.\n");
+               ast_log(LOG_WARNING, "No buddies for connection : %s\n", sender);
                return -1;
        }
-       buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, (resource)?screenname:jid);
+       buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, resource ? screenname: jid);
        if (!buddy) {
-               ast_log(LOG_WARNING, "Could not find Buddy in list.\n");
+               ast_log(LOG_WARNING, "Could not find buddy in list : %s\n", resource ? screenname : jid);
                return -1;
        }
        r = aji_find_resource(buddy, resource);
-       if(!r && buddy->resources) {
+       if(!r && buddy->resources) 
                r = buddy->resources;
-       }
-       if(!r){
+       if(!r)
                ast_log(LOG_NOTICE, "Resource %s of buddy %s not found \n", resource, screenname);
-       }
-       stat = r->status;
+       else
+               stat = r->status;
        sprintf(status, "%d", stat);
        pbx_builtin_setvar_helper(chan, variable, status);
        return 0;
@@ -379,8 +438,9 @@ static int aji_status_exec(struct ast_channel *chan, void *data)
 
 /*!
  * \brief Dial plan function to send a message.
- * \param channel, and data, data is sender, reciever, message.
- * \return 0.
+ * \param chan ast_channel
+ * \param data  Data is sender|reciever|message.
+ * \return 0 on success,-1 on error.
  */
 static int aji_send_exec(struct ast_channel *chan, void *data)
 {
@@ -389,10 +449,10 @@ static int aji_send_exec(struct ast_channel *chan, void *data)
        char *s = NULL, *sender = NULL, *recipient = NULL, *message = NULL;
 
        if (!data) {
-               ast_log(LOG_ERROR, "Out of memory\n");
-               return -1;
+               ast_log(LOG_ERROR, "This application requires arguments.\n");
+               return 0;
        }
-       s = ast_strdupa((char *) data);
+       s = ast_strdupa(data);
        if (s) {
                sender = strsep(&s, "|");
                if (sender && (sender[0] != '\0')) {
@@ -400,13 +460,13 @@ static int aji_send_exec(struct ast_channel *chan, void *data)
                        if (recipient && (recipient[0] != '\0')) {
                                message = s;
                        } else {
-                               ast_log(LOG_ERROR, "Bad arguments \n");
+                               ast_log(LOG_ERROR, "Bad arguments: %s\n", (char *) data);
                                return -1;
                        }
                }
        }
        if (!(client = ast_aji_get_client(sender))) {
-               ast_log(LOG_WARNING, "Could not find Sender.\n");
+               ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender);
                return -1;
        }
        if (strchr(recipient, '@') && message)
@@ -416,26 +476,85 @@ static int aji_send_exec(struct ast_channel *chan, void *data)
 
 /*!
  * \brief the debug loop.
- * \param aji_client structure, xml data as string, size of string, direction of packet, 1 for inbound 0 for outbound.
+ * \param data void
+ * \param xmpp xml data as string
+ * \param size size of string
+ * \param is_incoming direction of packet 1 for inbound 0 for outbound.
  */
 static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming)
 {
        struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
-       manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\n Packet: %s", client->name, xmpp);
 
-       if (client->debug == 1) {
+       if (!ast_strlen_zero(xmpp))
+               manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp);
+
+       if (client->debug) {
                if (is_incoming)
                        ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp);
-               else
-                       ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp);
+               else {
+                       if( strlen(xmpp) == 1) {
+                               if(option_debug > 2  && xmpp[0] == ' ')
+                               ast_verbose("\nJABBER: Keep alive packet\n");
+                       } else
+                               ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp);
+               }
 
        }
        ASTOBJ_UNREF(client, aji_client_destroy);
 }
 
 /*!
+ * \brief A wrapper function for iks_start_sasl
+ * \param prs the XML parser
+ * \param type the SASL authentication type. Supported types are PLAIN and MD5
+ * \param username
+ * \param pass
+ * If SASL authentication type is MD5, we simply call iks_start_sasl().
+ * If type is PLAIN, we compute the authentication string by ourselves, 
+ * because it looks like Google's jabber server does not accept the value 
+ * computed with iks_start_sasl().
+ * \return IKS_OK on success, IKSNET_NOTSUPP on failure.
+ */
+static int aji_start_sasl(iksparser *prs, enum ikssasltype type, char *username, char *pass)
+{
+       iks *x = NULL;
+       int len;
+       char *s;
+       char *base64;
+
+       if (type == IKS_STREAM_SASL_MD5)
+               return iks_start_sasl(prs, type, username, pass);
+
+       x = iks_new("auth"); 
+       if (!x) {
+               ast_log(LOG_ERROR, "Out of memory.\n");
+               return IKS_NET_NOTSUPP;
+       }
+
+       iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL);
+       len = strlen(username) + strlen(pass) + 3;
+       /* XXX Check return values XXX */
+       s = ast_malloc(80 + len);
+       base64 = ast_malloc(80 + len * 2);
+       iks_insert_attrib(x, "mechanism", "PLAIN");
+       sprintf(s, "%c%s%c%s", 0, username, 0, pass);
+       ast_base64encode(base64, (const unsigned char *) s, len, len * 2);
+       iks_insert_cdata(x, base64, 0);
+       iks_send(prs, x);
+       iks_delete(x);
+       if (base64)
+               free(base64);
+       if (s)
+               free(s);        
+
+       return IKS_OK;
+}
+
+/*!
  * \brief The action hook parses the inbound packets, constantly running.
- * \param aji client structure, type of packet, the actual packet.
+ * \param data aji client structure 
+ * \param type type of packet 
+ * \param node the actual packet.
  * \return IKS_OK or IKS_HOOK .
  */
 static int aji_act_hook(void *data, int type, iks *node)
@@ -443,17 +562,30 @@ static int aji_act_hook(void *data, int type, iks *node)
        struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
        ikspak *pak = NULL;
        iks *auth = NULL;
+       int features = 0;
+
+       if(!node) {
+               ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */
+               ASTOBJ_UNREF(client, aji_client_destroy);
+               return IKS_HOOK;
+       }
+
+       if (client->state == AJI_DISCONNECTING) {
+               ASTOBJ_UNREF(client, aji_client_destroy);
+               return IKS_HOOK;
+       }
 
        pak = iks_packet(node);
 
-       if (client->component == AJI_CLIENT) {
+       if (!client->component) { /*client */
                switch (type) {
                case IKS_NODE_START:
                        if (client->usetls && !iks_is_secure(client->p)) {
-                               if (iks_has_tls())
+                               if (iks_has_tls()) {
                                        iks_start_tls(client->p);
-                               else
-                                       ast_log(LOG_ERROR, "gnuTLS not installed.\n");
+                                       tls_initialized = TRUE;
+                               } else
+                                       ast_log(LOG_ERROR, "gnuTLS not installed. You need to recompile the Iksemel library with gnuTLS support\n");
                                break;
                        }
                        if (!client->usesasl) {
@@ -471,78 +603,59 @@ static int aji_act_hook(void *data, int type, iks *node)
                        break;
 
                case IKS_NODE_NORMAL:
-                       {
-                               int features = 0;
-                               if (!strcmp("stream:features", iks_name(node))) {
-                                       features = iks_stream_features(node);
-                                       if (client->usesasl) {
-                                               if (client->usetls && !iks_is_secure(client->p))
-                                                       break;
-                                               if (client->authorized) {
-                                                       if (features & IKS_STREAM_BIND) {
-                                                               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);
-                                                               auth = iks_make_resource_bind(client->jid);
-                                                               if (auth) {
-                                                                       iks_insert_attrib(auth, "id", client->mid);
-                                                                       ast_aji_increment_mid(client->mid);
-                                                                       iks_send(client->p, auth);
-                                                                       iks_delete(auth);
-                                                               } else {
-                                                                       ast_log(LOG_ERROR, "Out of memory.\n");
-                                                                       break;
-                                                               }
-                                                       }
-                                                       if (features & IKS_STREAM_SESSION) {
-                                                               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);
-                                                               auth = iks_make_session();
-                                                               if (auth) {
-                                                                       iks_insert_attrib(auth, "id", "auth");
-                                                                       ast_aji_increment_mid(client->mid);
-                                                                       iks_send(client->p, auth);
-                                                                       iks_delete(auth);
-                                                               } else {
-                                                                       ast_log(LOG_ERROR, "Out of memory.\n");
-                                                               }
+                       if (!strcmp("stream:features", iks_name(node))) {
+                               features = iks_stream_features(node);
+                               if (client->usesasl) {
+                                       if (client->usetls && !iks_is_secure(client->p))
+                                               break;
+                                       if (client->authorized) {
+                                               if (features & IKS_STREAM_BIND) {
+                                                       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);
+                                                       auth = iks_make_resource_bind(client->jid);
+                                                       if (auth) {
+                                                               iks_insert_attrib(auth, "id", client->mid);
+                                                               ast_aji_increment_mid(client->mid);
+                                                               iks_send(client->p, auth);
+                                                               iks_delete(auth);
+                                                       } else {
+                                                               ast_log(LOG_ERROR, "Out of memory.\n");
+                                                               break;
                                                        }
-                                               } else {
-                                                       features = aji_highest_bit(features);
-                                                       if (features == IKS_STREAM_SASL_MD5)
-                                                               iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, client->jid->user, client->password);
-                                                       else {
-                                                               if (features == IKS_STREAM_SASL_PLAIN) {
-                                                                       iks *x = NULL;
-                                                                       x = iks_new("auth");
-                                                                       if (x) {
-                                                                               iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL);
-                                                                               int len = strlen(client->jid->user) + strlen(client->password) + 3;
-                                                                               /* XXX Check return values XXX */
-                                                                               char *s = ast_malloc(80 + len);
-                                                                               char *base64 = ast_malloc(80 + len * 2);
-                                                                               iks_insert_attrib(x, "mechanism", "PLAIN");
-                                                                               sprintf(s, "%c%s%c%s", 0, client->jid->user, 0, client->password);
-                                                                               ast_base64encode(base64, (const unsigned char *) s, len, len * 2);
-                                                                               iks_insert_cdata(x, base64, 0);
-                                                                               iks_send(client->p, x);
-                                                                               iks_delete(x);
-                                                                               if (base64)
-                                                                                       free(base64);
-                                                                               if (s)
-                                                                                       free(s);
-                                                                       } else {
-                                                                               ast_log(LOG_ERROR, "Out of memory.\n");
-                                                                       }
-                                                               }
+                                               }
+                                               if (features & IKS_STREAM_SESSION) {
+                                                       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);
+                                                       auth = iks_make_session();
+                                                       if (auth) {
+                                                               iks_insert_attrib(auth, "id", "auth");
+                                                               ast_aji_increment_mid(client->mid);
+                                                               iks_send(client->p, auth);
+                                                               iks_delete(auth);
+                                                       } else {
+                                                               ast_log(LOG_ERROR, "Out of memory.\n");
                                                        }
                                                }
+                                       } else {
+                                               int ret;
+                                               if (!client->jid->user) {
+                                                       ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full);
+                                                       break;
+                                               }
+                                               features = aji_highest_bit(features);
+                                               ret = aji_start_sasl(client->p, features, client->jid->user, client->password);
+                                               if (ret != IKS_OK) {
+                                                       ASTOBJ_UNREF(client, aji_client_destroy);
+                                                       return IKS_HOOK;
+                                               }
+                                               break;
                                        }
-                               } else if (!strcmp("failure", iks_name(node))) {
-                                       ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n");
-                               } else if (!strcmp("success", iks_name(node))) {
-                                       client->authorized = 1;
-                                       iks_send_header(client->p, client->jid->server);
                                }
-                               break;
+                       } else if (!strcmp("failure", iks_name(node))) {
+                               ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n");
+                       } else if (!strcmp("success", iks_name(node))) {
+                               client->authorized = 1;
+                               iks_send_header(client->p, client->jid->server);
                        }
+                       break;
                case IKS_NODE_ERROR: 
                                ast_log(LOG_ERROR, "JABBER: Node Error\n");
                                ASTOBJ_UNREF(client, aji_client_destroy);
@@ -554,7 +667,7 @@ static int aji_act_hook(void *data, int type, iks *node)
                                return IKS_HOOK;
                                break;
                }
-       } else if (client->state != AJI_CONNECTED && client->component == AJI_COMPONENT) {
+       } else if (client->state != AJI_CONNECTED && client->component) {
                switch (type) {
                case IKS_NODE_START:
                        if (client->state == AJI_DISCONNECTED) {
@@ -566,10 +679,15 @@ static int aji_act_hook(void *data, int type, iks *node)
                                asprintf(&handshake, "<handshake>%s</handshake>", shasum);
                                if (handshake) {
                                        iks_send_raw(client->p, handshake);
-                                       free(handshake);
+                                       ast_free(handshake);
                                        handshake = NULL;
                                }
-                               client->state = AJI_CONNECTED;
+                               client->state = AJI_CONNECTING;
+                               if(iks_recv(client->p,1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/
+                                       client->state = AJI_CONNECTED;
+                               else
+                                       ast_log(LOG_WARNING,"Jabber didn't seem to handshake, failed to authenicate.\n");
+                               break;
                        }
                        break;
 
@@ -590,32 +708,26 @@ static int aji_act_hook(void *data, int type, iks *node)
 
        switch (pak->type) {
        case IKS_PAK_NONE:
-               if (option_verbose > 4)
-                       ast_verbose(VERBOSE_PREFIX_3 "JABBER: I Don't know what to do with you NONE\n");
+               ast_debug(1, "JABBER: I Don't know what to do with you NONE\n");
                break;
        case IKS_PAK_MESSAGE:
                aji_handle_message(client, pak);
-               if (option_verbose > 4)
-                       ast_verbose(VERBOSE_PREFIX_3 "JABBER: I Don't know what to do with you MESSAGE\n");
+               ast_debug(1, "JABBER: I Don't know what to do with you MESSAGE\n");
                break;
        case IKS_PAK_PRESENCE:
                aji_handle_presence(client, pak);
-               if (option_verbose > 4)
-                       ast_verbose(VERBOSE_PREFIX_3 "JABBER: I Do know how to handle presence!!\n");
+               ast_debug(1, "JABBER: I Do know how to handle presence!!\n");
                break;
        case IKS_PAK_S10N:
                aji_handle_subscribe(client, pak);
-               if (option_verbose > 4)
-                       ast_verbose(VERBOSE_PREFIX_3 "JABBER: I Dont know S10N subscribe!!\n");
+               ast_debug(1, "JABBER: I Dont know S10N subscribe!!\n");
                break;
        case IKS_PAK_IQ:
-               if (option_verbose > 4)
-                       ast_verbose(VERBOSE_PREFIX_3 "JABBER: I Dont have an IQ!!!\n");
+               ast_debug(1, "JABBER: I Dont have an IQ!!!\n");
                aji_handle_iq(client, node);
                break;
        default:
-               if (option_verbose > 4)
-                       ast_verbose(VERBOSE_PREFIX_3 "JABBER: I Dont know %i\n", pak->type);
+               ast_debug(1, "JABBER: I Dont know %i\n", pak->type);
                break;
        }
        
@@ -627,58 +739,98 @@ static int aji_act_hook(void *data, int type, iks *node)
        ASTOBJ_UNREF(client, aji_client_destroy);
        return IKS_OK;
 }
-
+/*!
+ * \brief Uknown
+ * \param data void
+ * \param pak ikspak
+ * \return IKS_FILTER_EAT.
+*/
 static int aji_register_approve_handler(void *data, ikspak *pak)
 {
        struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
-       iks *iq = NULL, *query = NULL, *item = NULL;
+       iks *iq = NULL, *presence = NULL, *x = NULL;
 
        iq = iks_new("iq");
-       query = iks_new("query");
-       item = iks_new("item");
-
-       if (client && iq && query && item) {
+       presence = iks_new("presence");
+       x = iks_new("x");
+       if (client && iq && presence && x) {
                if (!iks_find(pak->query, "remove")) {
                        iks_insert_attrib(iq, "from", client->jid->full);
                        iks_insert_attrib(iq, "to", pak->from->full);
                        iks_insert_attrib(iq, "id", pak->id);
                        iks_insert_attrib(iq, "type", "result");
-                       iks_insert_attrib(query, "xmlns", "jabber:iq:register");
-
-                       iks_insert_node(iq, query);
                        iks_send(client->p, iq);
-                       iks_insert_attrib(iq, "from", pak->from->full);
-                       iks_insert_attrib(iq, "to", pak->from->full);
-                       iks_insert_attrib(iq, "id", client->mid);
+
+                       iks_insert_attrib(presence, "from", client->jid->full);
+                       iks_insert_attrib(presence, "to", pak->from->partial);
+                       iks_insert_attrib(presence, "id", client->mid);
                        ast_aji_increment_mid(client->mid);
-                       iks_insert_attrib(iq, "type", "set");
-                       iks_insert_attrib(query, "xmlns", "jabber:iq:roster");
-                       iks_insert_attrib(item, "subscription", "none");
-                       iks_insert_attrib(item, "jid", client->jid->full);
-                       iks_insert_node(query, item);
-                       iks_send(client->p, iq);
+                       iks_insert_attrib(presence, "type", "subscribe");
+                       iks_insert_attrib(x, "xmlns", "vcard-temp:x:update");
+                       iks_insert_node(presence, x);
+                       iks_send(client->p, presence); 
                }
        } else {
                ast_log(LOG_ERROR, "Out of memory.\n");
        }
+
        if (iq)
                iks_delete(iq);
-       if (query)
-               iks_delete(query);
-       if (item)
-               iks_delete(item);
+       if(presence)
+               iks_delete(presence);
+       if (x)
+               iks_delete(x);
        ASTOBJ_UNREF(client, aji_client_destroy);
        return IKS_FILTER_EAT;
 }
-
+/*!
+ * \brief register query
+ * \param data incoming aji_client request
+ * \param pak ikspak
+ * \return IKS_FILTER_EAT.
+*/
 static int aji_register_query_handler(void *data, ikspak *pak)
 {
        struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
+       struct aji_buddy *buddy = NULL; 
        char *node = NULL;
 
        client = (struct aji_client *) data;
 
-       if (!(node = iks_find_attrib(pak->query, "node"))) {
+       buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
+       if (!buddy) {
+               iks *iq = NULL, *query = NULL, *error = NULL, *notacceptable = NULL;
+
+               ast_verbose("Someone.... %s tried to register but they aren't allowed\n", pak->from->partial);
+               iq = iks_new("iq");
+               query = iks_new("query");
+               error = iks_new("error");
+               notacceptable = iks_new("not-acceptable");
+               if(iq && query && error && notacceptable) {
+                       iks_insert_attrib(iq, "type", "error");
+                       iks_insert_attrib(iq, "from", client->user);
+                       iks_insert_attrib(iq, "to", pak->from->full);
+                       iks_insert_attrib(iq, "id", pak->id);
+                       iks_insert_attrib(query, "xmlns", "jabber:iq:register");
+                       iks_insert_attrib(error, "code" , "406");
+                       iks_insert_attrib(error, "type", "modify");
+                       iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
+                       iks_insert_node(iq, query);
+                       iks_insert_node(iq, error);
+                       iks_insert_node(error, notacceptable);
+                       iks_send(client->p, iq);
+               } else {
+                       ast_log(LOG_ERROR, "Out of memory.\n");
+               }
+               if (iq)
+                       iks_delete(iq);
+               if (query)
+                       iks_delete(query);
+               if (error)
+                       iks_delete(error);
+               if (notacceptable)
+                       iks_delete(notacceptable);
+       } else  if (!(node = iks_find_attrib(pak->query, "node"))) {
                iks *iq = NULL, *query = NULL, *instructions = NULL;
                char *explain = "Welcome to Asterisk - the Open Source PBX.\n";
                iq = iks_new("iq");
@@ -708,6 +860,12 @@ static int aji_register_query_handler(void *data, ikspak *pak)
        return IKS_FILTER_EAT;
 }
 
+/*!
+ * \brief Handles stuff
+ * \param data void
+ * \param pak ikspak 
+ * \return IKS_FILTER_EAT.
+*/
 static int aji_ditems_handler(void *data, ikspak *pak)
 {
        struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
@@ -803,7 +961,12 @@ static int aji_ditems_handler(void *data, ikspak *pak)
        return IKS_FILTER_EAT;
 
 }
-
+/*!
+ * \brief Handle add extra info
+ * \param data void
+ * \param pak ikspak
+ * \return IKS_FILTER_EAT
+*/
 static int aji_client_info_handler(void *data, ikspak *pak)
 {
        struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
@@ -811,7 +974,6 @@ static int aji_client_info_handler(void *data, ikspak *pak)
        struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
 
        resource = aji_find_resource(buddy, pak->from->resource);
-
        if (pak->subtype == IKS_TYPE_RESULT) {
                if (!resource) {
                        ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full);
@@ -863,13 +1025,35 @@ static int aji_client_info_handler(void *data, ikspak *pak)
        ASTOBJ_UNREF(client, aji_client_destroy);
        return IKS_FILTER_EAT;
 }
-
+/*!
+ * \brief Handler of the return info packet
+ * \param data aji_client
+ * \param pak ikspak
+ * \return IKS_FILTER_EAT
+*/
 static int aji_dinfo_handler(void *data, ikspak *pak)
 {
        struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
        char *node = NULL;
+       struct aji_resource *resource = NULL;
+       struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
 
-       if (!(node = iks_find_attrib(pak->query, "node"))) {
+       resource = aji_find_resource(buddy, pak->from->resource);
+       if (pak->subtype == IKS_TYPE_ERROR) {
+               ast_log(LOG_WARNING, "Recieved error from a client, turn on jabber debug!\n");
+               return IKS_FILTER_EAT;
+       }
+       if (pak->subtype == IKS_TYPE_RESULT) {
+               if (!resource) {
+                       ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full);
+                       ASTOBJ_UNREF(client, aji_client_destroy);
+                       return IKS_FILTER_EAT;
+               }
+               if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
+                       resource->cap->jingle = 1;
+               } else
+                       resource->cap->jingle = 0;
+       } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) {
                iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search;
 
                iq = iks_new("iq");
@@ -935,7 +1119,7 @@ static int aji_dinfo_handler(void *data, ikspak *pak)
                if (search)
                        iks_delete(search);
 
-       } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) {
+       } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) {
                iks *iq, *query, *confirm;
                iq = iks_new("iq");
                query = iks_new("query");
@@ -964,7 +1148,7 @@ static int aji_dinfo_handler(void *data, ikspak *pak)
                if (confirm)
                        iks_delete(confirm);
 
-       } else if (!strcasecmp(node, "confirmaccount")) {
+       } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) {
                iks *iq, *query, *feature;
 
                iq = iks_new("iq");
@@ -997,62 +1181,67 @@ static int aji_dinfo_handler(void *data, ikspak *pak)
 }
 
 /*!
- * \brief Handles <iq> tags.
- * \param client structure and the iq node.
+ * \brief Handles \verbatim <iq> \endverbatim tags.
+ * \param client aji_client
+ * \param node iks 
  * \return void.
  */
 static void aji_handle_iq(struct aji_client *client, iks *node)
 {
-       if (option_verbose > 4)
-               ast_verbose("MWAHHAHAHA NOTHING TO SEE HERE!\n");
+       /*Nothing to see here */
 }
 
 /*!
  * \brief Handles presence packets.
- * \param client structure and the node.
- * \return void.
+ * \param client aji_client
+ * \param pak ikspak the node
  */
 static void aji_handle_message(struct aji_client *client, ikspak *pak)
 {
        struct aji_message *insert, *tmp;
        int flag = 0;
        
-       if (!(insert = ast_calloc(1, sizeof(struct aji_message))))
+       if (!(insert = ast_calloc(1, sizeof(*insert))))
                return;
        time(&insert->arrived);
        if (iks_find_cdata(pak->x, "body"))
                insert->message = ast_strdup(iks_find_cdata(pak->x, "body"));
-       if(pak->id)
+       if (pak->id)
                ast_copy_string(insert->id, pak->id, sizeof(insert->message));
-       insert->from = ast_strdup(pak->from->full);
+       if (pak->from)
+               insert->from = ast_strdup(pak->from->full);
        AST_LIST_LOCK(&client->messages);
        AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) {
                if (flag) {
                        AST_LIST_REMOVE_CURRENT(&client->messages, list);
                        if (tmp->from)
-                               free(tmp->from);
+                               ast_free(tmp->from);
                        if (tmp->message)
-                               free(tmp->message);
+                               ast_free(tmp->message);
                } else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) {
                        flag = 1;
                        AST_LIST_REMOVE_CURRENT(&client->messages, list);
                        if (tmp->from)
-                               free(tmp->from);
+                               ast_free(tmp->from);
                        if (tmp->message)
-                               free(tmp->message);
+                               ast_free(tmp->message);
                }
        }
        AST_LIST_TRAVERSE_SAFE_END;
        AST_LIST_INSERT_HEAD(&client->messages, insert, list);
        AST_LIST_UNLOCK(&client->messages);
 }
-
+/*!
+ * \brief Check the presence info
+ * \param client aji_client
+ * \param pak ikspak
+*/
 static void aji_handle_presence(struct aji_client *client, ikspak *pak)
 {
        int status, priority;
        struct aji_buddy *buddy;
        struct aji_resource *tmp = NULL, *last = NULL, *found = NULL;
-       char *ver, *node, *descrip;
+       char *ver, *node, *descrip, *type;
        
        if(client->state != AJI_CONNECTED)
                aji_create_buddy(pak->from->partial, client);
@@ -1062,6 +1251,11 @@ static void aji_handle_presence(struct aji_client *client, ikspak *pak)
                ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial);
                return;
        }
+       type = iks_find_attrib(pak->x, "type");
+       if(client->component && type &&!strcasecmp("probe", type)) {
+               aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), 1, client->statusmessage);
+               ast_verbose("what i was looking for \n");
+       }
        ASTOBJ_WRLOCK(buddy);
        status = (pak->show) ? pak->show : 6;
        priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0");
@@ -1071,7 +1265,7 @@ static void aji_handle_presence(struct aji_client *client, ikspak *pak)
        while (tmp) {
                if (!strcasecmp(tmp->resource, pak->from->resource)) {
                        tmp->status = status;
-                       if (tmp->description) free(tmp->description);
+                       if (tmp->description) ast_free(tmp->description);
                        tmp->description = descrip;
                        found = tmp;
                        if (status == 6) {      /* Sign off Destroy resource */
@@ -1088,7 +1282,7 @@ static void aji_handle_presence(struct aji_client *client, ikspak *pak)
                                        else
                                                buddy->resources = NULL;
                                }
-                               free(found);
+                               ast_free(found);
                                found = NULL;
                                break;
                        }
@@ -1128,8 +1322,7 @@ static void aji_handle_presence(struct aji_client *client, ikspak *pak)
        }
 
        if (!found && status != 6) {
-               found = (struct aji_resource *) malloc(sizeof(struct aji_resource));
-               memset(found, 0, sizeof(struct aji_resource));
+               found = ast_calloc(1, sizeof(*found));
 
                if (!found) {
                        ast_log(LOG_ERROR, "Out of memory!\n");
@@ -1171,8 +1364,9 @@ static void aji_handle_presence(struct aji_client *client, ikspak *pak)
                found->cap = aji_find_version(node, ver, pak);
                if(gtalk_yuck(pak->x)) /* gtalk should do discover */
                        found->cap->jingle = 1;
-               if(found->cap->jingle && option_debug > 4)
-                       ast_log(LOG_DEBUG,"Special case for google till they support discover.\n");
+               if(found->cap->jingle && option_debug > 4) {
+                       ast_debug(1,"Special case for google till they support discover.\n");
+               }
                else {
                        iks *iq, *query;
                        iq = iks_new("iq");
@@ -1180,6 +1374,7 @@ static void aji_handle_presence(struct aji_client *client, ikspak *pak)
                        if(query && iq)  {
                                iks_insert_attrib(iq, "type", "get");
                                iks_insert_attrib(iq, "to", pak->from->full);
+                               iks_insert_attrib(iq,"from",iks_find_attrib(pak->x,"to"));
                                iks_insert_attrib(iq, "id", client->mid);
                                ast_aji_increment_mid(client->mid);
                                iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
@@ -1232,13 +1427,34 @@ static void aji_handle_presence(struct aji_client *client, ikspak *pak)
 
 /*!
  * \brief handles subscription requests.
- * \param aji_client struct and xml packet.
+ * \param client aji_client
+ * \param pak ikspak iksemel packet.
  * \return void.
  */
 static void aji_handle_subscribe(struct aji_client *client, ikspak *pak)
 {
-       if(pak->subtype == IKS_TYPE_SUBSCRIBE)
-               iks_send(client->p, iks_make_s10n(IKS_TYPE_SUBSCRIBED, iks_find_attrib(pak->x, "from"), "Asterisk has approved subscription"));
+       if(pak->subtype == IKS_TYPE_SUBSCRIBE) { 
+               iks *presence = NULL, *status = NULL;
+               presence = iks_new("presence");
+               status = iks_new("status");
+               if(presence && status) {
+                       iks_insert_attrib(presence, "type", "subscribed");
+                       iks_insert_attrib(presence, "to", pak->from->full);
+                       iks_insert_attrib(presence, "from", client->jid->full);
+                       if(pak->id)
+                               iks_insert_attrib(presence, "id", pak->id);
+                       iks_insert_cdata(status, "Asterisk has approved subscription", 0);
+                       iks_insert_node(presence, status);
+                       iks_send(client->p, presence);
+               } else
+                       ast_log(LOG_ERROR, "Unable to allocate nodes\n");
+               if(presence)
+                       iks_delete(presence);
+               if(status)
+                       iks_delete(status);
+               if(client->component)
+                       aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), 1, client->statusmessage);
+       }
        if (option_verbose > 4) {
                switch (pak->subtype) {
                case IKS_TYPE_SUBSCRIBE:
@@ -1262,10 +1478,12 @@ static void aji_handle_subscribe(struct aji_client *client, ikspak *pak)
 
 /*!
  * \brief sends messages.
- * \param aji_client struct , reciever, message.
+ * \param client aji_client 
+ * \param address
+ * \param message
  * \return 1.
  */
-int ast_aji_send(struct aji_client *client, char *address, char *message)
+int ast_aji_send(struct aji_client *client, const char *address, const char *message)
 {
        int res = 0;
        iks *message_packet = NULL;
@@ -1286,7 +1504,10 @@ int ast_aji_send(struct aji_client *client, char *address, char *message)
 
 /*!
  * \brief create a chatroom.
- * \param aji_client struct , room, server, topic for the room.
+ * \param client aji_client
+ * \param room name of room
+ * \param server name of server
+ * \param topic topic for the room.
  * \return 0.
  */
 int ast_aji_create_chat(struct aji_client *client, char *room, char *server, char *topic)
@@ -1307,7 +1528,8 @@ int ast_aji_create_chat(struct aji_client *client, char *room, char *server, cha
 
 /*!
  * \brief join a chatroom.
- * \param aji_client struct , room.
+ * \param client aji_client 
+ * \param room room to join
  * \return res.
  */
 int ast_aji_join_chat(struct aji_client *client, char *room)
@@ -1335,7 +1557,10 @@ int ast_aji_join_chat(struct aji_client *client, char *room)
 
 /*!
  * \brief invite to a chatroom.
- * \param aji_client struct ,user, room, message.
+ * \param client aji_client
+ * \param user 
+ * \param room
+ * \param message
  * \return res.
  */
 int ast_aji_invite_chat(struct aji_client *client, char *user, char *room, char *message)
@@ -1350,7 +1575,7 @@ int ast_aji_invite_chat(struct aji_client *client, char *user, char *room, char
                iks_insert_attrib(invite, "to", user);
                iks_insert_attrib(invite, "id", client->mid);
                ast_aji_increment_mid(client->mid);
-               iks_insert_cdata(body, message, strlen(message));
+               iks_insert_cdata(body, message, 0);
                iks_insert_attrib(namespace, "xmlns", "jabber:x:conference");
                iks_insert_attrib(namespace, "jid", room);
                iks_insert_node(invite, body);
@@ -1370,7 +1595,7 @@ int ast_aji_invite_chat(struct aji_client *client, char *user, char *room, char
 
 /*!
  * \brief receive message loop.
- * \param aji_client struct.
+ * \param data void
  * \return void.
  */
 static void *aji_recv_loop(void *data)
@@ -1388,14 +1613,22 @@ static void *aji_recv_loop(void *data)
                }
 
                res = iks_recv(client->p, 1);
+
+               if (client->state == AJI_DISCONNECTING) {
+                       ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n");
+                       pthread_exit(NULL);
+               }
                client->timeout--;
                if (res == IKS_HOOK) 
                        ast_log(LOG_WARNING, "JABBER: Got hook event.\n");
                else if (res == IKS_NET_TLSFAIL)
                        ast_log(LOG_WARNING, "JABBER:  Failure in TLS.\n");
                else if (client->timeout == 0 && client->state == AJI_CONNECTED) {
-                       res = -1;
-                       ast_log(LOG_WARNING, "JABBER:  Network Timeout\n");
+                       res = iks_send_raw(client->p, " ");
+                       if(res == IKS_OK)
+                               client->timeout = 50;
+                       else
+                               ast_log(LOG_WARNING, "JABBER:  Network Timeout\n");
                } else if (res == IKS_NET_RWERR)
                        ast_log(LOG_WARNING, "JABBER: socket read error\n");
        } while (client);
@@ -1405,7 +1638,7 @@ static void *aji_recv_loop(void *data)
 
 /*!
  * \brief increments the mid field for messages and other events.
- * \param message id.
+ * \param mid char.
  * \return void.
  */
 void ast_aji_increment_mid(char *mid)
@@ -1427,7 +1660,8 @@ void ast_aji_increment_mid(char *mid)
  * \param aji_client struct, and xml packet.
  * \return IKS_FILTER_EAT.
  */
-static int aji_register_transport(void *data, ikspak *pak)
+/*allows for registering to transport , was too sketch and is out for now. */
+/*static int aji_register_transport(void *data, ikspak *pak)
 {
        struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
        int res = 0;
@@ -1458,13 +1692,14 @@ static int aji_register_transport(void *data, ikspak *pak)
        return IKS_FILTER_EAT;
 
 }
-
+*/
 /*!
  * \brief attempts to register to a transport step 2.
  * \param aji_client struct, and xml packet.
  * \return IKS_FILTER_EAT.
  */
-static int aji_register_transport2(void *data, ikspak *pak)
+/* more of the same blob of code, too wonky for now*/
+/* static int aji_register_transport2(void *data, ikspak *pak)
 {
        struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
        int res = 0;
@@ -1488,8 +1723,8 @@ static int aji_register_transport2(void *data, ikspak *pak)
                ast_aji_increment_mid(client->mid);
                iks_insert_attrib(regiq, "from", client->user);
                iks_insert_attrib(regquery, "xmlns", "jabber:iq:register");
-               iks_insert_cdata(reguser, buddy->user, strlen(buddy->user));
-               iks_insert_cdata(regpass, buddy->pass, strlen(buddy->pass));
+               iks_insert_cdata(reguser, buddy->user, 0);
+               iks_insert_cdata(regpass, buddy->pass, 0);
                iks_insert_node(regiq, regquery);
                iks_insert_node(regquery, reguser);
                iks_insert_node(regquery, regpass);
@@ -1507,10 +1742,10 @@ static int aji_register_transport2(void *data, ikspak *pak)
        ASTOBJ_UNREF(client, aji_client_destroy);
        return IKS_FILTER_EAT;
 }
-
+*/
 /*!
  * \brief goes through roster and prunes users not needed in list, or adds them accordingly.
- * \param aji_client struct.
+ * \param client aji_client
  * \return void.
  */
 static void aji_pruneregister(struct aji_client *client)
@@ -1542,17 +1777,8 @@ static void aji_pruneregister(struct aji_client *client)
                                iks_insert_attrib(removeitem, "subscription", "remove");
                                res = iks_send(client->p, removeiq);
                        } else if (ast_test_flag(iterator, AJI_AUTOREGISTER)) {
-                               if (iterator->btype == AJI_USER) {      /*if it is not a transport */
-                                       res = iks_send(client->p, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 
-                                                       "Greetings I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"));
-                               } else {
-                                       iks_filter_add_rule(client->f, aji_register_transport, client,
-                                                                 IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_NS,
-                                                                 "http://jabber.org/protocol/disco#items", IKS_RULE_DONE);
-                                       iks_insert_attrib(send, "to", iterator->host);
-                                       iks_insert_attrib(send, "from", client->jid->full);
-                                       res = iks_send(client->p, send);
-                               }
+                               res = iks_send(client->p, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 
+                                               "Greetings I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"));
                                ast_clear_flag(iterator, AJI_AUTOREGISTER);
                        }
                        ASTOBJ_UNLOCK(iterator);
@@ -1572,7 +1798,8 @@ static void aji_pruneregister(struct aji_client *client)
 
 /*!
  * \brief filters the roster packet we get back from server.
- * \param aji_client struct, and xml packet.
+ * \param data void
+ * \param pak ikspak iksemel packet.
  * \return IKS_FILTER_EAT.
  */
 static int aji_filter_roster(void *data, ikspak *pak)
@@ -1589,16 +1816,9 @@ static int aji_filter_roster(void *data, ikspak *pak)
                flag = 0;
                while (x) {
                        if (!iks_strcmp(iks_name(x), "item")) {
-                               if (!ast_strlen_zero(iterator->pass)) {
-                                       if (!strcasecmp(iterator->host, iks_find_attrib(x, "jid"))) {
-                                                 ast_clear_flag(iterator, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 
-                                                 flag = 1;
-                                       }
-                               } else {
-                                       if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) {
-                                                 flag = 1;
-                                                 ast_clear_flag(iterator, AJI_AUTOPRUNE | AJI_AUTOREGISTER);
-                                       }
+                               if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) {
+                                       flag = 1;
+                                       ast_clear_flag(iterator, AJI_AUTOPRUNE | AJI_AUTOREGISTER);
                                }
                        }
                        x = iks_next(x);
@@ -1616,23 +1836,17 @@ static int aji_filter_roster(void *data, ikspak *pak)
                if (iks_strcmp(iks_name(x), "item") == 0) {
                        ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
                                ASTOBJ_RDLOCK(iterator);
-                               if (!ast_strlen_zero(iterator->pass)) {
-                                       if (!strcasecmp(iterator->host, iks_find_attrib(x, "jid")))
+                               if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid")))
                                        flag = 1;
-                               } else {
-                                       if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid")))
-                                               flag = 1;
-                               }
                                ASTOBJ_UNLOCK(iterator);
                        });
 
                        if (!flag) {
-                               buddy = (struct aji_buddy *) malloc(sizeof(struct aji_buddy));
+                               buddy = ast_calloc(1, sizeof(*buddy));
                                if (!buddy) {
                                        ast_log(LOG_WARNING, "Out of memory\n");
                                        return 0;
                                }
-                               memset(buddy, 0, sizeof(struct aji_buddy));
                                ASTOBJ_INIT(buddy);
                                ASTOBJ_WRLOCK(buddy);
                                ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name));
@@ -1658,37 +1872,39 @@ static int aji_filter_roster(void *data, ikspak *pak)
        ASTOBJ_UNREF(client, aji_client_destroy);
        return IKS_FILTER_EAT;
 }
-
+/*!
+ * \brief reconnect to jabber server
+ * \param client aji_client
+ * \return res.
+*/
 static int aji_reconnect(struct aji_client *client)
 {
        int res = 0;
 
        if (client->state)
                client->state = AJI_DISCONNECTED;
-       client->timeout=20;
+       client->timeout=50;
        if (client->p)
                iks_parser_reset(client->p);
        if (client->authorized)
                client->authorized = 0;
 
-       switch (client->component) {
-       case AJI_COMPONENT:
-               res = aji_component_initialize(client);
-               break;
-       case AJI_CLIENT:
-               res = aji_client_initialize(client);
-               break;
-       }
+       res = aji_initialize(client);
+
        return res;
 }
-
+/*!
+ * \brief Get the roster of jabber users
+ * \param client aji_client
+ * \return 1.
+*/
 static int aji_get_roster(struct aji_client *client)
 {
        iks *roster = NULL;
        roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER);
        if(roster) {
                iks_insert_attrib(roster, "id", "roster");
-               aji_set_presence(client, client->jid->full, 1, client->statusmessage);
+               aji_set_presence(client, NULL, client->jid->full, 1, client->statusmessage);
                iks_send(client->p, roster);
        }
        if (roster)
@@ -1698,7 +1914,8 @@ static int aji_get_roster(struct aji_client *client)
 
 /*!
  * \brief connects as a client to jabber server.
- * \param aji_client struct, and xml packet.
+ * \param data void
+ * \param pak ikspak iksemel packet
  * \return res.
  */
 static int aji_client_connect(void *data, ikspak *pak)
@@ -1712,7 +1929,7 @@ static int aji_client_connect(void *data, ikspak *pak)
                        client->state = AJI_CONNECTING;
                        client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid;
                        iks_filter_remove_hook(client->f, aji_client_connect);
-                       if(client->component == AJI_CLIENT)
+                       if(!client->component) /*client*/
                                aji_get_roster(client);
                }
        } else
@@ -1724,14 +1941,13 @@ static int aji_client_connect(void *data, ikspak *pak)
 
 /*!
  * \brief prepares client for connect.
- * \param aji_client struct.
+ * \param client aji_client
  * \return 1.
  */
-static int aji_client_initialize(struct aji_client *client)
+static int aji_initialize(struct aji_client *client)
 {
-       int connected = 0;
-
-       connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->jid->server);
+       /* If it's a component, connect to user, otherwise, connect to server */
+       int connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server);
 
        if (connected == IKS_NET_NOCONN) {
                ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
@@ -1739,32 +1955,14 @@ static int aji_client_initialize(struct aji_client *client)
        } else  if (connected == IKS_NET_NODNS) {
                ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to  %s\n", client->name, S_OR(client->serverhost, client->jid->server));
                return IKS_HOOK;
-       } else
+       } else /* if (!connected) phsultan: check if this is needed! */
                iks_recv(client->p, 30);
        return IKS_OK;
 }
 
 /*!
- * \brief prepares component for connect.
- * \param aji_client struct.
- * \return 1.
- */
-static int aji_component_initialize(struct aji_client *client)
-{
-       int connected = 1;
-       connected = iks_connect_via(client->p, client->jid->server, client->port, client->user);
-       if (connected == IKS_NET_NOCONN)
-               ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
-       else if (connected == IKS_NET_NODNS)
-               ast_log(LOG_ERROR, "JABBER ERROR: No DNS\n");
-       else if (!connected)
-               iks_recv(client->p, 30);
-       return 1;
-}
-
-/*!
  * \brief disconnect from jabber server.
- * \param aji_client struct.
+ * \param client aji_client
  * \return 1.
  */
 int ast_aji_disconnect(struct aji_client *client)
@@ -1782,10 +1980,14 @@ int ast_aji_disconnect(struct aji_client *client)
 
 /*!
  * \brief set presence of client.
- * \param aji_client struct, user to send it to, level, description.
+ * \param client aji_client
+ * \param to user send it to
+ * \param from user it came from
+ * \param level
+ * \param desc
  * \return void.
  */
-static void aji_set_presence(struct aji_client *client, char *user, int level, char *desc)
+static void aji_set_presence(struct aji_client *client, char *to, char *from, int level, char *desc)
 {
        int res = 0;
        iks *presence = iks_make_pres(level, desc);
@@ -1794,6 +1996,10 @@ static void aji_set_presence(struct aji_client *client, char *user, int level, c
 
        iks_insert_cdata(priority, "0", 1);
        if (presence && cnode && client) {
+               if(to)
+                       iks_insert_attrib(presence, "to", to);
+               if(from)
+                       iks_insert_attrib(presence, "from", from);
                iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps");
                iks_insert_attrib(cnode, "ver", "asterisk-xmpp");
                iks_insert_attrib(cnode, "ext", "voice-v1");
@@ -1810,7 +2016,9 @@ static void aji_set_presence(struct aji_client *client, char *user, int level, c
 
 /*!
  * \brief turnon console debugging.
- * \param fd, number of args, args.
+ * \param fd
+ * \param argc Integer. Number of args
+ * \param argv List of arguements
  * \return RESULT_SUCCESS.
  */
 static int aji_do_debug(int fd, int argc, char *argv[])
@@ -1826,7 +2034,9 @@ static int aji_do_debug(int fd, int argc, char *argv[])
 
 /*!
  * \brief reload jabber module.
- * \param fd, number of args, args.
+ * \param fd
+ * \param argc no of args
+ * \param argv list of arguements
  * \return RESULT_SUCCESS.
  */
 static int aji_do_reload(int fd, int argc, char *argv[])
@@ -1838,7 +2048,9 @@ static int aji_do_reload(int fd, int argc, char *argv[])
 
 /*!
  * \brief turnoff console debugging.
- * \param fd, number of args, args.
+ * \param fd
+ * \param argc Integer. number of args
+ * \param argv list of arguements
  * \return RESULT_SUCCESS.
  */
 static int aji_no_debug(int fd, int argc, char *argv[])
@@ -1854,7 +2066,9 @@ static int aji_no_debug(int fd, int argc, char *argv[])
 
 /*!
  * \brief show client status.
- * \param fd, number of args, args.
+ * \param fd
+ * \param argc Integer. number of args
+ * \param argv list of arguements
  * \return RESULT_SUCCESS.
  */
 static int aji_show_clients(int fd, int argc, char *argv[])
@@ -1888,8 +2102,10 @@ static int aji_show_clients(int fd, int argc, char *argv[])
 
 /*!
  * \brief send test message for debugging.
- * \param fd, number of args, args.
- * \return RESULT_SUCCESS.
+ * \param fd
+ * \param argc Integer. number of args
+ * \param argv list of arguements
+ * \return RESULT_SUCCESS,RESULT_FAILURE.
  */
 static int aji_test(int fd, int argc, char *argv[])
 {
@@ -1908,7 +2124,7 @@ static int aji_test(int fd, int argc, char *argv[])
                return RESULT_FAILURE;
        }
 
-       /* XXX Does Matt really want everyone to use his personal address for tests? */
+       /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */
        ast_aji_send(client, "mogorman@astjab.org", "blahblah");
        ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
                ASTOBJ_RDLOCK(iterator);
@@ -1939,7 +2155,9 @@ static int aji_test(int fd, int argc, char *argv[])
 
 /*!
  * \brief creates aji_client structure.
- * \param label, ast_variable, debug, pruneregister, component/client, aji_client to dump into. 
+ * \param label
+ * \param var ast_variable
+ * \param debug 
  * \return 0.
  */
 static int aji_create_client(char *label, struct ast_variable *var, int debug)
@@ -1951,12 +2169,11 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
        client = ASTOBJ_CONTAINER_FIND(&clients,label);
        if (!client) {
                flag = 1;
-               client = (struct aji_client *) malloc(sizeof(struct aji_client));
+               client = ast_calloc(1, sizeof(*client));
                if (!client) {
                        ast_log(LOG_ERROR, "Out of memory!\n");
                        return 0;
                }
-               memset(client, 0, sizeof(struct aji_client));
                ASTOBJ_INIT(client);
                ASTOBJ_WRLOCK(client);
                ASTOBJ_CONTAINER_INIT(&client->buddies);
@@ -1968,6 +2185,7 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
        ast_copy_string(client->name, label, sizeof(client->name));
        ast_copy_string(client->mid, "aaaaa", sizeof(client->mid));
 
+       /* Set default values for the client object */
        client->debug = debug;
        ast_copy_flags(client, &globalflags, AST_FLAGS_ALL);
        client->port = 5222;
@@ -1975,10 +2193,10 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
        client->usesasl = 1;
        client->forcessl = 0;
        client->keepalive = 1;
-       client->timeout = 20;
+       client->timeout = 50;
        client->message_timeout = 100;
        AST_LIST_HEAD_INIT(&client->messages);
-       client->component = AJI_CLIENT;
+       client->component = 0;
        ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage));
 
        if (flag) {
@@ -2002,7 +2220,7 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
                        client->debug = (ast_false(var->value)) ? 0 : 1;
                else if (!strcasecmp(var->name, "type")) {
                        if (!strcasecmp(var->value, "component"))
-                               client->component = AJI_COMPONENT;
+                               client->component = 1;
                } else if (!strcasecmp(var->name, "usetls")) {
                        client->usetls = (ast_false(var->value)) ? 0 : 1;
                } else if (!strcasecmp(var->name, "usesasl")) {
@@ -2017,8 +2235,10 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
                        ast_set2_flag(client, ast_true(var->value), AJI_AUTOREGISTER);
                else if (!strcasecmp(var->name, "buddy"))
                                aji_create_buddy(var->value, client);
-               else if (!strcasecmp(var->name, "transport"))
+       /* no transport support in this version */
+       /*      else if (!strcasecmp(var->name, "transport"))
                                aji_create_transport(var->value, client);
+       */
                var = var->next;
        }
        if (!flag) {
@@ -2026,7 +2246,7 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
                ASTOBJ_UNREF(client, aji_client_destroy);
                return 1;
        }
-       client->p = iks_stream_new(((client->component == AJI_CLIENT) ? "jabber:client" : "jabber:component:accept"), client, aji_act_hook);
+       client->p = iks_stream_new(((client->component) ? "jabber:component:accept" : "jabber:client"), client, aji_act_hook);
        if (!client->p) {
                ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name);
                return 0;
@@ -2041,16 +2261,16 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
                ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name);
                return 0;
        }
-       if (!strchr(client->user, '/') && client->component == AJI_CLIENT) {
+       if (!strchr(client->user, '/') && !client->component) { /*client */
                resource = NULL;
                asprintf(&resource, "%s/asterisk", client->user);
                if (resource) {
                        client->jid = iks_id_new(client->stack, resource);
-                       free(resource);
+                       ast_free(resource);
                }
        } else
                client->jid = iks_id_new(client->stack, client->user);
-       if (client->component == AJI_COMPONENT) {
+       if (client->component) {
                iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
                iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE);
                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);
@@ -2058,12 +2278,12 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
        } else {
                iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
        }
-       if (!strchr(client->user, '/') && client->component == AJI_CLIENT) {
+       if (!strchr(client->user, '/') && !client->component) { /*client */
                resource = NULL;
                asprintf(&resource, "%s/asterisk", client->user);
                if (resource) {
                        client->jid = iks_id_new(client->stack, resource);
-                       free(resource);
+                       ast_free(resource);
                }
        } else
                client->jid = iks_id_new(client->stack, client->user);
@@ -2078,6 +2298,8 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
  * \param label, buddy to dump it into. 
  * \return 0.
  */
+/* no connecting to transports today */
+/*
 static int aji_create_transport(char *label, struct aji_client *client)
 {
        char *server = NULL, *buddyname = NULL, *user = NULL, *pass = NULL;
@@ -2085,12 +2307,11 @@ static int aji_create_transport(char *label, struct aji_client *client)
 
        buddy = ASTOBJ_CONTAINER_FIND(&client->buddies,label);
        if (!buddy) {
-               buddy = malloc(sizeof(struct aji_buddy));
+               buddy = ast_calloc(1, sizeof(*buddy));
                if(!buddy) {
                        ast_log(LOG_WARNING, "Out of memory\n");
                        return 0;
                }
-               memset(buddy, 0, sizeof(struct aji_buddy));
                ASTOBJ_INIT(buddy);
        }
        ASTOBJ_WRLOCK(buddy);
@@ -2121,11 +2342,13 @@ static int aji_create_transport(char *label, struct aji_client *client)
        ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
        return 0;
 }
+*/
 
 /*!
  * \brief creates buddy.
- * \param label, buddy to dump it into. 
- * \return 0.
+ * \param label char.
+ * \param client aji_client buddy to dump it into. 
+ * \return 1 on success, 0 on failure.
  */
 static int aji_create_buddy(char *label, struct aji_client *client)
 {
@@ -2134,12 +2357,11 @@ static int aji_create_buddy(char *label, struct aji_client *client)
        buddy = ASTOBJ_CONTAINER_FIND(&client->buddies,label);
        if (!buddy) {
                flag = 1;
-               buddy = malloc(sizeof(struct aji_buddy));
+               buddy = ast_calloc(1, sizeof(*buddy));
                if(!buddy) {
                        ast_log(LOG_WARNING, "Out of memory\n");
                        return 0;
                }
-               memset(buddy, 0, sizeof(struct aji_buddy));
                ASTOBJ_INIT(buddy);
        }
        ASTOBJ_WRLOCK(buddy);
@@ -2154,11 +2376,7 @@ static int aji_create_buddy(char *label, struct aji_client *client)
        return 1;
 }
 
-/*!
- * \brief load config file.
- * \param void. 
- * \return 1.
- */
+/*!< load config file. \return 1. */
 static int aji_load_config(void)
 {
        char *cat = NULL;
@@ -2166,6 +2384,9 @@ static int aji_load_config(void)
        struct ast_config *cfg = NULL;
        struct ast_variable *var = NULL;
 
+       /* Reset flags to default value */
+       ast_set_flag(&globalflags, AJI_AUTOPRUNE | AJI_AUTOREGISTER);
+
        cfg = ast_config_load(JABBER_CONFIG);
        if (!cfg) {
                ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG);
@@ -2194,10 +2415,10 @@ static int aji_load_config(void)
 
 /*!
  * \brief grab a aji_client structure by label name.
- * \param void. 
- * \return 1.
+ * \param name label name 
+ * \return aji_client.
  */
-struct aji_client *ast_aji_get_client(char *name)
+struct aji_client *ast_aji_get_client(const char *name)
 {
        struct aji_client *client = NULL;
 
@@ -2219,14 +2440,19 @@ static char mandescr_jabber_send[] =
 "  ScreenName: User Name to message.\n"
 "  Message:    Message to be sent to the buddy\n";
 
-/*! \brief  Send a Jabber Message via call from the Manager */
-static int manager_jabber_send( struct mansession *s, struct message *m )
+/*! 
+ * \brief  Send a Jabber Message via call from the Manager 
+ * \param s mansession Manager session
+ * \param m message Message to send
+ * \return  0
+*/
+static int manager_jabber_send(struct mansession *s, const struct message *m)
 {
        struct aji_client *client = NULL;
-       char *id = astman_get_header(m,"ActionID");
-       char *jabber = astman_get_header(m,"Jabber");
-       char *screenname = astman_get_header(m,"ScreenName");
-       char *message = astman_get_header(m,"Message");
+       const char *id = astman_get_header(m,"ActionID");
+       const char *jabber = astman_get_header(m,"Jabber");
+       const char *screenname = astman_get_header(m,"ScreenName");
+       const char *message = astman_get_header(m,"Message");
 
        if (ast_strlen_zero(jabber)) {
                astman_send_error(s, m, "No transport specified");
@@ -2260,36 +2486,51 @@ static int manager_jabber_send( struct mansession *s, struct message *m )
        return 0;
 }
 
-
-static void aji_reload()
+/*! \brief Reload the jabber module */
+static int aji_reload()
 {
        ASTOBJ_CONTAINER_MARKALL(&clients);
-       if (!aji_load_config())
+       if (!aji_load_config()) {
                ast_log(LOG_ERROR, "JABBER: Failed to load config.\n");
-       else {
-               ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy);
-               ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
-                       ASTOBJ_RDLOCK(iterator);
-                       if(iterator->state == AJI_DISCONNECTED) {
-                               if (!iterator->thread)
-                                       ast_pthread_create(&iterator->thread, NULL, aji_recv_loop, iterator);
-                       } else if (iterator->state == AJI_CONNECTING)
-                               aji_get_roster(iterator);
-                       ASTOBJ_UNLOCK(iterator);
-               });
+               return 0;
        }
+       ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy);
+       ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
+               ASTOBJ_RDLOCK(iterator);
+               if(iterator->state == AJI_DISCONNECTED) {
+                       if (!iterator->thread)
+                               ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator);
+               } else if (iterator->state == AJI_CONNECTING)
+                       aji_get_roster(iterator);
+               ASTOBJ_UNLOCK(iterator);
+       });
+       
+       return 1;
 }
 
-static int unload_module(void *mod)
+/*! \brief Unload the jabber module */
+static int unload_module(void)
 {
-       ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(aji_cli[0]));
+
+       /* Check if TLS is initialized. If that's the case, we can't unload this
+          module due to a bug in the iksemel library that will cause a crash or
+          a deadlock. We're trying to find a way to handle this, but in the meantime
+          we will simply refuse to die... 
+        */
+       if (tls_initialized) {
+               ast_log(LOG_ERROR, "Module can't be unloaded due to a bug in the Iksemel library when using TLS.\n");
+               return 1;       /* You need a forced unload to get rid of this module */
+       }
+
+       ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
        ast_unregister_application(app_ajisend);
+       ast_unregister_application(app_ajistatus);
        ast_manager_unregister("JabberSend");
+       
        ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
                ASTOBJ_RDLOCK(iterator);
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3 "JABBER: %s\n", iterator->name);
-               iterator->state = AJI_DISCONNECTED;
+               ast_debug(3, "JABBER: Releasing and disconneing client: %s\n", iterator->name);
+               iterator->state = AJI_DISCONNECTING;
                ast_aji_disconnect(iterator);
                pthread_join(iterator->thread, NULL);
                ASTOBJ_UNLOCK(iterator);
@@ -2297,39 +2538,33 @@ static int unload_module(void *mod)
 
        ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy);
        ASTOBJ_CONTAINER_DESTROY(&clients);
-
-       ast_log(LOG_NOTICE, "res_jabber unloaded.\n");
        return 0;
 }
 
-static int load_module(void *mod)
+/*! \brief Unload the jabber module */
+static int load_module(void)
 {
        ASTOBJ_CONTAINER_INIT(&clients);
-       aji_reload();
+       if(!aji_reload())
+               return AST_MODULE_LOAD_DECLINE;
        ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send,
                        "Sends a message to a Jabber Client", mandescr_jabber_send);
        ast_register_application(app_ajisend, aji_send_exec, ajisend_synopsis, ajisend_descrip);
        ast_register_application(app_ajistatus, aji_status_exec, ajistatus_synopsis, ajistatus_descrip);
-       ast_cli_register_multiple(aji_cli, sizeof(aji_cli) / sizeof(aji_cli[0]));
+       ast_cli_register_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
 
-       ast_log(LOG_NOTICE, "res_jabber.so loaded.\n");
        return 0;
 }
 
-static int reload(void *mod)
+/*! \brief Wrapper for aji_reload */
+static int reload(void)
 {
        aji_reload();
        return 0;
 }
 
-static const char *description(void)
-{
-       return tdesc;
-}
-
-static const char *key(void)
-{
-       return ASTERISK_GPL_KEY;
-}
-
-STD_MOD(MOD_0, reload, NULL, NULL);
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "AJI - Asterisk Jabber Interface",
+               .load = load_module,
+               .unload = unload_module,
+               .reload = reload,
+              );