1. Getting started
  2. SIPr FAQs
  3. SIPr Online Release notes
  4. SIPr roadmap
  5. Developer setup instructions
  6. Mailing List

edit SideBar

 

SipperFAQs

Q1.What is SIPr?
Q2.What are the standards supported in SIPr?
Q3.What All Platforms SIPr supports?
Q4.What are the advantages of using SIPr?
Q5.What are the functionalities that can be tested with SIPr?
Q6.How to ensure that SIPr has installed properly?
Q7.How easy is to write a SIPr test case?
Q8.What is the difference between a test and a controller?
Q9.What is the significance of config file?
Q10.What all logs are generated?
Q11 How to validate in Sipper test cases
Q12.Does SIPr support automation?
Q13.Can we write our own parsers for headers?
Q14.Does SIPr support digest authentication?
Q15.Does SIPr support media?
Q16.What is the easy way to send 65535 bytes long INVITE?
Q17.How to override the “Content-Length” header?
Q18.How to assign values with white-spaces to a header?
Q19.How to change the messages arbitrarily? For example converting the “SIP/2.0” uppercase string of the request uri into “sip/2.0” lowercase string.
Q20.How to use pipe "|" operator with same class responses?
Q21.How to run two or more listeners(UAS) on different ports in a single test case?
Q22.How to use two different call ids in single test script?
Q23.How to send multiple contacts in REGISTER?
Q24.How to remove a certain header from the request?
Q25.How to get time diff b/w two messages in SIPr?
Q26.How to apply a SIPr patch?
Q27.When there are multiple instances of SIPr running on different machines then how would be they correlated?
Q28.How to move between two sessions?
Q29.How does offer-answer model work in SIPr?
Q30.What is the usage of transport filter and how to write it?
Q31.How to assign EMPTY value in headers?
Q32.How to send multiple identical responses?
Q33.How to include display name?
Q34.How to set current date in "date" header of a request?
Q35.How to modify ACK request headers?
Q36.Does SIPr support http server?
Q37.Can SIPr act as digest server?
Q38.How to generate xml contents in SIPr?
Q39.How to generate load in SIPr?

Q1.What is SIPr?
SIPr pronounced as Sipper is a SIP application testing framework that enables the developer and tester write new and complex test cases with extreme ease. While SIP applications are becoming more and more complex and feature rich the test tools have not been able to keep pace with them. SIPr was developed out of the necessity to test ever evolving SIP protocol and multi-faceted applications spanning SIP and Web. As new APIs for SIP application development made writing SIP applications accessible, we felt that writing tests for them, which are the cornerstone of agile development processes, should be even simpler. Sipper is our solution to that problem. SIPr is ideally suited for for feature, interop, regression, acceptance and field simulation. It has Servlet style API that ranges from extremely simple to very feature rich and powerful. While on one hand you can write simple test cases and controllers with very few lines of scripts, you can go further down the API depth and progressively control any aspect of SIP stack.

Q2.What are the standards supported in SIPr?
A number of RFCs such as RFC 3261 (SIP), 3262, 3265 (SIP Specific Event), 2327 (SDP), 2617 (Digest), 2833 (DTMF), 1889 (RTP) are natively supported by SIPr. Since SIPr is an application/test development framework, complying with a new RFC that does not change any basic protocol behavior is a breeze. Even for stack affecting changes hooks are provided at each layer to modify the default behavior of stack by writing extensions.

Q3.What All Platforms SIPr supports?
Operating System supported: Windows, Linux & Solaris
Language supported: Ruby

Q4.What are the advantages of using SIPr?
The most compelling reason would be simplicity, it keeps simple things simple and complex things possible. For advanced users SIPr offers complete flexibility in SIP development and testing -

  • SIPr is pluggable at each layer, starting from transport layer one can plug-in a transport filter chain. These filters can be applied on incoming or outgoing messages and these filters can be defined both at the global SIPr level affecting all messages and also at the individual testcase level.
  • SIPr has extensive in-built parsers for most SIP headers; users can not only define their own parsers for new/custom headers but also override the existing parsers to address custom extensions or even create malformed headers for testing.
  • SIPr transaction handling is FSM (Finite State Machine) based and SIPr provides simple method for controlling transactional behavior by providing a mechanism of call back handlers.
  • SIPr exposes all aspects of SIP stack as simple to use APIs that you can progressivley learn overtime on need basis.

