How session timers work

Session timers are disabled by default. An application that wants to use session timers must request them when creating dialog activities.

The session timer for a new dialog is configured using a SessionTimerOptions value. This value contains the mandatory session interval parameter, which is the time in seconds after which the dialog (session) is considered to have expired, if there were no session refresh requests sent or received in that time. RFC 4028 defines how the two parties on a dialog can negotiate the session interval, but it must always be at least 90 seconds.

A session refresh request is any re-INVITE or UPDATE sent on the dialog. If a session refresh request is successful, this means that both parties on the dialog are still alive, so the session timer is reset and the dialog can continue. If a session refresh request times out, or fails with 481 (dialog does not exist), then the application should terminate the dialog.

During dialog setup, one party on the dialog is selected to be the refresher, who must send a session refresh request periodically. An application can indicate its preferred refresher in its SessionTimerOptions, but this may not be applied, for example if the other party does not support session timers.

Note RFC 4028 is designed so that session timers can still be used even if only one party on the dialog supports them.

If a dialog activity in the SIP RA was selected to be the refresher, then periodically the SIP RA will fire a SessionRefreshRequiredEvent on the dialog, which tells the application that it should initiate a session refresh request. If this request fails with a timeout or 481 response then the application should terminate the dialog with a BYE.

Note Dialogs are deliberately not terminated automatically by the RA when a session refresh fails or a session expires. This is so the application has full control of how it cleans up its resources.

Regardless of who is selected to be the refresher, any successful re-INVITE or UPDATE on the dialog is implicitly a session refresh request, and resets the session timer automatically so the dialog may continue.

If there were no successful session refreshes within the session interval, then the SIP RA considers the dialog to be expired, and fires a SessionExpiredEvent. The application must then terminate the dialog by sending a BYE request.

Creating dialogs with session timers

To request the use of a session timer for a dialog, the application must pass in a SessionTimerOptions value when creating the dialog, before sending or responding to the initial request.

The dialog must be created using a dialog builder from OCSleeSipProvider.newDialogBuilder(). This lets you specify SessionTimerOptions in addition to other dialog options. For example:

// Create SessionTimerOptions value with 5 minute session interval.
SessionTimerOptions timerOptions = SessionTimerOptions.builder(300).build();

// Create new outgoing dialog activity using our timer options.
DialogActivity d = sleeSipProvider.newDialogBuilder()
                                  .outgoing(from, to)
                                  .withSessionTimer(timerOptions)
                                  .newDialog();

The session timer is activated when a successful response to the initial INVITE is sent or received. If the initial INVITE is not successful, then the dialog is not created and no session timer is started.

UAC behaviour

When a UAC application creates an outgoing dialog with a session timer, the initial outgoing INVITE is updated automatically by the SIP RA using the dialog’s SessionTimerOptions:

  • the Supported: timer header is added

  • the Session-Expires header is added, using the requested session interval

  • if the SessionTimerOptions value specifies a refresher, this is used for the "refresher" parameter in the Session-Expires header

  • if the SessionTimerOptions value specifies a minimum session interval, then a Min-SE header with this value is added to the request.

UAC behaviour includes handling 2xx, 422, and other error responses.

Handling 2xx responses

When a 2xx response arrives for the initial INVITE, the session timer is started, taking into account the session timer headers from the response:

  • If no session timer headers are present in the response, this means the UAS does not support session timers. In this case the UAC will start the session timer using its original settings, and act as the refresher.

  • The UAS may lower the Session-Expires value in its response, but not below the value of Min-SE, if it was present in the request. If the UAS wants a larger session interval it must send a 422 (Session interval too small) response.

  • If the UAC did not specify a refresher, then the UAS must decide who is the refresher, and add the "refresher" parameter to the Session-Expires header in its response. In case the UAS does not specify a refresher either, the UAC will be the refresher.

Handling 422 responses

A 422 response indicates that the UAS wants a larger session interval. The UAS specifies this value in the Min-SE header of the 422 response.

The UAC should retry the initial request using the larger session interval. This is not done automatically by the SIP RA, so that the application has a chance to decide whether it wants to retry or just abort the call.

The application can ask the RA to create a new dialog with the original parameters but with an updated session interval using OCSleeSipProvider.retryInitialSessionRefresh():

private void on422Response(ClientTransaction ct, Response response) {
    // create new dialog with SessionTimerOptions updated from 422 response
    DialogActivity newDialog = getSleeSipProvider().retryInitialSessionRefresh(ct, response);

    // attach SBB to new dialog
    ActivityContextInterface newACI = getSipACIFactory().getActivityContextInterface(newDialog);
    newACI.attach(getSbbLocalObject());

    // Send INVITE on the new dialog
    Request newInvite = newDialog.createRequest(Request.INVITE);
    newDialog.sendRequest(newInvite);
}

Handling other error responses

No special session timer handling is required for other error responses to the initial INVITE. No session timer is started and the dialog activity is terminated.

UAS behaviour

Enforcing a minimum session interval

