2012年5月24日木曜日

Asterisk Manager Interface (AMI) 検証 1)

Asterisk1.8を使用してAsteriskを外部システムから管理することができるAsterisk Manager Interface (以下 AMI)についてしらべて見ました。

環境整備


AMIのについては
http://www.voip-info.org/wiki/view/Asterisk+manager+API
で調べることができます。

AMIを有効にするためにはまずその機能を有効にする必要があります。

The Asterisk Manager Interface (AMI)
を参考にしました。

具体的には /etc/asterisk/manager.conf の
[general]
enabled = yes
port = 5038
bindaddr = 0.0.0.0

で機能をオンにします。
また使用するポート番号と、サーバーで使用するIPアドレスの指定ができますが、通常は上のように書きます。

また、
ユーザー「admin」を作る場合、同じファイルで
[admin]
secret = secret5
deny = 0.0.0.0/0.0.0.0
permit = 127.0.0.1/255.255.255.255
read = all,system,call,log,verbose,command,agent,user,config
write = all,system,call,log,verbose,command,agent,user,config

を追加してください。[ ] の中にはユーザー名を入力します。read/ writeは利用権限となります。
AMIでアクセスできる端末をIPアドレスでしていることが可能です。
この例ではAsteriskが起動している端末からのみアクセスの許可をしていますが、環境に応じて変更してください。私の環境では
permit = 192.168.0.0/255.255.255.0
として社内のLANから使用できるようにしています。

ここでAsteriskを起動するなり、コンフィグの再読み込みをしてください。
検証なので
asterisk -vvvvc
で起動してみるのもいいかもしれません。

動作確認


ファイアーウォールなどで設定が適切でない場合ちゃんと通信が行えません。
ファイアーウォールの設定をするか、検証でインターネットに直接接続していない環境であればファイアーウォールの機能を停止してみるのもいいかもしれません。
CentOSの場合は以下のような形で停止することが可能となります。

[root@localhost ~]# /etc/init.d/iptables stop
iptables: ファイアウォールルールを消去中:                  [  OK  ]
iptables: チェインをポリシー ACCEPT へ設定中filter         [  OK  ]
iptables: モジュールを取り外し中:                          [  OK  ]
[root@localhost ~]#

AMI自体はtelnetでその動きを確認することが可能となります。

たとえばLinuxでAsteriskを使用している場合

telnet localhost 5038

すると、
# telnet localhost 5038
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Asterisk Call Manager/1.1

と表示されます。
 
action:Login
Username:admin
Secret:secret5

といれることでログインが行えるようになります。(ここでパスワードを入れた後二回ほどEnterキーを押すこと)

Response: Success
Message: Authentication accepted

Event: FullyBooted
Privilege: system,all
Status: Fully Booted

と表示されます。ログイン中はAsteriskで何か動きがあれば表示されます。

たとえばSIPフォンがレジストされたとき

Event: PeerStatus
Privilege: system,all
ChannelType: SIP
Peer: SIP/201
PeerStatus: Registered
Address: 192.168.0.102:50666

とその端末の情報が表示されます。

ログオフは

Action: Logoff

としてください。

簡単なJAVAでのAMIクライアント

 実際AMIを利用する上ではtelnetを使用することは現実的ではないので何らかのプログラムを利用するか作成を行う必要があります。
そこでJavaを利用することを考えました。JavaにはAsteriskを利用するためのAPIがありそれを使用することを考えました。

http://www.asterisk-java.org/development/index.html

実際にここにあるチュートリアルから試してみたところ

5 24, 2012 3:36:47 午後 org.asteriskjava.manager.internal.ManagerConnectionImpl doLogin
情報: Determined Asterisk version: Asterisk 1.8
Error

と表示されました。(Netbeansの画面です)

どうもこのAPIはAsterisk1.4(もしかして1.6もサポートしているかもしれません)までのサポートのようです。

そこで1.4を入れなおすのもどうかなと思ったので

Java : Socketsプログラミング   http://www.gadgety.net/shin/java/sockets.html 

を参考にしてプログラムを作ってみました。

package testsocketclient;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

public class TestSocketClient {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
                // ソケットや入出力用のストリームの宣言
        Socket echoSocket = null;
        DataOutputStream os = null;
        BufferedReader is = null;
       
        // ポート5038番を開く
        try {
            echoSocket = new Socket("127.0.0.1", 5038);
            os = new DataOutputStream(echoSocket.getOutputStream());
            is = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host: localhost");
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to: localhost");
        }

        // サーバーにメッセージを送る
        if (echoSocket != null && os != null && is != null) {
            try {
                // メッセージを送ります
                os.writeBytes("Action: Login\r\nActionID: 1\r\nUsername: admin\r\nSecret: secret5\r\n\r\n");
               
                // サーバーからのメッセージを受け取り画面に表示します
                String responseLine;
                while ((responseLine = is.readLine()) != null) {
                    System.out.println(responseLine);
                }
               
                os.writeBytes("Action: Logoff\r\n\r\n");
               
                // 開いたソケットなどをクローズ
                os.close();
                is.close();
                echoSocket.close();
            } catch (UnknownHostException e) {
                System.err.println("Trying to connect to unknown host: " + e);
            } catch (IOException e) {
                System.err.println("IOException: " + e);
            }
        }
    }
}


参考にしたサイトからの主な変更点は2つです。
ひとつは
echoSocket = new Socket("127.0.0.1", 5038);
でポート番号をAMIの5038にしています。

もう一つはデータ受信の際に ifの部分をwhileに変更しています。これはifにすると一行しか表示をされません。またその後AMIをログオフし実際にログインしたことをちゃんと確認できません。

 もちろんAMIにログインするための部分を書き換えています。

実行すると

Asterisk Call Manager/1.1
Response: Success
ActionID: 1
Message: Authentication accepted

Event: FullyBooted
Privilege: system,all
Status: Fully Booted

と表示され実際にログインしたことが確認されます。
ただしwhileに変更したため、明示的に停止するまで実行し続けます。
停止するまでAsteriskに変更があった場合などにはEvent情報が出力されていきます。

0 件のコメント:

コメントを投稿