Understanding PRACK: The SIP Method for Reliable Provisional Responses

PRACK, or Provisional Response Acknowledgement, is an optional  SIP (Session Initiation Protocol) method, defined in the RFC 3262,  that is used to provide reliability for provisional responses in a SIP communication.

Provisional responses, also known as “1xx” responses, are used to indicate that a request has been received and understood by the server, but that additional information or action is needed before the request can be completed. Examples of provisional responses include “183 Session Progress” and “180 Ringing.”

The problem with provisional responses is that they are unreliable, meaning that they can be lost or delayed in transit. This can lead to confusion and delays in the communication process. PRACK addresses this issue by providing a mechanism for the client to acknowledge receipt of a provisional response and request retransmission if necessary.

When a client receives a provisional response, it can send a PRACK request to the server. The server will then respond with a “200 OK” response, indicating that the provisional response has been received and understood. If the client does not receive a “200 OK” response within a certain period of time, it can retransmit the PRACK request.

PRACK is useful in situations where the client and server are communicating over a network with high packet loss, such as a wireless network. It can also be used to provide reliability for provisional responses in situations where the client and server are communicating over a network with high delay, such as a satellite link.

According to the RFC3262:

The UAS MUST send any non-100 provisional response reliably if the
initial request contained a Require header field with the option tag
100rel.  If the UAS is unwilling to do so, it MUST reject the initial
request with a 420 (Bad Extension) and include an Unsupported header
field containing the option tag 100rel.

Lab – FreeSwitch, Obihai Phone

I’m going to demonstrate how to enable PRACK using FreeSwitch and a MicroSIP phone. On FreeSwitch you have to add the line <param name=”enable-100rel” value=”true”/> in the SIP profile for the phones. Then make a call to a phone who supports 100-rel such as the Obihai and the magic will appear. The SIP ladder of the exchange is shown below.

When I tried this lab with MicroSIP it didn’t work. MicroSIP includes in the 180 ringing response the header Supported: 100rel. For Obihai when you configure the phone for 100 rel support it adds the 100rel as Required. Once one of the sides have it as required, it starts.

2023/01/28 10:15:15.632273 192.168.15.128:5060 -> 192.168.15.52:5060
SIP/2.0 180 Ringing
Call-ID: 68582ad9-19c1-123c-1794-080027b770b9
CSeq: 62905665 INVITE
Content-Length: 0
From: “Extension 1000” <sip:1000@192.168.15.52>;tag=BSat99UpmZH5H
To: <sip:1001@192.168.15.128:5060>;tag=SP16daaf9e7e37fbe64
Via: SIP/2.0/UDP 192.168.15.52;branch=z9hG4bK3yccZUX0X27jm;received=192.168.15.52;rport=5060
Server: OBIHAI/OBi1062-5.1.11.5312
Contact: <sip:1001@192.168.15.128:5060>
Require: 100rel
RSeq: 39965
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, PRACK, NOTIFY
Allow-Events: hold,talk,dialog

You should use PRACK with care. These method is not often used, so it is easier to find bugs and incomplete implementations. The example is merely illustrative,I’m not suggesting you enable PRACK.

In conclusion, PRACK is a SIP method that provides reliability for provisional responses. It allows clients to acknowledge receipt of provisional responses and request retransmission if necessary.

GRUU – Globally Routable User-Agent URI

GRUU is a type of SIP (Session Initiation Protocol) URI (Uniform Resource Identifier) that is used to identify and route communications sessions in a VoIP network. It enables a user to be reached at a specific device or location, even if the user has multiple devices or locations.

In traditional telephone networks, a user’s telephone number is a unique identifier that can be used to reach that user at a specific device or location. However, in a SIP network, where users can have multiple devices using a single AOR (address of record) such as alice@example.org. GRUU addresses this issue by providing a way for users to be reached at a specific device or location, even if their IP address or network location changes.

There are some cases when it is required to identify a single instance of a SIP user. Let’s suppose you are making a transfer and the user has more than one device with the same AOR, in the target it is better to use a SIP instance identifier than the IP address. IP addresses are not so NAT friendly.  Also, in the REFER rather than forking the next INVITE to all registered devices it is possible to route to an specific device specifying the temporary or permanent GRUU.

Lab – Using GRUU with OpenSIPS and Blink

The free softphone Blink (www.icanblink.com) supports GRUU.
OpenSIPS also supports GRUU.

To activate, change the module parameter.

modparam("registrar", "disable_gruu", 0)

After changing this module parameter you will see in he 200OK of the register the temporary GRUU (temp-gruu=”sip:tgruu….) and the public gruu (pub-gruu=”sip…). Now you can route by the new URIs.