Q5.What are the functionalities that can be tested with SIPr?
Through SIPr’s openness and flexibility almost any converged application - consisting of SIP, HTTP and RTP (Voice/DTMF) - can be tested with SIPr. The typical models include:

  • SIP UA, SIP B2BUA
  • SIP Proxy Server, SIP Registrar
  • SIP Subscribe/Notify, SIP MWI
  • HTTP requests and responses
  • RTP Media testing with multiple codecs

Q6.How to ensure that SIPr has installed properly?
For ensuring that SIPr has installed properly there is a script called “ssmoke”. Open a new terminal window and type .ssmoke., you should see something similar to the following.

C:\>ssmoke
Loaded suite C:/Users/nasir/workspace_svn/sipper/sipper/bin/run_smoke
Started
.
Finished in 0.452 seconds.

This is a simple smoke test built in test that runs a SIP test case with a test case and a controller. If you see an output like above you can assume that the installation is fine, otherwise you need to re-install SIPr. Usually if the installation runs fine you should not have any problem with running the smoke test, however the common problems could be an existing incompatible version of Ruby or Ruby libraries on the system.

Q7.How easy is to write a SIPr test case?
SIPr comes with a “sgen” script to generate test cases. So if you want to create a test case, open a new terminal window and type the following command:

C:\test_regression>sgen -t TestUas "< INVITE, > 180, > 200, < ACK, < BYE, > 200"

Note the “-t” flag indicating a Test case and the direction of arrows indicating a message direction.

However, very soon you will pick up basic SIPr scripting, unless you are already Ruby guru. Writing SIPr scripts is very addictive and it is easy to get test infected using SIPr. We promise that you will soon begin to type up your complex test scripts and see your test suite war chest swell.

Q8.What is the difference between a test and a controller?
Controller is a piece of code that a user would write and deploy on the SIPr platform. It contains the business logic to decipher the incoming protocol messages and send out its own messages. A Test on the other hand is again a deployable piece of code that contains a controller in it and besides doing all the messaging it also validates the call flow and messages.

Q9.What is the significance of config file?
The SIPr configuration lives under the config directory and has “log4r.xml” as the log config file and sipper.cfg as SIPr configuration file. Below is the example of configuration of local and remote IP & port.

LocalSipperIP: 193.168.1.100
:LocalSipperPort: 5060
:DefaultRIP: 193.168.1.102
:DefaultRP: 5060

Here change the IPs and ports for your network accordingly.

Q10.What all logs are generated?
Logs are generated in the logs directory under your project directory. There are two types of logs file generated:

/01/2008 02:15 PM 1328_testname_sipmsgtrace.log
22/01/2008 02:15 PM 1328_sipper.log

The xxxx_sipmsgtrace.log is the protocol message capture and xxxx_sipper.log is the SIPr log file with all the detailed processing. Here .xxxx. is the process ID.

Q11 How to validate in Sipper test cases
Depends upon what you want to validate for simple message validation (e.g you sent/recvd INVITE, recv/sent 200 OK etc), please see page 16/17 of the SIPr book. You will see the simple test with validation of messages.
For any complex validation you can use the session.do_record() API. Here in the controller (within the test), you can invoke do_record() and then verify that expectation in the test you can also use many of the in built validation helper methods.
e.g. If you have a test that sends INVITE and received 200 OK and you received the 200 OK with a custom header "Test-Header" with param "mytag" and " and Via header with "rport=4567".
Via: SIP/2.0/UDP 127.0.0.1:6061;rport=4567;received=127.0.0.1;branch=z9hG4bK-2352-1-0
Test-Header: fooo;mytag=bar
then within do_success_res() call back you can have the following


def on_success_res(session)

  session.validate_presence_of_headers :test_header
  session.validate_presence_of_header_params :test_header, :mytag
  if (session.iresponse.test_header.has_param?(:mytag))
    session.do_record(session.iresponse.test_header.mytag.to_s)
  else
    session.do_record("not_found")
  end
  session.do_record(session.iresponse.via.rport)
  session.request_with('ack')

end


The first two assertions validate presence of Test-Header and mytag param on Test-Header, next if/else statement records the value of mytag in the Header and final do_record records the value of rport parameter.
and in your test in your test method you can have -

 
def test_header_params self.expected_flow = ["> INVITE", "< 200", "! true {2,2}", "! bar", "! 4567", "> ACK"] verify_call_flow(:out)

end
Here the two "true" assertions are the result of calling validate_presence_xxx methods. "! bar" is the value of "mytag" parameter recorded and "! 4567" is the value of rport parameter recorded.
Please create a few test cases using "sgen" command and then add custom assertions using do_record() and validated by "! xxx" as above.

