Transfer Call from Twilio to Asterisk Without Duration Charges

I am trying to achieve the following use case:

  1. A caller dials a Twilio number.
  2. Twilio forwards the call to my Asterisk server.
  3. Asterisk receives the call from Twilio and immediately connects the caller to sip:test@sip.linphone.org (essentially bridging the caller directly to the SIP address).
  4. Once the call is connected between the caller and sip:xxxx@sip.linphone.org, Twilio should no longer be involved in the call (to avoid duration charges).

The desired flow is: Caller → Twilio → Asterisk → sip:test@sip.linphone.org

At the end, the connection should be: Caller → sip:test@sip.linphone.org

I understand that I will need to pay Twilio for the incoming and outgoing leg until the caller is connected to Linphone SIP. However, I do not want Twilio to continue counting and charging for the whole call duration once the connection is established between the caller and the SIP address.

Problem: Right now, the call flow works, and the Linphone client receives the call successfully. However, Twilio continues to log the call duration and charge for the entire duration of the call.

Here is my current configuration: These are the complete configurations for receiving calls from Twilio and connecting the caller with Linphone SIP using Asterisk.

extensions.conf:

[from-twilio]

  • exten => s,1,NoOp(Call received from Twilio)
  • exten =>s,n,NoOp(Forwarding to sip:test@sip.linphone.org)
  • exten => s,n,Dial(PJSIP/sip-linphone) ; Forward the call to Linphone SIP address
  • exten => s,n,NoOp(Call to sip-linphone ended) exten => s,n,Hangup()

pjsip.conf:

[transport-udp-nat]

  • type=transport
  • protocol=udp
  • bind=0.0.0.0
  • local_net=xx.xx.xx.xx/16
  • external_media_address=xx.xx.xx.xx
  • external_signaling_address=xx.xx.xx.xx

[twilio0-aors]

  • type=aor
  • contact=sip:test.sip.twilio.com:5060

twilio-trunks

  • type=endpoint
  • transport=transport-udp-nat
  • context=from-twilio
  • disallow=all
  • allow=ulaw
  • direct_media=yes
  • force_rport=yes
  • rewrite_contact=yes

twilio0

  • aors=twilio0-aors

[twilio0-ident]

  • type=identify
  • endpoint=twilio0
  • match=54.172.60.0
  • match=54.172.60.1
  • match=54.172.60.2
  • match=54.172.60.3

[twilio0-auth]

  • password=xxxxxx
  • username=xxxxxx

[sip-linphone]

  • type=endpoint
  • transport=transport-udp-nat
  • context=from-sip-linphone
  • disallow=all
  • allow=ulaw
  • aors=sip-linphone-aors
  • direct_media=yes
  • force_rport=yes
  • rewrite_contact=yes

[sip-linphone-aors]

  • type=aor
  • contact=sip:xxxx@sip.linphone.org:5060

[linphone]

  • type=endpoint
  • context=from-pstn
  • disallow=all
  • allow=ulaw
  • aors=linphone
  • refer_blind_progress=yes

[linphone]

  • type=aor
  • contact=sip:linphone.org

[linphone]

  • type=auth
  • auth_type=userpass
  • password=xxxxx
  • username=xxxxx

Question:

  1. How can I configure Asterisk (or Twilio) so that Twilio disconnects completely after the call is bridged between the caller and sip:xxxx@sip.linphone.org?
  2. Is there a way to use Transfer or any other method to hand off the call to Asterisk entirely and stop Twilio’s billing?

Any help or guidance would be greatly appreciated! Thank you!

That’s not how ITSP charging works. They will always retain the signalling path, so that they an bill both legs, even if you manage to short circuit the media path. If there were technical ways of avoiding charging, they would probably ether be treated as breaches of acceptable use clauses, in the contract, or subject to penalty charges (an example of the latter is that I believe some providers impose these if there is an excessive proportion of short or unanswered calls).

