mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 11:25:35 +00:00
res_pjsip: Upgraded bundled pjsip to 2.13
Removed multiple patches. Code chages in res_pjsip_pubsub due to changes in evsub. Pjsip now calls on_evsub_state() before on_rx_refresh(), so the sub tree deletion that used to take place in on_evsub_state() now must take place in on_rx_refresh(). Additionally, pjsip now requires that you send the NOTIFY from within on_rx_refresh(), otherwise it will assert when going to send the 200 OK. The idea is that it will look for this NOTIFY and cache it until after sending the response in order to deal with the self-imposed message mis-order. Asterisk previously dealt with this by pushing the NOTIFY in on_rx_refresh(), but pjsip now forces us to use it's method. Changes were required to configure in order to detect which way pjsip handles this as the two are not compatible for the reasons mentioned above. A corresponding change in testsuite is required in order to deal with the small interal timing changes caused by moving the NOTIFY send. ASTERISK-30325 Change-Id: I50b00cac89d950d3511d7b250a1c641965d9fe7f
This commit is contained in:
@@ -3838,35 +3838,20 @@ static void set_state_terminated(struct ast_sip_subscription *sub)
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief PJSIP callback when underlying SIP subscription changes state
|
||||
*
|
||||
* Although this function is called for every state change, we only care
|
||||
* about the TERMINATED state, and only when we're actually processing the final
|
||||
* notify (SIP_SUB_TREE_TERMINATE_IN_PROGRESS) OR when a transmission failure
|
||||
* occurs (PJSIP_EVENT_TSX_STATE). In this case, we do all the subscription tree
|
||||
* cleanup tasks and decrement the evsub reference.
|
||||
|
||||
/* The code in this function was previously in pubsub_on_evsub_state. As of
|
||||
* pjsip 2.13 pubsub_on_evsub_state is called before pubsub_on_rx_refresh, so
|
||||
* if we clean the sub tree in pubsub_on_evsub_state it won't be available in
|
||||
* pubsub_on_rx_refresh. This means we won't be able to build or send the
|
||||
* corresponding NOTIFY (which also causes pjsip to assert.)
|
||||
* If HAVE_PJSIP_EVSUB_PENDING_NOTIFY is set based on configuration, this will
|
||||
* be called from pubsub_on_rx_refresh. If not set, the result is the legacy
|
||||
* behavior of calling this from pubsub_on_evsub_state.
|
||||
*/
|
||||
static void pubsub_on_evsub_state(pjsip_evsub *evsub, pjsip_event *event)
|
||||
{
|
||||
struct sip_subscription_tree *sub_tree =
|
||||
pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
|
||||
static void clean_sub_tree(pjsip_evsub *evsub){
|
||||
|
||||
ast_debug(3, "evsub %p state %s event %s sub_tree %p sub_tree state %s\n", evsub,
|
||||
pjsip_evsub_get_state_name(evsub), pjsip_event_str(event->type), sub_tree,
|
||||
(sub_tree ? sub_tree_state_description[sub_tree->state] : "UNKNOWN"));
|
||||
|
||||
if (!sub_tree || pjsip_evsub_get_state(evsub) != PJSIP_EVSUB_STATE_TERMINATED) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* It's easier to write this as what we WANT to process, then negate it. */
|
||||
if (!(sub_tree->state == SIP_SUB_TREE_TERMINATE_IN_PROGRESS
|
||||
|| (event->type == PJSIP_EVENT_TSX_STATE && sub_tree->state == SIP_SUB_TREE_NORMAL)
|
||||
)) {
|
||||
ast_debug(3, "Do nothing.\n");
|
||||
return;
|
||||
}
|
||||
struct sip_subscription_tree *sub_tree;
|
||||
sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
|
||||
|
||||
if (sub_tree->expiration_task) {
|
||||
char task_name[256];
|
||||
@@ -3899,6 +3884,45 @@ static void pubsub_on_evsub_state(pjsip_evsub *evsub, pjsip_event *event)
|
||||
ao2_ref(sub_tree, -1);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief PJSIP callback when underlying SIP subscription changes state
|
||||
*
|
||||
* Although this function is called for every state change, we only care
|
||||
* about the TERMINATED state, and only when we're actually processing the final
|
||||
* notify (SIP_SUB_TREE_TERMINATE_IN_PROGRESS) OR when a transmission failure
|
||||
* occurs (PJSIP_EVENT_TSX_STATE). In this case, we do all the subscription tree
|
||||
* cleanup tasks and decrement the evsub reference.
|
||||
*/
|
||||
static void pubsub_on_evsub_state(pjsip_evsub *evsub, pjsip_event *event)
|
||||
{
|
||||
struct sip_subscription_tree *sub_tree =
|
||||
pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
|
||||
|
||||
ast_debug(3, "evsub %p state %s event %s sub_tree %p sub_tree state %s\n", evsub,
|
||||
pjsip_evsub_get_state_name(evsub), pjsip_event_str(event->type), sub_tree,
|
||||
(sub_tree ? sub_tree_state_description[sub_tree->state] : "UNKNOWN"));
|
||||
|
||||
if (!sub_tree || pjsip_evsub_get_state(evsub) != PJSIP_EVSUB_STATE_TERMINATED) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* It's easier to write this as what we WANT to process, then negate it. */
|
||||
if (!(sub_tree->state == SIP_SUB_TREE_TERMINATE_IN_PROGRESS
|
||||
|| (event->type == PJSIP_EVENT_TSX_STATE && sub_tree->state == SIP_SUB_TREE_NORMAL)
|
||||
)) {
|
||||
ast_debug(3, "Do nothing.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef HAVE_PJSIP_EVSUB_PENDING_NOTIFY
|
||||
/* for pjproject <2.13, this cleanup occurs here. For >=2.13, pubsub_on_evsub_state
|
||||
is called before pubsub_on_rx_refresh and so must be cleaned there.*/
|
||||
clean_sub_tree(evsub);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static int pubsub_on_refresh_timeout(void *userdata)
|
||||
{
|
||||
struct sip_subscription_tree *sub_tree = userdata;
|
||||
@@ -4107,16 +4131,37 @@ static void pubsub_on_rx_refresh(pjsip_evsub *evsub, pjsip_rx_data *rdata,
|
||||
|
||||
subscription_persistence_update(sub_tree, rdata, SUBSCRIPTION_PERSISTENCE_REFRESHED);
|
||||
|
||||
#ifdef HAVE_PJSIP_EVSUB_PENDING_NOTIFY
|
||||
/* As of pjsip 2.13, the NOTIFY has to be sent within this function as pjproject now
|
||||
requires it. Previously this would have caused an early NOTIFY to go out before the
|
||||
SUBSCRIBE's 200 OK. The previous solution was to push the NOTIFY, but now pjproject
|
||||
looks for the NOTIFY on send and delays it until after it auto-replies.
|
||||
If the NOTIFY is not there when it looks to send, pjproject will assert. */
|
||||
serialized_pubsub_on_refresh_timeout(sub_tree);
|
||||
#else
|
||||
if (ast_sip_push_task(sub_tree->serializer, serialized_pubsub_on_refresh_timeout, ao2_bump(sub_tree))) {
|
||||
/* If we can't push the NOTIFY refreshing task...we'll just go with it. */
|
||||
ast_log(LOG_ERROR, "Failed to push task to send NOTIFY.\n");
|
||||
sub_tree->state = SIP_SUB_TREE_NORMAL;
|
||||
ao2_ref(sub_tree, -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sub_tree->is_list) {
|
||||
pj_list_insert_before(res_hdr, create_require_eventlist(rdata->tp_info.pool));
|
||||
}
|
||||
|
||||
#ifdef HAVE_PJSIP_EVSUB_PENDING_NOTIFY
|
||||
/* for pjproject <2.13, this cleanup occurs in pubsub_on_evsub_state. For >=2.13,
|
||||
pubsub_on_rx_refresh is called after pubsub_on_evsub_state and so the tree must be
|
||||
cleaned here. */
|
||||
if( pjsip_evsub_get_state(evsub) == PJSIP_EVSUB_STATE_TERMINATED &&
|
||||
sub_tree->state == SIP_SUB_TREE_TERMINATE_PENDING ) {
|
||||
clean_sub_tree(evsub);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void pubsub_on_rx_notify(pjsip_evsub *evsub, pjsip_rx_data *rdata, int *p_st_code,
|
||||
|
Reference in New Issue
Block a user