When a UAS application receives an initial INVITE, it should first check that the request’s Session-Expires value (if present) agrees with the UAS application’s desired minimum session interval. The application should inspect the request and send a 422 response if the request’s session interval was too small.

This check can be done simply by using the convenience method rejectIfBelowMinSE():

public void onInitialInvite(RequestEvent event, ActivityContextInterface aci) {
    ServerTransaction st = event.getServerTransaction();

    boolean rejected = getSleeSipProvider().rejectIfBelowMinSE(st, 600);

    if (rejected) {
        return;  // 422 has been sent, nothing more to do
    }

    // continue processing initial INVITE...
}

This method checks the Session-Expires value in the incoming request. If it is too small, a 422 response will be sent automatically, containing the desired session interval in the Min-SE header. The method returns true so the application knows it has responded. No more processing is required; it is up to the UAC to retry if it wants.

Otherwise the application can continue processing the request, knowing that the INVITE’s Session-Expires was large enough.

Sending the 2xx response

Once the minimum session interval has been checked, the UAS application can create the dialog, passing in its desired SessionTimerOptions.

When the UAS application sends a 2xx response, it will be updated according to the session timer headers in the initial request, and the dialog’s SessionTimerOptions:

  • The Require: timer header will be added, if the request contained Supported: timer.

  • The Session-Expires header from the request will be used, unless the UAS’s timer options requested a lower value (but not lower than Min-SE).

    Note

    The UAS cannot increase the session expiry, or lower it below Min-SE. If the UAS wanted to increase the session expiry it should have rejected the INVITE with 422 (see Enforcing a minimum session interval).

  • The "refresher" parameter in the Session-Expires header will be set.

    • If the UAC dos not support session timers, then the UAS is always the refresher.

    • If the UAC specified a refresher, then this value will be used.

    • Otherwise, the refresher specified by the UAS’s SessionTimerOptions is used.

    • If the UAS did not specify a refresher either, then the RA’s SessionTimer:default-refresher config property is used (see Configuration).

ForkActivity support

Dialogs created by a ForkActivity "big fork" operation can also make use of session timers.

The application can pass its desired SessionTimerOptions value to the ForkActivity.forkTo() method.

When the INVITE is forked to its targets, each copy of the INVITE will contain the session timer headers corresponding to the SessionTimerOptions value that was supplied.

If there is a winning 2xx response, this creates a dialog and activates the session timer. The negotiated session timer options are derived as described in handling 2xx responses.

Subsequent invocations of ForkActivity.forkTo() on the same ForkActivity may pass in different SessionTimerOptions values. The winning 2xx cancels all other branches, and the resulting dialog’s session timer options are based on those that were passed to the forkTo() call that sent the winning INVITE.

Accessing session timer state

The session timer state of a dialog activity can be queried using SessionTimerDialog.getSessionTimer(). SessionTimerDialog is a subclass of Dialog, and any dialog activity object may be safely type cast to this type.

The SessionTimer interface shows whether the timer is active or expired, and also shows the dialog’s currently applied SessionTimerOptions.

Session refreshes

Once the dialog has been setup successfully, a session expiry timer is started using the session interval negotiated by the initial INVITE transaction. Session refresh requests must now be sent periodically to reset the expiry timer and keep the session alive. The party selected to be the refresher will do this at regular intervals if there has been no other activity, but either party may send a session refresh request at any time.

Refresher (UAC) behaviour

The dialog of the refresher starts another timer that fires halfway through the session expiry interval (as per RFC 4028). If no other session refresh requests are seen on the dialog, this timer causes a SessionRefreshRequiredEvent to be fired on the dialog’s ACI. When the application receives this event, it should send a re-INVITE or UPDATE request on the dialog to perform the session refresh.

Sending the session refresh request

The session refresh request can be created as a normal mid-dialog request, for example using Dialog.createRequest(). The SessionTimer interface also provides methods for creating the session refresh request, which can also take a SessionTimerOptions value, so that the session timer can be re-negotiated if necessary.

Note

When sending a re-INVITE, the application must set the message body to contain the currently active SDP, from the last successful offer-answer exchange.

Using UPDATE is recommended by RFC 4028, if the other party allows it.

The application sends the request by the usual means, for example DialogActivity.sendRequest(). When the session refresh request is sent, the SIP RA will update the request using the current SessionTimerOptions, or any new options that were passed to generateSessionRefreshRequest():

Receiving the session refresh response

If a 2xx response is received for the session refresh request, the session timer is reset, and any new session timer options are applied, such as changing the session interval or the refresher.

If the session refresh request fails with an error response or timeout, then the session timer is not reset. The session timer will eventually expire unless a new session refresh request is sent and succeeds.

If the request fails with a timeout, 408, or 481 response, the application should terminate the dialog with a BYE.

For all other error responses, the application should retry the session refresh as appropriate based on the type of error.

SIP ResponseEvents or TimeoutEvents for a failed session refresh request are decorated with the SessionRefreshFailedEvent marker interface. This can be used to check if the event should be processed as a failed session refresh, as in the example below.

