2015年2月5日 星期四

kamailio 命令搞

從《kamailio 簡易命令檔》可理解到 kamailio 的設定檔就是如何處理 SIP 封包的命令檔,kamailio 讀取後會編譯成內部的 SIP 處理邏輯。撰寫命令檔需要對 SIP 協定有一些基本的了解。命令檔的語法類似 C 語言,使用 kamailio 內建及外掛模組的函數及變數。一般 kamailio 命令檔包括核心參數設定、模組載入、模組參數設定、以及 SIP 協定處理區塊這些部份,如果命令檔有修改,kamailio 需要重啟。

前置處理指引 (Preprocessor Directives)

類似 C 語言,kamailio 也有類似的前置處理。

#!include_file "path_to_file"
  • 插入檔案內容
#!import_file "path_to_file"
  • 跟 include_file 一樣,但檔案不存在沒關係
#!define, #!trydef, #!redefine
  • define
#!ifdef, #!ifndef, #!else, #!endif
  • 選擇性載入
#!subst "/regexp/subst/[flags]"
  • 字串內的取代 (define 只能取代 ID -- alphanumeric tokens not enclosed in quotes)
  • flags:'i' - ignore case; 'g' - global replacement
#!substdef "/ID/subst/":subst 加上 define ID subst

核心參數設定、模組載入、及模組參數設定

命令檔通常都有一些核心參數 (core parameter) 設定,包含要載入哪些模組、以及模組的參數設定,也都是透過核心參數設定達成。有些核心參數會設定成全域變數,在 kamailio 或模組內部可以使用。

check_via (或指令參數 -K)
  • reply 檢查第一個 VIA 是不是自己。
onsend_route_reply
  • reply 也執行 onsend_route 區塊,預設 reply 是不執行 onsend_route
pv_buffer_size, pv_buffer_slots
  • 設定動態字串的 buffer。字串用到虛擬變數需要動態產生。
loadpath (或 mpath), loadmodule "modulepath", modparam:
  • 模組相關,分別用來設定模組路徑、載入模組、及設定模組參數。有些模組有相依性而有載入先後的差別。
mhomed
server_header,server_signature
  • 預設 kamailio 本身產生的 SIP reply 會含 header「Server: Kamailio (<version> (<arch>/<os>))」,server_header 可更改內容,server_signature=no 關閉不產生
其它還有 advertised_address advertised_port alias async_workers auto_aliases auto_bind_ipv6 children chroot corelog debug description disable_core_dump disable_tls enable_tls exit_timeout flags force_rport fork fork_delay group http_reply_parse latency_limit_action latency_limit_db latency_log listen log_facility log_name log_prefix log_stderror maxbuffer sql_buffer_size max_recursive_level max_while_loops mcast_loopback mcast_ttl memdbg memlog mem_join mem_safety mem_summary mlock_pages modinit_delay open_files_limit phone2tel pmtu_discovery port  reply_to_via server_id shm_force_alloc sip_warning (noisy feedback) socket_workers statistics tos udp_mtu udp_mtu_try_proto user user_agent_header workdir

SIP 協定處理區塊

kamailio 是個處理 SIP 封包的程式,SIP 封包分成請求 (SIP request) 跟回覆 (SIP reply) 兩類。基本上命令檔需要告訴 kamailio 如何處理進來的 SIP 請求封包,最後看是要轉送、產生回覆封包、還是要忽略等等。SIP 請求由命令檔中的 route (或 request_route) 區塊負責,有 SIP 請求進來就執行,有點像 C 語言內定的 main 函數。如果收到的是 SIP 回覆封包就執行另一個內定的區塊 -- onreply_route,但這部份不是必要的,因為 kamailio 對於 SIP 回覆預設會移除第一個 VIA,並依據第二個 VIA 的位址轉送。kamailio 還有其它內定的區塊,包括 onsend_route、branch_route、failure_route、及 event_route[module:event],其中 branch_route 跟 failure_route 搭配 tm 模組才會用到,event_route[module:event] 也需要搭配其它模組。

區塊內有內建函數 (function)、內建 keyword、內建 value 等可以利用,可透過載入模組來擴充函數。

Routing blocks

route 或 route[0] 或 request_route
  • 收到 SIP 請求所要做的動作,需明確的處置,看是要回覆、轉送等等,不然預設是丟棄。
onreply_route
  • 收到 SIP 回覆所作的動作,最後有個隱含的動作是依據 Via 轉送,結束、或者中途執行 exit 或 return(0) 而離開,都會執行。如果執行 drop 離開的話,不會執行隱含的動作,而直接丟棄。
onsend_route
  • 送出 SIP 封包前執行,預設只有請求封包,如果命令檔參數 onsend_route_reply 有設,則包括回覆封包。能執行的指令有限制。