Your dialplan doesn’t even take you out of the signalling path, but even if you did take yourself out of the signalling path, Twilio would stay in it.

Charging for forwarded legs has been standard practice since before ARPANET became the Internet and long before SIP was ever formalised.

PS your configuration files are badly mangled. They should be posted wrapped in pre-formatted text markup, but they have actually been posted marked up, in multiple places, in different ways, and with at least two lines run together in the original text.

PS I would be rather surprised if either provider actually had broken NAT, requiring the NAT work arounds that you have enabled.

Hi,

My call flow is as follows:

  1. The call starts from the Twilio SIP trunk. Under this SIP trunk, I have configured my Asterisk server.
  2. Every call begins when the user dials the Twilio number, and it is received by the Asterisk server.
  3. My Asterisk server immediately calls the Twilio SIP domain.
  4. Under the Twilio SIP domain, I have a webhook that routes the call to my worker.
  5. If my Twilio client’s workers do not respond within 30 seconds, I use Twilio Refer to send the call back to my Asterisk server, which then connects to my backup SIP.
  6. The backup SIP is a simple SIP for Linphone.

Flow:

  • Caller → Twilio SIP Trunk → Asterisk Server → Twilio SIP Domain → Worker (if available)
  • If no response from workers:
    Twilio SIP Domain → Asterisk Server → Backup SIP (Linphone)
  • Final Connection: Caller → Backup SIP (Linphone)

The whole flow is working fine, and the caller is successfully connected to the backup SIP.


The Issue:
The issue occurs after disconnecting the call.

Twilio shows logs like this:

  • Status: Completed
  • Type: Trunking Originating
  • From: +11xxxxxxxxxx
  • To: sip:+11mmmmmm@nn.nn.nn.nn;region=us1
  • SIP-PSTN
  • Duration: 18 seconds

Definitions:

  • +11xxxxxxxxxx: My mobile/landline/SIM number from which the call started.
  • +11mmmmmm: The Twilio number under which I have the SIP trunk.
  • nn.nn.nn.nn: My server’s IP address.
  • sip-linphone: The backup SIP domain.

Goal:
I want Twilio to stop charging once the call is connected between the caller and my backup SIP.

Here is my current dial plan:

[from-twilio]

; Step 1: Call received from Twilio SIP trunk

exten => +11mmmmmm,1,NoOp(Call received from Twilio for +11mmmmmm)

exten => +11mmmmmm,n,NoOp(Forwarding to Twilio SIP domain)

; Step 2: Forward the call to the backup SIP domain

exten => +11mmmmmm,n,Dial(PJSIP/twilio0,30) ; Forward to Twilio back>

