본문 바로가기

Cisco UC Manager

[연재] SIP Normalization 의 이해 - 하. 복잡한 스크립트 만들기

글 싣는 순서

상. SIP Normalization 과 LUA 

중. 루아 스크립팅을 도와주는 도구들
하. 복잡한 스크립트 만들기   

 


시작하며
복잡한 루아 스크립트를 만들어 볼 것이며, 어떤 문서들을 참조하는 지를 같이 살펴보겠습니다. 나중에 다른 스크립트를 만들때도 문서들을 참조하도록 할 것입니다. 고기를 주는 것이 아니라 낚시하는 법을 알려주는 라인하트입니다. 



예제 
아래의 생략된 SIP INVITE 메세지에서 From 헤더에 있는 이름 변경하겠습니다. 


INVITE sip:8001;reg=40040001@192.168.0.133:5061;transport=tls SIP/2.0 

Via: SIP/2.0/TLS 192.168.0.4:5061;branch=z9hG4bK1bd6384ba952;received=192.168.0.4;ingress-zone=cucm 

Call-ID: a5b8ce80-5f61b29a-1bd6-400a8c0@192.168.0.4 

CSeq: 101 INVITE 

Remote-Party-ID: <sip:1009@cisco.lab>;party=calling;screen=yes;privacy=off 

Contact: <sip:1009@192.168.0.4:5061;transport=tls>;video;audio;bfcp 

From: "Alice Adams" <sip:1009@cisco.lab>;tag=16128~80f34be1-735a-462d-8134

To: <sip:8001@vcs.cisco.lab> 

Max-Forwards: 68 




스크립트 순서 정하기
먼저 스크립트를 짜기 위해 작업 순서를 정합니다. 

  1. From 헤더의 값 가져오기 
    "Alice Adams" <sip:1009@cisco.lab>;tag=16128~80f34be1-735a-462d-8134

  2. From 헤더에서 이름 찾기
    "Alice Adams" 
    단순 이름을 적용할 경우 범용으로 사용할 수 없으므로 다른 이름에도 적용할 수 있도록 만듬
    "이름"

  3. From 헤더에서 이름 삭제하기
    <sip:1009@cisco.lab>;tag=16128~80f34be1-735a-462d-8134 

  4. 변경된 값을 From 헤더로 되돌려 주기
    From : 
    <sip:1009@cisco.lab>;tag=16128~80f34be1-735a-462d-8134 

스크립트 만들기 - 1. From 헤더의 값 가져 오기 
먼저 From 헤더의 값을 가져오기 위해 "Developer Guide for SIP Transparency and Normalization" 의 SIP Message API 챕터를 참조합니다. 

http://www.cisco.com/c/en/us/td/docs/voice_ip_comm/cucm/sip_tn/9_1_1/sip_t_n/3-sip_msg.html

여기에서 From 헤더의 값을 가져오기 위한 SIP Message API를 찾습니다. 적당한 것은 getHeader 함수이며 사용 방법은 예제 스크립트에 나와 있습니다. 




우선 CUCM에서 외부로 발신되는 INVITE 요청의 From 헤더를 변경할 것이므로 아래와 깉이 스크립트를 시작합니다.
 
M= { }
function M.outbound_INVITE(msg)
local from = msg:getHeader("From")



스크립트 만들기 - 2. From 헤더의 값에서 이름 찾기  
문자열에서 특정 이름이나 문자를 찾기 위해서는 string 라이브러리를 이용해야 합니다. 구글에서 "LUA String Library" 라고 검색하면 제일 처음 LUA WIKI가 나옵니다. 


링크를 클릭하면 String Library Tutorial 페이지가 열립니다. 문자열을 변경 삭제하기 위한 함수들이 모여있습니다.  




구글에서 뒤지기 싫으신 분들은 아래 링크를 클릭하면 바로 이동합니다. 

http://lua-users.org/wiki/StringLibraryTutorial



String (문자열)에서 원하는 글자(이름)을 찾는 것이 목적이므로 string.find 를 이용합니다. From 헤더에서 이름을 변경하는 것이 목적이므로 "이름" 을 찾기 위하 처음 "와 그 다음 "의 위치를 확인할 수 있는 함수를 사용합니다. string.find (s,pattern,[index]) 는 s는 문자열, pattern은 찾고자하는 문자, index는 순서이며 옵션입니다. 상세한 사용 예는 아래에 나와 있습니다. 



위의 함수를 기반으로 원하는 글자의 시작과 마지막 문자를 확인하면 아래와 같습니다. 
 
M= { }
function M.outbound_INVITE(msg)
local from = msg:getHeader("From")
local start = string.find(from,"\"")
local end_start = string.find(from,"\"",start+1)


찾은 두 개의 스트링 start 와 end_start 변수 사이의 값을 돌려 받는 함수는 string.sub(s,i,[j])입니다. s는 문자열, i는 시작하는 문자의 위지, j는 마지막 문자의 위치입니다.  


 
M= { }
function M.outbound_INVITE(msg)
local from = msg:getHeader("From")
local start = string.find(from,"\"")
local end_start = string.find(from,"\"",start+1)
local target = string.sub(from,start,end_start)

여기서 target 변수의 값은 "Alice Adams" 입니다. "Alice Adams"라는 이름은 언제든지 바뀔 수 있으므로 이를 찾기 위해 " " 사이의 글자를 찾은 것입니다.  


