Tuesday, July 5, 2011

Problems in sending SIP Requests with TCP mode enabled.

Here I am discussing some problems which I faced while sending SIP Requests with TCP mode enabled.

  1. SIP Request is not hitting the SIP Servlet.
    • Some time it happens that when you write -t t1 (enable transport as TCP) in command your Request does not hit the servlet, but when you are not enable TCP i.e. not writing -t t1 in your command Request works fine.
    • It might be because of some Request headers are missing in your scenario file. When enabling TCP mode, Content-Type header becomes compulsory - check if it is there in your Request header (Courtesy - Sameer Saurabh). Similarly check for other headers as well. Also check for special characters in your scenario file, these should not be there (Courtesy - Sri Narayanan).
  2. SIP Request is behaving abnormally in your SIP Servlet.
    • Sometime it happens your Request is reaching to your SIP Servlet but behaving abnormally means not doing the JOB intended to be done. 
    • There might be many reasons for this, check the log carefully. The problem that I found was in the Contact header of my Request there is no "transport=tcp" written, which must be there in your Contact header if TCP mode is enabled.
    • For Example : Contact: <sip:;transport=tcp;fid=server_1> (Just for fun - there is no place called
  3. Success log is printing but Request is not sent by SIP Servlet.
    • Suppose in your logs you will see that "Request successfully sent" or something like that as per your logging, but still Request is not received at other end.
    • Again there could be many reasons for this, the one that encountered by me is the one while adding the address of my client in Route Header. 
    • For your information, for sending the created request from you SIP Servlet to any client you have to give real client address (IP:PORT) either in Request-Uri Header by using sipServletRequest.setRequestUri("IP:PORT") method or in Route Header by using sipServletRequest.pushRoute(Address/SipUri). Actually pushRoute has two overloaded versions, one takes javax.servlet.sip.Address and the other takes javax.servlet.sip.SipURI.
    • Now if you are using second approach (Route Header) then take care of the real address in hand, if it is in the format sip:IP:Port then use pushRoute(javax.servlet.sip.Address) and if it is in the format IP:Port then use pushRoute(javax.servlet.sip.SipURI) overloaded method. Taking care of this would possibly help you.
  4.  Runtime exception (java.lang.IllegalStateException: Message cannot be modified.) is coming.
    • While executing SIP Servlet you are encountered with Runtime Exception java.lang.IllegalStateException : Message cannot be modified. Then there could be two (probable more, but I am aware of only two) reasons for this : 
      •  It seems that when dispatching an ACK response on a 200OK which included a contact without a transport parameter results in this exception. For more info visit : http://old.nabble.com/handling-a-contact-without-a-transport-param-td29462668.html. (Courtesy - Shantnu Jain)
      • Another one which is encountered by me is : Whenever you create a request whether in-session or out-of-session, whether Dialog Initiation Request or Dialog Inside Request, you have to set real client address either in Route header or in Request-Uri header. In UDP mode if you are creating a request with linked session or in-dialog session, then setting real address in Route header or Request-Uri header is not mandatory, it will take it from the session by which you created the request, but in TCP you have to set the real address explicitly.
Hope this post helps you .... Please update if you find some more problems.

Regards : Basit { theTechnoCreative(); }

Sending SIP Requests with TCP mode enabled.

First of all we need to know - why TCP is required over UDP ?

The problem occurs when the application attempts to send out a request over UDP, and the request message exceeds the MTU (Message Transfer Unit) size. By default, the MTU boundary is 1300 bytes. If the request is larger than the MTU size, the underlying stack is responsible to switch the transport connection from UDP to TCP.

This process is explained in section 18.1.1 of RFC 3261. (Courtesy - Swarnapriya)
For more info visit 18.1.1 (Page 141-142) of http://tools.ietf.org/html/rfc3261

Here are the steps to send SIP request using Glassfish/sailfin with TCP :

1. Start the Server and login to admin console (http://localhost:4848) (Note : Admin port is configurable so check your admin port in config settings).
2. Now in Sidebar go to Configurations Link ---> Sip Service as shown below :

3. Now Click on SIP Protocol Tab on SIP Service Page and check the "Default Transport" Enabled check box as shown below :

4. Now your SIP Application Server is ready for SIP Transmission via TCP. 

5. As far as I concerned Sipp is the tool most of the SIP Programmers use for testing SIP Servlets. Using Sipp you can write scenario files describing the flow of your requests in XML and then from command line you can run that scenario file which will hit your SIP Servlet and shows the result. For more information on how to use Sipp for testing and for sample sipp scenario files visit another post of this Blog.

6. At this point I hope you read lot about Sipp, so I am directly jumping on the command option you have to write for enable transport=tcp. In the command you write for running the Scenario file you have to add -t t1 at the end of command but before the -timeout option if you are using one in your command.
    Depending on the value of -t parameter, this will take the values "UDP", "TCP" etc.
    t1: TCP with one socket
    u1: UDP with one socket (default)
    l1: TLS with one socket. etc...
    Example Commands : 
    UAC : sipp -sf <scenario file> <server ip>:<server port> -i <client ip> -p <client port> -m 1 
    -mp 7000 -cp 8990 -t t1 -timeout 20s
    UAS : sipp -sf <scenario file> <server ip>:<server port> -i <client ip> -p <client port> -m 1 
               -t t1 -timeout 40s
    Regards : Basit { theTechnoCreative(); }