[asterisk-commits] file: branch file/res_xmpp r369039 - in /team/file/res_xmpp: include/asterisk...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Jun 16 15:47:41 CDT 2012


Author: file
Date: Sat Jun 16 15:47:36 2012
New Revision: 369039

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=369039
Log:
Convert to using the new configuration options API. Still needs more testing but seems to work so far!

Modified:
    team/file/res_xmpp/include/asterisk/xmpp.h
    team/file/res_xmpp/res/res_xmpp.c

Modified: team/file/res_xmpp/include/asterisk/xmpp.h
URL: http://svnview.digium.com/svn/asterisk/team/file/res_xmpp/include/asterisk/xmpp.h?view=diff&rev=369039&r1=369038&r2=369039
==============================================================================
--- team/file/res_xmpp/include/asterisk/xmpp.h (original)
+++ team/file/res_xmpp/include/asterisk/xmpp.h Sat Jun 16 15:47:36 2012
@@ -115,15 +115,9 @@
 /*! \brief XMPP Client Connection */
 struct ast_xmpp_client {
         AST_DECLARE_STRING_FIELDS(
-                AST_STRING_FIELD(name);        /*!< Name of the client connection */
-                AST_STRING_FIELD(user);        /*!< Username to use for authentication */
-                AST_STRING_FIELD(password);    /*!< Password to use for authentication */
-                AST_STRING_FIELD(server);      /*!< Server hostname */
-                AST_STRING_FIELD(statusmsg);   /*!< Status message for presence */
-                AST_STRING_FIELD(pubsubnode);  /*!< Pubsub node */
+                AST_STRING_FIELD(name); /*!< Name of the client configuration */
                 );
         char mid[6]; /* Message ID */
-        char context[AST_MAX_CONTEXT]; /*!< Context for incoming messages */
         iksid *jid;
         iksparser *parser;
         iksfilter *filter;
@@ -135,16 +129,11 @@
         unsigned int stream_flags;
 #endif /* HAVE_OPENSSL */
         enum xmpp_state state;
-        int port;
-        int timeout;
-        int message_timeout;
-        struct ast_flags flags;
         struct ao2_container *buddies;
         AST_LIST_HEAD(, ast_xmpp_message) messages;
         pthread_t thread;
-        int priority;
-        enum ikshowtype status;
-        unsigned int destroy:1;
+	int timeout;
+	unsigned int reconnect:1; /*!< Reconnect this client */
 };
 
 /*!

Modified: team/file/res_xmpp/res/res_xmpp.c
URL: http://svnview.digium.com/svn/asterisk/team/file/res_xmpp/res/res_xmpp.c?view=diff&rev=369039&r1=369038&r2=369039
==============================================================================
--- team/file/res_xmpp/res/res_xmpp.c (original)
+++ team/file/res_xmpp/res/res_xmpp.c Sat Jun 16 15:47:36 2012
@@ -52,6 +52,7 @@
 #include "asterisk/manager.h"
 #include "asterisk/event.h"
 #include "asterisk/cli.h"
+#include "asterisk/config_options.h"
 
 /*** DOCUMENTATION
 	<application name="JabberSend" language="en_US">
@@ -314,31 +315,55 @@
 /*! \brief Status for a disappearing buddy */
 #define STATUS_DISAPPEAR 6
 
-/*! \brief Container for configured XMPP client connections */
-static struct ao2_container *clients;
-
-/*! \brief Enabled general configuration flags */
-static struct ast_flags generalflags = { XMPP_AUTOREGISTER | XMPP_AUTOACCEPT | XMPP_USETLS | XMPP_USESASL | XMPP_KEEPALIVE };
-
-/*! \brief Enabled pubsub configuration flags */
-static struct ast_flags pubsubflags = { 0 };
-
 /*! \brief Global debug status */
 static int debug;
 
-static int xmpp_client_request_tls(struct ast_xmpp_client *client, int type, iks *node);
-static int xmpp_client_requested_tls(struct ast_xmpp_client *client, int type, iks *node);
-static int xmpp_client_authenticate(struct ast_xmpp_client *client, int type, iks *node);
-static int xmpp_client_authenticating(struct ast_xmpp_client *client, int type, iks *node);
-
-static int xmpp_component_authenticate(struct ast_xmpp_client *client, int type, iks *node);
-static int xmpp_component_authenticating(struct ast_xmpp_client *client, int type, iks *node);
+/*! \brief XMPP Global Configuration */
+struct ast_xmpp_global_config {
+	struct ast_flags general; /*!< General configuration options */
+	struct ast_flags pubsub;  /*!< Pubsub related configuration options */
+};
+
+/*! \brief XMPP Client Configuration */
+struct ast_xmpp_client_config {
+        AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(name);        /*!< Name of the client connection */
+		AST_STRING_FIELD(user);        /*!< Username to use for authentication */
+		AST_STRING_FIELD(password);    /*!< Password to use for authentication */
+		AST_STRING_FIELD(server);      /*!< Server hostname */
+		AST_STRING_FIELD(statusmsg);   /*!< Status message for presence */
+		AST_STRING_FIELD(pubsubnode);  /*!< Pubsub node */
+		AST_STRING_FIELD(context);     /*!< Context for incoming messages */
+		);
+	int port;                       /*!< Port to use when connecting to server */
+	int message_timeout;            /*!< Timeout for messages */
+	int priority;                   /*!< Resource priority */
+	struct ast_flags flags;         /*!< Various options that have been set */
+	enum ikshowtype status;         /*!< Presence status */
+	struct ast_xmpp_client *client; /*!< Pointer to the client */
+	struct ao2_container *buddies;  /*!< Configured buddies */
+};
+
+struct xmpp_config {
+	struct ast_xmpp_global_config *global; /*!< Global configuration options */
+	struct ao2_container *clients;         /*!< Configured clients */
+};
+
+static AO2_GLOBAL_OBJ_STATIC(globals);
+
+static int xmpp_client_request_tls(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node);
+static int xmpp_client_requested_tls(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node);
+static int xmpp_client_authenticate(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node);
+static int xmpp_client_authenticating(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node);
+
+static int xmpp_component_authenticate(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node);
+static int xmpp_component_authenticating(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node);
 
 /*! \brief Defined handlers for XMPP client states */
 static const struct xmpp_state_handler {
 	int state;
 	int component;
-	int (*handler)(struct ast_xmpp_client *client, int type, iks *node);
+	int (*handler)(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node);
 } xmpp_state_handlers[] = {
 	{ XMPP_STATE_REQUEST_TLS, 0, xmpp_client_request_tls, },
 	{ XMPP_STATE_REQUESTED_TLS, 0, xmpp_client_requested_tls, },
@@ -348,14 +373,14 @@
 	{ XMPP_STATE_AUTHENTICATING, 1, xmpp_component_authenticating, },
 };
 
