How to measure INVITE to 200 OK ring duration in OpenSips? - sip

OpenSips provides various timeout for configuration: http://www.opensips.org/html/docs/modules/1.8.x/tm.html
How to measure the time (ring duration) between receiving an INVITE and 200 OK? Is there a special function?

I was able to solve this using the $Ts core variable.
i) Record the initial timestamp:
$dlg_val(inviteStartTimestamp) = $Ts;
ii) When 200 OK is received in the reply route, find the time difference in seconds:
$var(ringDurationSec) = $Ts - $dlg_val(inviteStartTimestamp{s.int});

Related

Simulate a continuous client-server communication in ns3

I want to simulate a simple continuous client-server request-response behaviour; i.e. the client sends a packet to server, then server receives the packet and responds to the client, then client receives the response packet and it again sends out a new packet to server and so on. I have figured out to send one round of communication (client->server->client) but don't know how to continue this. This is my code to achieve one round:
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (wifiApNode.Get (nWifiAp - 1));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
UdpEchoClientHelper echoClient (apDevicesInterfaces.GetAddress (nWifiAp - 1), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
ApplicationContainer clientApps;
clientApps = echoClient.Install (wifiStaNodes.Get (nWifiSta - 1));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
If I set any other int than 1 in echoClient.SetAttribute ("MaxPackets", UintegerValue (1));, I am able to have that many rounds but the problem is that they all start at 1 second gap (due to this: echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));). I want that client starts sending out as soon as it receives response from the server and not after waiting for 1 second.
You will need to modify the echoClient application and in particularly the 'HandleRead' method that is respnsible for the reception of packets.
Currently it only prints that one is received. Take a look at the UdpEchoServer application, where the HandleRead is generating the response.

Request-response life cycle in Play(Scala) 2.4.X

Few days back, I faced issue where client was receiving response from play application after 20 seconds. I have new relic set on production server which keeps telling about RPM, average response time, CPU and memory usage, etc. As per new relic response time was not exceeding 500 milli-seconds, but I verified that client was receiving response after 20 seconds. To dig out more I added logs in that tells about time required to serve request in play application. I added logs Filter as per following:
val noCache = Filter { (next, rh) =>
val startTime = System.currentTimeMillis
next(rh).map { result =>
val requestTime = System.currentTimeMillis - startTime
Logger.warn(s"${rh.method} ${rh.uri} took ${requestTime}ms and returned ${result.header.status}")
result.withHeaders(
PRAGMA -> "no-cache",
CACHE_CONTROL -> "no-cache, no-store, must-revalidate, max-age=0",
EXPIRES -> serverTime
)
}
}
private def serverTime = {
val calendar = Calendar.getInstance()
val dateFormat = new SimpleDateFormat(
"EEE, dd MMM yyyy HH:mm:ss z")
dateFormat.setTimeZone(calendar.getTimeZone)
dateFormat.format(calendar.getTime())
}
During my load test, I sent around 3K concurrent requests to play-app and captured TCPDUMP for all requests. Following are my observations:
As per play-application-log, max time play app took to response was 68 milli seconds.
As per TCPDUMP max time required to response any request was around 10 seconds.
As per new relic max response time was around 84 milli-seconds(as this is very close to logs I added, we can ignore this one)
As far as I know Filter is one of the last stage in request-response life cycle. So if logs in Filter says that request needed 68 milli-seconds and TCPDUMP claims that response was sent after 10 seconds then what caused delay in responding the request?
I understand that in multi-threading environment there is possibility of context switch after particular statement execution. But context switch should not cause this much delay. As per new relic there were less than 50 threads during this load test.
Can someone explain what can cause this? You are welcome to provide deep insights in request-response life cycle.
I was able to fix above issue by increasing FD limit. FD was causing late response.

How timeout works in Dispatch

