cancel
Showing results for 
Search instead for 
Did you mean: 
cancel

A guide to SIP Normalization on CUCM and Lua Scripting

17196
Views
50
Helpful
89
Comments
Cisco Employee

 

(view in My Videos)

 

I have recorded this guide for SIP Normalization on call manager and also have elaborated a little bit on how we use the Lua scripting.

 

A SIP Normalization script could really help the customer as a workaround or a permanent solution for issues related to calling and CLID.

 

Disclaimer:

Cisco TAC does NOT support SIP Normalization scripts. If the customer has already applied a script, TAC does NOT troubleshoot it. It is the customer's responsiblity to make it work.

89 Comments
Beginner

Thanks for the pointer!  I'll give it a try.

Beginner

Dear Sreekanth and Community

I hope that you can help us with the issue we faced. We have a customer, who has CUCM connected to SIP Provider directy (yeah, no CUBE, this is a long story). The topology is like this:

Phones----CUCM----ASA-----SIP_SP

The issue is that when someone is calling from outside, and there should be transfer, pickup or anything which requires UPDATE message, as this message will contain internal extension (for ex. transferring from one IP Phone to another), this message is going to SP and calls fails.

I believe I need to run some script on CUCM Trunk so it will change from: field inside UPDATE header. Do you guys can help me with it?

Hi Solomon,

According to the SIP Normalization Developer guide, REFER and associated responses are not supported for SIP Transparency.

Moreover, in thte outbound.INVITE function you are using rfchange, which is a local variable in the inbound function, so I don't expect to be usable out of it.

Regards,

Carlos

Participant

Hi ,

I want to remove following line on the  SDP messages about incoming calls.

I see something on sip normalization guide but it contain only outbound calls .

I need to remove below parameters on the sdp from  incoming calls.

b=AS:64
b=CT:64
b=TIAS:64000

Thanks,

Participant

Thanks Sreekanth,

Between this video and the Cisco Live Berlin presentation I now have a good handle on normalisation. I'm stuck converting a SIP-profile from CUBE to Lua (the CUBE is managed by a network team who don't know voice).

The profile;

voice class sip-profiles 1
request CANCEL sip-header Max-Forwards modify ".*" "User-Agent: CUBE"
response ANY sip-header Remote-Party-ID modify "(.*@).*>(.*)" "\1mydomain.com>\2
request ANY sip-header Remote-Party-ID modify "(mailto:.*@).*%3e(.*)".*@).*>(.*)" "\1mydomain.com>\2"
request REINVITE sdp-header Audio-Attribute modify "inactive" "sendrecv"
 request ACK sdp-header Audio-Attribute modify "sendonly" "sendrecv"
request INVITE sip-header P-Asserted-Identity modify "(.*)" "P-Asserted-Identity: <sip:N1234567R@mydomain.com>"
request INVITE peer-header sip Remote-Party-ID copy ".*<sip:(.*)@.*" u01
request INVITE sip-header From modify ".*<sip.*@.*>(.*)" "From:<sip:\u01@mydomain.com>\1"

Which I've converted to the following code;

