Plivo Inbound trunking on Freepbx (Inbound routes)

Hiya,

i’m having trouble with freepbx routing inbound calls correctly when they come in from plivo.

routing seems to only work with DDI numbers (or CID) - would it be possible to route calls based on the number the caller actually Dialed? i have set up routes but the inbound routing is simply sending the number to my normal anycall IVR not to a certain extension!!!

what do you mean by “number the caller actually Dialed” isn’t this the DID?

not really sure, when i am looking at the call logs, freepbx says the DID is “s”

no idea why that is happening but the inbound Routing is not working even though i have set up the DID correctly.

probably the DID that is coming in is not setup in your freepbx. have you tried looking at the verbose output of the cli (asterisk -r -vvvv) while receiving a call?

As you suggested i fired up Asterisk in verbose (asterisk -r -vvvv) whilst receiving a call.

which is very helpful for debuging by the way.

Here is the output of the log of the call.

I cannot see any references to the DDI actually dield in the CLI Log.

`  == Using SIP RTP CoS mark 5
-- Executing [s@from-trunk:1] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__DIRECTION=INBOUND") in new stack
-- Executing [s@from-trunk:2] Gosub("SIP/PlivoTrunkxxxxxyyyyyzzzz", "sub-record-check,s,1(in,s,force)") in new stack
-- Executing [s@sub-record-check:1] GotoIf("SIP/PlivoTrunkxxxxxyyyyyzzzz", "0?initialized") in new stack
-- Executing [s@sub-record-check:2] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__REC_STATUS=INITIALIZED") in new stack
-- Executing [s@sub-record-check:3] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "NOW=1483715367") in new stack
-- Executing [s@sub-record-check:4] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__DAY=06") in new stack
-- Executing [s@sub-record-check:5] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__MONTH=01") in new stack
-- Executing [s@sub-record-check:6] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__YEAR=2017") in new stack
-- Executing [s@sub-record-check:7] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__TIMESTR=20170106-150927") in new stack
-- Executing [s@sub-record-check:8] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__FROMEXTEN=unknown") in new stack
-- Executing [s@sub-record-check:9] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__MON_FMT=wav") in new stack
-- Executing [s@sub-record-check:10] NoOp("SIP/PlivoTrunkxxxxxyyyyyzzzz", "Recordings initialized") in new stack
-- Executing [s@sub-record-check:11] ExecIf("SIP/PlivoTrunkxxxxxyyyyyzzzz", "0?Set(ARG3=dontcare)") in new stack
-- Executing [s@sub-record-check:12] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "REC_POLICY_MODE_SAVE=") in new stack
-- Executing [s@sub-record-check:13] ExecIf("SIP/PlivoTrunkxxxxxyyyyyzzzz", "0?Set(REC_STATUS=NO)") in new stack
-- Executing [s@sub-record-check:14] GotoIf("SIP/PlivoTrunkxxxxxyyyyyzzzz", "2?checkaction") in new stack
-- Goto (sub-record-check,s,17)
-- Executing [s@sub-record-check:17] GotoIf("SIP/PlivoTrunkxxxxxyyyyyzzzz", "1?sub-record-check,in,1") in new stack
-- Goto (sub-record-check,in,1)
-- Executing [in@sub-record-check:1] NoOp("SIP/PlivoTrunkxxxxxyyyyyzzzz", "Inbound Recording Check to s") in new stack
-- Executing [in@sub-record-check:2] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "FROMEXTEN=unknown") in new stack
-- Executing [in@sub-record-check:3] ExecIf("SIP/PlivoTrunkxxxxxyyyyyzzzz", "13?Set(FROMEXTEN=+442070000000)") in new stack
-- Executing [in@sub-record-check:4] Gosub("SIP/PlivoTrunkxxxxxyyyyyzzzz", "recordcheck,1(force,in,s)") in new stack
-- Executing [recordcheck@sub-record-check:1] NoOp("SIP/PlivoTrunkxxxxxyyyyyzzzz", "Starting recording check against force") in new stack
-- Executing [recordcheck@sub-record-check:2] Goto("SIP/PlivoTrunkxxxxxyyyyyzzzz", "force") in new stack
-- Goto (sub-record-check,recordcheck,5)
-- Executing [recordcheck@sub-record-check:5] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__REC_POLICY_MODE=FORCE") in new stack
-- Executing [recordcheck@sub-record-check:6] GotoIf("SIP/PlivoTrunkxxxxxyyyyyzzzz", "1?startrec") in new stack
-- Goto (sub-record-check,recordcheck,16)
-- Executing [recordcheck@sub-record-check:16] NoOp("SIP/PlivoTrunkxxxxxyyyyyzzzz", "Starting recording: in, s") in new stack
-- Executing [recordcheck@sub-record-check:17] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "AUDIOHOOK_INHERIT(MixMonitor)=yes") in new stack
-- Executing [recordcheck@sub-record-check:18] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__CALLFILENAME=in-s-+442070000000-20170106-150927-1483715367.158") in new stack
-- Executing [recordcheck@sub-record-check:19] MixMonitor("SIP/PlivoTrunkxxxxxyyyyyzzzz", "2017/01/06/in-s-+442070000000-20170106-150927-1483715367.158.wav,ai(LOCAL_MIXMON_ID),") in new stack
-- Executing [recordcheck@sub-record-check:20] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__MIXMON_ID=0x7fb3149ec360") in new stack
-- Executing [recordcheck@sub-record-check:21] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__RECORD_ID=SIP/PlivoTrunkxxxxxyyyyyzzzz") in new stack
-- Executing [recordcheck@sub-record-check:22] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__REC_STATUS=RECORDING") in new stack
-- Executing [recordcheck@sub-record-check:23] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "CDR(recordingfile)=in-s-+442070000000-20170106-150927-1483715367.158.wav") in new stack
-- Executing [recordcheck@sub-record-check:24] Return("SIP/PlivoTrunkxxxxxyyyyyzzzz", "") in new stack
-- Executing [in@sub-record-check:5] Return("SIP/PlivoTrunkxxxxxyyyyyzzzz", "") in new stack
-- Executing [s@from-trunk:3] Gosub("SIP/PlivoTrunkxxxxxyyyyyzzzz", "app-blacklist-check,s,1()") in new stack
-- Executing [s@app-blacklist-check:1] GotoIf("SIP/PlivoTrunkxxxxxyyyyyzzzz", "0?blacklisted") in new stack
-- Executing [s@app-blacklist-check:2] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "CALLED_BLACKLIST=1") in new stack
-- Executing [s@app-blacklist-check:3] Return("SIP/PlivoTrunkxxxxxyyyyyzzzz", "") in new stack
-- Executing [s@from-trunk:4] ExecIf("SIP/PlivoTrunkxxxxxyyyyyzzzz", "1?Set(__FROM_DID=s)") in new stack
-- Executing [s@from-trunk:5] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "CDR(did)=s") in new stack
-- Executing [s@from-trunk:6] ExecIf("SIP/PlivoTrunkxxxxxyyyyyzzzz", "0 ?Set(CALLERID(name)=+442070000000)") in new stack
-- Executing [s@from-trunk:7] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__MOHCLASS=") in new stack
-- Executing [s@from-trunk:8] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__REVERSAL_REJECT=FALSE") in new stack
-- Executing [s@from-trunk:9] GotoIf("SIP/PlivoTrunkxxxxxyyyyyzzzz", "1?post-reverse-charge") in new stack
-- Goto (from-trunk,s,11)
-- Executing [s@from-trunk:11] NoOp("SIP/PlivoTrunkxxxxxyyyyyzzzz", "") in new stack
-- Executing [s@from-trunk:12] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__CALLINGNAMEPRES_SV=allowed_not_screened") in new stack
-- Executing [s@from-trunk:13] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "__CALLINGNUMPRES_SV=allowed_not_screened") in new stack
-- Executing [s@from-trunk:14] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "CALLERID(name-pres)=allowed_not_screened") in new stack
-- Executing [s@from-trunk:15] Set("SIP/PlivoTrunkxxxxxyyyyyzzzz", "CALLERID(num-pres)=allowed_not_screened") in new stack
-- Executing [s@from-trunk:16] NoOp("SIP/PlivoTrunkxxxxxyyyyyzzzz", "CallerID Entry Point") in new stack
-- Executing [s@from-trunk:17] Goto("SIP/PlivoTrunkxxxxxyyyyyzzzz", "ivr-3,s,1") in new stack

== Begin MixMonitor Recording SIP/PlivoTrunkxxxxxyyyyyzzzz
– Goto (ivr-3,s,1)
– Executing [s@ivr-3:1] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “INVALID_LOOPCOUNT=0”) in new stack
– Executing [s@ivr-3:2] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “_IVR_CONTEXT_ivr-3=”) in new stack
– Executing [s@ivr-3:3] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “_IVR_CONTEXT=ivr-3”) in new stack
– Executing [s@ivr-3:4] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “__IVR_RETVM=”) in new stack
– Executing [s@ivr-3:5] GotoIf(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “0?skip”) in new stack
– Executing [s@ivr-3:6] Answer(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “”) in new stack
> 0x7fb31879c9e0 – Probation passed - setting RTP source address to 52.59.63.228:16808
– Executing [s@ivr-3:7] Wait(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “1”) in new stack
– Executing [s@ivr-3:8] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “IVR_MSG=custom/welcomeuncompressed”) in new stack
– Executing [s@ivr-3:9] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “TIMEOUT(digit)=3”) in new stack
– Digit timeout set to 3.000
– Executing [s@ivr-3:10] ExecIf(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “1?Background(custom/welcomeuncompressed)”) in new stack
– <SIP/PlivoTrunkxxxxxyyyyyzzzz> Playing ‘custom/welcomeuncompressed.slin’ (language ‘en_GB’)
– Executing [s@ivr-3:11] WaitExten(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “1,”) in new stack
– Timeout on SIP/PlivoTrunkxxxxxyyyyyzzzz, going to ‘t’
– Executing [t@ivr-3:1] Goto(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “timeconditions,1,1”) in new stack
– Goto (timeconditions,1,1)
– Executing [1@timeconditions:1] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “DB(TC/1/INUSESTATE)=INUSE”) in new stack
– Executing [1@timeconditions:2] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “DB(TC/1/NOT_INUSESTATE)=NOT_INUSE”) in new stack
– Executing [1@timeconditions:3] GotoIfTime(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “09:00-19:00,mon-sat,,,Europe/London?truestate”) in new stack
– Goto (timeconditions,1,12)
– Executing [1@timeconditions:12] GotoIf(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “0?falsegoto”) in new stack
– Executing [1@timeconditions:13] ExecIf(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “0?Set(DB(TC/1)=)”) in new stack
– Executing [1@timeconditions:14] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “DEVICE_STATE(Custom:TC1)=NOT_INUSE”) in new stack
– Executing [1@timeconditions:15] ExecIf(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “0?Set(DEVICE_STATE(Custom:TCSTICKY)=INUSE)”) in new stack
– Executing [1@timeconditions:16] GotoIf(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “1?ivr-2,s,1”) in new stack
– Goto (ivr-2,s,1)
– Executing [s@ivr-2:1] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “TIMEOUT_LOOPCOUNT=0”) in new stack
– Executing [s@ivr-2:2] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “INVALID_LOOPCOUNT=0”) in new stack
– Executing [s@ivr-2:3] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “_IVR_CONTEXT_ivr-2=ivr-3”) in new stack
– Executing [s@ivr-2:4] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “_IVR_CONTEXT=ivr-2”) in new stack
– Executing [s@ivr-2:5] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “__IVR_RETVM=”) in new stack
– Executing [s@ivr-2:6] GotoIf(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “1?skip”) in new stack
– Goto (ivr-2,s,9)
– Executing [s@ivr-2:9] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “IVR_MSG=custom/press12test”) in new stack
– Executing [s@ivr-2:10] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “TIMEOUT(digit)=3”) in new stack
– Digit timeout set to 3.000
– Executing [s@ivr-2:11] ExecIf(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “1?Background(custom/press12test)”) in new stack
– <SIP/PlivoTrunkxxxxxyyyyyzzzz> Playing ‘custom/press12test.slin’ (language ‘en_GB’)
– Executing [s@ivr-2:12] WaitExten(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “5,”) in new stack
– Timeout on SIP/PlivoTrunkxxxxxyyyyyzzzz, going to ‘t’
– Executing [t@ivr-2:1] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “TIMEOUT_LOOPCOUNT=1”) in new stack
– Executing [t@ivr-2:2] GotoIf(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “0?final”) in new stack
– Executing [t@ivr-2:3] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “IVR_MSG=no-valid-responce-pls-try-again”) in new stack
– Executing [t@ivr-2:4] Goto(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “s,start”) in new stack
– Goto (ivr-2,s,10)
– Executing [s@ivr-2:10] Set(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “TIMEOUT(digit)=3”) in new stack
– Digit timeout set to 3.000
– Executing [s@ivr-2:11] ExecIf(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “1?Background(no-valid-responce-pls-try-again)”) in new stack
– <SIP/PlivoTrunkxxxxxyyyyyzzzz> Playing ‘no-valid-responce-pls-try-again.ulaw’ (language ‘en_GB’)
== Spawn extension (ivr-2, s, 11) exited non-zero on ‘SIP/PlivoTrunkxxxxxyyyyyzzzz’
– Executing [h@ivr-2:1] Hangup(“SIP/PlivoTrunkxxxxxyyyyyzzzz”, “”) in new stack
== Spawn extension (ivr-2, h, 1) exited non-zero on ‘SIP/PlivoTrunkxxxxxyyyyyzzzz’
== MixMonitor close filestream (mixed)
== End MixMonitor Recording SIP/PlivoTrunkxxxxxyyyyyzzzz`

your pivo trunk is coming in as PlivoTrunkxxxxxyyyyyzzzz there must be settings in sip_custom.conf that you need to add to assign a DID to that trunk. read the Plivo docs, i am not familiar with this supplier,

ok so the solution is to have a DID setup to each particular trunk and have each DID with plivo come into the PBX on a different sip trunk to route it?

The thing is, I can rent many many numbers from Plivo and have them all come in though PlivoTrunkxxxxxyyyyyzzzz.

but how will freepbx identify calls from different DID’s?

this should be something explained in Plivo documentation. normally you would have different trunks set up for each DID (or group of DIDs) and you would make the routing based on the trunk.

I can easily set up inbound numbers to different endpoint trunks and then pass different trunks to freepbx.

but it seems super laboursome to have to create add and assign a new trunk for every did.

there is no better way huh?

I have another trunk with Numbergroup which passes both CID and DiD too.

if it passes DID then you can use that and route based on the DID in FPBX

so the problem is with Plivo not passing the DID?

i am not sure, you must communicate with Plivo to check what different options you have in routing incoming calls to your PBX. i faced a similar problem with another provider and was resolved by creating different trunks for different DIDs and then forwarding to the appropriate trunk from the provider.

I recall a thread about this with Plivo from a couple of months ago. There was something in the SIP headers that had to be used instead of the “standard” way that DID is received. Use the search function and see if you can’t find that discussion.

You could also look for other occurrences of “DID not working” - I know we’ve discussed this in some detail recently.

Hi Cynjut,

Thanks for your reply.

I have read several guides on setting up plivo to work on freepbx for inbound & for outbound.

For outbound the default way does require headers to be added in a config file, however plivo have this beta thing called “zentrunk” which works more like a regular sip trunk for outbound calls so the headers are not really needed.

To use Plivo Zentrunk for outbound calls a guide is here:

for inbound calls the guide I used is here:

At the top of that guide it does say Plivo does not send DID over registration/trunk so i am trying to work out how the headers apply to incoming calls.

right now the calls are getting through but the DID is not so i cannot apply Specific Inbound routes to those calls.

I have tried searching this forum and the internet for Plivo and “DID not working” but i have not had any luck.

can you send me some links to posts that have discussed this that could point me in the right direction? hopefully this can solve this issue for other people if i work it out.

OK - coming clearer.

If I remember correctly, Plivo requires a separate trunk for each DID, so you should be able to set the DID on the inbound trunk. You can also skip the DID stuff and just press on through the network.

Of course, if you switch to a better ITSP (almost any of them) you’ll get the DID information from the switch and don’t have to worry about getting jerked around by these guys.

Hi Cynjut,

Thanks for the fast reply. -> so Plivo does not require a seperate trunk for each DiD

they have a system on their dashboard that allows you to set up applications and endpoints to link to DID’s.

its completely possible to have multiple DID’s (rented from plivo) to link to the same Application/trunk.

setting up a different application & trunk for every number would become very laborsome both on the Plivo end and the Freepbx end (and would be difficult to manage too)

so I want to avoid the Multiple Application + Endpoint on the Plivo side, and trunk on the freepbx side for every DID I rent on Plivo.

But if I did choose to go that route, how would i route it inbound. How do I assign a DID to the trunk (inbound) inside freepbx so that it can be routed by incomming routes? i thought the CID /DID option in the trunk settings applies only to outbound calls?

I’m hating Plivo the more you talk about it.

Seriously, the search function should return this entire discussion. We just hashed this out a few weeks ago - there’s a weird header that they are sending with the DID in it, You’ll need to write a custom context that reads the DID out of that header and applies it to the incoming call. It’s all out there - please don’t make me Google it for you.

Another option - switch to an ITSP that doesn’t screw around with stupid crap like this. None of my providers do this - you set up an endpoint and they route whatever DIDs you want to that endpoint and provide the DID to you in the standard headers.

Ok I’m getting closer, I found this:

https://sites.google.com/site/samsig/techie/How-to-get-the-DID-of-a-SIP-trunk-when-the-provider-doesnt-send-it-and-why-some-incoming-SIP-calls-fail

it seems to be working in the sense that it puts the sip URI name in the dialed field,

i think it needs a little tweaking to work with Plivo.

any suggestions of alternatives Cynjut?

i need to be able to send and receive SMS messages too (virtual mobile phone numbers) so plivo ticks some boxes for me and some it does not.

getting closer but i think i need a bit of a tweak.

Question: How do i dump the entire Sip Header to see if the information i want exists in there, perhaps then i could write a relevant custom context for Plivo to share with everyone.

At the Asterisk CLI:

sip set debug peer <peer-name>

Use the tab key to get the name for your plivo trunk then enter. Watch console during an inbound call and somewhere in that mess will be the sip headers with the DID. Slightly harder is to capture a pcap and analyze with Wireshark.