mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-29 18:19:30 +00:00
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 ........ 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
This commit is contained in:
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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) {
|
||||
|
Reference in New Issue
Block a user