exten => +11mmmmmm,n,ExecIf($[“${DIALSTATUS}” != “ANSWER”]?NoOp(Call >

exten => +11mmmmmm,n,ExecIf($[“${DIALSTATUS}” != “ANSWER”]?Hangup()) >

exten => +11mmmmmm,n,NoOp(Call to Twilio SIP domain ended)

; Step 3: If the worker is not available, attempt to forward the call aga>

exten => +11mmmmmm,n,NoOp(Worker not available, forwarding to backup >

exten => +11mmmmmm,n,Dial(PJSIP/twilio0,60) ; Forward again with a 6>

exten => +11mmmmmm,n,NoOp(Call to backup SIP completed or failed)

exten => +11mmmmmm,n,ExecIf($[“${DIALSTATUS}” = “NOANSWER”]?Hangup())>

; Step 4: Forward the call to Linphone

exten => ++11mmmmmm,n,NoOp(Forwarding call to Linphone)

exten => +11mmmmmm,n,Dial(PJSIP/sip-linphone,30) ; Forward the call >

exten => +11mmmmmm,n,ExecIf($[“${DIALSTATUS}” != “ANSWER”]?NoOp(Linph>

exten => +11mmmmmm,n,ExecIf($[“${DIALSTATUS}” != “ANSWER”]?Hangup()) >

exten => +11mmmmmm,n,NoOp(Call to Linphone completed)

; Step 5: Ensure proper cleanup and call termination

exten => +11mmmmmm,n,Hangup() ; Disconnect the original SIP trunk

; Fallback handling for blind transfers or unexpected scenarios

exten => s,1,NoOp(Blind transfer or fallback triggered from Twilio SIP do>

exten => s,n,Dial(PJSIP/sip-linphone,30) ; Attempt to forward the call t>

exten => s,n,NoOp(Transfer to Linphone completed or failed)

exten => s,n,Hangup() ; Cleanly hang up after the transfer

Please provide a solution so that, in the final step, when the caller and Linphone are connected, the Twilio SIP trunk can be removed from the connection.

Thanks

@ali.raza-i Please do not start new threads for the same thing you’ve posted about before.

Before It was PSTN call right now its SIP TRUNK

It’s still a PSTN call going through Twilio.

DIALSTATUS will never be ANSWER (or ANSWERED), as, without options to say otherwise, answered calls result in dial returning a non-zero status, which cause Asterisk to end dialplan execution.

What does “Twilio SIP domain” mean? The bit of dialplan that seems to match this calls an endpoint, called twillio0, using its unmodified contact URI. If this represented what some people (but not Asterisk or SIP) call a trunk, there would be dialled digits.

Forwarding is something of a loose term in telephony, but what this dialplan actually does is establish a tandem connection (relays the call).

What does “Twilio Refer” mean? There is nothing in your dialplan that would result in a REFER being generated.

Even if you did generate a REFER, Twilio will have set themselves up as a back to back user agent, and would not signal to the caller to establish the call without a provider or via another provider, and normal SIP users would not have their clients configured to be able to do that, e.g they would have firewall and NAT rules that only worked with their provider.

In practice, if a REFER is sent to them, your provider will bill the call as though it was being relayed through their connection point to you, even if they actually repeat the REFER back towards the call’s origin.

This dialplan would stall here, which suggests you have rekeyed it, which is never helpful when others are trying to debug it.

The caller is never going to be directly connected. If they are Twillio customers, they will be connected to Twilio and Twilio will be connected to Asterisk. A REFER might remove the Asterisk connection, but you are not generating a REFER.

A classic example is how European roaming was handled before tariffs got complicated. If you were outside your home country and called to someone on the same provider and in the same foreign country, the call would access the other person’s HLR, in their home country and get a roaming number, in the visited country, and final call would then be set up entirely in the foreign country. However, even though only minimal international traffic was involved, the call would be charged as an outgoing call from the home country to the visited country, and the incoming call as a roaming call, as though originated in the home country.

In a pure SIP world, with no NAT and minimal firewalling, it would be possible to send a REFER/Replaces back to the originating VoIP phone, but once you introduce SIP providers, they are just not going to support that topology. Historically, SIP providers came into existence to allow PSTN to interwork with the SIP world, but nowadays they are taking the place of the PSTN, as a mandatory man in the middle, but also people setting up SIP based phone systems have used them to act as gatekeepers, to prevent voice spam. (Actually things are much the same way with internet email.

The original design uses SMTP everywhere, and only requires DNS as global infrastructure, but nowadays most people experience email as an asymmetric system in which they only use SMTP to providers, and pull incoming email with, for example IMAP. When I first had home internet, I actually used SMTP direct to the incoming mail host of the destination, but I suspect that, nowadays, many of their systems would refuse to talk to me, as users have come to accept that email has to have a provider in the middle.

If the call originates in the PSTN, I think it even less likely that the first VoIP operator n the chain would try to request the PSTN to reroute the call. For a start, PSTN operators also operate on the basis that the transferror pays for the leg to the new destination, so, if Twillio did instruct the PSTN operator to transfer the call, they would have to bear the cost.