2015年4月26日 星期日

Kamailio pseudo variables ($)

虛擬變數 (pseudo variable, pvar,對應到內部的實際變數?) 以「$」開頭,如果需要字元「$」,寫成「$$」。有預先定義的虛擬變數及對應到 AVP (Attribute Value Pair) 或 Headers 的特殊虛擬變數,大部分由 pv 模組提供。詳細虛擬變數列表可見 Kamailio SIP Server v4.2.x (stable): Pseudo-Variables

$rc, $retcode:return code
$ru, $rd, $rU, $rp (來自 pv 模組):分別是 Request URI 及其 domain, user, port
$du (來自 pv 模組):destination URI,rewritehost() 等會設定 $du
$fd (來自 pv 模組):From domain
$td (來自 pv 模組):To domain
$sel(name):來自 pv 模組,相當於 @name
$branch(name): 取得額外分支的 name 屬性。可用 index 取得特定分支,沒有 index 代表第一個分支,-1 代表最後分支。
$var(name):自訂名為 name 的記憶體變數,值可為整數或字串,使用上比 AVP 快。

虛擬變數可以轉換成另一個值,例如字串長度、md5 值等,格式是 $(pv{transformation}),轉換用「{」、「}」包起來緊接在虛擬變數名稱後面,整個再用「(」、「)」包起來。大部分的虛擬變數轉換仍由 pv 模組提供。詳情見:http://www.kamailio.org/wiki/cookbooks/4.2.x/transformations

2015年4月21日 星期二

assert()

#include <assert.h>

void assert(scalar expression);

assert(表示式) 是個標準的 macro,用來方便程式除錯。當表示式結果為 0 (邏輯判斷為假) 時,會印包含檔名、行數、函數名及表示式的訊息到 stderr,然後呼叫 abort() 結束程式。如果在 <assert.h> 之前有定義 NDEBUG 的話,就會關閉 assert() 功能,整個 assert() 會省略掉,不會產生任何程式碼。所以 assert() 不能含有有作用的程式。

簡略的 assert.h 如下:
#ifdef  NDEBUG
#define assert(expr)        ((void) (0))
#else /* Not NDEBUG.  */
#define assert(expr)       ((void) ((expr) ? 0 :                                                             \
                       (__assert (__STRING(expr), __FILE__, __LINE__, __func__), 0)))
#endif /* NDEBUG.  */
而 __assert() 函數如下:
static smallint in_assert;                      /* bss inits to 0. */

void __assert(const char *assertion, const char * filename,
              unsigned int linenumber, register const char * function)
{
        if (!in_assert) {
                in_assert = 1;

                fprintf(stderr,
                                "%s: %d: %s: Assertion `%s' failed.\n",
                                filename,
                                linenumber,
                                /* Function name isn't available with some compilers. */
                                ((function == NULL) ? "?function?" : function),
                                assertion
                                );
        }
        abort();
}

參考來源:man assert, assert.h, __assert.c

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

SIP header Via

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