2023/01/27 13:56:38.821684 192.168.15.93:5060 -> 192.168.15.31:63523
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.15.31:63523;received=192.168.15.31;rport=63523;branch=z9hG4bKPjfc5e9377637a4af7a2c0276486bf89ac
To: "Flavio Goncalves" <sip:alice@domaina.com>;tag=a067.ad68745297904767ba5e92957a0613ae
From: "Flavio Goncalves" <sip:alice@domaina.com>;tag=e1794c2b31b04c83a78a03de9e8f0878
Call-ID: f31c9b20962143399f52f20ccbeaafaf
CSeq: 2 REGISTER
Contact: <sip:alice@192.168.15.31:54043;ob>;expires=12, <sip:14297635@192.168.15.31:63523>;expires=600;pub-gruu="sip:alice@domaina.com;gr=urn:uuid:fbd61308-0
b-4f37-bc8c-0be1cd33cd8f";temp-gruu="sip:tgruu.AUYEWmsFRWQJSBMPP1gTNnAUXAMyWB4yHhNcA3NEAj0KBUYHNwsWMVRGAl1jCV1jARRRQ2dXQ2QdElBWMBxAMVVBUApgAhM3CBYTCGAAE2pSQg
ZQNBZwNDClc1BEI1AkBQDTFUETJWEVU=@192.168.15.93:5060;gr";+sip.instance="urn:uuid:fbd61308-01db-4f37-bc8c-0be1cd33cd8f"
Server: OpenSIPS (3.2.10 (x86_64/linux))
Content-Length: 0

For sequential requests it is important now that you can route properly. Looking at the ACK below you will notice that the address in the RURI is not the final address, but the GRUU.

2023/01/27 14:15:47.520837 192.168.15.31:5080 -> 192.168.15.93:5060
ACK sip:alice@domaina.com;gr=urn:uuid:fbd61308-01db-4f37-bc8c-0be1cd33cd8f SIP/2.0
Via: SIP/2.0/UDP 192.168.15.31:5080;rport;branch=z9hG4bKPj762eec6221574c13a201e4b55717e1b8
Max-Forwards: 70
From: "bob" <sip:bob@domaina.com>;tag=c72cfe7516434b8d864918366a4bdc69
To: <sip:alice@domaina.com>;tag=2b45621a6a35482e97a16046c2e0ef74
Call-ID: 7457248f27d4475fbf5d062106e4af1d
CSeq: 24702 ACK
Route: <sip:192.168.15.93;lr;did=7ca.7d91344>
Content-Length: 0

So, for sequential requests with GRUU support, you need to do a lookup before sending.