-static int xmpp_pak_message(struct ast_xmpp_client *client, iks *node, ikspak *pak);
-static int xmpp_pak_presence(struct ast_xmpp_client *client, iks *node, ikspak *pak);
-static int xmpp_pak_s10n(struct ast_xmpp_client *client, iks *node, ikspak *pak);
+static int xmpp_pak_message(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak);
+static int xmpp_pak_presence(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak);
+static int xmpp_pak_s10n(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak);
 
 /*! \brief Defined handlers for different PAK types */
 static const struct xmpp_pak_handler {
 	int type;
-	int (*handler)(struct ast_xmpp_client *client, iks *node, ikspak *pak);
+	int (*handler)(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak);
 } xmpp_pak_handlers[] = {
 	{ IKS_PAK_MESSAGE, xmpp_pak_message, },
 	{ IKS_PAK_PRESENCE, xmpp_pak_presence, },
@@ -374,6 +399,17 @@
 static ast_cond_t message_received_condition;
 static ast_mutex_t messagelock;
 
+static int xmpp_client_config_post_apply(void *obj, void *arg, int flags);
+
+/*! \brief Destructor function for configuration */
+static void ast_xmpp_client_config_destructor(void *obj)
+{
+	struct ast_xmpp_client_config *cfg = obj;
+	ast_string_field_free_memory(cfg);
+	ao2_cleanup(cfg->client);
+	ao2_cleanup(cfg->buddies);
+}
+
 /*! \brief Destroy function for XMPP messages */
 static void xmpp_message_destroy(struct ast_xmpp_message *message)
 {
@@ -387,6 +423,258 @@
 	ast_free(message);
 }
 
+/*! \brief Destructor callback function for XMPP client */
+static void xmpp_client_destructor(void *obj)
+{
+	struct ast_xmpp_client *client = obj;
+	struct ast_xmpp_message *message;
+
+	ast_xmpp_client_disconnect(client);
+
+	if (client->stack) {
+		iks_stack_delete(client->stack);
+	}
+
+	ao2_cleanup(client->buddies);
+
+	while ((message = AST_LIST_REMOVE_HEAD(&client->messages, list))) {
+		xmpp_message_destroy(message);
+	}
+	AST_LIST_HEAD_DESTROY(&client->messages);
+}
+
+/*! \brief Hashing function for XMPP buddy */
+static int xmpp_buddy_hash(const void *obj, const int flags)
+{
+	const struct ast_xmpp_buddy *buddy = obj;
+	const char *id = obj;
+
+	return ast_str_hash(flags & OBJ_KEY ? id : buddy->id);
+}
+
+/*! \brief Comparator function for XMPP buddy */
+static int xmpp_buddy_cmp(void *obj, void *arg, int flags)
+{
+	struct ast_xmpp_buddy *buddy1 = obj, *buddy2 = arg;
+	const char *id = arg;
+
+	return !strcmp(buddy1->id, flags & OBJ_KEY ? id : buddy2->id) ? CMP_MATCH | CMP_STOP : 0;
+}
+
+/*! \brief Allocator function for ast_xmpp_client */
+static struct ast_xmpp_client *xmpp_client_alloc(const char *name)
+{
+	struct ast_xmpp_client *client;
+
+	if (!(client = ao2_alloc(sizeof(*client), xmpp_client_destructor))) {
+		return NULL;
+	}
+
+	AST_LIST_HEAD_INIT(&client->messages);
+	client->thread = AST_PTHREADT_NULL;
+
+	if (!(client->buddies = ao2_container_alloc(BUDDY_BUCKETS, xmpp_buddy_hash, xmpp_buddy_cmp))) {
+		ast_log(LOG_ERROR, "Could not initialize buddy container for '%s'\n", name);
+		ao2_ref(client, -1);
+		return NULL;
+	}
+
+	if (ast_string_field_init(client, 512)) {
+		ast_log(LOG_ERROR, "Could not initialize stringfields for '%s'\n", name);
+		ao2_ref(client, -1);
+		return NULL;
+	}
+
+	if (!(client->stack = iks_stack_new(8192, 8192))) {
+		ast_log(LOG_ERROR, "Could not create an Iksemel stack for '%s'\n", name);
+		ao2_ref(client, -1);
+		return NULL;
+	}
+
+	ast_string_field_set(client, name, name);
+
+	client->timeout = 50;
+	client->state = XMPP_STATE_DISCONNECTED;
+	ast_copy_string(client->mid, "aaaaa", sizeof(client->mid));
+
+	return client;
+}
+
+/*! \brief Find function for configuration */
+static void *xmpp_config_find(struct ao2_container *tmp_container, const char *category)
+{
+	return ao2_find(tmp_container, category, OBJ_KEY);
+}
+
+/*! \brief Look up existing client or create a new one */
+static void *xmpp_client_find_or_create(const char *category)
+{
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
+
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, category))) {
+		return xmpp_client_alloc(category);
+	}
+ 
+	ao2_ref(clientcfg->client, +1);
+	return clientcfg->client;
+}
+
+/*! \brief Allocator function for configuration */
+static void *ast_xmpp_client_config_alloc(const char *cat)
+{
+	struct ast_xmpp_client_config *cfg;
+
+	if (!(cfg = ao2_alloc(sizeof(*cfg), ast_xmpp_client_config_destructor))) {
+		return NULL;
+	}
+
+	if (ast_string_field_init(cfg, 512)) {
+		ao2_ref(cfg, -1);
+		return NULL;
+	}
+
+	if (!(cfg->client = xmpp_client_find_or_create(cat))) {
+		ao2_ref(cfg, -1);
+		return NULL;
+	}
+
+	if (!(cfg->buddies = ao2_container_alloc(BUDDY_BUCKETS, xmpp_buddy_hash, xmpp_buddy_cmp))) {
+		ao2_ref(cfg, -1);
+		return NULL;
+	}
+
+	ast_string_field_set(cfg, name, cat);
+
+	return cfg;
+}
+
+/*! \brief Destructor for XMPP configuration */
+static void xmpp_config_destructor(void *obj)
+{
+	struct xmpp_config *cfg = obj;
+	ao2_cleanup(cfg->global);
+	ao2_cleanup(cfg->clients);
+}
+
+/*! \brief Hashing function for configuration */
+static int xmpp_config_hash(const void *obj, const int flags)
+{
+	const struct ast_xmpp_client_config *cfg = obj;
+	const char *name = (flags & OBJ_KEY) ? obj : cfg->name;
+	return ast_str_case_hash(name);
+}
+
+/*! \brief Comparator function for configuration */
+static int xmpp_config_cmp(void *obj, void *arg, int flags)
+{
+	struct ast_xmpp_client_config *one = obj, *two = arg;
+	const char *match = (flags & OBJ_KEY) ? arg : two->name;
+	return strcasecmp(one->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
+}
+
+/*! \brief Allocator for XMPP configuration */
+static void *xmpp_config_alloc(void)
+{
+	struct xmpp_config *cfg;
+
+	if (!(cfg = ao2_alloc(sizeof(*cfg), xmpp_config_destructor))) {
+		return NULL;
+	}
+
+	if (!(cfg->global = ao2_alloc(sizeof(*cfg->global), NULL))) {
+		goto error;
+	}
+
+	ast_set_flag(&cfg->global->general, XMPP_AUTOREGISTER | XMPP_AUTOACCEPT | XMPP_USETLS | XMPP_USESASL | XMPP_KEEPALIVE);
+
+	if (!(cfg->clients = ao2_container_alloc(1, xmpp_config_hash, xmpp_config_cmp))) {
+		goto error;
+	}
+
+	return cfg;
+error:
+	ao2_ref(cfg, -1);
+	return NULL;
+}
+
+static int xmpp_config_prelink(void *newitem)
+{
+	struct ast_xmpp_client_config *clientcfg = newitem;
+        RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+        RAII_VAR(struct ast_xmpp_client_config *, oldclientcfg, NULL, ao2_cleanup);
+
+	if (ast_strlen_zero(clientcfg->user)) {
+		ast_log(LOG_ERROR, "No user specified on client '%s'\n", clientcfg->name);
+		return -1;
+	} else if (ast_strlen_zero(clientcfg->password)) {
+		ast_log(LOG_ERROR, "No password specified on client '%s'\n", clientcfg->name);
+		return -1;
+	} else if (ast_strlen_zero(clientcfg->server)) {
+		ast_log(LOG_ERROR, "No server specified on client '%s'\n", clientcfg->name);
+		return -1;
+	}
+
+	/* If this is a new connection force a reconnect */
+	if (!cfg || !cfg->clients || !(oldclientcfg = xmpp_config_find(cfg->clients, clientcfg->name))) {
+		clientcfg->client->reconnect = 1;
+		return 0;
+	}
+
+	/* If any configuration options are changing that would require reconnecting set the bit so we will do so if possible */
+	if (strcmp(clientcfg->user, oldclientcfg->user) ||
+	    strcmp(clientcfg->password, oldclientcfg->password) ||
+	    strcmp(clientcfg->server, oldclientcfg->server) ||
+	    (clientcfg->port != oldclientcfg->port) ||
+	    (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT) != ast_test_flag(&oldclientcfg->flags, XMPP_COMPONENT)) ||
+	    (clientcfg->priority != oldclientcfg->priority)) {
+		clientcfg->client->reconnect = 1;
+	} else {
+		clientcfg->client->reconnect = 0;
+	}
+
+	return 0;
+}
+
+static void xmpp_config_post_apply(void)
+{
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+
+	ao2_callback(cfg->clients, OBJ_NODATA | OBJ_MULTIPLE, xmpp_client_config_post_apply, NULL);
+}
+
+static struct aco_type global_option = {
+	.type = ACO_GLOBAL,
+	.item_offset = offsetof(struct xmpp_config, global),
+	.category_match = ACO_WHITELIST,
+	.category = "^general$",
+};
+
+struct aco_type *global_options[] = ACO_TYPES(&global_option);
+
+static struct aco_type client_option = {
+	.type = ACO_ITEM,
+	.category_match = ACO_BLACKLIST,
+	.category = "^(general)$",
+	.item_alloc = ast_xmpp_client_config_alloc,
+	.item_find = xmpp_config_find,
+	.item_prelink = xmpp_config_prelink,
+	.item_offset = offsetof(struct xmpp_config, clients),
+};
+
+struct aco_type *client_options[] = ACO_TYPES(&client_option);
+
+struct aco_file res_xmpp_conf = {
+        .filename = "xmpp.conf",
+	.alias = "jabber.conf",
+        .types = ACO_TYPES(&global_option, &client_option),
+};
+
+CONFIG_INFO_STANDARD(cfg_info, globals, xmpp_config_alloc,
+		     .files = ACO_FILES(&res_xmpp_conf),
+		     .post_apply_config = xmpp_config_post_apply,
+	);
+
 /*! \brief Destructor callback function for XMPP resource */
 static void xmpp_resource_destructor(void *obj)
 {
@@ -422,64 +710,6 @@
 	if (buddy->resources) {
 		ao2_ref(buddy->resources, -1);
 	}
-}
-
-/*! \brief Hashing function for XMPP buddy */
-static int xmpp_buddy_hash(const void *obj, const int flags)
-{
-	const struct ast_xmpp_buddy *buddy = obj;
-	const char *id = obj;
-
-	return ast_str_hash(flags & OBJ_KEY ? id : buddy->id);
-}
-
-/*! \brief Comparator function for XMPP buddy */
-static int xmpp_buddy_cmp(void *obj, void *arg, int flags)
-{
-	struct ast_xmpp_buddy *buddy1 = obj, *buddy2 = arg;
-	const char *id = arg;
-
-	return !strcmp(buddy1->id, flags & OBJ_KEY ? id : buddy2->id) ? CMP_MATCH | CMP_STOP : 0;
-}
-
-/*! \brief Destructor callback function for XMPP client */
-static void xmpp_client_destructor(void *obj)
-{
-	struct ast_xmpp_client *client = obj;
-	struct ast_xmpp_message *message;
-
-	ast_xmpp_client_disconnect(client);
-
-	if (client->stack) {
-		iks_stack_delete(client->stack);
-	}
-
-	if (client->buddies) {
-		ao2_ref(client->buddies, -1);
-	}
-
-	while ((message = AST_LIST_REMOVE_HEAD(&client->messages, list))) {
-		xmpp_message_destroy(message);
-	}
-	AST_LIST_HEAD_DESTROY(&client->messages);
-}
-
-/*! \brief Hashing function for XMPP client */
-static int xmpp_client_hash(const void *obj, const int flags)
-{
-	const struct ast_xmpp_client *client = obj;
-	const char *name = obj;
-
-	return ast_str_hash(flags & OBJ_KEY ? name : client->name);
-}
-
-/*! \brief Comparator function for XMPP client */
-static int xmpp_client_cmp(void *obj, void *arg, int flags)
-{
-	struct ast_xmpp_client *client1 = obj, *client2 = arg;
-	const char *name = arg;
-
-	return !strcmp(client1->name, flags & OBJ_KEY ? name : client2->name) ? CMP_MATCH | CMP_STOP : 0;
 }
 
 /*! \brief Helper function which returns whether an XMPP client connection is secure or not */
