summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2014-11-14 14:24:02 +0000
committerMark Michelson <mmichelson@digium.com>2014-11-14 14:24:02 +0000
commit77c57f2b1adac6652a5c776bbdcde9f6e4060b92 (patch)
tree5b486bd4615dfe8ff3f646808693077c18fb3f81 /res
parent721ae89155676c7028ae13e9c95a65c879f0dce7 (diff)
Fix race condition where duplicated requests may be handled by multiple threads.
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 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@427841 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res')
-rw-r--r--res/res_pjsip.c11
-rw-r--r--res/res_pjsip_pubsub.c22
-rw-r--r--res/res_pjsip_session.c7
3 files changed, 27 insertions, 13 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index f76d994f7..a04d365aa 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -2191,12 +2191,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,
@@ -2209,11 +2210,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;
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index 4a1076d18..344bda3cd 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -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);
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index d5dc98e9d..ebe321958 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -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) {