Fix race condition where duplicated requests may be handled by multiple threads.
authorMark Michelson <mmichelson@digium.com>
Fri, 14 Nov 2014 14:40:17 +0000 (14:40 +0000)
committerMark Michelson <mmichelson@digium.com>
Fri, 14 Nov 2014 14:40:17 +0000 (14:40 +0000)
This is the Asterisk 13 version of the patch. The main difference is in the pubsub
code since it was completely refactored between Asterisk 12 and 13.

Review: https://reviewboard.asterisk.org/r/4175
........

Merged revisions 427841 from http://svn.asterisk.org/svn/asterisk/branches/13

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427842 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/res_pjsip.h
res/res_pjsip.c
res/res_pjsip_pubsub.c
res/res_pjsip_session.c

index 1c21c1e..0c8d303 100644 (file)
@@ -1227,8 +1227,9 @@ pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
  *
  * \param endpoint A pointer to the endpoint
  * \param rdata The request that is starting the dialog
+ * \param[out] status On failure, the reason for failure in creating the dialog
  */
-pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
+pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status);
 
 /*!
  * \brief General purpose method for creating an rdata structure using specific information
index d350cdb..510be6d 100644 (file)
@@ -2250,12 +2250,13 @@ pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
        return dlg;
 }
 
-pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
+pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
 {
        pjsip_dialog *dlg;
        pj_str_t contact;
        pjsip_transport_type_e type = rdata->tp_info.transport->key.type;
-       pj_status_t status;
+
+       ast_assert(status != NULL);
 
        contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
        contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE,
@@ -2268,11 +2269,11 @@ pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint,
                        (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
                        (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
 
-       status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, &contact, &dlg);
-       if (status != PJ_SUCCESS) {
+       *status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, &contact, &dlg);
+       if (*status != PJ_SUCCESS) {
                char err[PJ_ERR_MSG_SIZE];
 
-               pj_strerror(status, err, sizeof(err));
+               pj_strerror(*status, err, sizeof(err));
                ast_log(LOG_ERROR, "Could not create dialog with endpoint %s. %s\n",
                                ast_sorcery_object_get_id(endpoint), err);
                return NULL;
index 4a1076d..344bda3 100644 (file)
@@ -1230,6 +1230,7 @@ static struct sip_subscription_tree *allocate_subscription_tree(struct ast_sip_e
  * \param resource The requested resource in the SUBSCRIBE request
  * \param generator The body generator to use in leaf subscriptions
  * \param tree The resource tree on which the subscription tree is based
+ * \param dlg_status[out] The result of attempting to create a dialog.
  *
  * \retval NULL Could not create the subscription tree
  * \retval non-NULL The root of the created subscription tree
@@ -1237,7 +1238,8 @@ static struct sip_subscription_tree *allocate_subscription_tree(struct ast_sip_e
 
 static struct sip_subscription_tree *create_subscription_tree(const struct ast_sip_subscription_handler *handler,
                struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *resource,
-               struct ast_sip_pubsub_body_generator *generator, struct resource_tree *tree)
+               struct ast_sip_pubsub_body_generator *generator, struct resource_tree *tree,
+               pj_status_t *dlg_status)
 {
        struct sip_subscription_tree *sub_tree;
        pjsip_dialog *dlg;
@@ -1245,13 +1247,16 @@ static struct sip_subscription_tree *create_subscription_tree(const struct ast_s
 
        sub_tree = allocate_subscription_tree(endpoint);
        if (!sub_tree) {
+               pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
                return NULL;
        }
        sub_tree->role = AST_SIP_NOTIFIER;
 
-       dlg = ast_sip_create_dialog_uas(endpoint, rdata);
+       dlg = ast_sip_create_dialog_uas(endpoint, rdata, dlg_status);
        if (!dlg) {
-               ast_log(LOG_WARNING, "Unable to create dialog for SIP subscription\n");
+               if (*dlg_status != PJ_EEXISTS) {
+                       ast_log(LOG_WARNING, "Unable to create dialog for SIP subscription\n");
+               }
                ao2_ref(sub_tree, -1);
                return NULL;
        }
@@ -1362,7 +1367,9 @@ static int subscription_persistence_recreate(void *obj, void *arg, int flags)
        resp = build_resource_tree(endpoint, handler, resource, &tree,
                ast_sip_pubsub_has_eventlist_support(&rdata));
        if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
-               sub_tree = create_subscription_tree(handler, endpoint, &rdata, resource, generator, &tree);
+               pj_status_t dlg_status;
+
+               sub_tree = create_subscription_tree(handler, endpoint, &rdata, resource, generator, &tree, &dlg_status);
                if (!sub_tree) {
                        ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
                        ast_log(LOG_WARNING, "Failed to re-create subscription for %s\n", persistence->endpoint);
@@ -2506,6 +2513,7 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
        size_t resource_size;
        int resp;
        struct resource_tree tree;
+       pj_status_t dlg_status;
 
        endpoint = ast_pjsip_rdata_get_endpoint(rdata);
        ast_assert(endpoint != NULL);
@@ -2570,9 +2578,11 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
                return PJ_TRUE;
        }
 
-       sub_tree = create_subscription_tree(handler, endpoint, rdata, resource, generator, &tree);
+       sub_tree = create_subscription_tree(handler, endpoint, rdata, resource, generator, &tree, &dlg_status);
        if (!sub_tree) {
-               pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
+               if (dlg_status != PJ_EEXISTS) {
+                       pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
+               }
        } else {
                sub_tree->persistence = subscription_persistence_create(sub_tree);
                subscription_persistence_update(sub_tree, rdata);
index d5dc98e..ebe3219 100644 (file)
@@ -1416,6 +1416,7 @@ static pjsip_inv_session *pre_session_setup(pjsip_rx_data *rdata, const struct a
        pjsip_dialog *dlg;
        pjsip_inv_session *inv_session;
        unsigned int options = endpoint->extensions.flags;
+       pj_status_t dlg_status;
 
        if (pjsip_inv_verify_request(rdata, &options, NULL, NULL, ast_sip_get_pjsip_endpoint(), &tdata) != PJ_SUCCESS) {
                if (tdata) {
@@ -1425,9 +1426,11 @@ static pjsip_inv_session *pre_session_setup(pjsip_rx_data *rdata, const struct a
                }
                return NULL;
        }
-       dlg = ast_sip_create_dialog_uas(endpoint, rdata);
+       dlg = ast_sip_create_dialog_uas(endpoint, rdata, &dlg_status);
        if (!dlg) {
-               pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
+               if (dlg_status != PJ_EEXISTS) {
+                       pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
+               }
                return NULL;
        }
        if (pjsip_inv_create_uas(dlg, rdata, NULL, options, &inv_session) != PJ_SUCCESS) {