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 ->
SIP/2.0 180 Ringing
Call-ID: 68582ad9-19c1-123c-1794-080027b770b9
CSeq: 62905665 INVITE
Content-Length: 0
From: “Extension 1000” <sip:1000@>;tag=BSat99UpmZH5H
To: <sip:1001@>;tag=SP16daaf9e7e37fbe64
Via: SIP/2.0/UDP;branch=z9hG4bK3yccZUX0X27jm;received=;rport=5060
Server: OBIHAI/OBi1062-
Contact: <sip:1001@>
Require: 100rel
RSeq: 39965
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.

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"/>

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"/>

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"/>


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:


You can change the the valet announce changing the phrase macro


Change valet_anounce_ext to 

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


You can find more details on valet parking at:


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:")

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!="") {
    .... 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.