Asterisk 1.6 初試啼聲 – Asterisk 1.6.x 的實際環境測試

April 29, 2010
By

Asterisk 1.6 初試啼聲!

實作環境如下:

硬件:
Intel Desktop Board D865GBF
Intel Pentium 4 2.6G CPU
4 x 1GB DDR 400 RAM
2 x WD 80GB SATA HDD
Digium TE110 T1 board
軟件:
CentOS 5.2
Asterisk 1.6.0.3
Asterisk Addons 1.6.0
libpri 1.4.7
DAHDI 2.1.0.3
DAHDI Tools 2.1.0.2
SpanDSP 0.0.5 pre 4
mpg123 1.6.4

T1 是用香港某大電信供應商,所以今次並不是實驗室環境下工作,是直接接駁街線,一個完全真實的環境下工作。

關於 T1 下的Switch type 和 Protocol的設定如下:

/etc/dahdi/system.conf 的內容節錄:

span=1,1,0,esf,b8zs
bchan=1-23
dchan=24
echocanceller=mg2,1-23

/etc/asterisk/chan_dahdi.conf  的內容節錄:

switchtype=4ess
allow=ulaw
signalling=pri_cpe
echocancel=yes

實作1: 收發傳真,Asterisk 作為一台 Fax Server 的實作

以往,Asterisk 在收發傳真這一功能上一直不合格。雖然Asterisk可以安裝 SpanDSP 這一 library 來支援傳真的功能,但可惜SpanDSP 在傳真這功能上一直未如理想。以往我們會倚靠一套老牌的 OpenSource Fax Server 名叫 Hylafax 來收發傳真。如果在 1.4.x 下而 linux kernel ver. 是 2.6.x 以上,我們可以選擇 Third party 的 module 來支援 Asterisk傳真例如 PikaFax這一個收費的 asterisk module。

