This page describes how SIS-SIP automatically uses Record-Route
and Contact
headers when participating in SIP dialogs.
Introduction
SIS-SIP services are typically invoked as part of a SIP dialog. The dialog represents an end-to-end relationship between two user agents, such as that used for a voice call.
A dialog is established by the User Agent Client (UAC) device sending an initial request (such as INVITE
),
and the User Agent Server (UAS) responding with a provisional (1xx
) or success (2xx
) response containing a new to-tag.
Any nodes on the path between the UAC and UAS can add their SIP URI to the Record-Route
header in the initial request.
This indicates that they want to monitor the dialog until it ends.
When the UAS sends a dialog-creating response, it copies the request’s Record-Route
header into the response.
This is passed all the way back to the UAC, so both sides have a list of all the intermediary nodes that the request passed through.
The UAC and UAS also put their device’s SIP URI in the Contact
header of the initial request or the dialog-creating response.
The diagram below shows a dialog being established between user agents A and B, with proxy servers P1 and P2 in between, both record-routing:
Each party now has some dialog state, which contains the complete path back to the other party:
-
The "route set", created from the
Record-Route
header, specifies which nodes will be on theRoute
header of mid-dialog requests. Note that the direction is reversed on the other side. -
The "remote target" is the current address of the other parties' device, and will be the
Request-URI
in mid-dialog requests.
So if "A" sends a mid-dialog request, it will look like this:
UPDATE sip:B-device SIP/2.0 Route: P1 Route: P2
Conversely a mid-dialog request sent by B will look like this:
UPDATE sip:A-device SIP/2.0 Route: P2 Route: P1
By SIP routing rules, once a mid-dialog request has traversed all the nodes in the Route
header, it will be sent to the address in the Request-URI
.
SIS-SIP dialog routing behaviour
SIS-SIP services are usually implemented to act in a proxy or B2BUA (Back-To-Back User Agent) role.
They can also act as a UAC or UAS.
When involved in a dialog, SIS-SIP automatically updates Record-Route
and Contact
as appropriate for its role, but service developers can override the default behaviour if necessary.
Proxying
A service acting as a proxy using the Proxy
activity will automatically add Record-Route
to forwarded initial requests by default.
This can be disabled by calling Proxy.setRecordRoute(false)
before forwarding the request.
A proxy does not modify the Contact
header.
The diagram below shows the SIS-SIP acting as a record-routing proxy when forwarding the initial request.
B2BUA
A B2BUA service has two or more dialogs and forwards requests and responses between them.
Typically a B2BUA will have a dialog on each "side", upstream and downstream.
The downstream dialog (or SipSession
) is created using
SipFactory.createRequest(incomingRequest, boolean)
.
More dialogs may be necessary to handle forking or more complex scenarios like transfers or announcements.
When the SIS-SIP forwards initial messages as a B2BUA, it resets the Record-Route
header so that it appears to be the originator of the message.
It adds Record-Route
to the initial request forwarded downstream, and any dialog-creating responses forwarded upstream.
This means that the SIS remains in the route set of the dialogs on each side, so requests sent by either party will be routed to the SIS.
Then the B2BUA service will forward the request on the other dialog, using that dialog’s route set and remote target.
The default B2BUA routing behaviour is shown below.
Note that the Contact
header from either party is not changed.
This is deliberate so that any parameters or feature tags in the device’s Contact
header are preserved for correct operation of the dialog.
It doesn’t matter that the SIS is not in the Contact
header itself, the Record-Route
header ensures that requests in either direction must pass-through the SIS.
UAC or UAS
A SIS-SIP service can also act in a UAC or UAS role.
In UAC scenarios, SIS-SIP by default puts its own address in the initial request’s Contact
header, as it is the originator of the request.
The default Contact
header may also be updated before the request is sent.
SIS-SIP also adds itself to the Record-Route
header.
This may seem redundant because the Contact
header has the SIS-SIP’s address as well.
This is done because the Contact
header can change over the course of a dialog (see Target refreshes below).
The route set is fixed once the dialog is established, so adding Record-Route
to the initial request means the SIS stays on the route, even if Contact
changes later.
Note that although the SIS-SIP UAC received its own address in the response’s Record-Route
, it is ignored, so an empty route set is shown in the dialog state.
The behaviour when the SIS in a UAS role is similar, but Record-Route
and Contact
are automatically added to dialog-creating responses.
Local SIP service addresses
Multiple services can run on the SIS.
When SIS-SIP needs to add a Contact
or Record-Route
header, it uses the local SIP service address.
This is a SIP URI containing the SIP-SIS address and a reference to the currently executing service.
This ensures that requests in the other direction will arrive at the SIS and trigger the correct service.
The local SIP service address has a SIP URI of the form: sip:host:port;oc-svc=<token>
.
The oc-svc
parameter is derived from the SLEE Service ID, and tells the SIS which service to invoke.
A service can obtain its local SIP service address by calling the method
getLocalSipURI()
.
Target refreshes
As explained above, a SIP dialog contains a route set and remote target, used for routing mid-dialog requests to the other party.
The remote target is the Contact
header that was received from the other party in the initial request or response.
Either party on the dialog can initiate a target refresh request. A target refresh request is a request that may modify a dialog’s remote target. In SIP, INVITE, UPDATE, SUBSCRIBE, NOTIFY and REFER are defined to be target refresh requests.
When a user agent sends a target refresh request, it can elect to send a changed Contact
header value.
The other party receiving the target refresh request will replace the dialog’s remote target with the new value.
Similarly the Contact
header sent by the server in a success response will replace the client dialog’s remote target.
The SIS-SIP SipSession
automatically handles target refreshes by default.
As well as the remote target, it also maintains the dialog’s current local contact address.
This is the value used when SIS-SIP sends a target refresh request or response, which need a Contact
header.
Local contact addresses
By default, the local contact address is automatically updated when sending a target refresh request or response.
A service can change its local contact address by simply updating the Contact
header before sending the message.
Similarly, when forwarding target refresh messages from upstream or downstream, if the remote party has used a new Contact
value, then this will be passed through to the other party, and updates the local contact in the dialog sending the forwarded request.
The diagram below shows a target refresh request (UPDATE) on an established dialog, with a SIS-SIP B2BUA service in the middle.
Disabling pass-through
This default "pass-through" behaviour can be disabled if necessary.
Some services might want to ensure that their dialog has a fixed local contact address, that isn’t automatically updated when sending target refresh messages.
To do this a service can call
SipSession.setLocalContactAddress(address)
.
This sets a fixed local contact address that will be used in subsequent target refreshes.
Pass-through is disabled, so the local contact won’t change until the method is called again.
There is also the overloaded method
SipSession.setLocalContactAddress(address, enablePassthrough)
, where the local address can be set and optionally enable or disable the pass-through behaviour.
If pass-through is disabled for the initial request or response by one of the above methods, and the local contact address is a
local SIP service address, then SIS-SIP won’t automatically add itself to the Record-Route
header.
The assumption here is the service knows what it is doing, and is using a valid local contact address that will correctly route back to the SIS.
This behaviour can be useful in failover scenarios where the service might want to update the local contact address to point at a different node.
![]() |
Use caution if updating the local contact address when the SIS-SIP wasn’t added to Record-Route .
If the updated local contact address was not a valid SIS-SIP address, mid-dialog requests could be missed, putting the dialog in an unusable state.
|
Summary
When acting in a forwarding role (Proxy or B2BUA), SIS-SIP will by default:
-
Add the local SIP service address to
Record-Route
. -
Pass-through the
Contact
headers received from the calling and called parties. -
Automatically update the local contact and remote target addresses when a target refresh occurs.
When acting as an endpoint (UAC or UAS), SIS-SIP will by default:
-
Add the local SIP service address to
Record-Route
. -
Use the local SIP service address as its
Contact
. -
Automatically update the local contact and remote target addresses when a target refresh occurs.
Automatic pass-through of Contact
headers and target refreshes can be disabled using the
SipSession.setLocalContactAddress(address)
or
SipSession.setLocalContactAddress(address, enablePassthrough)
methods.
If pass-through was disabled before sending the initial request or dialog-creating response, and the local contact was set to a
local SIP service address,
then Record-Route
is not added to the message.