Fixed issues with event subscription regarding on_rx_refresh() and unsubscription #3126
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There are several issues with the event subscription, in particular with the
on_rx_refresh()
callback and the unsubscription handling.on_rx_refresh()
callback is optional, but it will trigger an assertion inpjsip_evsub_create_uas()
:We will fix the doc in this PR, and also add the missing parameter documentations.
Upon incoming SUBSCRIBE,
on_rx_refresh()
will be called, and the doc says that app MUST send NOTIFY request inside the callback. The callback also provides a parameterp_st_code
that will be used to send the response to the incoming SUBSCRIBE after the callback. This means that the NOTIFY will be sent first before the SUBSCRIBE response. While this is unlikely to cause any problem to the remote, which should be able to handle out-of-order messages, it's counterintuitive and goes against the RFC 3265's recommendation in section 3.1.6.2:Note that a NOTIFY message is always sent immediately after any 200-class response to a SUBSCRIBE request
Even our sipp pjsua test
uac-subscribe.xml
will fail since it expects to receive the SUBSCRIBE response first:The proposed fix in this PR is to delay sending the NOTIFY request when we're inside the callback.
Upon receiving unsubscription request, evsub will set the state to TERMINATED before calling
on_rx_refresh()
:This is most likely done so that when enquiring the subscription state via
pjsip_evsub_get_state()
inside the callback, the app can easily differentiate between unsubscription (state TERMINATED) and refresh (otherwise). And the state setting is done without callingset_state()
because there's a possibility the state can be reverted if the app rejects the SUBSCRIBE by specifying non-200p_st_code
. But this causes several issues:a. The state never transitions smoothly to TERMINATED (the log will ouput
"Subscription state changed ACCEPTED --> ACTIVE"
followed by"Subscription state changed TERMINATED --> TERMINATED"
). This causes timer to be still active, i.e. the following code inset_state()
will never be executed:As a result, timer, such as timeout timer, will still be triggered later (invoking
on_server_timeout()
callback), long after the subscription is deemed to have terminated.b. When app tries to send the (final) NOTIFY request inside the callback, it's not handled properly. Instead it will get the log:
Subscription already terminated for NOTIFY, event=presence;id=
It is quite complicated to fix the issue. The proposed fix in this PR is to always reply with success/200 upon unsubscription and therefore, disallow the state reversion. This is consistent with the behaviour of registration and call, where after sending unregistration or hanging up call, user is not going to stick around much longer and wait until it's accepted.
Behaviour change due to the patch: Upon unsubscription, app will now receive callback
on_evsub_state()
beforeon_rx_refresh()
.The PR also fixes a bug in
uac-subscribe.xml
missing the To tag that causes the unsubscription request to be treated as new subscription instead.