--[[ Description: Provides interoperability for Microsoft Lync Handle Below Scenarios 1. Add user=phone for all outbound Invite messages because it is mandatory for Lync 2. Change the CT=Line values to 1000 , Moderate bandwidth in all outgoing messages from CUCM to Lync 3. There is Remote ringback hear issue There is ssue with PRACK enabled on CUCM and media bypass enabled on Lync. Enabling media bypass on Lync allows the rtp from lync endpoint to flow through CUCM directly instead of flowing through mediation server. The problem with PRACK enabled is that Lync end point is now not able to answer the incoming call.Looking into the traces, it appears that even though Lync sent updated connection information in 183 w/sdp, the call manager is still sending rtp to the mediation server which seems to be incorrect" So In this scenario CUCM expects 180 Ringing not 183 Session progress. So added the Script to convert 183 Session Progress to 180 Ringing. 4. There is incoming Invite from Lync and in From Header there is "user=phone" which cause CUCM to send malformed data in to different layers which cause call failure.So this is work around for that scenario. 5. Script modify the AS header which from outgoing messages because call forward fails due to bandwith negotiation value is A=64 is not supported 6. Script convert the History info to diversion Header since call forward to unity is not supported. 7. Transfer Scenario: Referred-By in Incoming Invite is converted to Diversion Header. Script Parameters: Release: 9.1(2) , 10.0.(1) Copyright (c) 2009-2011 Cisco Systems, Inc. All rights reserved. All rights reserved. --]] M = {} M.allowHeaders = {"History-Info"} -- trace.enable() local function modify_CT_bandwidth(msg) local sdp = msg:getSdp() if sdp then local b_CT_line = sdp:getLine("b=CT","64") if not b_CT_line then local b_CT_line = sdp:getLine("b=CT","0") if not b_CT_line then return end b_CT_line = b_CT_line:gsub("0", "1000") sdp = sdp:modifyLine("b=CT", "0", b_CT_line) msg:setSdp(sdp) return end b_CT_line = b_CT_line:gsub("64", "1000") sdp = sdp:modifyLine("b=CT", "64", b_CT_line) msg:setSdp(sdp) end end local function remove_AS_bandwidth(msg) local sdp = msg:getSdp() if sdp then local b_AS_line = sdp:getLine("b=AS","64") if b_AS_line then sdp = sdp:removeLine("b=AS", "64") msg:setSdp(sdp) end end end local function process_outbound_request(msg) local method, ruri, ver = msg:getRequestLine() if string.find(ruri, "@") then local uri = ruri .. ";user=phone" msg:setRequestUri(uri) end modify_CT_bandwidth(msg) remove_AS_bandwidth(msg) end local function process_outbound_message(msg) modify_CT_bandwidth(msg) remove_AS_bandwidth(msg) end local function process_inbound_progress(msg) msg:setResponseCode(180, "Ringing") local req = msg:getHeader("Require") local reqHeader = req if req then msg:removeHeader("Require") end local rseq = msg:getHeader("Rseq") local rseqPresnt = rseq if rseq then seqVal = msg:getHeaderValues("Rseq") msg:removeHeader("Rseq") end local sdp = msg:getSdp() if sdp then msg:removeUnreliableSdp() end if reqHeader then msg:addHeader("Require", "100rel") end if rseqPresnt then msg:addHeader("RSeq",seqVal[1]) end end -- Future reference for changing cause values in divertion header scenario -- local HiCauseToDiversion = { } -- HiCauseToDiversion["302"] = "unconditional" -- HiCauseToDiversion["486"] = "user-busy" -- HiCauseToDiversion["408"] = "no-answer" -- HiCauseToDiversion["480"] = "deflection" -- HiCauseToDiversion["487"] = "deflection" -- HiCauseToDiversion["503"] = "unavailable" -- HiCauseToDiversion["404"] = "unknown" function convertHIToDiversion(msg) local historyInfos = msg:getHeaderValues("History-Info") for i, hi in ipairs(historyInfos) do hi = string.gsub(hi, "%%3B", ";") hi = string.gsub(hi, "%%3D", "=") hi = string.gsub(hi, "%%22", "\"") hi = string.gsub(hi, "%%20", " ") -- MS format: ;index=1;ms-retarget-reason=forwarding local uri, index, reason = string.match(hi, "<(sip:.*@.*)>;index=(.*)reason=(.*)") trace.format("hi: uri '%s', reason '%s'", uri or "nil", reason or "nil") if uri then local diversion = string.format("<%s>", uri) if reason then diversion = string.format("<%s>;reason=\"unconditional\"", uri) end msg:addHeader("Diversion", diversion) end end end function convertReferredByToDiversion(msg) local refInfo = msg:getHeader("Referred-By") if refInfo then local diversion = string.format("%s;reason=\"unconditional\"", refInfo) msg:addHeader("Diversion", diversion) end end local function replaceHistoryHeader(msg) local hist = msg:getHeader("History-Info") if hist then convertHIToDiversion(msg) local di = msg:getHeader("Diversion") if di then msg:removeHeader("History-Info") end end end local function replaceReferredByHeader(msg) local refby = msg:getHeader("Referred-By") if refby then convertReferredByToDiversion(msg) end end local function modifyUserFrom(msg) -- get a data from "From" header and replace local removeUser= "" local value = msg:getHeader("From") if value then value = value:gsub(";user=phone", removeUser) if value then msg:modifyHeader("From", value) end end end local function process_inbound_request(msg) modifyUserFrom(msg) replaceHistoryHeader(msg) replaceReferredByHeader(msg) end M.outbound_INVITE = process_outbound_request M.outbound_ACK = process_outbound_message M.outbound_200_INVITE = process_outbound_message M.outbound_18X_INVITE = process_outbound_message M.inbound_183_INVITE = process_inbound_progress M.inbound_INVITE = process_inbound_request return M