For the past number of months my life has centred on the development of a SIP-based instant messaging client (extensible for other protocols but focussed on SIP). Naturally, the aim of writing any SIP client these days is with a goal to achieving IMS (IP Multimedia Subsystem) compliance, whose backbone is SIP.
The development is Java-based for a number of reasons that I won’t enter into. It’s not the only choice but it made sense in this situation. The availability of Java SIP stacks is however far less than satisfactory and made the task far more arduous than one would have thought. In the end a decision was made to roll with the apparent leader and seeder of the JSR180 reference implementation, the NIST Jain SIP libraries. No doubt though the development was exciting and we managed to send the client to trade shows at 3GSM, CTIA, Globalcomm and Fall VON – no mean feat!
Read on if you are interested in the route to success…
As part of the development, on route to achieving IMS compliance, one of the tasks was to ensure IPv6 compatibility. This is where Java of course starts to shine with its dual-stack nature. The task was starting to look good but being a seasoned developer I knew that a certain degree of cynicism would be required irrespective of the levels of confidence.
The first problem that we noted was the Jain SIP libraries that we were using. For the duration of the development we were implementing against v1.1 of Jain SIP API and had no requirement to change from this; until IPv6 that is. Jain SIP v1.1 is not IPv6 compliant and in fact the compliance has only been introduced as of the most recent releases of the libraries (v1.2). Word of warning, rolling in these libraries is not as straight forward as one might expect. It doesn’t involve copying in new jar files. A few of the method signatures have changed in the interfaces and require a reasonable amount of reworking in your code base.
With SIP libraries now updated the next task was to rigorously inspect the application code for nasty IPv4 specific code misdemeanors. Naturally there are always going to be a few minor issues but we had been vigilant enough in our development effort to keep these to a bare minimum. In fact the most challenging task was to ensure that all IP addresses used in the code definitely came from the one, initial setting and were never resolved again down the call stack. There are a couple of reasons for this: Firstly on dual stack machines resolving the local host address may not always give you the preferred IPv6 address. Secondly, if you have multiple NICs in the machine then you have the problem of determining the preferred adapter and so forth. Once that was out of the way then it was reasonably plain sailing from the SIP perspective as all addresses were manipulated through String objects and not specific InetAddress classes, therefore the dual stack would always be able to infer the correct address type.
Almost there but not just yet! Any good IM client worth its salt will not just enable person-to-person text messages but also voice and video. Voice and video introduce another complexity to the client that must be checked for compliance and guaranteed IPv6. So voice and video, after the initial call setup via a SIP invite, no longer have anything to do with SIP. Arise RTP as yet another protocol that now must be checked for IPv6 compatibility. When a SIP invite message is sent to initiate a voice or video call between two clients there needs to be a little negotiation done.
Hi how are you? Do you speak ULAW, G711a? Would you like to talk now? What port and address should we talk on? etc.
In SIP this negotiation is done through SDP (Session Description Protocol) which is a payload appended to the invite messages that are sent. As part of the content of this SDP, the IP protocol version needs to be specified. Here is an example of what that content looks like:
v=0 o=Bob 2890844526 2890842807 IN IP4 192.168.100.100
s=ClientApp c=IN IP4 192.168.100.100 t=0 0
m=audio 8000 RTP/AVP 0 a=rtpmap:0 pcmu/8000
m=video 8002 RTP/AVP 34 a=rtpmap:34 H263/90000
As you can see both the IP address format and the protocol version specifier need to be changed depending on the IP version used. Determining an IPv6 address, in absolute terms, is not that easy. In fact it took over 800 characters of a regular expression to guarantee that we had matched all acceptable IPv6 formats! This regular expression was also necessary outside of RTP as in SIP, the specification of an IPv6 address in the SIP headers requires the address to be placed within ‘[‘ and ‘]’ characters. That however was it, as soon as we could determine the IP version and modify the SDP content on-the-fly, all was good and harmony had been restored. Running a few tests on the code base to check for IPv6 connectivity and communication between two Windows-based machines yielded a positive and joyous result. Setting up the Windows machines for IPv6 only connections was much less enjoyable but that’s another story.
So long story short, IPv6 is not really that difficult in principle but should definitely not be taken for granted. Roll it in early and don’t walk into traps that will cause you trouble in the long run. IPv6 from the beginning is far less effort than rolling in IPv6 afterwards. Our development always had it in mind and as such we avoided any serious problems. However, only when we tried to test compliance did we notice a discrepancy or two. For this reason alone I cannot stress the importance and requirement for IPv6 testbeds in all organisations.
Couple of notes:
Credit for the success of this development is shared with my colleague Tom Walsh (aka RTP guru). Also a note of thanks is due to both John Ronan and Miguel Ponce de Leon who, in the context of the IST ENABLE project, provided us with a very useful IPv6 test network so that we could get things moving.