cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
6973
Views
1
Helpful
13
Replies

SIP Normalization Script in Lua: Modifying individual headers within a Header table

Jonathan Els
Level 5
Level 5

Hi,

The SIP Messages APIs support the following methods for updating tables of headers (e.g. multiple Diversion headers):

  • getHeaderValues
  • removeHeaderValue

However, I cannot find a mechanism to modify individual headers in a table.  For example, if the SIP message contains:

Diversion: <sip:1000@192.168.100.10>;reason=user-busy;privacy=off;screen=yes

Diversion: "Jonathan Els" <sip:2000@192.168.100.10>;reason=unconditional;privacy=off;screen=yes


If we apply the modifyHeader API,  assuming we have a new header string newHeaderString string, which has modified SIP URI sip:9999@192.168.100.10


msg:modifyHeader("Diversion", newHeaderString)


This will modify the first header, and delete subsequent headers, resulting in:


Diversion: <sip:9999@192.168.100.10>;reason=user-busy;privacy=off;screen=yes


Is there a way to modify specific diversion headers in the header table from the getHeaderValues API , without having to read in the table, modify the table values, delete all headers from the SIP Message using a for loop, and then re-provision them again?  My intended end result should be:


Diversion: <sip:9999@192.168.100.10>;reason=user-busy;privacy=off;screen=yes

Diversion: "Jonathan Els" <sip:2000@192.168.100.10>;reason=unconditional;privacy=off;screen=yes


1 Accepted Solution

Accepted Solutions

dstaudt
Cisco Employee
Cisco Employee

Given the current set of header manipulation functions available, it looks like your approach - read all header values, remove the headers from the message, then re-add the modified headers - is going to be the one to go with.

View solution in original post

13 Replies 13

dstaudt
Cisco Employee
Cisco Employee

Given the current set of header manipulation functions available, it looks like your approach - read all header values, remove the headers from the message, then re-add the modified headers - is going to be the one to go with.

Thanks.  I presumed so but wanted to make sure...  Half-baked API.

Hi,

I'm trying to add new headers to the table which I got from getHeaderValues.

local diversionTable = msg:getHeaderValues("Diversion")

local lastForwardingStation = diversionTable[1]

local newForwardingStation = string.gsub(lastForwardingStation , "<sip:.*@" , "<sip:" .. finalVmUser .. "@")

table.insert(diversionTable, 1, newForwardingStation)

When I try run this, CUCM logs the following script error:

attempt to index global 'table' (a nil value)"

is there any reason that it wouldn't find table.insert?  This works running against a local Lua shell using v5.3.  It appears to be looking for a variable instead of finding the built-in table methods...

Am I doing something wrong,  or are the table built-ins not available on CUCM?  I read the CiscoLive presentation BRKCOL-2455, which does allude to this being supported.

HI Jonathan,

Table add-ins aren't available.

Do you want to drop everything except the first diversion header? Or just change the first header and leave the rest in place?

Mark

I want to insert a new header at the start of the table, then replace the existing list of diversion headers with my modified table.  I know my initial question indicated just an in-line modify of one header - apologies for that.  The principle is the same though

So, start with:

Diversion: <sip:1000@192.168.100.10>;reason=user-busy;privacy=off;screen=yes

Diversion: "Jonathan Els" <sip:2000@192.168.100.10>;reason=unconditional;privacy=off;screen=yes

Desired output:

Diversion: <sip:9999@192.168.100.10>;reason=user-busy;privacy=off;screen=yes

Diversion: <sip:1000@192.168.100.10>;reason=user-busy;privacy=off;screen=yes

Diversion: "Jonathan Els" <sip:2000@192.168.100.10>;reason=unconditional;privacy=off;screen=yes

Ive successfully achieved the desired result doing this, but its ugly:

local diversionTable = msg:getHeaderValues("Diversion")

local lastForwardingStation = diversionTable[1]

local newForwardingStation = string.gsub(lastForwardingStation , "<sip:.*@" , "<sip:" .. finalVmUser .. "@")

for k,v in ipairs(msg:getHeaderValues("Diversion")) do

    msg:removeHeaderValue("Diversion", v)

end

msg:addHeader("Diversion", newForwardingStation) -- workaround for table.insert failing

-- write new header from modified Diversion table

for k,v in ipairs(diversionTable) do

    msg:addHeader("Diversion", v)

end


Any suggestions would be appreciated!

Dropping everything and replacing with a single header seems to work with just single call to modifyHeader.  That removes the need to delete, then re-add...

However...  this results in the Diversion headers being split in the INVITE, as the SIP Messages API appends headers by default.

Unfortunately, you can't add a header to the beginning of a list of Diversion headers...we don't have that fine level of control.

Have you tried just doing a

msg:removeHeader("Diversion")

to remove the full list of Diversion headers? I thought that worked that way, but it's been a while since I tried it.

Then you have to 'readd' the new header, then loop through the table to add the rest of the headers since addHeader only appends a single header to the message.

Mark

Thanks again for your prompt response, I will try a simple msg:removeHeader("Diversion") without specifying the exact Diversion header as I have now in a for-loop.

I tried msg:removeHeader("Diversion") but the script fails with:

64922113.009 |09:35:43.986 |AppInfo  |SIPNormalizationScriptError - A script error occurred Device Name:MYCUCMNAME Script Name:line-group-forwarder Script Function:M.outbound_INVITE Script Type:Custom Error Code:3 Error Code Text:Execution Error Error Message:line-group-forwarder at line 65: wrong number of arguments, usage: msg:removeHeaderValue(header-name, header-value) where header- Configured Action:Rollback Only Resulting Action:Rollback Only In Use Memory:6530 Memory Threshold:51200 In Use Lua Instructions:0 Lua Instruction Threshold:1000 App ID:Cisco CallManager Cluster ID:StandAloneCluster Node ID:MYCUCMNAME


Based on this, looks like I have to loop through all the headers twice.


This behaviour conflicts with the API guide:

removeHeader

removeHeader(header-name) 

Given the string name of a header, this method removes the header from the message.

Interesting...the error message references the 'removeHeaderValue' function, though you are talking about 'removeHeader'.  The former does require an additional parameter (the value to be removed from the header), though I believe you do want to be using removeHeader for your scenario.

If there is no typo, and you are specifying removeHeader but the interpreter is trying to parse it as removeHeaderValue then this would seem to indicate an issue with the Lua parser in CUCM.

If you can provide a basic sample script that reproduces the problem, along with the full CUCM version, we can probably go ahead and open a defect.  I can also suggest opening a ticket with DevNet Developer Support, who can work directly with engineering to analyze the issue in more detail, potentially working towards including a fix in a CUCM 'engineering special' release: Cisco DevNet: DevNet Developer Support

OK, let's back up a second.  My deletion for-loop used removeHeaderValue, so I may have (read: most probably) made a copy-paste fail.  I'm pretty sure I messed this up, and it's probably a legitimate failure then.  This should then work as @mstover suggested.

Let me re-test on Monday, and will report back.  In any case, I'm not gonna pay 250 USD to open a ticket for this, if I'm honest

Tested again.  remove API works as expected.  I had incorrectly used by removeHeaderValue mistake.  Changing to use a single call to removeHeader deleted all diversion headers.

Cool, glad to hear it worked. Thanks for being persistent.

Mark