A couple months ago I switched my Dad’s business over to Twilio Elastic SIP trunks. I have been very happy with the service. Not only was it really easy to deploy, but the service has been rock solid. The only downside that I discovered during my initial testing was that Twilio doesn’t deliver the caller name in the SIP header! Twilio offers a service for lookups and there are a couple add-ons that will do caller name lookups, however, they don’t alter the SIP headers. In the solution below, I am using the addOn OpenCNAM by telo. This will work with Twilio’s lookup service, but the function will need to be altered to capture the correct data. I found OpenCNAM to be more accurate. It took me a bit of trial and error, but I finally figured out a solution! In order to make this work, follow the steps below.
- Twilio Function: Here we will send the caller name as a custom SIP header
- CUBE SIP Profile: Using SIP Profiles on the Cisco Unified Border Element, we can insert the customer header containing the Caller Name into the P-Asserted-Identity SIP header
Twilio Function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
var fromName; exports.handler = function(context, event, callback) { if(event.AddOns){ fromName = getName(event.AddOns); }else{ fromName = event.From; // send the original calling number if no AddOns are found } let twiml = new Twilio.twiml.VoiceResponse() let dial = twiml.dial(); dial.sip('sip:1000@example.com?fromName='+fromName) // replace with a URI directed at CUBE callback(null, twiml) } var getName = function(input){ var addOn = JSON.parse(input); //var callerName = JSON.parse(); if(addOn.results.opencnam.result.name){ var name = addOn.results.opencnam.result.name; // remove spaces, Twilio doesn't allow spaces to be passed in the custom headers name = name.replace(/\s/g, '_'); // limit to 15 characters name = name.substring(0,15); console.log('returning name: ', name); return name; }else{ // if a name isn't found, the number will be returned console.log('returning number: ', addOn.results.opencnam.result.number); return addOn.results.opencnam.result.number; } } |
CUBE
A handful of things need to be done on CUBE. First a sip-copylist and sip-profile will need to be created.
sip-copylist
1 2 |
voice class sip-copylist 1 sip-header X-fromName |
sip-profiles
1 2 3 |
voice class sip-profiles 1 request INVITE peer-header sip X-fromName copy "(.*)" u01 request INVITE sip-header P-Asserted-Identity modify ".*(<.*)" "P-Asserted-Identity: \"\u01\" \1" |
Once the copylist and profile have been created, they will be applied to an inbound and outbound dial-peer.
dial-peer example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
dial-peer voice 1 voip description ** SP to CUBE catchall ** session protocol sipv2 incoming called-number . voice-class sip copy-list 1 voice-class sip bind control source-interface FastEthernet0/0 voice-class sip bind media source-interface FastEthernet0/0 dtmf-relay rtp-nte sip-kpml sip-notify codec g711ulaw no vad dial-peer voice 1000 voip description ** CUBE to CUCM ** destination-pattern 1000 session protocol sipv2 session target ipv4:<CUCM IP Address> voice-class sip profiles 1 voice-class sip options-keepalive down-interval 10 voice-class sip bind control source-interface GigabitEthernet1/0.10 voice-class sip bind media source-interface GigabitEthernet1/0.10 dtmf-relay rtp-nte codec g711ulaw no vad |
The final step is to point the phone number at the Twilio Function. You should now see caller name on inbound calls!
Hopefully this will save some time for the next person trying to figure this out!
Enjoy,
– Brad