Prevent data race in PJSIP presence (#3847)
This commit is contained in:
parent
776c70ef01
commit
a32d7c2907
|
@ -98,8 +98,6 @@ struct pjsip_pres_status
|
||||||
this valud will be set to NULL */
|
this valud will be set to NULL */
|
||||||
|
|
||||||
} info[PJSIP_PRES_STATUS_MAX_INFO]; /**< Array of info. */
|
} info[PJSIP_PRES_STATUS_MAX_INFO]; /**< Array of info. */
|
||||||
|
|
||||||
pj_bool_t _is_valid; /**< Internal flag. */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,9 @@ struct pjsip_pres
|
||||||
pjsip_pres_status status; /**< Presence status. */
|
pjsip_pres_status status; /**< Presence status. */
|
||||||
pj_pool_t *tmp_pool; /**< Pool for tmp_status */
|
pj_pool_t *tmp_pool; /**< Pool for tmp_status */
|
||||||
pjsip_pres_status tmp_status; /**< Temp, before NOTIFY is answred.*/
|
pjsip_pres_status tmp_status; /**< Temp, before NOTIFY is answred.*/
|
||||||
|
pj_bool_t is_ts_valid; /**< Is tmp_status valid? */
|
||||||
pjsip_evsub_user user_cb; /**< The user callback. */
|
pjsip_evsub_user user_cb; /**< The user callback. */
|
||||||
|
pj_mutex_t *mutex; /**< Mutex. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,6 +215,11 @@ PJ_DEF(pj_status_t) pjsip_pres_create_uac( pjsip_dialog *dlg,
|
||||||
if (user_cb)
|
if (user_cb)
|
||||||
pj_memcpy(&pres->user_cb, user_cb, sizeof(pjsip_evsub_user));
|
pj_memcpy(&pres->user_cb, user_cb, sizeof(pjsip_evsub_user));
|
||||||
|
|
||||||
|
status = pj_mutex_create_recursive(dlg->pool, "pres_mutex",
|
||||||
|
&pres->mutex);
|
||||||
|
if (status != PJ_SUCCESS)
|
||||||
|
goto on_return;
|
||||||
|
|
||||||
pj_ansi_snprintf(obj_name, PJ_MAX_OBJ_NAME, "pres%p", dlg->pool);
|
pj_ansi_snprintf(obj_name, PJ_MAX_OBJ_NAME, "pres%p", dlg->pool);
|
||||||
pres->status_pool = pj_pool_create(dlg->pool->factory, obj_name,
|
pres->status_pool = pj_pool_create(dlg->pool->factory, obj_name,
|
||||||
512, 512, NULL);
|
512, 512, NULL);
|
||||||
|
@ -389,14 +396,24 @@ PJ_DEF(pj_status_t) pjsip_pres_get_status( pjsip_evsub *sub,
|
||||||
pres = (pjsip_pres*) pjsip_evsub_get_mod_data(sub, mod_presence.id);
|
pres = (pjsip_pres*) pjsip_evsub_get_mod_data(sub, mod_presence.id);
|
||||||
PJ_ASSERT_RETURN(pres!=NULL, PJSIP_SIMPLE_ENOPRESENCE);
|
PJ_ASSERT_RETURN(pres!=NULL, PJSIP_SIMPLE_ENOPRESENCE);
|
||||||
|
|
||||||
if (pres->tmp_status._is_valid) {
|
if (pres->mutex)
|
||||||
PJ_ASSERT_RETURN(pres->tmp_pool!=NULL, PJSIP_SIMPLE_ENOPRESENCE);
|
pj_mutex_lock(pres->mutex);
|
||||||
|
|
||||||
|
if (pres->is_ts_valid) {
|
||||||
|
PJ_ASSERT_ON_FAIL(pres->tmp_pool!=NULL,
|
||||||
|
{if (pres->mutex) pj_mutex_unlock(pres->mutex);
|
||||||
|
return PJSIP_SIMPLE_ENOPRESENCE;});
|
||||||
pj_memcpy(status, &pres->tmp_status, sizeof(pjsip_pres_status));
|
pj_memcpy(status, &pres->tmp_status, sizeof(pjsip_pres_status));
|
||||||
} else {
|
} else {
|
||||||
PJ_ASSERT_RETURN(pres->status_pool!=NULL, PJSIP_SIMPLE_ENOPRESENCE);
|
PJ_ASSERT_ON_FAIL(pres->status_pool!=NULL,
|
||||||
|
{if (pres->mutex) pj_mutex_unlock(pres->mutex);
|
||||||
|
return PJSIP_SIMPLE_ENOPRESENCE;});
|
||||||
pj_memcpy(status, &pres->status, sizeof(pjsip_pres_status));
|
pj_memcpy(status, &pres->status, sizeof(pjsip_pres_status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pres->mutex)
|
||||||
|
pj_mutex_unlock(pres->mutex);
|
||||||
|
|
||||||
return PJ_SUCCESS;
|
return PJ_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,6 +645,10 @@ static void pres_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
|
||||||
pj_pool_release(pres->tmp_pool);
|
pj_pool_release(pres->tmp_pool);
|
||||||
pres->tmp_pool = NULL;
|
pres->tmp_pool = NULL;
|
||||||
}
|
}
|
||||||
|
if (pres->mutex) {
|
||||||
|
pj_mutex_destroy(pres->mutex);
|
||||||
|
pres->mutex = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,6 +793,11 @@ static pj_status_t pres_process_rx_notify( pjsip_pres *pres,
|
||||||
status = PJSIP_SIMPLE_EBADCONTENT;
|
status = PJSIP_SIMPLE_EBADCONTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If application calls pres_get_status(), redirect the call to
|
||||||
|
* retrieve the temporary status.
|
||||||
|
*/
|
||||||
|
pres->is_ts_valid = (status == PJ_SUCCESS? PJ_TRUE: PJ_FALSE);
|
||||||
|
|
||||||
if (status != PJ_SUCCESS) {
|
if (status != PJ_SUCCESS) {
|
||||||
/* Unsupported or bad Content-Type */
|
/* Unsupported or bad Content-Type */
|
||||||
if (PJSIP_PRES_BAD_CONTENT_RESPONSE >= 300) {
|
if (PJSIP_PRES_BAD_CONTENT_RESPONSE >= 300) {
|
||||||
|
@ -805,11 +831,6 @@ static pj_status_t pres_process_rx_notify( pjsip_pres *pres,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If application calls pres_get_status(), redirect the call to
|
|
||||||
* retrieve the temporary status.
|
|
||||||
*/
|
|
||||||
pres->tmp_status._is_valid = PJ_TRUE;
|
|
||||||
|
|
||||||
return PJ_SUCCESS;
|
return PJ_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -845,10 +866,11 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
|
||||||
* "tuple_node" in pjsip_pres_status to NULL.
|
* "tuple_node" in pjsip_pres_status to NULL.
|
||||||
*/
|
*/
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
pj_mutex_lock(pres->mutex);
|
||||||
for (i=0; i<pres->status.info_cnt; ++i) {
|
for (i=0; i<pres->status.info_cnt; ++i) {
|
||||||
pres->status.info[i].tuple_node = NULL;
|
pres->status.info[i].tuple_node = NULL;
|
||||||
}
|
}
|
||||||
|
pj_mutex_unlock(pres->mutex);
|
||||||
#elif 0
|
#elif 0
|
||||||
/* This has just been changed. Previously, we treat incoming NOTIFY
|
/* This has just been changed. Previously, we treat incoming NOTIFY
|
||||||
* with no message body as having the presence subscription closed.
|
* with no message body as having the presence subscription closed.
|
||||||
|
@ -859,7 +881,7 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
|
||||||
#else
|
#else
|
||||||
unsigned i;
|
unsigned i;
|
||||||
/* Subscription is terminated. Consider contact is offline */
|
/* Subscription is terminated. Consider contact is offline */
|
||||||
pres->tmp_status._is_valid = PJ_TRUE;
|
pres->is_ts_valid = PJ_TRUE;
|
||||||
for (i=0; i<pres->tmp_status.info_cnt; ++i)
|
for (i=0; i<pres->tmp_status.info_cnt; ++i)
|
||||||
pres->tmp_status.info[i].basic_open = PJ_FALSE;
|
pres->tmp_status.info[i].basic_open = PJ_FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
@ -875,6 +897,8 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
|
||||||
/* If application responded NOTIFY with 2xx, copy temporary status
|
/* If application responded NOTIFY with 2xx, copy temporary status
|
||||||
* to main status, and mark the temporary status as invalid.
|
* to main status, and mark the temporary status as invalid.
|
||||||
*/
|
*/
|
||||||
|
pj_mutex_lock(pres->mutex);
|
||||||
|
|
||||||
if ((*p_st_code)/100 == 2) {
|
if ((*p_st_code)/100 == 2) {
|
||||||
pj_pool_t *tmp;
|
pj_pool_t *tmp;
|
||||||
|
|
||||||
|
@ -886,9 +910,11 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
|
||||||
pres->status_pool = tmp;
|
pres->status_pool = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
pres->tmp_status._is_valid = PJ_FALSE;
|
pres->is_ts_valid = PJ_FALSE;
|
||||||
pj_pool_reset(pres->tmp_pool);
|
pj_pool_reset(pres->tmp_pool);
|
||||||
|
|
||||||
|
pj_mutex_unlock(pres->mutex);
|
||||||
|
|
||||||
/* Done */
|
/* Done */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue