2014/11/24

再用 list comprehension 解魔方陣

小朋友的學校又給了一個特殊的魔方陣題目,erlang 的 list comprehension 解魔方陣真的很快,把每一種可能發生的狀況慢慢列出來,就可以得出結果了。

題目:
五芒星共十個節點,填入 1 ~ 10 的數字,外側有五個小三角形,每一個小三角形的三個數字和,如果是 13,請列出十個節點的填法。再把總和改為14,15,16,17,18,19,20,分別找出可能的填寫方法。

如果用筆慢慢計算,必須要這樣想,五個三角形總和都是 13,13*5=45,因為 1~10 十個數字的總和是 55,但中間的 A,B,C,D,E 各被多加了一次,所以 A+B+C+D+E+55=45,因此 A+B+C+D+E = -10,此題無解。

至於 14,就是 A+B+C+D+E+55=14*5,所以 A+B+C+D+E=15,再慢慢列舉 A,B,C,D,E 進而找出 F,G,H,I,J。

用 erlang 可以這樣寫 matrix.erl

-module(matrix).
-export([resolve/1]).

resolve(SUM) ->
    statistics(runtime),
    statistics(wall_clock),
    K = lists:seq(1,10),
    L=[{A,B,C,D,E,F,G,H,I,J}||
     A <- K,
     B <- K--[A],
     F <- K--[A,B],
     A+B+F == SUM,

     C <- K--[A,B,F],
     G <- K--[A,B,F,C],
     B+C+G == SUM,

     D <- K--[A,B,F,C,G],
     H <- K--[A,B,F,C,G,D],
     C+D+H == SUM,

     E <- K--[A,B,F,C,G,D,H],
     I <- K--[A,B,F,C,G,D,H,E],
     D+E+I == SUM,

     J <- K--[A,B,F,C,G,D,H,E,I],
     A+E+J == SUM
    ],
    {_, Time1} = statistics(runtime),
    {_, Time2} = statistics(wall_clock),
    io:format("runtime=~p wall_clock=~p ~n", [Time1, Time2]),
    L.

編譯後,再到 erl 執行。

1> matrix:resolve(13).
runtime=0 wall_clock=0
[]
2> matrix:resolve(14).
runtime=15 wall_clock=15
[{1,3,5,2,4,10,6,7,8,9},
 {1,4,2,5,3,9,8,7,6,10},
 {2,4,1,3,5,8,9,10,6,7},
 {2,5,3,1,4,7,6,10,9,8},
 {3,1,4,2,5,10,9,8,7,6},
 {3,5,2,4,1,6,7,8,9,10},
 {4,1,3,5,2,9,10,6,7,8},
 {4,2,5,3,1,8,7,6,10,9},
 {5,2,4,1,3,7,8,9,10,6},
 {5,3,1,4,2,6,10,9,8,7}]

我們把一個答案填到五芒星中。

目前的缺點是 A,B,C,D,E 重複的 set,並沒有排除掉相同的答案,還沒想到要怎麼處理。

結果蠻奇怪的,13, 15, 18, 20 沒有解,14,16,17,19 有解,沒有什麼特別的規則。

2014/11/17

kamailio installation step by step

先前已經測試過 opensips,雖然可以使用,但還是遇到一些問題,例如網頁使用者界面的套件一直沒辦法運作地很順利,我們試著改成版本更新速度比較快的 kamailio,接下來就是安裝的過程。

準備工作

安裝 kamailio 之前,必須把 CentOS 基本的套件裝好,通常我們會把開發者工具、kernel 的開發套件都裝上去,還會裝上 EPEL、rpmforge 這兩個 package repository。

因為 kamailio 的 dialplan 需要,所以必須要安裝 pcre,因為 rtpengine 的需要,所以要安裝 xmlrpc-c-devel iptables-devel。

yum -y install pcre pcre-devel libpcap libpcap-devel libunistring libunistring-devel xmlrpc-c-devel iptables-devel

安裝 kamailio

kamailio 才剛在 2014/10/16 發布 kamailio 4.2.0 版,我們可以到 kamailio download page 下載 kamailio-4.2.0_src.tar.gz。

把原始程式碼放在 /usr/local/src 資料夾中。

cd /usr/local/src
tar zxvf kamailio-4.2.0_src.tar.gz

cd kamailio-4.2.0
make cfg

修改 modules.lst 一行資料

vi modules.lst

include_modules= db_mysql websocket tls dialplan

編譯並安裝 kamailio

make all
make install

現在安裝完成的 kamailio

設定檔在 /usr/local/etc/kamailio
執行擋在 /usr/local/sbin

這裡面有4個執行檔

kamailio - Kamailio SIP server
kamdbctl - script to create and manage the Databases
kamctl - script to manage and control Kamailio SIP server
sercmd - CLI - command line tool to interface with Kamailio SIP server

modules在 /usr/local/lib64/kamailio/modules/
文件在 /usr/local/share/doc/kamailio/
man page 在 /usr/local/share/man/man5/ 以及 /usr/local/share/man/man8/

產生 mysql database

編輯 /usr/local/etc/kamailio/kamctlrc

vi /usr/local/etc/kamailio/kamctlrc
把這一行設定的註解移掉
DBENGINE=MYSQL

修改 DB 預設的密碼

DBRWPW="dbpassword"
DBROPW="dbpassword"

執行

/usr/local/sbin/kamdbctl create

結果會產生兩個 mysql users,預設密碼的部份剛剛有改過了,應該會變成 dbpassword。

kamailio 預設密碼 kamailiorw
    有 'kamailio' database 完整權限
kamailioro 預設密碼 kamailioro
    有 'kamailio' database read-only 權限

雖然 已經改過 /usr/local/etc/kamailio/kamctlrc 的密碼,需要再一次覆寫資料庫的密碼。

mysql -u root -p
use mysql;
UPDATE user SET Password=PASSWORD("dbpassword") WHERE User='kamailio';
UPDATE user SET Password=PASSWORD("dbpassword") WHERE User='kamailioro';
flush privileges;

製作啟動服務的 script

先把 kamailio 核心的設定檔改好。

cp /usr/local/src/kamailio-4.2.0/pkg/kamailio/centos/6/kamailio.init /etc/init.d/kamailio
mkdir -p /etc/kamailio
cp /usr/local/etc/kamailio/kamailio.cfg /etc/kamailio/

修改 DB 的設定

vi /etc/kamailio/kamailio.cfg

在檔案前面增加三行
#!define WITH_MYSQL
#!define WITH_AUTH
#!define WITH_USRLOCDB
修改 DBURL 密碼
#!ifndef DBURL
#!define DBURL "mysql://kamailio:max168kit@localhost/kamailio"
#!endif

以 kamailio 的 init script sample 把啟動服務的 script 做好。

cp /usr/local/src/kamailio-4.2.0/pkg/kamailio/centos/6/kamailio.sysconfig /etc/sysconfig/kamailio

chmod 755 /etc/init.d/kamailio

修改 script 內容

vi /etc/init.d/kamailio
修改這2行
KAM=/usr/local/sbin/kamailio
RUN_KAMAILIO=yes


# 最後面增加 -f $KAMCFG 
OPTIONS="-P $PID_FILE -m $SHM_MEMORY -M $PKG_MEMORY -u $USER -g $GROUP $EXTRA_OPTIONS -f $KAMCFG "

修改執行 kamailio 的 user 權限

mkdir -p /var/run/kamailio
adduser --system --shell "/sbin/nologin" --home /var/run/kamailio kamailio
chown kamailio:kamailio /var/run/kamailio

設定 SIP Domain 變數, 有二種方式

1.
export SIP_DOMAIN=192.168.1.24
2.
vi /root/.kamctlrc
SIP_DOMAIN=192.168.1.24

執行 script 時有一些錯誤。

which: no greadlink in (/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/)

修改第 19 行可以解決這個問題

vi /usr/local/sbin/kamctl

which greadlink > /dev/null 2>&1

使用獨立的log檔案

檢查 kamailio.cfg 設定

vi /etc/kamailio/kamailio.cfg
debug=3 #此值控制日誌輸出的詳細程度,3為普通,4為詳細(會產生很多日誌)。
log_stderror=no #設置為no表示將日誌輸出到文件,否則輸出到控制台(應該是以前台方式啟動opensips服務時才有用)。
log_facility=LOG_LOCAL0 #應該是用於在syslog服務的配置文件裡區分opensips產生的日誌(見下面"使用獨立的log文件")。
fork=yes #設置為yes表示在後台啟動opensips服務,設置為no表示在前台啟動。

kamailio 使用syslog服務,在沒有作任何設定的狀況下,log 會進入/var/log/message這個檔案,如果希望使用獨立的log檔案,可以這樣設定

touch /var/log/kamailio.log
vi /etc/rsyslog.conf
增加一行
local0.* /var/log/kamailio.log

/etc/init.d/rsyslog restart

一併把 logrotate 設定好

vi /etc/logrotate.d/kamailio.logrotate
/var/log/kamailio.log {
   missingok
   rotate 5
   daily
   create 0640 root root
}

安裝 網頁界面 siremis

把 siremis 準備好

cd /usr/local/src
tar zxvf siremis-4.1.0.tgz
mv siremis-4.1.0 /var/www/html/siremis

產生 apache conf file

cd /var/www/html/siremis
make apache-conf

依照內容建議,編寫 apache httpd config for siremis

vi /etc/httpd/conf.d/siremis.conf
Alias /siremis "/var/www/html/siremis/siremis"
<Directory "/var/www/html/siremis/siremis">
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    Allow from all
    <FilesMatch "\.xml$">
        Order deny,allow
        Deny from all
    </FilesMatch>
    <FilesMatch "\.inc$">
        Order deny,allow
        Deny from all
    </FilesMatch>
</Directory>

修改資料夾權限,重新啟動 httpd

make prepare
chown -R apache:apache /var/www/html/siremis

service httpd restart

建立 siremis DB

mysqladmin create siremis -p

mysql -uroot -p
GRANT ALL PRIVILEGES ON siremis.* TO siremis@localhost IDENTIFIED BY 'dbpassword';

連上 siremis 網頁,一開始會是一個設定的 wizard,我們必須把資料庫的密碼,改成剛剛修改後的 dbpassword。

http://localhost/siremis/

在產生 DB 的畫面最下面,把這三個項目打勾

Import Default Data 打勾
Update sip database 打勾
Replace DB Config 打勾

最後只要看到 Installation Completed 的畫面,就完成安裝程序了。

2014/11/12

Test Simple SIP application with Mobicents and Eclipse

看了幾篇,主要介绍如何使用Mobicents、Tomcat和eclipse創建Sip Servlet應用的方式。參考Developping a Simple SIP application with Mobicents and Eclipse的步驟,很快就能將測試環境安裝好。

目前手邊的程式在jboss下執行是沒問題的,但如果能在這樣的eclipse&tomcat的環境下開發測試,應該會省下一些麻煩的步驟,因此花了些時間測試一下。

我使用的測試環境是
作業系統:Window7 32位元
Eclipse Java EE IDE for Web Developers:Luna Service Release 1 (4.4.1) (download url http://www.eclipse.org/downloads/ )
Mobicents Sip Servlets:mss-3.0.564-apache-tomcat-7.0.50.zip ( download url https://github.com/Mobicents/sip-servlets/releases )

環境安裝請參考Developping a Simple SIP application with Mobicents and Eclipse ,這裡不再贅述。

Creating a new simple project in Eclipse

  • Click File / New / Dynamic Web Project
We will generate a simple SIP application without any Web support (only basic JSP).
  • In the dialog
  1. enter "SimpleServlet" as project name.
  2. select 2.4 as module version (2.5 version does not allow simple SIP app)
  3. Select "Converged SIP / Web" as configuration
如果順利安裝完Mobicents plugin 以上步驟是沒有問題的。

以下這個步驟非常重要,否則server是跑不起來的...
  • Open the file Servers / Mobicents at localhost-config / server.xml
  • At the end of the file, locate the Context definition :
<context docbase="SimpleServlet" path="/SimpleServlet" reloadable="true" source="org.eclipse.jst.j2ee.server:SimpleServlet"></host>

  • Remove the Context tag. KEEP </host> the tag only !!
Guru's help needed : if you do not remove the context definition from server.xml, Sip servlets are not started at launch time.......

在SimpleSipServlet.java 加入測試 code 後就就可以deploy,但檢查的步驟證明我的範例程式出了問題。

  • Deploy your application : in the servers pane, right clic on your server, then deploy.
  • Now start the server. On the servers pane, right click on your server, then choose Deploy, and Start
  • Check the log file ("console" view). Check that you do not have any error (no excpetion).
  • You should see the log ****** the simple sip servlet has been started *********
  • Now, the server should be listening on the UDP port 5080 (can be checked by the netstat -an command). It should contain the following line. (if you want grep, I recommand you install MINGW to get grep and tail).

UDP 127.0.0.1:5080 *:*    ----> 找不到 冏

---------------
紅字的部份就是檢查失敗的地方,查找了sip servlet相關文章,仍然搞不清楚問題是出在哪?
解決方法待續...