스크립트 만들기 - 3. From  헤더에서 이름 지우기
From 헤더에서 " " 사이에 있는 이름을 항상 찾을 수 있습니다. 찾아낸 글자를 From 헤더에서 삭제하기 위해 다시 String Library를 뒤져봅니다.  



string.gsub(s,pattern,replace) 함수로 기존의 이름을 삭제합니다. s는 문자열, pattern은 문자, replace는 대체하려는 문자입니다. 

 
M= { }
function M.outbound_INVITE(msg)
local from = msg:getHeader("From")
local start = string.find(from,"\"")
local end_start = string.find(from,"\"",start+1)
local target = string.sub(from,start,end_start)
local fromchange = string.gsub(from, target, " ") 

" "를 이용하여 빈 블랭크를 만들어서 기존 이름을 삭제합니다.  



스크립트 만들기 - 4. From 헤더 적용하기 
이제 만들어진 fromchange 값을 From 헤더에 적용해야 합니다. fromchange를 적용한 From 헤더의 값은  " " <sip:1009@cisco.lab>;tag=16128~80f34be1-735a-462d-8134 로 표시됩니다. 헤더의값을 변경하기 위해 From 헤더를 삭제한 후에 다시 변경된 값으로 From 헤더를 삽입하겠습니다. 이를 위해 함수 SIP Message API를 확인하기 위해 구글에서 "SIP Transparency"로 검색하면 됩니다. 



여기서 "Developer Guide for SIP Transparency and Normalization"을 선택하거나 아래 링크를 선택하면됩니다. 


위의 문서에서 removeHeader 와 addHeader를 이용하여 From 헤더를 삭제 및 추가합니다.  


M= { }
function M.outbound_INVITE(msg)
local from = msg:getHeader("From")
local start = string.find(from,"\"")
local end_start = string.find(from,"\"",start+1)
local target = string.sub(from,start,end_start)
local fromchange = string.gsub(from, target, " ") 
msg:removeHeader("From")
msg:addHeader("From", fromchange)
end
return M

이제 작성이 제대로 되었는 지 확인하기 위해 repl.it에 접속해서 복사해서 살펴봅니다.




여기서 SIP Message API 자세히 살펴보면 addHeader와 removeHeader를 사용하는 것보다 modifyHeader를 이용하는 것이 효과적입니다.  



좀 더 세련되 보이는 구문을 만들어 보겠습니다. 차근차근 정리해 보면 매우 복잡한 스크립트도손쉽게 만들 수 있습니다. 


M= { }
function M.outbound_INVITE(msg)
local from = msg:getHeader("From")
local start = string.find(from,"\"")
local end_start = string.find(from,"\"",start+1)
local target = string.sub(from,start,end_start)
local fromchange = string.gsub(from, target, " ") 
msg:modifyHeader("From", fromchange)
end
return M

복잡한 과정도 해야할 순서를 차근차근 정리해 보면 손쉽게 루아 스크립트를 만들 수 있습니다. 


repl.it 를 이용한 사전 스크립트 점검하기 
CUCM에 적용해 보지 않고도 스크립트가 정상적으로 동작하는 지를 확인하기 위해 repl.it 웹사이트를 이용해 보겠습니다. 스크립트에서 선언한 변수들이 제대로 값을 가지고 있는 지를 알아야합니다. 앞에서 만든 스크립트를 변수 확인을 위해 아래와 같이 변경합니다.

from = '"Alice Adams" <sip:1009@cisco.lab>;tag=16128~80f34be1-735a-462d-8134'

local start = string.find(from,"\"")
local end_start = string.find(from,"\"",start+1)
local target = string.sub(from,start,end_start)
local fromchange = string.gsub(from, target, " ") 

print (fromchange)

여기서 새로운 print 함수는 변수 또는 문자열을 출력해 줍니다.  


변수를 확인하기 위해 아래와 같이 선언하면 각 변수의 값을 알수 있습니다.



만일 변수 선언이 잘못되었을 경우에는 잘못된 값을 표시할 것입니다. 


마치며
CUCM을 만지면서 1년에 한 두번 사용할까 말까한 이런 내용을 정리하다 보면, 누구를 위한 글인가라는 생각을 해봅니다. 역시 이런 글들은 필자를 위한 글입니다. 나중에 다시 할 때 손쉽게 참조하기 위한 용도 정도일 듯... 

다시 말하지만, CUBE에서 하는 것이 편한 분들은 CUBE에서 하면됩니다.
  



루아스크립트를 가장 잘 설명한 동영상

https://supportforums.cisco.com/video/12151771/guide-sip-normalization-cucm-and-lua-scripting



라인하트 유씨누스(UCnus) (CCIEV #18487)  --------------------------------------
ucwana@gmail.com (라인하트의 구글 이메일) 
http://twitter.com/nexpertnet (넥스퍼트 블로그의 트위터, 최신 업데이트 정보 및 공지 사항) 
http://groups.google.com/group/cciev (시스코 UC를 공부하는 사람들이 모인 구글 구룹스) 
http://groups.google.com/group/ucforum (UC를 공부하는 사람들이 모인 구글 구룹스) 
세상을 이롭게 하는 기술을 지향합니다. ________________________________________________________