@@ -494,7 +724,15 @@
 
 struct ast_xmpp_client *ast_xmpp_client_find(const char *name)
 {
-	return ao2_find(clients, name, OBJ_KEY);
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
+
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
+		return NULL;
+	}
+
+	ao2_ref(clientcfg->client, +1);
+	return clientcfg->client;
 }
 
 void ast_xmpp_client_unref(struct ast_xmpp_client *client)
@@ -515,15 +753,18 @@
 /*! \brief Internal function used to send a message to a user or chatroom */
 static int xmpp_client_send_message(struct ast_xmpp_client *client, int group, const char *nick, const char *address, const char *message)
 {
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	int res = 0;
 	char from[XMPP_MAX_JIDLEN];
 	iks *message_packet;
 
-	if (!(message_packet = iks_make_msg(group ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message))) {
-		return -1;
-	}
-
-	if (!ast_strlen_zero(nick) && ast_test_flag(&client->flags, XMPP_COMPONENT)) {
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
+	    !(message_packet = iks_make_msg(group ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message))) {
+		return -1;
+	}
+
+	if (!ast_strlen_zero(nick) && ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
 		snprintf(from, sizeof(from), "%s@%s/%s", nick, client->jid->full, nick);
 	} else {
 		snprintf(from, sizeof(from), "%s", client->jid->full);
@@ -576,16 +817,19 @@
 
 static int xmpp_client_set_group_presence(struct ast_xmpp_client *client, const char *room, int level, const char *nick)
 {
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	int res = 0;
-	iks *presence, *x = NULL;
+	iks *presence = NULL, *x = NULL;
 	char from[XMPP_MAX_JIDLEN], roomid[XMPP_MAX_JIDLEN];
 
-	if (!(presence = iks_make_pres(level, NULL)) || !(x = iks_new("x"))) {
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
+	    !(presence = iks_make_pres(level, NULL)) || !(x = iks_new("x"))) {
 		res = -1;
 		goto done;
 	}
 
-	if (ast_test_flag(&client->flags, XMPP_COMPONENT)) {
+	if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
 		snprintf(from, sizeof(from), "%s@%s/%s", nick, client->jid->full, nick);
 		snprintf(roomid, sizeof(roomid), "%s/%s", room, nick);
 	} else {
@@ -644,14 +888,17 @@
  */
 static iks* xmpp_pubsub_iq_create(struct ast_xmpp_client *client, const char *type)
 {
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	iks *request;
 
-	if (!(request = iks_new("iq"))) {
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
+	    !(request = iks_new("iq"))) {
 		return NULL;
 	}
 
 
-	iks_insert_attrib(request, "to", client->pubsubnode);
+	iks_insert_attrib(request, "to", clientcfg->pubsubnode);
 	iks_insert_attrib(request, "from", client->jid->full);
 	iks_insert_attrib(request, "type", type);
 	ast_xmpp_client_lock(client);
@@ -672,16 +919,17 @@
 static iks* xmpp_pubsub_build_publish_skeleton(struct ast_xmpp_client *client, const char *node,
 					       const char *event_type)
 {
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
 	iks *request, *pubsub, *publish, *item;
 
-	if (!(request = xmpp_pubsub_iq_create(client, "set"))) {
+	if (!cfg || !cfg->global || !(request = xmpp_pubsub_iq_create(client, "set"))) {
 		return NULL;
 	}
 
 	pubsub = iks_insert(request, "pubsub");
 	iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
 	publish = iks_insert(pubsub, "publish");
-	iks_insert_attrib(publish, "node", ast_test_flag(&pubsubflags, XMPP_XEP0248) ? node : event_type);
+	iks_insert_attrib(publish, "node", ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248) ? node : event_type);
 	item = iks_insert(publish, "item");
 	iks_insert_attrib(item, "id", node);
 
@@ -883,15 +1131,16 @@
 static void xmpp_pubsub_publish_device_state(struct ast_xmpp_client *client, const char *device,
 					     const char *device_state)
 {
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
 	iks *request, *state;
 	char eid_str[20];
 
-	if (!(request = xmpp_pubsub_build_publish_skeleton(client, device, "device_state"))) {
+	if (!cfg || !cfg->global || !(request = xmpp_pubsub_build_publish_skeleton(client, device, "device_state"))) {
 		return;
 	}
 
-	if (ast_test_flag(&pubsubflags, XMPP_PUBSUB_AUTOCREATE)) {
-		if (ast_test_flag(&pubsubflags, XMPP_XEP0248)) {
+	if (ast_test_flag(&cfg->global->pubsub, XMPP_PUBSUB_AUTOCREATE)) {
+		if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
 			xmpp_pubsub_create_node(client, "leaf", device, "device_state");
 		} else {
 			xmpp_pubsub_create_node(client, NULL, device, NULL);
@@ -964,10 +1213,11 @@
  */
 static void xmpp_pubsub_subscribe(struct ast_xmpp_client *client, const char *node)
 {
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
 	iks *request = xmpp_pubsub_iq_create(client, "set");
 	iks *pubsub, *subscribe;
 
-	if (!request) {
+	if (!cfg || !cfg->global || !request) {
 		ast_log(LOG_ERROR, "Could not create IQ when creating pubsub subscription on client '%s'\n", client->name);
 		return;
 	}
@@ -977,7 +1227,7 @@
 	subscribe = iks_insert(pubsub, "subscribe");
 	iks_insert_attrib(subscribe, "jid", client->jid->partial);
 	iks_insert_attrib(subscribe, "node", node);
-	if (ast_test_flag(&pubsubflags, XMPP_XEP0248)) {
+	if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
 		iks *options, *x, *sub_options, *sub_type, *sub_depth;
 		options = iks_insert(pubsub, "options");
 		x = iks_insert(options, "x");
@@ -1055,10 +1305,16 @@
 
 static int xmpp_pubsub_handle_error(void *data, ikspak *pak)
 {
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
 	char *node_name, *error;
 	int error_num;
 	iks *orig_request, *orig_pubsub = iks_find(pak->x, "pubsub");
 	struct ast_xmpp_client *client = data;
+
+	if (!cfg || !cfg->global) {
+		ast_log(LOG_ERROR, "No global configuration available\n");
+		return IKS_FILTER_EAT;
+	}
 
 	if (!orig_pubsub) {
 		ast_log(LOG_ERROR, "Error isn't a PubSub error, why are we here?\n");
@@ -1085,7 +1341,7 @@
 	if (!strcasecmp(iks_name(orig_request), "publish")) {
 		iks *request;
 
-		if (ast_test_flag(&pubsubflags, XMPP_XEP0248)) {
+		if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
 			if (iks_find(iks_find(orig_request, "item"), "state")) {
 				xmpp_pubsub_create_leaf(client, "device_state", node_name);
 			} else if (iks_find(iks_find(orig_request, "item"), "mailbox")) {
@@ -1105,7 +1361,7 @@
 
 		return IKS_FILTER_EAT;
 	} else if (!strcasecmp(iks_name(orig_request), "subscribe")) {
-		if (ast_test_flag(&pubsubflags, XMPP_XEP0248)) {
+		if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
 			xmpp_pubsub_create_collection(client, node_name);
 		} else {
 			xmpp_pubsub_create_node(client, NULL, node_name, NULL);
@@ -1122,6 +1378,13 @@
  */
 static void xmpp_init_event_distribution(struct ast_xmpp_client *client)
 {
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
+
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
+		return;
+	}
+
 	if (!mwi_sub) {
 		mwi_sub = ast_event_subscribe(AST_EVENT_MWI, xmpp_pubsub_mwi_cb, "xmpp_pubsub_mwi_subscription",
 					      client, AST_EVENT_IE_END);
@@ -1138,7 +1401,7 @@
 	xmpp_pubsub_subscribe(client, "device_state");
 	xmpp_pubsub_subscribe(client, "message_waiting");
 	iks_filter_add_rule(client->filter, xmpp_pubsub_handle_event, client, IKS_RULE_TYPE,
-			    IKS_PAK_MESSAGE, IKS_RULE_FROM, client->pubsubnode, IKS_RULE_DONE);
+			    IKS_PAK_MESSAGE, IKS_RULE_FROM, clientcfg->pubsubnode, IKS_RULE_DONE);
 	iks_filter_add_rule(client->filter, xmpp_pubsub_handle_error, client, IKS_RULE_TYPE,
 			    IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE);
 
@@ -1161,7 +1424,8 @@
  */
 static int xmpp_status_exec(struct ast_channel *chan, const char *data)
 {
-	struct ast_xmpp_client *client;
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	struct ast_xmpp_buddy *buddy;
 	struct ast_xmpp_resource *resource;
 	char *s = NULL, status[2];
@@ -1199,14 +1463,13 @@
 		return -1;
 	}
 
-	if (!(client = ao2_find(clients, args.sender, OBJ_KEY))) {
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
 		ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender);
 		return -1;
 	}
 
-	if (!(buddy = ao2_find(client->buddies, jid.screenname, OBJ_KEY))) {
+	if (!(buddy = ao2_find(clientcfg->client->buddies, jid.screenname, OBJ_KEY))) {
 		ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname);
-		ao2_ref(client, -1);
 		return -1;
 	}
 
@@ -1215,7 +1478,6 @@
 	}
 
 	ao2_ref(buddy, -1);
-	ao2_ref(client, -1);
 
 	if (resource) {
 		stat = resource->status;
@@ -1241,7 +1503,8 @@
  */
 static int acf_jabberstatus_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
 {
-	struct ast_xmpp_client *client;
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	struct ast_xmpp_buddy *buddy;
 	struct ast_xmpp_resource *resource;
 	int stat = 7;
@@ -1271,14 +1534,13 @@
 		return -1;
 	}
 
-	if (!(client = ao2_find(clients, args.sender, OBJ_KEY))) {
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
 		ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender);
 		return -1;
 	}
 
-	if (!(buddy = ao2_find(client->buddies, jid.screenname, OBJ_KEY))) {
+	if (!(buddy = ao2_find(clientcfg->client->buddies, jid.screenname, OBJ_KEY))) {
 		ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname);
-		ao2_ref(client, -1);
 		return -1;
 	}
 
@@ -1287,7 +1549,6 @@
 	}
 
 	ao2_ref(buddy, -1);
-	ao2_ref(client, -1);
 
 	if (resource) {
 		stat = resource->status;
@@ -1315,7 +1576,8 @@
  */
 static int xmpp_join_exec(struct ast_channel *chan, const char *data)
 {
-	struct ast_xmpp_client *client;
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	char *s, nick[XMPP_MAX_RESJIDLEN];
 	AST_DECLARE_APP_ARGS(args,
 			     AST_APP_ARG(sender);
@@ -1340,28 +1602,26 @@
 		return -1;
 	}
 
-	if (!(client = ao2_find(clients, args.sender, OBJ_KEY))) {
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
 		ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
 		return -1;
 	}
 
 	if (ast_strlen_zero(args.nick)) {
-		if (ast_test_flag(&client->flags, XMPP_COMPONENT)) {
+		if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
 			snprintf(nick, sizeof(nick), "asterisk");
 		} else {
-			snprintf(nick, sizeof(nick), "%s", client->jid->user);
+			snprintf(nick, sizeof(nick), "%s", clientcfg->client->jid->user);
 		}
 	} else {
 		snprintf(nick, sizeof(nick), "%s", args.nick);
 	}
 
 	if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) {
-		ast_xmpp_chatroom_join(client, args.jid, nick);
+		ast_xmpp_chatroom_join(clientcfg->client, args.jid, nick);
 	} else {
 		ast_log(LOG_ERROR, "Problem with specified jid of '%s'\n", args.jid);
 	}
-
-	ao2_ref(client, -1);
 
 	return 0;
 }
@@ -1375,7 +1635,8 @@
  */
 static int xmpp_leave_exec(struct ast_channel *chan, const char *data)
 {
-	struct ast_xmpp_client *client;
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	char *s, nick[XMPP_MAX_RESJIDLEN];
 	AST_DECLARE_APP_ARGS(args,
 			     AST_APP_ARG(sender);
@@ -1405,24 +1666,22 @@
 		return -1;
 	}
 
-	if (!(client = ao2_find(clients, args.sender, OBJ_KEY))) {
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
 		ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
 		return -1;
 	}
 
 	if (ast_strlen_zero(args.nick)) {
-		if (ast_test_flag(&client->flags, XMPP_COMPONENT)) {
+		if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
 			snprintf(nick, sizeof(nick), "asterisk");
 		} else {
-			snprintf(nick, sizeof(nick), "%s", client->jid->user);
+			snprintf(nick, sizeof(nick), "%s", clientcfg->client->jid->user);
 		}
 	} else {
 		snprintf(nick, sizeof(nick), "%s", args.nick);
 	}
 
-	ast_xmpp_chatroom_leave(client, args.jid, nick);
-
-	ao2_ref(client, -1);
+	ast_xmpp_chatroom_leave(clientcfg->client, args.jid, nick);
 
 	return 0;
 }
@@ -1437,7 +1696,8 @@
  */
 static int xmpp_send_exec(struct ast_channel *chan, const char *data)
 {
-	struct ast_xmpp_client *client;
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	char *s;
 	AST_DECLARE_APP_ARGS(args,
 			     AST_APP_ARG(sender);
@@ -1458,14 +1718,12 @@
 		return -1;
 	}
 
-	if (!(client = ao2_find(clients, args.sender, OBJ_KEY))) {
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
 		ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender);
 		return -1;
 	}
 
-	ast_xmpp_client_send_message(client, args.recipient, args.message);
-
-	ao2_ref(client, -1);
+	ast_xmpp_client_send_message(clientcfg->client, args.recipient, args.message);
 
 	return 0;
 }
@@ -1479,7 +1737,8 @@
  */
 static int xmpp_sendgroup_exec(struct ast_channel *chan, const char *data)
 {
-	struct ast_xmpp_client *client;
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	char *s, nick[XMPP_MAX_RESJIDLEN];
 	AST_DECLARE_APP_ARGS(args,
 			     AST_APP_ARG(sender);
@@ -1500,24 +1759,22 @@
 		return -1;
 	}
 
-	if (!(client = ao2_find(clients, args.sender, OBJ_KEY))) {
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
 		ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
 		return -1;
 	}
 
 	if (ast_strlen_zero(args.nick) || args.argc == 3) {
-		if (ast_test_flag(&client->flags, XMPP_COMPONENT)) {
+		if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
 			snprintf(nick, sizeof(nick), "asterisk");
 		} else {
-			snprintf(nick, sizeof(nick), "%s", client->jid->user);
+			snprintf(nick, sizeof(nick), "%s", clientcfg->client->jid->user);
 		}
 	} else {
 		snprintf(nick, sizeof(nick), "%s", args.nick);
 	}
 
-	ast_xmpp_chatroom_send(client, nick, args.groupchat, args.message);
-
-	ao2_ref(client, -1);
+	ast_xmpp_chatroom_send(clientcfg->client, nick, args.groupchat, args.message);
 
 	return 0;
 }
@@ -1533,11 +1790,12 @@
  */
 static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
 {
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	char *aux = NULL, *parse = NULL;
 	int timeout, jidlen, resourcelen, found = 0;
 	struct timeval start;
 	long diff = 0;
-	struct ast_xmpp_client *client;
 	struct ast_xmpp_message *message;
 	AST_DECLARE_APP_ARGS(args,
 			     AST_APP_ARG(account);
@@ -1582,7 +1840,7 @@
 	jidlen = strlen(jid.screenname);
 	resourcelen = ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource);
 
-	if (!(client = ao2_find(clients, args.account, OBJ_KEY))) {
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.account))) {
 		ast_log(LOG_WARNING, "Could not find client %s, exiting\n", args.account);
 		return -1;
 	}
@@ -1593,7 +1851,6 @@
 
 	if (ast_autoservice_start(chan) < 0) {
 		ast_log(LOG_WARNING, "Cannot start autoservice for channel %s\n", ast_channel_name(chan));
-		ao2_ref(client, -1);
 		return -1;
 	}
 
@@ -1617,8 +1874,8 @@
 			break;
 		}
 
-		AST_LIST_LOCK(&client->messages);
-		AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, message, list) {
+		AST_LIST_LOCK(&clientcfg->client->messages);
+		AST_LIST_TRAVERSE_SAFE_BEGIN(&clientcfg->client->messages, message, list) {
 			if (jid.argc == 1) {
 				/* no resource provided, compare bare JIDs */
 				if (strncasecmp(jid.screenname, message->from, jidlen)) {
@@ -1640,7 +1897,7 @@
 				}
 			}
 			/* check if the message is not too old */
-			if (ast_tvdiff_sec(ast_tvnow(), message->arrived) >= client->message_timeout) {
+			if (ast_tvdiff_sec(ast_tvnow(), message->arrived) >= clientcfg->message_timeout) {
 				ast_debug(3, "Found old message from %s, deleting it\n", message->from);
 				AST_LIST_REMOVE_CURRENT(list);
 				xmpp_message_destroy(message);
@@ -1653,7 +1910,7 @@
 			break;
 		}
 		AST_LIST_TRAVERSE_SAFE_END;
-		AST_LIST_UNLOCK(&client->messages);
+		AST_LIST_UNLOCK(&clientcfg->client->messages);
 		if (found) {
 			break;
 		}
@@ -1661,8 +1918,6 @@
 		/* check timeout */
 		diff = ast_tvdiff_ms(ast_tvnow(), start);
 	}
-
-	ao2_ref(client, -1);
 
 	if (ast_autoservice_stop(chan) < 0) {
 		ast_log(LOG_WARNING, "Cannot stop autoservice for channel %s\n", ast_channel_name(chan));
@@ -1693,8 +1948,14 @@
  */
 static int delete_old_messages(struct ast_xmpp_client *client, char *from)
 {
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	int deleted = 0, isold = 0;
 	struct ast_xmpp_message *message = NULL;
+
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
+		return 0;
+	}
 
 	AST_LIST_LOCK(&client->messages);
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, message, list) {
@@ -1704,7 +1965,7 @@
 				xmpp_message_destroy(message);
 				deleted++;
 			}
-		} else if (ast_tvdiff_sec(ast_tvnow(), message->arrived) >= client->message_timeout) {
+		} else if (ast_tvdiff_sec(ast_tvnow(), message->arrived) >= clientcfg->message_timeout) {
 			isold = 1;
 			if (!from || !strncasecmp(from, message->from, strlen(from))) {
 				AST_LIST_REMOVE_CURRENT(list);
@@ -1721,7 +1982,8 @@
 
 static int xmpp_send_cb(const struct ast_msg *msg, const char *to, const char *from)
 {
-	struct ast_xmpp_client *client;
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	char *sender, *dest;
 	int res;
 
@@ -1735,18 +1997,16 @@
 		return -1;
 	}
 
-	if (!(client = ao2_find(clients, sender, OBJ_KEY))) {
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, sender))) {
 		ast_log(LOG_WARNING, "Could not finder account to send from as '%s'\n", sender);
 		return -1;
 	}
 
-	ast_debug(1, "Sending message to '%s' from '%s'\n", dest, client->name);
-
-	if ((res = ast_xmpp_client_send_message(client, dest, ast_msg_get_body(msg))) != IKS_OK) {
+	ast_debug(1, "Sending message to '%s' from '%s'\n", dest, clientcfg->name);
+
+	if ((res = ast_xmpp_client_send_message(clientcfg->client, dest, ast_msg_get_body(msg))) != IKS_OK) {
 		ast_log(LOG_WARNING, "Failed to send XMPP message (%d).\n", res);
 	}
-
-	ao2_ref(client, -1);
 
 	return res == IKS_OK ? 0 : -1;
 }
@@ -1763,7 +2023,7 @@
 }
 
 /*! \brief Internal function which creates a buddy on a client */
-static struct ast_xmpp_buddy *xmpp_client_create_buddy(struct ast_xmpp_client *client, const char *id)
+static struct ast_xmpp_buddy *xmpp_client_create_buddy(struct ao2_container *container, const char *id)
 {
 	struct ast_xmpp_buddy *buddy;
 
@@ -1781,7 +2041,7 @@
 	/* Assume we need to subscribe to get their presence until proven otherwise */
 	buddy->subscribe = 1;
 
-	ao2_link(client->buddies, buddy);
+	ao2_link(container, buddy);
 
 	return buddy;
 }
@@ -1847,9 +2107,15 @@
 /*! \brief Hook function called when roster is received from server */
 static int xmpp_roster_hook(void *data, ikspak *pak)
 {
+	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
 	struct ast_xmpp_client *client = data;
 	iks *item;
 
+	if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
+		return IKS_FILTER_EAT;
+	}
+
 	for (item = iks_child(pak->query); item; item = iks_next(item)) {
 		struct ast_xmpp_buddy *buddy;
 
@@ -1858,7 +2124,7 @@
 		}
 
 		if (!(buddy = ao2_find(client->buddies, iks_find_attrib(item, "jid"), OBJ_KEY))) {
-			if (ast_test_flag(&client->flags, XMPP_AUTOPRUNE)) {
+			if (ast_test_flag(&clientcfg->flags, XMPP_AUTOPRUNE)) {
 				/* The buddy has not been specified in the configuration file, we no longer
 				 * want them on our buddy list or to receive their presence. */
 				if (xmpp_client_unsubscribe_user(client, iks_find_attrib(item, "jid"))) {
@@ -1868,7 +2134,7 @@
 				continue;
 			}
 
-			if (!(buddy = xmpp_client_create_buddy(client, iks_find_attrib(item, "jid")))) {
+			if (!(buddy = xmpp_client_create_buddy(client->buddies, iks_find_attrib(item, "jid")))) {
 				ast_log(LOG_ERROR, "Could not allocate buddy '%s' on client '%s'\n", iks_find_attrib(item, "jid"),
 					client->name);
 				continue;
@@ -1887,7 +2153,7 @@
 	}
 
 	/* If autoregister is enabled we need to go through every buddy that we need to subscribe to and do so */
-	if (ast_test_flag(&client->flags, XMPP_AUTOREGISTER)) {
+	if (ast_test_flag(&clientcfg->flags, XMPP_AUTOREGISTER)) {
 		ao2_callback(client->buddies, OBJ_NODATA | OBJ_MULTIPLE, xmpp_client_subscribe_user, client);
 	}
 
@@ -1899,10 +2165,13 @@
 /*! \brief Internal function which changes the presence status of an XMPP client */

[... 1250 lines stripped ...]



More information about the asterisk-commits mailing list