branch_route[name]
  • 呼叫 tm 模組的 t_on_branch(name) 時所作的動作,最後隱含的動作是轉送
failure_route
  • tm 模組
event_route

內建函數

exit() 或 return(0)
  • 結束命令檔處理,執行預設動作
return([retcode])
  • 結束函數。回傳的值預設是 1,可用 $retcode 或 $? 取得,邏輯判斷正數為 true,負數為 false。
drop()
  • 結束命令檔處理,並丟棄,不執行預設動作。
forward()
  • stateless 依據 $du 轉送。$du 是 L3 IP 位址或 L4 port,跟 SIP 內容無關。
rewritehost("domain") 或 sethost, seth
rewriteport("port") 或 setport, setp
rewritehostport("domain:port") 或 sethostport, sethp
rewritehostporttrans("...") 或 sethostporttrans, sethpt
rewriteuser("user") 或 setuser, setu
rewriteuserpass("password") 或 setuserpass, setup
rewriteuri("uri") 或 seturi
  • 這些改寫 request URI,包含 L3/L4 位址
revert_uri()
  • 回復 request URI 修改
force_send_socket(ip [ :port] )
  • 強制使用其它 listen 的 socket 送封包
route(name)
  • 呼叫指定名稱的 route 區塊。指定名稱也可以是字串組合的表示式。
其它還有 add_local_rport avpflags break error exec force_rport add_rport force_tcp_alias isavpflagset isflagset is_int log prefix resetavpflag resetflag set_advertised_address set_advertised_port set_forward_no_connect set_forward_close set_reply_no_connect set_reply_close setavpflag setflag strip strip_tail udp_mtu_try_proto(proto) userphone

Keywords 及 values

keyword 就是 SIP 封包解析後的欄位,通常用在 if 描述 (唯讀?)。另外提供了 value 方便跟 keyword 比較。

af, dst_ip, src_ip, proto, dst_port, src_port, proto
  • 這些是所收到 SIP 封包的 address family、目的/來源 IP 位址、目的/來源 port 及協定
  • af 的值可能是 INET 或 INET6,proto 的值可能是 UDP、TCP、TLS、SCTP、WS、WSS。
method
  • SIP 封包的 method
  • 不確定是否包含 reply
msg:len
uri, status
  • request uri 及 reply 的 status
  • uri 可跟值 myself 作測試,看請求的對象就是自己、還是需要轉送給其它伺服器。myself 是個列表,由設定檔設定的 local IP addresses、hostnames 及 aliases 組成,也就是 kamailio 伺服器服務的 domains。命令檔參數 alias 可加 hostnames、IP addresses、及 aliases 到 myself 列表。 
  • $ru
to_ip, to_port, to_uri, from_uri
  • SIP 封包的 TO 及 FROM 欄位
snd_af, snd_ip, snd_proto, snd_port
  • 類似 af、src_ip、proto、src_port,但是封包要送出的狀況。

Script statements

if-else 或 while 表示式,包括
==相等
!=不相等
=~Posix 正規表示式比對。使用 [[:digit:]]{3} 取代 \d\d\d。
>大於
>=greater or equal
<小於
<=less or equal
&&邏輯 AND
||邏輯 OR
!邏輯 NOT
[ ... ]test operator - 裡面可以是任何算術式。
switch 虛擬變數

Script operations

Assignment (=) 的左邊可以是虛擬變數
  • Unordered List Item AVPs - to set the value of an AVP
    • 附在 SIP 訊息的 Attribute-value pair
  • script variables ($var(…)) - to set the value of a script variable
  • shared variables ($shv(…))
  • $fs - to set send socket
  • $br - to set branch
  • $mf - to set message flags value
  • $sf - to set script flags value
  • $bf - to set branch flags value
字串用「+」串起來,算術運算支援類似 C 語言,有「+」「-」「*」「/」「mod」「|」「&」「^」「~」「<<」「>>」。

Operators

  • (int), (str):type cast
  • eq, ne:字串比較
  • ieq, ine:整數比較
  • ==, !=:字串或整數比較。原則上市轉換成左 operand 的 type,除非左 operand 是 undef
kamailio 的資料型態有整數 (int)、字串 (str)、及 null
一些例子
  • 0 == "" (true)
  • 0 eq "" (false,0 轉成字串是 "0")
  • "a" ieq "b" (true: "a" 跟 "b" 轉成整數都是 0)
  • "a  == "b" (false)

其它

unordered list item AVPs
script variable
shared variable
$null

參考來源

  1. http://www.kamailio.org/wiki/cookbooks/4.2.x/core
  2. http://www.kamailio.org/wiki/cookbooks/4.2.x/pseudovariables
  3. kamailio source code

延伸閱讀

沒有留言:

張貼留言

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...