Q12.Does SIPr support automation?
Rakefile is a special file that contains the some automation tasks you can deal with it. You will typically write several independent tests in your project and would like to run them in a batch. All you need to do is to configure the proper listen points for SIPr in the sipper.cfg file. With all the configuration set up you can now just type “rake” in your project to automatically run all the tests.

X:\>rake
Started
.........................................................................
.........................................................................
.......................
Finished in 10.076 seconds.
55 tests, 843 assertions, 0 failures, 0 errors

The dot indicates a successful test completion. In case of a failure or an error “rake” will report with a .F. or .E. and then finally when tests complete will print a result of failure with line number where the failure happened.

Q13.Can we write our own parsers for headers?
Providing a custom pluggable parser is extremely easy to do. Your parser need to be in the lib/sipper_extensions directory under your controller source tree. It should be a class in the module SipHeaders and the class itself should be a subclass of Header. So for a header called Foo your class will look like

module SipHeaders
  class Foo < Header
  end
end

The next thing that you may want to do is to provide an assign method that would parse and populate various header constituents. You may also provide header_value and optionally a private _format and header_params.

Q14.Does SIPr support digest authentication?
SIPr comes with a complete and easy to use support of Digest authentication according to RFC 2617 and with all the changes proposed in RFC 3261. The client Digest Authentication usage comes into picture when the request sent by a SIPr controller is challenged by a 401 or a 407 response. The failure response contains a challenge in the form of a challenge header which can be any one of WWW-Authenticate or Proxy-Authenticate for 401 and 407 respectively. A simple session method

session.create_request_with_response_to_challenge()

is defined to re-create the new request but with proper response to the challenge, the response contains the digest credential of the user provided in the argument to the above method. For more details, please have look into the section 12 in SIPr book.

Q15.Does SIPr support media?
SIPr has simple but effective media support. Using SIPr you can create and receive the following media streams.

  1. G711U
  2. G711A
  3. DTMF according to RFC 2833

You can read up on chapter 15 from the SIPr book that deals exclusively with media.

Q16.What is the easy way to send 65535 bytes long INVITE?
There are two ways 1. You can read the content from a file and then assign the content in the controller. Please look at test_request.rb

request.content = File.new(File.join(File.dirname(__FILE__),"c_134.txt")).readlines

2. Or you can simply use

s = ''
65535.times { s << 'x' }
r.content = s

Note that Ruby strings are 8-bit bytes. So "s" variable here has exactly 65535 bytes.

Q17.How to override the “Content-Length” header?
By default SIPr puts the correct value by examining the content, but you can override the “Content-Length” header using the following method:

r = session.create_initial_request('INVITE','sip:nasir@sipper.com')
r.sdp = SDP::SdpGenerator.make_no_media_sdp         
r.content_length = "99"
r.content_length.freeze
session.send r

Note the usage of ‘content_length.freeze’. Calling freeze fixes the value of the header and now the value would not change for this header on the request.

Q18.How to assign values with white-spaces to a header?
To assign arbitrary values to any headers including system headers you can call method ‘assign_unparsed()’:

r = session.create_initial_request('INVITE','sip:nasir@sipper.com')
r.assign_unparsed(:abc, "        abc")
r.assign_unparsed(:xyz, "  \n      abc")
session.send r

The first argument is a symbol indicating the header name and second argument is the value. This bypasses any parser and assigns the string directly.

Q19.How to change the messages arbitrarily? For example converting the “SIP/2.0” uppercase string of the request uri into “sip/2.0” lowercase string.
Please have a look at transport filters (incoming and outgoing) in SIPr book. You can write a filter and change the message in any way you like. Have a look at transport filter tests under sipper_test “test_transport_handler.rb” and “test_transport_multi_handler.rb”

Q20.How to use pipe "|" operator with same class responses?
Using an expression like ‘< 401|407’ gives the error “ArgumentError: Bad exp str, use wildcard instead of |”. This is by design. Please use the wildcard as the exception says. Refer to section 6.6 of SIPr book. In this case the wildcard will be

['> INVITE','< 40x'…]

For more control, you can write custom assertion in the ‘on_failure_res()’ and use ‘do_record(“401_received”)’ or ‘do_record(“407_received”)’.

Q21.How to run two or more listeners(UAS) on different ports in a single test case?
SIPr supports multi-homing. One can provide multiple IPs and Ports for LocalSipperIP and LocalSipperPort setting. The way to do that in sipper.cfg is