M = {}
trace.enable()
local top_level_domain = scriptParameters.getValue("top-level-domain")
if not top_level_domain
then
top_level_domain = "mydomain.com"
top
end
local function change_domain(msg)
if not top_level_domain
then
return
end
local from = msg:getHeader("From")
if from
then
local start = string.find(from, "@")
if start
then
local end_str = string.find(from,">", start+1)
local target = string.sub(from,start+1,end_str-1)
local fromchange = string.gsub(from, target, top_level_domain)
if fromchange
then
msg:modifyHeader("From",fromchange)
end
end
end
local to = msg:getHeader("To")
if to
then
local start = string.find(to, "@")
if start
then
local end_str = string.find(to,">", start+1)
local target = string.sub(to,start+1,end_str-1)
local tochange = string.gsub(to, target, top_level_domain)
if tochange
then
msg:modifyHeader("To",tochange)
end
end
end
return (msg)
end
function M.outbound_INVITE(msg)
local isReInvite = msg:isReInviteRequest()
msg = change_domain(msg)
if isReInvite
then
local sdp = msg:getSdp()
if sdp
then
local inactive_line = sdp:getLine("a=","inactive")
if inactive_line
then
sdp = sdp:modifyLine("a=", "inactive", "a=sendrecv")
msg:setSdp(sdp)
end
end
end
end
function M.outbound_ACK(msg)
msg = change_domain(msg)
local sdp = msg:getSdp()
if sdp
then
local inactive_line = sdp:getLine("a=","sendonly")
if inactive_line
then
sdp = sdp:modifyLine("a=", "sendonly", "a=sendrecv")
msg:setSdp(sdp)
end
end
end
function M.outbound_CANCEL(msg)
msg = change_domain(msg)
msg:removeHeader("Max-Forwards")
msg:addHeader("User-Agent", "CUBE")
end
function M.outbound_ANY(msg)
msg = change_domain(msg)
end
return M

The P-Asserted-Identity seems to be used by CUBE to rewrite the From address so I've left it out of the script. The code seems to fail on calling the function change_domain with an error that msg is empty, but testing calling functions on repl.it seems that the syntax is correct. I don't want to have to replicate the translations for each message type but if I can't get calling functions to work I may have to.

It's hard to debug in realtime and of course the Cisco functions don't work on repl.it so I can only test scraps of code not the whole thing.

Do you have any thoughts on this implementation?

Joe

Cisco Employee

Ruslan, I am not sure if we can change the UPDATE method. I haven't tried this in my lab yet. Sorry for the really delayed response.

Cisco Employee

Hi Joe,

Your script looks OK from a syntax standpoint, and should work. Perhaps the 'msg' is not available for a custom function and can only be accessed by the Call manager's built-in lua functions.

Can you try changing the name of the argument passed to the change_domain function to something else and appropriately change the variable name in the rest of the function as well? Any other name might be OK but not the 'msg'.

Beginner
Hi Sreekanth, Currently, the From: field for all of our outbound SIP video calls going through Expressway is being set with the directorynumber@domain.com (I.E. +14015551212@domain.com). Is it possible to edit the vcs-interop script to change it to use the SIP URI configured on the directory number instead? I.E. VideoRoom@domain.com Thank you, James

hi,

got a bit of bug here with the Hyphen in my first name in LUA. if i change Louis-Philippe to LouisPhilippe. it works

in repl.it

from = '"Louis-Philippe Descamps"<sip:4920000@192.168.1.254:5060>;tag=E3ntppq' -- string

    local start = string.find (from, "\"") --find the 1st quote
    local finish = string.find (from, "\"", start+1) --find the last quote. start+1 to include the quote
    local target = string.sub (from, start, finish) --display the word we want to replace
    local newfrom = string.gsub(from, target, "Global Service Desk")

print (target)
print (from)
print (newfrom)

the output is

Lua 5.1  Copyright (C) 1994-2006 Lua.org, PUC-Rio
[GCC 4.2.1 (LLVM, Emscripten 1.5)] on linux2
   
"Louis-Philippe Descamps"	
"Louis-Philippe Descamps"<sip:4920000@192.168.1.254:5060>;tag=E3ntppq	
"Louis-Philippe Descamps"<sip:4920000@192.168.1.254:5060>;tag=E3ntppq	

Hi Louis-Philippe,

The problem is when adding the hyphon in the pattern of the string.gsub it behaves as a magic character, so it needs to be escaped. What you can do is to edit the target and add it an %, the following example may be appropiate:

from = '"Louis-Philippe Descamps"<sip:4920000@192.168.1.254:5060>;tag=E3ntppq' -- string

local start = string.find (from, "\"") --find the 1st quote
local finish = string.find (from, "\"", start+1) --find the last quote. start+1 to include the quote
local target = string.sub (from, start, finish) --display the word we want to replace
local targetPattern = string.gsub (target, "%-", "%%-")
local newfrom = string.gsub(from, targetPattern, '"Global Service Desk"')


This is quite simple, and it may not be applicable to a generic script, but it should work for your case.

PS: Note that I have add it '' to the Global Service desk, so it will go between "" in the output.

Let me know if this works for you.

Hi Carlos,

very clever trick !

here is the final script

M={}
function M.inbound_INVITE(msg)
    local from = msg:getHeader("From")
    
    local start = string.find (from, "\"") --find the 1st quote
    local finish = string.find (from, "\"", start+1) --find the last quote. start+1 to include the quote
    local target = string.sub (from, start, finish) --display the word we want to replace
    local targetPattern = string.gsub (target, "%-", "%%-")
    local newfrom = string.gsub(from, targetPattern, '"Global Service Desk"')
    
    msg:modifyHeader("From", newfrom)
end
return M

thank you very much!

Hi James,

You actually can change the right-hand side of the script as you want. What you would need to do is to copy the vcs-interop and paste it in a new one (the one by default cannot be modified) and then add the part of code to change the directory number. There is actually a function that already interoperates whit the left-hand side so, it shouldn't be complicate to add manipulations for the right part and make it to be called when required.

The key thing here is about scalability, if you just want to change all calls using that script from a number to VideoRoom it is easy to get it, the problem is if you have several numbers to be matched to different names it may not be that easier.

For instance this would change the reight side of the from URI to a uri-name added via parameter script (this is some add-on to the original script where uri-name is teh name of the room):

M = {}
local uri_name = scriptParameters.getValue("uri-name")
local function modify_lhs_of_uri(msg, header, lhs)
local value = msg:getHeader(header)
if value and lhs
then
local position_of_uri = string.find (value, "<")
local position_of_domain = string.find (value, "@", position_of_uri+1)
local fulldn = string.sub (value, position_of_uri+5, position_of_domain-1)
local dn_pattern = string.gsub (fulldn, "%+", "%%+")
local newfrom = string.gsub(value, dn_pattern, uri_name)
end
end
local function modify_lhs_of_uri_for_calling_party(msg)
if not uri_name
then
return
end
modify_lhs_of_uri(msg, "From", uri_name)
end
local function process_outbound_request(msg, isInvite)
modify_lhs_of_uri_for_calling_party(msg)
end
M.outbound_INVITE = function(msg)
process_outbound_request(msg, true)
end
return M


What your case here?

Regards,

Carlos M.

Participant

How can I convert diversion header via  incoming sip trunk thought Lync and Siemens HiPath.

I could not see diversion header when I receiving call from Lync and Siemens HiPath.

Hi Sreekanth (and all),

 

I was trying to passthrouhg the SDP for an incoming 200 OK (answer to an INVITE). Curretnly we have an incoming 200 OK with SDP that is being sent as 200 OK without SDP to an IP Phone, I wanted to copy this SDP and add it to the 200 that goes to the phone.

 

Whenever the script start executing there is an error:

 

30547889.006 |16:15:53.425 |AppInfo |SIPNormalizationScriptError - A script error occurred Device Name:CUST20-CL1-AGGR-Leganes-TRK Script Name:LUA_AGG.v1.4.3.3 Script Function:M.inbound_200_INVITE Script Type:Custom Error Code:3 Error Code Text:Execution Error Error Message:LUA_AGG.v1.4.3.3 at line 73: attempt to pass through SDP Configured Action:Rollback Only Resulting Action:Rollback Only In Use Memory:27234 Memory Threshold:102400 In Use Lua Instructions:0 Lua Instruction Threshold:2000 App ID:Cisco CallManager Cluster ID:C20-EU-CL1 Node ID:CLUSTERID

Do you know if there is any restriction?

Thanks in advance.

Carlos.

CreatePlease to create content
Content for Community-Ad
August's Community Spotlight Awards