12-17-2015 09:19 PM
Hello all! I have been working on a TCL script that performs an external query for CNAM lookups and then modifies the From field in the SIP header to include the returned CNAM then continues with the call. I have this applied to the inbound dial peer from my SIP provider. This process works just fine. I can see the query happen, I get my CNAM data back and then I have it continue to call the original destination which needs to be translated to the pattern for my extensions that live either on Call Manager or Asterisk. So depending on the inbound DNIS, I route the call differently via a translation profile applied to the same dial peer. However, once the script completes, it doesn't apply the translation profile either before nor after script termination and therefore, there is no outbound dial peer matched so the call fails. How can I get around this? From what I read, the order of operations would be the translation rules first. I shouldn't have to be forced to program a mechanism into my script to do the translation. The following are the translations that I have setup:
voice translation-rule 1
rule 1 /514586287/ /6060/
rule 2 /8885758460/ /6060/
rule 3 /8883562243/ /6061/
rule 4 /199839654/ /6068/
rule 5 /532100339/ /6067/
voice translation-profile callwithus
translate called 1
This is then applied to the incoming dial peer along with the TCL script:
dial-peer voice 1 voip
description Incoming calls from callwithus
translation-profile incoming callwithus
call-block translation-profile incoming call_block
call-block disconnect-cause incoming invalid-number
service cnam_lookup
session protocol sipv2
session transport udp
incoming called-number .
dtmf-relay rtp-nte
codec g711ulaw
no vad
Without the script applied, calls come in, get translated to the appropriate extension and then match the appropriate outbound dial-peer to get shipped off to their destination correctly:
dial-peer voice 1000 voip
description To Call Manager
destination-pattern 606.$
session protocol sipv2
session target ipv4:10.22.169.160
session transport udp
incoming called-number 606.$
voice-class codec 1
dtmf-relay rtp-nte sip-notify
dial-peer voice 1001 voip
description To Asterisk
destination-pattern 606[78]
session protocol sipv2
session target ipv4:192.168.60.250
session transport udp
no voice-class sip early-offer forced
no voice-class sip pass-thru content sdp
dtmf-relay rtp-nte sip-notify
codec g711ulaw
ip qos dscp cs5 media
ip qos dscp cs4 signaling
With the script applied, however, when everything finishes, I still get the destination as the original DNIS called (since that's what I can retrieve from the call and I set it to continue to that destination) and the translation profile never gets evaluated or applied. How can I have these work in tandem or somehow retrieve the translated destination from the call within the TCL script?
Here is the working script:
proc init {} {
global param
global dnis
global dn
global ani
global ani_pi
global requested_cnam
}
proc act_Setup {} {
global dnis
leg setupack leg_incoming
set ani [infotag get leg_username]
set cid_original [infotag get leg_display_info]
puts "\n Calling Number is $cid_original"
set ani_pi [infotag get leg_ani_pi]
if { $ani_pi != "presentation_allowed" } {
set ani ""
}
if {[infotag get cfg_avpair_exists cnam-lookup]} {
set cnam_flag [infotag get cfg_avpair cnam-lookup]
switch $cnam_flag {
0 {
puts "\n No CNAM lookup will be performed"
act_CID_DID "$cid_original"
}
1 {
puts "\n Let's try to get the CNAM for this caller..."
get_cnam "$ani"
}
default {
puts "\n Invalid option or no option specified for CNAM lookup. CNAM lookups will not be performed."
act_CID_DID "$cid_original"
}
}
}
}
proc act_CID_DID {CNAM} {
puts "IN CID/DID CHECK ROUTINE AND CNAM IS \"$CNAM\""
set dnis [infotag get leg_dnis]
set dest [regexp {(\d+)} $dnis whole dest_num]
set ani [infotag get leg_username]
set cid_current [infotag get leg_display_info leg_incoming]
switch $CNAM {
"" {
puts "\n No CNAM specified so it will be set to the calling number, $cid_current"
set CNAM "$cid_current"
}
" " {
puts "\n No CNAM specified so it will be set to the calling number, $cid_current"
set CNAM "$cid_current"
}
default {
puts "\n The CNAM is $CNAM"
}
}
puts "\n DNIS is $dnis"
puts "\n Destination is $dest_num"
place_call "$dest_num" "$CNAM"
}
proc get_cnam {number} {
global requested_cnam
if {[infotag get cfg_avpair_exists url]} {
set lookup_url [infotag get cfg_avpair url]
} else {
puts "\n No URL specified for CNAM lookup - syntax 'param url http://url.com'"
return -code return
}
switch $number {
anonymous {
puts "No CNAM lookup performed on anonymous callers"
return
}
default {
httpios::geturl "$lookup_url$number" -command cnam_data
}
}
}
proc cnam_data {token} {
set callback_status [httpios::status $token]
if {[string compare $callback_status ok] == 0} {
set requested_cnam [httpios::data $token]
if {$requested_cnam != ""} {
puts "Response=$requested_cnam"
httpios::cleanup $token
act_CID_DID "$requested_cnam"
}
} else {
httpios::cleanup $token
act_CID_DID ""
}
}
proc act_Ignore {} {
# Procedure to ignore events
puts "Ignore this here --> IGNORE"
}
proc place_call {called_num caller_name} {
# Gather SIP header information
set From_Header [infotag get leg_proto_headers "From"]
set SIP_From [regexp {.+(<sip:.+@.+)} $From_Header whole_string 2nd_Section]
puts "\n The second half of the SIP From Header is $2nd_Section"
puts "\n Updating the SIP From field to include the caller name, \"$caller_name\""
set SIP_String "\"$caller_name\" "
append SIP_String $2nd_Section
puts "\n SIP From Header is modified to be $SIP_String"
# Set CNAM Information
set callInfo(displayInfo) "$caller_name"
set callInfo(originationNum) "$called_num"
set headers(From) $SIP_String
set callInfo(protoHeaders) headers
set param(name) "$caller_name"
set param(number) "$called_num"
leg callerid leg_incoming param
# Insert a brief pause before continuing....
timer start leg_time 4 leg_incoming
# Place the call
puts "\n Ring, Ring... Incoming call from $caller_name"
leg proceeding leg_incoming
leg setup "$called_num" callInfo leg_incoming
}
proc act_CallSetupDone {} {
set status [infotag get evt_status]
puts "\n Call Status is $status"
if {$status == "ls_000"} {
puts "\n Call was successful"
} else {
puts "\n There was an error in connecting the call"
call close
}
}
proc act_Cleanup {} {
puts "Entering act_Cleanup"
call close
}
init
#----------------------------------
# State Machine
#----------------------------------
set TopFSM(any_state,ev_disconnected) "act_Cleanup,same_state"
set TopFSM(CALL_INIT,ev_setup_indication) "act_Setup,PLACECALL"
set TopFSM(PLACECALL,ev_leg_timer) "act_Ignore,same_state"
set TopFSM(PLACECALL,ev_setup_done) "act_CallSetupDone,CALLACTIVE"
#set TopFSM(CALLACTIVE,ev_setup_done) "act_Ignore,same_state"
set TopFSM(CALLACTIVE,ev_disconnected) "act_Cleanup,CALLDISCONNECT"
set TopFSM(CALLDISCONNECT,ev_disconnect_done) "act_Cleanup,same_state"
fsm define TopFSM CALL_INIT
Thanks for reading. Any suggestions or assistance is greatly appreciated!
-Matt
12-17-2015 09:36 PM
Hi Matt,
please try to use the below command to get the translated dnis.
[infotag get leg_dnis callnumber leg_incoming]
You can refer below blog for more information about this command.
https://communities.cisco.com/community/developer/voice-gateway/blog/2014/03/18/new-tcl-ivr-command-option-for-infotag-get-legdnis-and-infotag-get-legani
Thanks,
Raghavendra
12-18-2015 03:02 PM
Raghavendra,
Thanks for the suggestion. I had found that same post shortly after posting my original request. However, the VG that I am working with, a 2811, is only capable of version 15.1.4M10, so I don't believe that command is available in that version since that came out in version 15.2. It doesn't look like they are putting out any more code updates for that version VG either. I also have a 3825 VG I could use to replace this one but that also is only capable of the same version IOS. Is there any other workaround or command if that one is not available? Before it became available in version 15.2, was there no way to be able to grab that information from the call leg and both a Voice Translation Rule/Profile and TCL script could not exist on the same dial peer?
-Matt
12-18-2015 08:53 PM
Hi Matt,
I don't think you can use translation rule with TCL script before this command, but you can trick TCL script to change dnis using regexp.
Thanks,
Raghavendra
12-21-2015 07:07 PM
Raghavendra,
Thank you for all of the suggestions. I tried to get the already programmed voice translation-rule by using a parameter passed to the script then the exec command to parse the running configuration by finding the appropriate translation rule. I tested that successfully from the shell but apparently you can't use the exec command within a script which doesn't help me either. So I just ended up creating additional dial-peers, then matching the voice translation rule outbound so it will match the appropriate dial peer based upon called number then translate it out and send the translated extension to CM or Asterisk. It involves a few more dial peers but that's how I have to deal with it until I can upgrade the hardware that will support a newer IOS that can avail of that other command to try to get the translate extension.
-Matt
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide