2015年2月21日 星期六

BLF

BLF (Busy Line Field):monitor 其它 SIP 帳號的狀態,由燈號可看出是 idle, ringing, active, or unavailable,背後的機制是透過 RFC-3265 的 SIP SUBSCRIBE/NOTIFYSNOM 話機 (see also) 可將「programmable keys」設成 「destination」提供 BLF 功能。另外,Polycom (500/600)、Aastra ( 480i9133i )、Sayson 話機也有 BLF 功能。

BLF 跟速撥鍵結合:速撥鍵也同時是燈號,顯示其它分機的狀態,並且提供單鍵轉接到那個分機。
BLF 跟代接:燈號顯示其它分機正在響,單鍵代接那通電話

支援的 SIP Phone
Asterisk 1.6 有支援,例如 MyPBX
Asterisk 1.4
  • https://trac.anneal.com.tw/aa/ticket/1021
  • sip.conf configuration
    • If you're using RealTime, ensure you have both rtcachefriends and rtupdate set to "yes".
    • limitonpeers must be set to "yes" - this is the most likely culprit since it's missing from the 1.4 default config files
    • subscribecontext= (可以 subscribe 的 context)
  • SIP SUBSCRIBE Event: dialog
  • SIP NOTIFY 內容是 XML 格式,其中 <state> 跟 </state> 之間的訊息表示可能的狀態
    • 「無」:掛機
    • trying:摘機至撥號、送 INVITE 後
    • early:聽到 ring-back tone、收到 Ringing
    • confirmed:通話中
    • terminated:部份結束,例如被轉到語音信箱,會跟語音信相接通,跟話機的部份就結束
  • 最簡單是只提供 confirmed 跟「無」。(是不是只判斷有無 <state></state> 就知道是不是在使用中?)

http://forum.snom.com/index.php?showtopic=4836 說 Asterisk 1.4.24.1 可用

SNOM SIP phone 的 BLF 功能 (參考:SNOM 3x0 User Manual)
每個 Free Function Keys 包括一個按鍵、一個 LED、及一個 label
LED 顯示對方狀態:off => idle, blinking rapidly => ringing, on => busy or connected
按鍵功能:對方 ringing => call pickup (代接,IP PBX 需支援 RFC 4235), 對方 idle => speed dial, 自己有來電 (振鈴中) => manual call forwarding (將來電轉給對方)
設定對方 URL:extension@sip.domain,應該是用來送 SIP SUBSCRIBE
SIP NOTIFY 訊息範例:RingingConnectedDisconnected

Asterisk channel

Asterisk PBX 的通話通道用 struct ast_channel 表示,採用某種通道技術 (channel technology,struct ast_channel_tech)。

channel 模組呼叫 ast_channel_register() 註冊 ast_channel_tech 到 Asterisk,可能需要讀取設定檔,其中包括了解硬體 channel 的狀況。

channel 模組運作可分成撥入和撥出兩種情形。撥入時,建立一個 ast_channel,設定 ast_channel_tech ,並開始一個 pbx thread 執行 dialplan,此時 Asterisk 可能應答並收送 media,或者建立 outbound channel 撥出。如果是撥出,當受話端應答,Asterisk 將兩邊的 media stream 搭起來。

native bridge:如果兩邊的 ast_channel_tech 相同,media stream 可以不用經過 PBX,直接在 channel driver 內部,甚至在 channel driver 之前就可以互通。

 struct ast_channel_tech
  • 由 type 字串識別
  • ast_get_channel_tech() 取得指定 type 的 channel technology
  • ast_request() 在指定 channel technology 的 cap 相容的情況下,執行其 requester 來請求一個某個位址的 channel。可能是某個 channel 來請求的。

call in 是外部要 call 到 Asterisk,channel 模組通常會啟動一個 thread 來監控所有閒置的 channel。當偵測到「RING」或相當的事件時,配置一個新 channel 資料結構呼叫 ast_pbx_start() 建立一個 pbx_thread 呼叫__ast_pbx_run() 來執行 dialplan 直到結束,最後預設會執行掛斷的動作。

註:ast_pbx_run() 可以直接呼叫 __ast_pbx_run() 執行 dialplan
註:.indicate() 可告知對方 callee 狀態,例如響鈴中、忙線中、已連線等。.indicate() 也可告知 HOLD/UNHOLD 來開始/停止 MOH、要 hookflash 等,且不限於 call in。
註:.answer() 表示對方應答

call out 透過 channel technology 提供的 API 完成。首先 .requester() 請求一個 channel (seize),然後 .call() 讓 callee 振鈴及送 caller ID,callee 應答時送 AST_CONTROL_ANSWER。掛斷時 ast_queue_hangup()[待續]

struct ast_channel @ main/channel_internal_api.c

Asterisk DTMF Detection/Generation

DTMF Detection

Asterisk 的 DSP 有 DTMF 偵測功能。

準備工作:用 ast_dsp_new() 取得一個 DSP 處理的 instance,並設定有 DTMF 偵測功能 -- ast_dsp_set_features(dsp,  DSP_FEATURE_DIGIT_DETECT)。

每 voice frame 丟給 ast_dsp_process() 處理,如果有偵測到 DTMF,會回 AST_FRAME_DTMF_BEGIN 的 frame,到回 AST_FRAME_DTMF (或 AST_FRAME_DTMF_END) 結束。

DTMF Generation

相關函數
struct ast_channel_tech 的
  • send_digit_begin():沒提供此函數則完全不能送 DTMF。回傳 0 表示自己產生 DTMF,回傳其它值 (通常為 -1) 表示由 Asterisk 產生 DTMF。
  • send_digit_end
ast_senddigit():依序呼叫 ast_senddigit_begin() 及 ast_senddigit_end()
ast_senddigit_begin():ast_playtones_start
ast_senddigit_end():ast_playtones_stop
ast_rtp_instance_dtmf_begin
ast_rtp_instance_dtmf_end

2015年2月17日 星期二

Media Independent Interface

MAC 跟 PHY 之間的界面稱為 MII (Media Independent Interface),讓 MAC 可以接不同的 PHY。其它相關擴展有 RMII、GMII、RGMII、SGMII 等,在 10M Ethernet 稱為 AUI。

MII 支援 10 Mb/s 及 100 Mb/s,每個方向包含 7 個訊號 (4-bit Data、Delimiter、Error、及 Clock) 跟兩個 media 狀態訊號 (carrier 及 collision),總共 16 個信號。

MIIGMII
→TXD[3:0]→TDX[7:0]
→TX_ER→TX_ER
→TX_EN→TX_EN
←TX_CLK:25 MHz 或 2.5 MHz→GTX_CLK:125 MHz
←RXD[3:0]←RXD[7:0]
←RX_ER←RX_ER
←RX_CLK:25 MHz 或 2.5 MH←RX_CLK
←RX_DV←RX_DV
←CRS (Carrier Sense)←CRS
←COL (Collision Detected)←COL

SGMII (Serial Gigabit Media Independent Interface) 支援 10/100/1000 Mb/s 及 half- 跟 full-duplex 的串列界面,收發各為一對差分訊號線,可用在背板應用。在發送的訊號中,每 8-bit 會插入 TX_EN/TX_ER 兩 bit 控制信息;在接收訊號中,每 8-bit 會插入 RX_DV/RX_ER 兩 bit 控制信息,所以總和速率為 1 Gbps * 10/8 = 1.25 Gbps。CRS 訊號使用 RX_DV,COL 訊號使用 RX_DV AND TX_EN。MAC 跟 PHY 一般都用 CDR 恢復時鐘,也可另外提供時鐘訊號 1.25 GHz /2 = 625 MHz。

大部份 SGMII 介面都可以設定成 SerDes 介面直接接光模組,不過此時速率提高是因為事先進行了 8B/10B 變換。

8B/10B 變換的主要作用是擾碼,讓信號中不出現過長的連續 0 或連續 1 的情況,影響時鐘訊號的提取。

界面除了資料訊號外,還有 SMI (Serial Management Interface) 用來管理 PHY,使用 MDC 跟 MDIO 兩個訊號來讀寫 32 個 PHY 位址的 32 個暫存器位址。

regdescription
0Control
1Status
2PHY Identification
3
4Ability Advertisement
5Link Partner Ability
6Auto Negotiation Expansion

參考來源
  1. IEEE 802.3 Ethernet:目前 2012 版,分成下列 section
    1. Clause 1 ~ 20 及 Annex A ~ H, 4A:10 Mb/s operation and the MAC, frame formats and service interfaces used for all speeds of operation.
    2. Clause 21 ~ 33 及 Annex 22A ~ 33E:management attributes for multiple protocols and speed of operation as well as specifications for providing power over twisted-pair cabling for multiple operational speeds. 100 Mb/s PHY
    3. Clause 34 ~ 43 及 Annex 36A ~ 43C:1000 Mb/s PHY
    4. Clause 44 ~ 55 及 Annex 44A ~ 55B:10 Gb/s PHY
    5. Clause 56 through Clause 77 and Annex 57A through Annex 76A. Clause 56 through Clause 67 and Clause 75 through Clause 77, as well as associated annexes, specify subscriber access and other Physical Layers and sublayers for operation from 512 kb/s to 10 Gb/s, and defines services and protocol elements that enable the exchange of IEEE Std 802.3 format frames between stations in a subscriber access network. Clause 68 specifies a 10 Gb/s Physical Layer specification.Clause 69 ~ 74 and associated annexes specify Ethernet operation over electrical
      backplanes at speeds of 1000 Mb/s and 10 Gb/s.
    6. Clause 78: Energy-Efficient Ethernet
      Clause 79: Link Layer Discovery Protocol (LLDP) type, length, and value (TLV).
      Clause 80 ~ 89:40 Gb/s 及 100 Gb/s PHY
      Clause 90:time synchronization protocols.
  2. http://en.wikipedia.org/wiki/Media_Independent_Interface
  3. http://www.angelfire.com/electronic2/sharads/protocols/MII_Protocols/sgmii.pdf

Asterisk PBX

Asterisk 是一個軟體通訊平台,可作為 IP PBX systems、VoIP gateways、conference servers 等。

簡易設定
Channel 模組
  • chan_sip:處理 SIP 協定
  • chan_zap 或 chan_dahdi:chan_zap 在 1.4.22 之後改為 chan_dahdi。
dialplan
  • app_dial:dialplan 中,Dial() 算是連接通話兩端的靈魂人物。Dial()、RetryDial()
    • Music ringback:SIP INVITE 後收到 180 Ringing、182 Queued、183 Session progress、或者其它不知如何處理的 1xx 的回覆,如果含有 SDP 時,就會送 AST_CONTROL_PROGRESS 給 Dial(),Dial() 可能執行 ast_channel_early_bridge()、可能往另一端送 AST_CONTROL_PROGRESS、或者可能送 DTMF。執行 ast_channel_early_bridge() 的條件 1. 只有單一受話方 2. 不能有 m 或 r 選項 3. 不能有 h, H, t, T, w, W, k, K, A, M, U,雙方沒有 audiohooks 及雙方framehooks 是空的 [待確認]。雙方的 early_bridge 要同一個才能執行,目前只有 ast_rtp_instance_early_bridge。相關函數:Progress():送 AST_CONTROL_PROGRESS

DTMF
大容量:ref: http://www.voip-info.org/wiki/view/Asterisk+at+largehttp://www.voip-info.org/wiki/view/file+descriptors
Asterisk on OpenWrt

參考

  1. http://solomon.ipv6.club.tw/Visiting/ACT-200701/programming_asterisk_pbx.pdf

2015年2月5日 星期四

systemd

system management daemon,是 Linux userspace 第一個 process,可取代 init。systemd 改進軟體相依性的框架、允許更多動作可以在開機時同時處理、減少 shell 計算的 overhead。

延伸閱讀
  • http://www.freedesktop.org/wiki/Software/systemd/
  • http://linoxide.com/linux-command/systemd-vs-sysvinit-cheatsheet/

SIP/RTP NAT Traversal

NAT 後面的設備只知道自己的內部位址,不曉得在公網的位址。SIP 訊息裡包含了用於 signaling 及 media 的 IP 及通訊埠,除非是經過 ALG 的 NAT,不然這些位址並不會轉換,公網上的設備並不認得這些內部位址。

在 SIP/SDP 訊息中會有內部位址地方包括:
  • SIP Message Header 中的「From:」:似乎沒關係。
  • SIP Message Header 中的「Contact:」:SIP 話機註冊時,Contact 欄告知目前的位置,讓其他設備可以查到。若 Contact 用內部位址,在公網並不曉得在哪裡,無法 SIP INVITE。
    • registrar 只需要改用 SIP 封包 IP 層的實際來源位址,而不用 SIP Contact 欄位的位址。
    • 需要維持這個 NAT 通道。註冊之後,NAT 開了一個外面的通訊埠,對應到內部的 SIP 話機,公網的封包就可以透過這個通訊埠進到 SIP 話機,但此通訊埠在 NAT 對應到期後就會關閉了,需要持續送收封包來避免到期。SIP 話機註冊週期短於 NAT 對應過期時間可維持 NAT 通道,但 SIP REGISTER 的處理較費力,會加重伺服器的負擔,最好 SIP 話機可以送處理較省力的 SIP OPTIONS,或改由伺服器送 stateless OPTIONS 給 SIP 話機。
  • SIP Message Header 中的「Via:」:SIP 回應訊息是依據 Via 的路徑反向送回,若 Via 用內部位址,路徑就斷了而無法回送回應訊息。
    • SIP 定義的 received 及 RFC 3581 新增 rport:請求時,Via: 加上 ;rport 來告知支援 rport,伺服器端收到後加上「=<通訊埠號碼>」及「;received=<位址>」。回覆時路徑是依據 received 位址及 rport 通訊埠。這個作法比 STUN 好,支援對稱式 NAT。
  • SIP 內容放 SDP 時,欄位「c」和「m」分別是欲接收 RTP 封包的 IP 位址與通訊埠。若這些欄位填入的是內部位址,則通話建立後的 RTP 影音封包將無法收到。 有下列可能的解決方式:
    • 靜態指定 (Static Mapping) -- 事先設定 NAT 要轉換的 IP 位址並指定要轉換後的通訊埠。
    • STUN -- 取得公網 IP 及 port,不支援對稱式 NAT
    • UPnP -- SIP 話機透過 UPnP 尋找 NAT 並得知其公眾 IP。UA 可以要求 NAT 對閒置的外部通訊埠建立對應關係,用於 SIP 及 SDP 訊息中。
    • Session Border Controller (SBC,或稱為 Session Controller、Back-to-Back User-Agent、B2BUA):由公網上的 SBC 修正 SIP/SDP 訊息中的 IP 與通訊埠,並在 SIP 請求訊息加入 Record-Route:,讓之後的 SIP 訊息都會經過 SBC 修正。
    • 將雙方的 SDP 中的「c」與「m」欄位分別修改為 RTP Proxy 的 IP 與通訊埠,讓原本點對點傳送的傳送方式,變成雙方皆和 RTP Proxy 建立通話,由 RTP Proxy 負責轉送和控制雙方 RTP 封包的傳輸。
參考文獻
  1. Best practices for SIP NAT traversal
延伸閱讀
  1. http://www.cs.nccu.edu.tw/~lien/Writing/NGN/firewall.htm
  2. STUN
  3. TURN
  4. ICE

kamailio dispatcher module

dispatcher 模組:從檔案或資料庫讀取轉送目的,規則可以是 round-robin、weight based load balancing、call load distribution、hashing over SIP 封包內容等。
  • 可作為 stateless load balancer。如果需要自動偵測 gateways 是否正常運作,則需要 tm 模組。
  • lightweight 所以執行速度快
  • 可以 runtime 重新載入 routing records
參數
  • 檔案:list_file
  • 資料庫:db_url, table_name, setid_col, destination_col, flags_col, priority_col
  • force_dst, flags (影響 dispatcher 行為), use_default, dst_avp, grp_avp, cnt_avp, dstid_avp, attrs_avp, hash_pvar, setid_pvname, attrs_pvname
  • probe:ds_ping_method, ds_ping_from, ds_ping_interval
  • ds_probing_threshold, ds_ping_reply_codes, ds_probing_mode, ds_hash_size, ds_hash_expire, ds_hash_initexpire, ds_hash_check_interval, outbound_proxy
函數
  • ds_select_dst(setid, alg [, limit]):設定 dst_uri 欄位 (也就是 outbound proxy address 或 $du 變數),請求 URI 沒動。
    • setid:destination set ID
    • alg:選擇 destination 使用的演算法
    • limit
  • ds_select_domain(setid, alg [, limit]):改寫請求 URI
  • ds_next_dst(), ds_next_domain()
  • ds_mark_dst()
  • ds_is_from_list(
  • ds_load_update()
  • ds_load_unset()
MI 或 RPC 指令 
  • ds_set_state
  • ds_list
  • ds_reload

應用範例

stateless forwarding
# Dispatch requests
route[DISPATCH] {
        # round robin dispatching on gateways group '1'
        if(!ds_select_dst("1", "4"))
        {
                send_reply("404", "No destination");
                exit;
        }
        xlog("L_DBG", "--- SCRIPT: going to <$ru> via <$du>\n");
        forward("RTF_DISPATCH");
        exit;
}
stateful forwarding
# Dispatch requests
route[DISPATCH] {
        # round robin dispatching on gateways group '1'
        if(!ds_select_dst("1", "4"))
        {
                send_reply("404", "No destination");
                exit;
        }
        xlog("L_DBG", "--- SCRIPT: going to <$ru> via <$du>\n");
        t_on_failure("RTF_DISPATCH");
        t_relay();
        exit;
}

# Sample failure route
failure_route[RTF_DISPATCH] {
        if (t_is_canceled()) {
                exit;
        }
        # next DST - only for 500 or local timeout
        if (t_check_status("500")
                        or (t_branch_timeout() and !t_branch_replied()))
        {
                if(ds_next_dst())
                {
                        t_on_failure("RTF_DISPATCH");
                        t_relay();
                        exit;
                }
        }
}
discard
route {
        );
}
to one host
route {
        forward(1.2.3.4);
}

route {
        rewritehost(1.2.3.4);
        forward();
}

參考來源

  1. dispatcher
  2. 簡報:Kamailio - Load Balancing Load Balancers
延伸閱讀

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

延伸閱讀

2015年2月4日 星期三

AM335x pinmux

Beaglebone Black 的處理器 AM335x 每個多工接腳都有一個 Pad Control Register 控制,內容如下:

bitfielddescription
2:0MUXMODEpin mux 模式選擇
3PULLUDEN0 = 啟用 pull up/down,1 = 停用
4PULLTYPESEL0 = pull down, 1 = pull up
5RXACTIVE0 = output only, 1 = input or output
6SLEWCTRL選擇 slew rate
  • Pad Control Register 見 TRM 9.2.2 Table 9-1,每個接腳的位址見 TRM 9.3.1 Table 9-7 的 offset 0x800 開始的 conf_<module>_<pin> 暫存器
  • 完整的 pinmux mode 及預設值見 datasheet (Rev. G) 4.2 Table 4-1 Ball Characteristics ,有些會受到開機模式影響
  • pinmux 模式 7 是 GPIO,大部分預設是 GPIO
  • mmc0, mdio, mii1, mii2, I2C0, spi0, uart0, uart1 只有一種選擇
  • USB0 可轉成 UART2,USB1 可轉成 UART3

