From 44345b097337614bbfa5a080f745a770b6e04581 Mon Sep 17 00:00:00 2001 From: Joshua Colp Date: Tue, 17 Jul 2012 16:32:10 +0000 Subject: [PATCH] Fix a crash as a result of propagating MWI or device state over XMPP when the client is disconnected. The MWI and device state propagation code wrongly assumes that an XMPP client connection will remain established at all times. This fix corrects that by making the lifetime of the subscription the same as the lifetime of the connection itself. As the connection is established and disconnected the subscription itself is created and destroyed. (closes issue ASTERISK-18078) Reported by: elguero git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@370152 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- include/asterisk/xmpp.h | 2 ++ res/res_xmpp.c | 55 +++++++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/include/asterisk/xmpp.h b/include/asterisk/xmpp.h index 1bac900429..d0c25707fb 100644 --- a/include/asterisk/xmpp.h +++ b/include/asterisk/xmpp.h @@ -134,6 +134,8 @@ struct ast_xmpp_client { pthread_t thread; int timeout; unsigned int reconnect:1; /*!< Reconnect this client */ + struct ast_event_sub *mwi_sub; /*!< If distributing event information the MWI subscription */ + struct ast_event_sub *device_state_sub; /*!< If distributing event information the device state subscription */ }; /*! diff --git a/res/res_xmpp.c b/res/res_xmpp.c index 91be7afbdd..9ac788e603 100644 --- a/res/res_xmpp.c +++ b/res/res_xmpp.c @@ -387,9 +387,6 @@ static const char *app_ajistatus = "JabberStatus"; static const char *app_ajijoin = "JabberJoin"; static const char *app_ajileave = "JabberLeave"; -static struct ast_event_sub *mwi_sub = NULL; -static struct ast_event_sub *device_state_sub = NULL; - static ast_cond_t message_received_condition; static ast_mutex_t messagelock; @@ -1379,18 +1376,24 @@ static void xmpp_init_event_distribution(struct ast_xmpp_client *client) 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); + if (!(client->mwi_sub = ast_event_subscribe(AST_EVENT_MWI, xmpp_pubsub_mwi_cb, "xmpp_pubsub_mwi_subscription", + client, AST_EVENT_IE_END))) { + return; } - if (!device_state_sub) { - if (ast_enable_distributed_devstate()) { - return; - } - device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE, - xmpp_pubsub_devstate_cb, "xmpp_pubsub_devstate_subscription", client, AST_EVENT_IE_END); - ast_event_dump_cache(device_state_sub); + + if (ast_enable_distributed_devstate()) { + return; } + + + if (!(client->device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE, + xmpp_pubsub_devstate_cb, "xmpp_pubsub_devstate_subscription", client, AST_EVENT_IE_END))) { + ast_event_unsubscribe(client->mwi_sub); + client->mwi_sub = NULL; + return; + } + + ast_event_dump_cache(client->device_state_sub); xmpp_pubsub_subscribe(client, "device_state"); xmpp_pubsub_subscribe(client, "message_waiting"); @@ -3278,18 +3281,30 @@ static int xmpp_action_hook(void *data, int type, iks *node) int ast_xmpp_client_disconnect(struct ast_xmpp_client *client) { - if (client->thread != AST_PTHREADT_NULL) { + if ((client->thread != AST_PTHREADT_NULL) && !pthread_equal(pthread_self(), client->thread)) { client->state = XMPP_STATE_DISCONNECTING; pthread_join(client->thread, NULL); client->thread = AST_PTHREADT_NULL; } + if (client->mwi_sub) { + ast_event_unsubscribe(client->mwi_sub); + client->mwi_sub = NULL; + } + + if (client->device_state_sub) { + ast_event_unsubscribe(client->device_state_sub); + client->device_state_sub = NULL; + } + #ifdef HAVE_OPENSSL if (client->stream_flags & SECURE) { SSL_shutdown(client->ssl_session); SSL_CTX_free(client->ssl_context); SSL_free(client->ssl_session); } + + client->stream_flags = 0; #endif if (client->parser) { @@ -3318,11 +3333,8 @@ static int xmpp_client_reconnect(struct ast_xmpp_client *client) return -1; } -#ifdef HAVE_OPENSSL - client->stream_flags = 0; -#endif + ast_xmpp_client_disconnect(client); - client->state = XMPP_STATE_DISCONNECTED; client->timeout = 50; iks_parser_reset(client->parser); @@ -3459,6 +3471,7 @@ static void *xmpp_client_thread(void *data) ast_debug(3, "Connecting client '%s'\n", client->name); if ((res = xmpp_client_reconnect(client)) != IKS_OK) { sleep(4); + res = IKS_NET_RWERR; } continue; } @@ -4141,12 +4154,6 @@ static int unload_module(void) ast_unregister_application(app_ajileave); ast_manager_unregister("JabberSend"); ast_custom_function_unregister(&jabberstatus_function); - if (mwi_sub) { - ast_event_unsubscribe(mwi_sub); - } - if (device_state_sub) { - ast_event_unsubscribe(device_state_sub); - } ast_custom_function_unregister(&jabberreceive_function); ast_cond_destroy(&message_received_condition);