現在,Asterisk 1.6.x 如支持傳真功能的話便要安裝 SpanDSP 0.0.5 。實作上也確定 Asterisk 1.6.x 的收發傳真功能是成功的。我自己會用以下四個方式來測試傳真。

  1. 經由 T1 Trunk 直接收發傳真
  2. 用最新版本的 ZoIPER (http://www.attractel.com/)經T.38 Protocol
  3. 架設兩部Asterisk。用第一部 Asterisk 經由 T1 Trunk 作Gateway,Fax traffic 會由 T1經第一部 Asterisk 再經 T.38 轉接到 第二部Asterisk收發傳真 。
  4. 架設兩部Asterisk。用第一部 Asterisk 經由 T1 Trunk 作Gateway,Fax traffic 會由 T1經第一部 Asterisk 再經SIP轉接到 第二部Asterisk收發傳真 。SIP 的 CODEC 會用 uLaw。

無論系統是經由 T1 Trunk或T.38 Fax Over IP 收發傳真也沒有問題。但如果對方沒有 T.38 Protocol 而是經由 SIP 再用 muLaw 來收發傳真的話也可以,但是 SIP + muLaw 我發現會有 loss Frame 的情況出現。但總括來說,今次Asterisk 收發傳真的實作是相當成功的。她現在已不須要用其他 Fax Server 比如 HylaFax 和其他 Third Party Module,自己已經 native support 傳真。我們也可以用 Dialplan 或是用 AGI 來直接管理收發傳真的功能。在Fax Server 或將來的Unified Messaging 系統上的實作上有很大的幫助!

Asterisk 1.6.x的傳真的實作有一樣要注意。在Dialplan 內呼叫 Fax application 與以往有所不同。以前收發傳真的 application 是 rxfaxtxfax,但現在已經改為 ReceiveFaxTransmitFax 了。

實作2:Asterisk 1.6.0.3 Manager API 的 Originate打不到電話的問題

Manager API 有一個 Originate 的功能,可以指示 Asterisk 打電話,但發覺 Asterisk 1.6.x 的 Originate 無論我怎樣呼叫她也會傳回錯誤回來。

這應該是 Asterisk Manager 的錯誤了。

Asterisk Manager 的 source code 是在:

/asterisk-1.6.0.3/main/manager.c

在 manager.c 大約 2140 行有一 function 名:

static int action_originate(struct mansession *s, const struct message *m)

這裏便是 Asterisk Manager  Originate 的真身了。

再看第2166 行,這裡是用作測試 channel name 是否 empty string,如果是empty string便傳回錯誤,否則便繼續。原本的 sorrce code 是這樣:

[2140] static int action_originate(struct mansession *s, const struct message *m)
{
[2142]    const char *name = astman_get_header(m, “Channel”);
[2143]    const char *exten = astman_get_header(m, “Exten”);
[2144]    const char *context = astman_get_header(m, “Context”);
[2145]    const char *priority = astman_get_header(m, “Priority”);
[2146]    const char *timeout = astman_get_header(m, “Timeout”);
[2147]    const char *callerid = astman_get_header(m, “CallerID”);
[2148]    const char *account = astman_get_header(m, “Account”);
[2149]    const char *app = astman_get_header(m, “Application”);
[2150]    const char *appdata = astman_get_header(m, “Data”);
[2151]    const char *async = astman_get_header(m, “Async”);
[2152]    const char *id = astman_get_header(m, “ActionID”);
[2153]    const char *codecs = astman_get_header(m, “Codecs”);
[2154]    struct ast_variable *vars = astman_get_variables(m);
[2155]    char *tech, *data;
[2156]    char *l = NULL, *n = NULL;
[2157]    int pi = 0;
[2158]    int res;
[2159]    int to = 30000;
[2160]    int reason = 0;
[2161]    char tmp[256];
[2162]    char tmp2[256];
[2163]    int format = AST_FORMAT_SLINEAR;

[2165]    pthread_t th;
[2166]    if (!ast_strlen_zero(name)) {
[2167]        astman_send_error(s, m, “Channel not specified”);
[2168]        return 0;
[2169]    }

看來第2166行應該錯了。這裡應該改為:

[2165]    pthread_t th;
[2166]    if (ast_strlen_zero(name)) {
[2167]        astman_send_error(s, m, “Channel not specified”);
[2168]        return 0;
[2169]    }

改好了後,再compile 和 install。Originate 便可以正常工作了。

實作3:Asterisk 1.6.x FastAGI和 Asterisk Java 與舊版本的小小不同

如果你的 Asterisk Java(http://asterisk-java.org/) FastAGI Server 要和新的Asterisk 1.6.x 實作時便要注意。以往如果 Asterisk 有 channel hangup 時,因為 FastAGI Server 的TCP connect 在 cahnnel hangup 後同時中斷的關係,AsteriskJava會throw一個 org.asteriskjava.fastagi.AgiNetworkException。但現在 Asterisk 1.6.x 在 channel hangup 後 TCP channel 仍然保持連線,所以這個 exception 便收不到了。如果你的 FastAGI Server 用Asterisk Java 的話,這點要注意。而channel hangup 後用 getChannelStatus() 這一個 function 會傳回 -1來代表 channel down。這點好Asterisk Java像沒有 doucment 到。而她們的 doucment 只說getChannelStatus()會傳回 0 來代表 channel down。但實作上這效果並不是這樣。

實作4:Asterisk 1.6.x 大量關於設定的 Syntax不能與前版本相容

比方以下的例子:

exten => _X.,n,SetTransferCapability(SPEECH)

在 Asterisk 1.6 以後便不能再使用了。這應改為:

exten => _X.,1,Set(TRANSFERCAPABILITY=SPEECH)

相關的資訊如下:

http://www.voip-info.org/wiki/view/Asterisk+variables

結論:

作為一部 IP-PBX來說,Asterisk 的功能絶對超班!而 Asterisk 1.6.x 絶對有當 Unified Messaging Service 的 IP-PBX 的潛力。問題是在較複雜的 Call Centre環境下,ACD 需要作較大的修改來支持Unified Messaging,而且作為一部IP-PBX ,穩定絶對是第一位!這點Asterisk 1.2.x 表現很優秀!Asterisk 1.6 必須通過數以年計的穩定性試煉。無論我們的 IP-PBX的功能是何等強大,始終電話已經是必須品,現在有很多緊急服務也需要用電話提供重要服務,客戶是很難容許一套不穩定的電話系統。所以把 Asterisk 納入你的專案時,不要當 Asterisk 是一套普通的電腦系統來看待,電話系統的 Service Level 的要求是相比其他的 IT 系統高出很多很多很多!所以如果開始計劃 Asterisk 作為你的 Key System時,不要吝嗇硬件的支出。稳定的系統是有利 Asterisk 的發揮。

2 Responses to “ Asterisk 1.6 初試啼聲 – Asterisk 1.6.x 的實際環境測試 ”

  1. Patrick on May 24, 2010 at 9:23 PM

    Hi,
    您好!
    看到您的文章,對我這Asterisk初學者獲益不少!
    小弟安裝了Asterisk+ vicidial (astguiclient)
    http://astguiclient.sourceforge.net/Ubuntu_Install.txt
    看似運作正常
    不過透過gui 新增的sip phone user卻無法成功註冊
    透過手動更改sip.conf 加入的user
    卻能成功註冊

    我在手冊上沒看到這方面訊息
    請問這兩者中間是怎樣連繫的呢
    對於debug有何建議
    感謝
    Patrick from Germany

  2. admin on May 26, 2010 at 2:24 PM

    我沒有研究 astguiclient,但以我所知,這類系統很少情況會直接修改asterisk 預設的設定檔。她們會把設定直接寫入一個檔案,例如 sip-custom.conf,然後你需要在 sip.conf 中 include 這個檔案。接着 reload setting 便成。

Leave a Reply

合作伙伴




Slideshow