GPIO
有 4 個 GPIO module,每個 module 有 32 個 GPIO,總共 128 個 GPIO,其中只有部份接到 BBB 的 expansion header P8 及 P9。透過 GPIO 暫存器,可存取資料、設定為中斷等。

待整理
  • cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins 可看到 pinmux 的設定
  • https://github.com/derekmolloy/boneDeviceTree/blob/master/docs/BeagleboneBlackP8HeaderTable.pdf?raw=true
  • https://github.com/derekmolloy/boneDeviceTree/blob/master/docs/BeagleboneBlackP9HeaderTable.pdf?raw=true
  • device tree
  • cat /sys/kernel/debug/pinctrl/pinctrl-handles
  • /sys/kernel/debug/omap_mux
參考來源:
  1. http://derekmolloy.ie/beaglebone/beaglebone-gpio-programming-on-arm-embedded-linux/

2015年2月3日 星期二

kamailio 簡易 proxy

kamailio 執行時透過命令檔載入需要的模組、設定模組的參數、以及提供 SIP 封包的處理方式。SIP 封包處理語法類似 C 語言,使用 kamailio 核心內建及外掛模組的函數及變數。

下面是一個簡易的 stateless proxy,含免認證 REGISTRAR,可給 SIP 話機註冊後互撥,不用建立帳號。
#!KAMAILIO

# 載入模組
loadmodule "sl.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"

# 處理 SIP 請求,預設是丟棄
route {
    # REGISTER 則 save() 執行 SIP 註冊動作後結束。
    if (method=="REGISTER") {
        if (!save("location"))
            sl_reply_error();
        exit;
    }

    # 其它則 lookup() 查是否有註冊。
    if (!lookup("location")) {
        # 查詢失敗,回 404 等之後結束。
        switch ($rc) {
        case -1:
        # 查不到
        case -3:
        # 內部錯誤
            sl_send_reply("404", "Not Found");
            exit;
        case -2:
        # 有查到,但 Method 不支援
            sl_send_reply("405", "Method Not Allowed");
            exit;
        }
    }

    # 如有查到會置換 uri,呼叫內建函數 forward() 將封包轉送。
    forward();
}

# SIP 回應預設依 Via 轉送,所以不需要回應處理區塊。
載入的模組說明
  • sl:stateless replier,提供 sl_send_reply(code, reason) 及 sl_send_error() 等回覆 SIP status code 的函數。
    • sl_send_reply(code, reason):送 SIP 回覆
    • sl_send_error():依據錯誤碼送 SIP 回覆
    • sl_forward_reply([ code [, reason ] ]):轉送 SIP 回覆,可更改 code 或 reason
    • send_reply(code, reason):取決是否是在 tm 的 transaction 中而 stateful 或 stateless 送 SIP 回覆。
  • usrloc:提供 location database 給 registrar 等其它模組使用
  • registrar:使用 usrloc database 來提供 SIP 註冊功能,這裡用到下列兩個函數
    • save(domain[, flag[, uri]]):儲存註冊資料到 usrloc database,並回 200 OK
    • lookup(domain[, uri]):查詢 usrloc database 取代 uri
問題
  • 如果 INVITE 收到多個不同 To tag 的回應會怎樣?可以怎樣處理?
延伸閱讀

2015年2月2日 星期一

kamailio on Ubuntu

要在 Ubuntu 跑 kamailio 很簡單:
  1. 安裝
    sudo apt-get install kamailio
  2. 編輯 /etc/default/kamailio
    sudo vi /etc/default/kamailio
    將 #RUN_KAMAILIO=yes 行首的 # 移除
  3. 啟動
    sudo service kamailio start
然後不用建帳號或密碼就可以讓網路電話註冊,註冊後就可以互打。

使用的命令檔是 /etc/kamailio/kamailio.cfg。

延伸閱讀

SIP header Via

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