Skip to content

Commit

Permalink
Prevent data race in PJSIP presence
Browse files Browse the repository at this point in the history
  • Loading branch information
sauwming committed Jan 30, 2024
1 parent e12a8d1 commit 939c1f6
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 11 deletions.
2 changes: 0 additions & 2 deletions pjsip/include/pjsip-simple/presence.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,6 @@ struct pjsip_pres_status
this valud will be set to NULL */

} info[PJSIP_PRES_STATUS_MAX_INFO]; /**< Array of info. */

pj_bool_t _is_valid; /**< Internal flag. */
};


Expand Down
38 changes: 29 additions & 9 deletions pjsip/src/pjsip-simple/presence.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ struct pjsip_pres
pjsip_pres_status status; /**< Presence status. */
pj_pool_t *tmp_pool; /**< Pool for tmp_status */
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. */
pj_mutex_t *mutex; /**< Mutex. */
};


Expand Down Expand Up @@ -213,6 +215,11 @@ PJ_DEF(pj_status_t) pjsip_pres_create_uac( pjsip_dialog *dlg,
if (user_cb)
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);
pres->status_pool = pj_pool_create(dlg->pool->factory, obj_name,
512, 512, NULL);
Expand Down Expand Up @@ -389,14 +396,18 @@ PJ_DEF(pj_status_t) pjsip_pres_get_status( pjsip_evsub *sub,
pres = (pjsip_pres*) pjsip_evsub_get_mod_data(sub, mod_presence.id);
PJ_ASSERT_RETURN(pres!=NULL, PJSIP_SIMPLE_ENOPRESENCE);

if (pres->tmp_status._is_valid) {
pj_mutex_lock(pres->mutex);

if (pres->is_ts_valid) {
PJ_ASSERT_RETURN(pres->tmp_pool!=NULL, PJSIP_SIMPLE_ENOPRESENCE);
pj_memcpy(status, &pres->tmp_status, sizeof(pjsip_pres_status));
} else {
PJ_ASSERT_RETURN(pres->status_pool!=NULL, PJSIP_SIMPLE_ENOPRESENCE);
pj_memcpy(status, &pres->status, sizeof(pjsip_pres_status));
}

pj_mutex_unlock(pres->mutex);

return PJ_SUCCESS;
}

Expand Down Expand Up @@ -628,6 +639,10 @@ static void pres_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
pj_pool_release(pres->tmp_pool);
pres->tmp_pool = NULL;
}
if (pres->mutex) {
pj_mutex_destroy(pres->mutex);
pres->mutex = NULL;
}
}
}

Expand Down Expand Up @@ -772,6 +787,11 @@ static pj_status_t pres_process_rx_notify( pjsip_pres *pres,
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) {
/* Unsupported or bad Content-Type */
if (PJSIP_PRES_BAD_CONTENT_RESPONSE >= 300) {
Expand Down Expand Up @@ -805,11 +825,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;
}

Expand Down Expand Up @@ -845,10 +860,11 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
* "tuple_node" in pjsip_pres_status to NULL.
*/
unsigned i;
pj_mutex_lock(pres->mutex);
for (i=0; i<pres->status.info_cnt; ++i) {
pres->status.info[i].tuple_node = NULL;
}

pj_mutex_unlock(pres->mutex);
#elif 0
/* This has just been changed. Previously, we treat incoming NOTIFY
* with no message body as having the presence subscription closed.
Expand All @@ -859,7 +875,7 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
#else
unsigned i;
/* 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)
pres->tmp_status.info[i].basic_open = PJ_FALSE;
#endif
Expand All @@ -875,6 +891,8 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
/* If application responded NOTIFY with 2xx, copy temporary status
* to main status, and mark the temporary status as invalid.
*/
pj_mutex_lock(pres->mutex);

if ((*p_st_code)/100 == 2) {
pj_pool_t *tmp;

Expand All @@ -886,9 +904,11 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
pres->status_pool = tmp;
}

pres->tmp_status._is_valid = PJ_FALSE;
pres->is_ts_valid = PJ_FALSE;
pj_pool_reset(pres->tmp_pool);

pj_mutex_unlock(pres->mutex);

/* Done */
}

Expand Down

0 comments on commit 939c1f6

Please sign in to comment.