Every once in a while I feel the need to get away from SIP the architecture and write about SIP the protocol (which is a little bit like the department of redundancy department – Session Initiation Protocol Protocol). Yes, I adore all those servers and services, but it’s the bits and bytes that attracted me to SIP in the first place.
Waylon Jennings said it best in his song, “Luckenbach, Texas.”
Maybe it’s time we got back to the basics of love.
Today, I want to share the love and write about an extremely important, but sometimes misunderstood SIP header.
When a user agent client (UAC) creates a SIP request, it must insert a Via header into that request. The Via header identifies the protocol name (SIP), protocol version (2.0), transport type (e.g. UDP or TCP), IP address of the UAC, and the protocol port (typically 5060) used for the request. This information allows the recipient of the request (a user agent server) to return SIP responses to the correct device. For example, if my SIP soft-phone were to send an INVITE request, it would contain a Via similar to the following.
Via: SIP/2.0/UDP 10.11.228.67:5060
If I were operating in a point-to-point configuration, the soft-phone that received the INVITE would inspect the Via header to determine the location of my PC. It would then use that information to return a “100 Trying” response. Of course, unless I am in a lab environment, I never use SIP in a point-to-point fashion. Here at work, there are all sorts of SIP components between my soft-phone and the soft-phone I am calling. There is a Session Manager, Communication Manager, and perhaps a Session Border Controller between us. Thankfully, via headers are not reserved for endpoints. Every SIP entity uses them.
The rules for processing Via headers are very simple. Every UAC must add its own Via header before sending a SIP request. If there is already a Via header in the message, the UAC adds the new one at the top of the list before sending it to the next hop.
Remember that INVITE I sent in my example? When it ends up on the called party’s device, it might contain several Via headers. When the called party is ready to send the “100 Trying,” it simply removes the top Via header and sends the response to the indicated party. In my work configuration, that top Via would most likely identify a Session Manager. However, if the soft client was a remote user, it would be my company’s SBC. It doesn’t matter, though. Whoever receives the response will remove the top Via header and send it to the next hop. This keeps happening until the Trying message lands on my PC.
This Via stacking allows a SIP request to pass through any number of intermediaries and every recipient of that message will know exactly how to pass back any subsequent responses.
Ah, but there’s more
To keep things simple I failed to mention something important about Via headers. Along with the protocol and IP information, every Via header contains a “branch” parameter. Here is that Via again with a branch parameter I pulled from a Wireshark trace.
Via: SIP/2.0/UDP 10.11.228.67:5060; branch=z9hG4bK10_16a83292baa1de54e0b7843_I
The branch parameter must be unique across space and time for all requests sent by a user agent. The exceptions to this rule are CANCEL and ACK for non-2xx responses. A CANCEL will have the same branch parameter as the request it cancels. An ACK for a non-2xx response will have the same branch parameter as the INVITE whose response it acknowledges.
The uniqueness of the branch header is used to facilitate its use as a transaction ID. A SIP transaction is a message exchange between two user agents that starts with a request and ends with a final response. For a simple call, the INVITE through final response is one transaction, the ACK is another transaction, and the Bye through the 200 OK is yet another transaction. All these transactions combine to make a single dialog.
If you crave more knowledge about SIP message uniqueness, please see my blog, Let’s Play (SIP) Tag.
The branch parameter always begins with the same string of seven characters — “z9hG4bK.” This requirement was added to identify that the branch was created in accordance with RFC 3261 and not the older RFC 2543 which did not require global uniqueness.
Okay, that’s it. I got my protocol fix for the day. I hope you are as thrilled as I am.
Take me on out, Waylon…
So, Baby let’s sell your diamond ring
buy some boots and faded jeans
and go away