Fix a crash as a result of propagating MWI or device state over XMPP when the client...
authorJoshua Colp <jcolp@digium.com>
Tue, 17 Jul 2012 16:32:10 +0000 (16:32 +0000)
committerJoshua Colp <jcolp@digium.com>
Tue, 17 Jul 2012 16:32:10 +0000 (16:32 +0000)
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
res/res_xmpp.c

index 1bac900..d0c2570 100644 (file)
@@ -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 */
 };
 
 /*!
index 91be7af..9ac788e 100644 (file)
@@ -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);