private void processResponse(ResponseEvent event, ActivityContextInterface aci) {
    if (event instanceof SessionRefreshFailedEvent) {
        if (((SessionRefreshFailedEvent)event).shouldTerminate()) {
            // Must have been 408 or 481, I need to send BYE now
        }
    }
}

Refreshee (UAS) behaviour

When a session refresh request is received on a dialog activity, it will be fired as a normal mid-dialog request event.

The UAS application can just respond to the request as it would normally. The SIP RA will automatically add session timer headers to the response.

If the UAS wants to change the session timer options, it can use the method generateSessionRefreshResponse(), passing in a new SessionTimerOptions value. Note that the new session interval must fall within the refresh request’s Session-Expires and Min-SE range — values outside this range will be automatically restricted to the nearest upper or lower bound.

If the response is a 2xx (success) response, the dialog’s session expiry timer will be reset using the currently agreed session interval. If either party requested that the UAS becomes the refresher, then the dialog remembers that it is now the refresher, and starts a session refresh timer that will expire halfway through the session interval to fire a SessionRefreshRequiredEvent on this dialog activity.

If the response is an error response, the session expiry timer is not reset, so the session will expire eventually unless a subsequent session refresh request (from either party) is successful.

Note

If responding to a re-INVITE, the application must set the message body to contain the currently active SDP, from the last successful offer-answer exchange.

Session expiration

If there were no successful session refresh requests sent or received within the session interval, the dialog’s session expiry timer will fire, causing a SessionExpiredEvent to be fired on the dialog activity.

Session expiry time

As per RFC 4028 §10, the session expiry timer fires slightly before the end of the session interval.

If the session interval is E seconds, then the timer fires at E - min(32, E/3) seconds.

In practice this means E - 32 seconds for most values of E, greater than 96 seconds.

The application processing the SessionExpiredEvent should terminate the dialog by sending a BYE. Again this is not done automatically by the RA, so that the application can control how it cleans up its resources.

If no SBB processed the SessionExpiredEvent, the RA will automatically send a BYE. This avoids dialogs leaking if no service was active or able to process the event.

Warning

Once a dialog’s session timer has expired, there is no going back. The application cannot reset the timer and carry on. The dialog activity is still operational, but the only sensible course of action is to terminate the dialog as soon as possible.

Proxy mode

Applications that need to forward messages between dialogs, such as B2BUAs, might just want to pass all messages through without directly taking part in session timer negotiation and refreshing. But it would still be useful if the application could be notified when a session expired, if the endpoints were using session timers.

This is what proxy mode is used for. In proxy mode, a dialog does not need to configure any session timer options. Instead it observes the session interval negotiated by the endpoints on the dialog, and starts a session expiry timer.

The dialog does not initiate any session refresh requests on its own. It observes all session refresh requests that pass through, and resets the expiry timer when a refresh succeeds.

If neither endpoint sends a successful session refresh within the session interval, a SessionExpiredEvent is fired so the application can clean up the expired dialog.

Enabling proxy mode on a dialog

All that is required to enable proxy mode for a dialog is to use the special SessionTimerOptions constant value, SessionTimerOptions.PROXY, when creating the dialog. No further configuration is needed.

Now if either endpoint uses a session timer, the dialog will observe the Session-Expires header in the initial request and/or response, and use this value to start its own session expiry timer.

If a successful session refresh request re-negotiates the session interval, this will be observed as well, and the session expiry timer will be reset with the new value.

Replication

When SIP dialog replication is enabled (using the ReplicatedDialogSupport=true config property), session timers are replicated as well so they can recover from a node failure.

In a Rhino cluster, session timer refresh and expiry events will be fired on the same node that created the dialog activity.

If a node fails, its dialogs are automatically taken over by surviving nodes in the cluster. When a dialog is recovered on a surviving node, any session timers for that dialog are recovered as well, and will now fire on the surviving node at the expected time.

Subsequent session timer refresh and expiry events for the dialog activity will now fire on the node that took over that dialog.

Configuration properties

The SIP RA’s session timer support adds one new configuration property: SessionTimer:default_refresher.

This is only required when a UAS has to select the refresher for a dialog, because the UAC did not specify one, and the UAS application did not set a refresher in its SessionTimerOptions for the dialog. In this case the SessionTimer:default_refresher property is used so the UAS can decide.

All other session timer parameters are configured by the application for each dialog, using the appropriate SessionTimerOptions values.

Application changes to use session timers

To use session timers, an application must:

  1. Create dialogs using OCSleeSipProvider.newDialogBuilder() and passing in a SessionTimerOptions value.

  2. When using ForkActivity, pass SessionTimerOptions to ForkActivity.forkTo() when initiating a fork operation.

  3. UAS applications may use rejectIfBelowMinSE() to enforce a minimum session interval.

  4. UAC applications may use OCSleeSipProvider.retryInitialSessionRefresh() to retry the initial request when handling a 422 response.

  5. Handle SessionRefreshRequiredEvents and send re-INVITE or UPDATE requests when needed.

  6. Handle failed session refreshes and terminate the dialog if necessary.

  7. Handle session refresh requests.

  8. Handle SessionExpiredEvents and terminate the dialog.

Previous page Next page