…
:LocalSipperIP: 127.0.0.1
:LocalSipperPort: 
- 5062
- 5063

Note: one can also have multiple IPs in similar way.

Next thing to do is to affiliate the controller to a certain transport. This affiliation is optional. You can optionally define a method specified_transport() on the controller .Note for incoming messages if a controller is selected and it has defined specified_transport() then it will only be triggered when the IP and ports specified match with IP and port “received” on. Also note that in the absence of specified_transport() definition on a controller it can be triggered for any transport and can use any transport to send messages. So to use this feature and to clearly segregate the controllers then define this method on all controllers in the test. Ideally you would read this from controller specific config from sipper.cfg but the method is as simple as:

def specified_transport
   ['127.0.0.1', 5062]
end

Q22.How to use two different call ids in single test script?
Use a new session for the second REGISTER, this will create a new Call-Id and use the session recording continuation mechanism as defined in section 6.6.1 of SIPr book.

Q23.How to send multiple contacts in REGISTER?
There are several ways to have multiple contacts. You can use add_contact() or push_contact() convenience methods or can use comma separated values or an array of headers. e.g.

msg.contact = "contact1,contact2,contact3"
msg.contact = ["contact1","contact2","contact3"]
msg.add_contact("contact1").add_contact("contact2").add_contact("contact3")
msg.push_contact("contact3").push_contact("contact2").push_contact("contact1")

Please refer to test_message.rb/test_multi_valued(). You can also read section 7.4 of SIPr book.

Q24.How to remove a certain header from the request?
To remove a certain header from the request all one need to do is to set it to nil. e.g.

r = session.create_initial_request('INVITE','sip:nasir@sipper.com')
r.contact = nil
session.send r

Q25.How to get time diff b/w two messages in SIPr?
There are many way to get time difference depending upon what you want to do. If you are testing that the IUT retransmits a request in time then you can write a controller without transactions and let the remote retransmission come. He can record the times in a hash in session. e.g.

on first REGISTER -
 session[:first_register] = Time.now

on second register one can do things like 

 if session[:first_register]
   session[:second_register] = Time.now
 else 
   session[:first_register] = Time.now
 end

then later on   - 
 diff = session[:second_register] – session[:first_register]

Note that session object is the only stateful entity and can be used as a hash to store data between messages.

Q26.How to apply a SIPr patch?
Whenever you get or create a new SIPr gem, do the following steps on command prompt:

  • gem uninstall Sipper
  • gem install Sipper-x.x.x.gem -l

Q27.When there are multiple instances of SIPr running on different machines then how would be they correlated?
It is possible to run the test and controller(s) on different nodes and still make use of this completion signaling feature. The only thing that you would need to do is to make sure that :TestManagerName and :TestManagerPort configuration is set properly. The value for this should be same for all the nodes in the setup regardless of their role.

So assume that there are two nodes running a UAC and UAS each (both running SIPr tests), one can configure any one as TestManager, use its IP and Port (any free port). Use the same IP and port in both UAC and UAS and then they will be able to use the completion signaling (as done in locally running tests). Since one can run SIPr on different IPs and ports (multihoming) on the same machine, it can be done with just one box as well.One can write tests in such a way that he can get the success/failure of the overall testing from the SIPr instance that starts the test. Therefore, no great correlation is required in general.

Q28.How to move between two sessions?
Lets take an example - "Transfer - Attended" scenario: http://www.tools.ietf.org/html/draft-ietf-sipping-service-examples-14#section-2.5. In this particular scenario, at message F15 one wants to send a REFER to Alice is when there is a need to switch back to the session with Alice. What you can do is to save either the whole session object or the key to the session in the new session that you will create for Carol. So before sending message F8, create a new session towards Carol. Say carol_session, in that session save the original session (say alice_session) as attribute.

carol_session[:alice_session] = alice_session