if (has_totag()) {
  if($(ru{uri.param,gr})!=null) {
    lookup("location");
  }
  ...

In the snippet above, we are checking for the presence of the parameter gr in the request URI. If gr is present we do a lookup to find the IP address of the specific instance.

In conclusion, GRUU is a powerful solution for maintaining reliable and consistent communication in a VoIP network. It allows users to be reached at a specific device or location, regardless of their IP address or network location. It is essential in some advanced scenarios such as transfers. Implementing GRUU in a VoIP network can be easily done using open-source SIP servers, and is an excellent choice for businesses and individuals looking for a cost-effective and flexible communication solution.

Paging and Intercom

Paging was immortalized in the “Charlie’s Angel television series. It is not difficult to do it in your own IP phone.  This is useful when you want to make a call directly to the speaker of the callee on the other phone. The destination phone auto-answers the call and enable the speaker. 

The experiments show that these features are highly dependent on the phone and they are implemented in slightly different ways depending on the device’s vendor. Many phones simply don’t support them or have to be configured. Zoiper Free is an example of phone not supporting the Call-info header, but the setting to support is available in the paid version. Microsip supports it and most good phones supports, but have to be configured. 

Most implementations use the Call-Info header. Below is a quick table for the most popular phones.

Vendor Implementation
Grandstream Call-info: answer-after=0
Yealink Call-info: answer-after=0
Alert-info: alert-autoanswer
Alert-info: answer-after=0
Polycom Alert-info:  Ring-Answer

Please, check the documentation of your device to  verify which header it supports. Some phones also support Intercom using a request uri parameter called intercom=true.

Example:

INVITE sip:alice@domain.com;intercom=true SIP/2.0

Most phones will require a previous configuration authorizing the auto-answer. Enabling intercom on your phones pose a security risk because many people will not be aware  of the Intercom feature and may leave the phone open. This allows an attacker to eavesdrop the sound of the destination room.  

To implement is very simple, create a feature code. As an example *6. After typing *6 + the number, strip the prefix and add the header.

Example for OpenSIPS:

if($rU=~"^*6"") {
    strip(2);
    append_hf("Call-info: ;answer-after=0\r\n") ;
}

Example for FreeSwitch. With the variable sip_auto_answer, FS inserts the appropriate headers. You could also add a header using:

<extension name="intercom">
  <condition field="destination_number" expression="^\*6(.*)$">
    <action application="set" data="dialed_extension=$1"/>
    <action application="export" data="sip_auto_answer=true"/>
    <action application="bridge" data="user/${dialed_extension}@${domain_name}"/>
  </condition>
</extension>

For Asterisk:

[intercom]
exten=> _*6.,1,Set(PJSIP_HEADER(add,Call-Info)=;answer-after=0)
same => Dial(PJSIP/{EXTEN:2})

I have tested the first example and worked quite well.

This article generated a new chapter on the training “SIP Training for Professionals” and a new feature in the WeHostVoIP Cloud PBX.

I hope you enjoy!

 

Multi-tenant parking with FreeSwitch

In this brief article we will explain how to implement Call Parking on FreeSwitch.

What is Call Parking?

Call parking is a feature in a telephone system that allows a call to be placed on hold and “parked” at a designated extension, where it can be retrieved by any phone within the system. This can be useful when a call needs to be transferred to someone who is not available at the moment, or when a call needs to be transferred to to yourself in a different room.

How FreeSwitch Implements Call Parking

You can use two functions,  valet_park() from  mod_valet_parking() or  park() from mod_dptools to implement call parking. 

Park() is very simple and just sends the call to a “limbo” where it can be retrieved using uuid_bridge or uuid_transfer.  You have to implement your own logic of parking. 

Valet_park() is more robust and implements the whole logic of call parking.

Valet park options:

<lotname> <extension>|[ask [<min>] [<max>] [<to>] [<prompt>]|auto [in|out] [min] [max]]

Parking a Call 

<extension name="park-in">
  <condition field="destination_number" expression="^(700)$">
     <action application="valet_park" data="{domain} auto in 701 799"/>
  </condition>
</extension>

Retrieving a Call

 <extension name="park-out">
 <condition field="destination_number" expression="^(7\d\d)$">
   <action application="answer"/>
   <action application="valet_park" data="{domain} $1"/>
 </condition>
</extension>

Using DTMF to park a call

During the call you can call *7 to park a call. The application bind_meta_app ties a DTMF number to a function. 

<action application="bind_meta_app" data="7 a s valet_park::{domain} auto in 701 799"/>

Announcement

The standard announcement is a bit rude. I want to change to “your call is parked at the extension <extension>

To change the phrase macros associated to valet parking you have to edit:

/etc/freeswitch/lang/en/vm/sounds.xml

You can change the the valet announce changing the phrase macro

valet_announce_ext
valet_lot_full
valet_lot_empty

Change valet_anounce_ext to 

<macro name="valet_announce_ext">
<input pattern="^([^\:]+):(.*)$">
<match>
<action function="play-file" data="ivr/ivr-extension_number.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>

Reference

You can find more details on valet parking at:

https://developer.signalwire.com/freeswitch/FreeSWITCH-Explained/Modules/mod_valet_parking_3966447

Originating a call using OpenSIPS B2BUA

One of the most used commands for FreeSwitch and Asterisk is the originate command. It is an essential feature for dialers, apis and click to call. OpenSIPS is a SIP proxy and theoretically it shouldn’t originate a call. However, OpenSIPS can also work as a B2BUA server. In this article I will show you how to originate calls.

For this lab I have used the same configuration of the SIP training, just added the commands below. The version is OpenSIPS 3.2.

In the first place let’s load and configure the module. Importante below is the parameter server_address. This address will be present in the contact of the call being sent.

loadmodule "b2b_logic.so"
loadmodule "b2b_entities.so"
modparam("b2b_entities", "script_req_route", "b2b_request")
modparam("b2b_entities", "script_reply_route", "b2b_reply")
modparam("b2b_logic", "server_address", "sip:192.168.15.93:5060")

You should not authenticate requests coming from your own server. After generating a call using the B2BUA, the module will send a SIP request back to the proxy. This request should be accepted without authentication.

if ($si!="192.168.15.93") {
    .... authentication commands
}

You don’t need anything special on the B2B routes

route[b2b_request] {
    xlog("b2b_request ($ci)\n");
}
route[b2b_reply] {
    xlog("b2b_reply ($ci)\n");
}

The B2BUA scenario in this case is irrelevant. In the past the scenarios were defined in an XML file. Now they are defined in the B2B routes. In this case the scenario is the default.

Now to generate a call use:

opensips-cli -x " mi b2b_trigger_scenario scenario_id=default entity1=client1,sip:alice@domaina.com entity2=client2,sip:bob@domaina.com

As you can see two calls were generated.

In the link below you will see two things. The first is the server sending the call to itself and then to the final destination. SIP reinjected in the routing script. The second thing, in the INVITE you will it does not have an SDP body.  This is allowed and is called Late negotiation or 3PCC. You will see the first SDP in the 200OK and the second in the ACK. For some systems such as FreeSwitch to work with a call like this requires some settings such as enable-3pcc. For the MicroSIP phones worked like a charm.

Well, now you now how to generate calls using OpenSIPS. It may be advantageous because by not using media will give you a large scale of dialing.

This article is generating a chapter in the future release of the OpenSIPS Advanced Course. Stay tuned.

If you want to learn more about OpenSIPS, the free course Quick Start to FreeSwitch is a good start.