[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