SIPr by design synchronizes the operation on the session, thereby thread safety is ensured even though there are multiple processing thread. So after saveing the alice_session in carol_session and in the scope of carol_session tries to do operation on alice_session (e.g. self[:alice_session].create_request("Refer"), synchronization on alice_session is not ensured and the controller written will become thread unsafe. To avoid such cases make use of the custom messages.

In Carol_session Controller
    msg = CustomMessage.new
    msg.command = "sendRefer"
    self[:alice_session].post_custom_message(msg)
In Alice_session Controller
    def on_custom_msg(alice_session1, msg)
    	if msg.command == "sendRefer"
             	alice_session1.create_request("Refer")
    	end
    end

The use of custom message converts the direct call into an event-based call and synchronization is ensured on the Alice session.

Q29.How does offer-answer model work in SIPr?
If you wish to add offer in the initial invite

       --------------> Invite with Offer SDP
       <-------------  200OK with Answer
      ---------------> ACK.

       ###UAC Code###
       def start
         session = create_udp_session(SipperConfigurator[:DefaultRIP],
                   SipperConfigurator[:DefaultRP])
         session.offer_answer.make_new_offer
         r=session.create_initial_request('INVITE','sip:nasir@sipper.com')
         session.send r
        end

       ### UAS ###
       ## No controller coding is required.##

For Invite Transaction with offer/answer in 200OK & ACK

       --------------> Invite Without SDP
       <------------- 200 OK with Offer
       ---------------> ACK with Answer

       ###UAC code ###

       def start
           session = create_udp_session(SipperConfigurator[:DefaultRIP],
                     SipperConfigurator[:DefaultRP])
           r=session.create_initial_request('INVITE','sip:nasir@sipper.com')
           session.send r
        end

       ###UAS Code ###

       on_invite(session)
              session.offer_answer.make_new_offer unless session.irequest.sdp
       end

Q30.What is the usage of transport filter and how to write it?
The simple use could be to transform the message before sending or just after receiving on the wire for -

  1. Performing compression (SigComp) on the message or change some message attributes.
  2. Logging and auditing-Tracking users using a regex match.
  3. Content conversion-Scaling maps, and so on.
  4. Localization-Targeting the request and response to a particular locale.
  5. XSL/T transformations of XML content-Targeting responses to more that one type of client.
  6. Message, Header, Content manipulation.
  7. Drop incoming or outgoing packet

Here is an example of inline transport filter used to create a request/response without the mandatory From header:

class MyInTransportHandler < Transport::TransportOutgressFilter
 def do_filter(msg)
   start_index = msg.index("From")
   end_index = msg.index("\r\n", start_index)
   m = msg[0...start_index] + msg[end_index+1..-1]
   return m  
 end 
end

For more details, please see the sipper book.

Q31.How to assign EMPTY value in headers?
Following is the convention used to set an empty header or to remove a header from the sipmessage. -

mymessage.myheader = nil  //To remove the myheader from the Sip mymessage 
mymessage.myheader = ''    // To set an empty value for myheader in the Sip mymessage

Q32.How to send multiple identical responses?
To send multiple identical responses, call the API session.respond_with(response) as many times as you need. And change the self expected flow in your test script. Example:

def on_register(session) 
    session.respond_with(200) 
    session.respond_with(200) 
end

And
self.expected_flow = ['< REGISTER', '> 200 {1,2}']

In above mentioned code, on register request, we send two 200 responses and in expression, "200 {1,2}'" implies at least 1 outgoing 200 response and at most 2 outgoing 200 responses.

Q33.How to include display name?
To include display name into From header:

request.from.display_name = "Sipper"

Q34.How to set current date in "date" header of a request?
To set the current date in date header of a request:

Request.date = Time.now.gmtime.strftime("%a, %d %b %Y %T GMT")

Q35.How to modify ACK request headers?
To modify the ACK request headers, use the API called “create_subsequent_request()” . Example:

request = session.create_subsequent_request('ACK') 
request.from.display_name = “nasir_123” 
session.send(request) 

<<<<<<<

Q36.Does SIPr support http server?
Sipper comes with HTTP Server support as well. WEBrick webserver is integrated with Sipper and now our controllers can not only generate HTTP requests but also receive HTTP Requests. So now we can easily do things like click to call etc. In order to configure Sipper for HTTP Server just set SipperHttpServer = true in config. Optionally you can set SipperHttpServerPort, the default is 2000. Also you can optionally use SipperHttpServerConfig that is a hash which can be passed to WEBrick. Please see WEBrick doc for this config, this is not required for most of Sipper scenarios but for HTTPS can be used to set certificate etc. Then in the controller you can optionally implement interested_http?(req) method, if interested return true, false otherwise. The request is WEBrick::HTTPRequest object and interesting things could be req.path (which gives the relative URL to check if you are interested in this request). The other interesting attribute in request could be req.query which is a hash of name value pairs for a form submission in a POST request. The interested_http?(req) is optional because if you have implemented the on_http_xxx() method that it means you are interested just like on_invite etc. Finally you need to implement on_http_xxx(req, res, session) method in controller. The xxx can be get/put/post etc (the HTTP methods). The session is the Sipper session and req , res are WEBrick::HTTPRequest and WEBrick::HTTPResponse objects.

Note in HTTP you don’t need to send HTTP Response but only fill the values in response, on return from the method the response is automatically sent.

class UasHttp1Controller < SIP::SipTestDriverController

        transaction_usage :use_transactions=>true

        def on_invite(session)
          session.send_http_get_to('http://127.0.0.1:2000/get')  
        end


        def on_http_res(session)
          res = session.create_response(200)
          res.set_body session.ihttp_response.body.split(/\r|\n\r|\n/), 'text/xml' 
          session.send res
          logd("Received INVITE sent a 200 from "+name)
        end
end

Q37.Can SIPr act as digest server?
Sipper can also act as Digest Server. The server Digest Authentication usage comes into picture when Sipper wants to challenge any incoming request by a 401 or a 407 response. For simpler usage a directive is provided. Here you can simply set a directive as to what methods you want to authenticate using directives e.g “authenticate_requests :invite, :ack” or “authenticate_proxy_requests :invite” etc. Here the control will come to on_xxx() method in the controller only after authentication has succeeded.

class UasDigestS3Controller < SIP::SipTestDriverController

  transaction_usage :use_transactions=>true
  realm "my_sipper.com"
  authenticate_requests :invite

  def on_invite(session)      
    session.respond_with(200)     
  end

  def on_ack(session)
    session.request_with 'BYE'  
  end

  def on_success_res(s)
    s.invalidate(true)
  end
end

For Fine grained control - There are two basic methods that you will use. “session.create_challenge_response()” with various arguments creates a challenge response. In on_xx method you can use “session.authenticate_request()” which returns two Boolean values, first if true means that authentication succeeded and second returns true if the request was seen before, which means that if first value is true and second is also true then this request failed twice at which time you may send a 403 (or something else).

class UasDigestS1Controller < SIP::SipTestDriverController

  transaction_usage :use_transactions=>true

  def on_invite(session)
    result, old =  session.authenticate_request
    if result
      session.respond_with(200)
    else
      if old
        session.respond_with(403)  
      else
        r = session.create_challenge_response(session.irequest, false,
            "sipper2.com")
        session.send(r)
      end  
    end
  end
end

Also note that passwords from server side are read from a csv file “passwd_store” ( we may also read from DB). By default this is same directory as logs but can be set by SipperPstorePath variable. Also the default realm is “sipper.com” but again it can be set globally as SipperRealm config key or can be set as directive “realm ‘my_sipper.com’” etc. by the controller. Or can be set on the Session object.

Q38.How to generate xml contents in SIPr?
SIPr provides the facility to the users to add xml content to a message. You can add registration information document (reginfo+xml, RFC 3680) and Presence Information Data Format (pidf+xml, RFC 3863).

To add the PIDF (Presence Information Data Format) content to a message:

pidfdata = XmlDoc::PidfTuple.new("open", "sip:nasir@sipper.com", "0.2", "Welcome to SIPr World !!")

In the above example, pidfdata contains the pidf tuple object whose fields are optional: status, contact_addr, contact_priority and tuple_note

r.content = session.create_pidf_doc("sip:joe@example.com",pidfdata,"Registration done !!").to_s

Then the API called create_pidf_doc() adds the content to the message, that takes the parameters entity, pidftuple and presence_note. You can also pass array of pidftuple and presence_note if required. Here “r” could be request or response object.

To add RegInfo content to a message:

r.content_type = "application/reginfo+xml"
r.content= session.create_reginfo_doc('sip:joe@example.com',0).to_s

The arguments are the AOR, document version and an array of Contact addresses. If contact address is nil, it picks the contacts from sipper RegistrationStore for the aor registered.

Q39.How to generate load in SIPr?
SIPr can be used for Load testing. One can generate load using the simple command line options:

srun -i <source IP> -p <source Port> -r <remote IP> -o <remote Port> -l <laod option> -b <Number of calls> -n <calls/sec> -c <controllername>

Here are some guidelines for load testing:

1. It is recommanded to use a controller script instead of a test script in case of load generation to get better performance (as controller doesn't involve call flow verification).

2. If somebody wants to run load using a test case, please set the value of variable SessionLimit to a lower value e,g 6000

3. Make the log level to "ERROR" in the config/log4r.xml file.

4.If u get the "Too many open files" error, add the following line in your test script at:

def test_case
  Process.setrlimit(Process::RLIMIT_NOFILE, 4096, 65536)  
  :	
  :
end