At API there is:
val http = Http.configure(_
.setConnectionTimeoutInMs(1)
)
What for is this config? I use it with:
.setMaxRequestRetry(0)
I fought I will get failed future after timeout. Future I create like that:
val f = http(u OK as.String)
f.map {
NotificationClientConnectionParams.parseFromString
}
But instead of failure I get success long after my timeout.
How it should work?
My test looks like this:
val startTime = java.time.LocalTime.now()
val f = TcpUtil2.registerClientViaDispatch(ClientHeaders("12345", "123456789"))
f onSuccess {
case c =>
println(s"Success: $c")
println(java.time.Duration.between(startTime, java.time.LocalTime.now()).toMillis)
}
f onFailure {
case e =>
println(s"failure:${e.getMessage}")
}
Thread.sleep(2000)
Response time is in hundreds of milliseconds and I got success. Is it a bug of dispatch?
An HTTP roundtrip goes through several phases (overly simplified):
establishing connection
connection established
sending request payload
request payload sent
waiting for response payload
receiving response payload
response payload received
From what I understand you measure the time between states 1 and 7.
setConnectionTimeoutInMs comes from async-http-client which is used by Dispatch internally. Here's an excerpt from its documentation:
Set the maximum time in millisecond an AsyncHttpClient can wait when connecting to a remote host
Thus, this method sets the maximum time the client will wait between states 1 and 2.
There's also setRequestTimeoutInMs:
Set the maximum time in millisecond an AsyncHttpClient wait for a response
This method seems to set the time between states 5 and 6 (or 7, I'm not sure which one).
So here's what's probably happening in your case. You connect to remote host, the server accepts the connection very quickly (the time between 1 and 2 is small), so your Future doesn't get failed. Then there are several options: either server takes a lot of time to prepare the response before it starts sending it back to you (the time between 5 and 6), or the response is very big so it takes a lot of time to deliver it to you (the time between 6 and 7), or both. But since you don't set the request timeout, your Future is not getting failed because of this.

Reactive Extensions mix multiple sequences

I'm working in a TCP context and I need to react to incoming data: If too much data is received i need to ignore all but the last received; if no data comes in for a long time I have to send a request to the server.
First proposition is solved like this:
Observable.FromEventPattern<ObjectReceivedEventArgs>( _client, "ObjectReceived" )
.Throttle( TimeSpan.FromMilliseconds( 500 ) )
.Subscribe( args => ... );
Second proposition is solved with a Timer:
Observable.Timer( ... ).Subscribe( ... );
Now, I can mix it this two things so I can send a request to the server if no data comes in, in a timely fashion?
Yes, you can make a second subscription to your source event like this:
Observable.FromEventPattern<ObjectReceivedEventArgs>(_client, "ObjectReceived")
.Select(_ => Unit.Default)
.StartWith(Unit.Default)
.Throttle(TimeSpan.FromSeconds(/*desired timeout here */))
.Take(1).Repeat()
.Subscribe(_ => /* poke server here */);
What this does is start a stream off with a Unit value and attempt to throttle it with the arrival of events. As long as events arrive within the timeout period, the stream is suppressed by the throttle, as soon as events pause for the timespan then OnNext is fired. Note that the Take(1) causes the timeout to keep firing after each subsequent pause even if no further events arrive - simply remove that if you want to only call the server one time after events cease.

Asterisk - how to change ringing timeout in realtime extension?

I use Asterisk 11 and try to change ringing timeout in MySQL realtime extention. It takes only 7~10 seconds to hangup automatically. I checked extension and it was like this.
here is a screeshot of extension table in asteriskrealtime mysql database.
SIP/5162860921,60
I changed this one to
SIP/5162860921,300
However, there was no change. How can I extend ringing timeout to 60 seconds?
extensions.conf (I use realtime database)
[general]
[globals]
;
[from-sip]
switch =>Realtime
CLI log
== Using SIP RTP CoS mark 5
-- Executing [2000#from-sip:1] Dial("SIP/1000-00000000", "SIP/2000,30")
== Using SIP RTP CoS mark 5
-- Called SIP/2000
-- SIP/2000-00000001 is ringing
-- Got SIP response 486 "Busy here" back from 14.63.12.134:5060
-- SIP/2000-00000001 is busy
== Everyone is busy/congested at this time (1:1/0/0)
-- Executing [2000#from-sip:2] Answer("SIP/1000-00000000", "2000#from-sip")
> 0x7fe6fc01bc00 -- Probation passed - setting RTP source address to 223.62.180.115:47204
-- Executing [2000#from-sip:3] hangup("SIP/1000-00000000", "")
== Spawn extension (from-sip, 2000, 3) exited non-zero on 'SIP/1000-00000000'
It was softphone application problem. I changed it to 60 seconds and it is working fine now.. SIP/1000,60 was right.