ブログ
これまでに経験してきたプロジェクトで気になる技術の情報を紹介していきます。
SIPフォンを作る【第一回】
UnityでSIPフォンを作ります。
なぜかUnityでSIPフォンを作る話がインターネットのどこを探しても日本語英語問わず存在しなかったので、めちゃくちゃ大変でしたが作りました。 SIPフォンとは電話回線ではなく、インターネット回線を使用して電話するアプリのこと(意訳)で、Asterisk等のPBX(電話交換機)サーバーを通して通話ができるというものです。
社内やチームのみにつながる内線電話等の設定を作れますが、それはPBXサーバーの設定であり今回はクライアントアプリの話なのでその辺の話は割愛します。
SIPで通話できるアプリは既存のもので結構いろいろなものがありますし正直それらを使うのはめっちゃ便利で品質も良くて機能も多いですが、やはり自分で作ったものだと好きに拡張しやすいし、サーバー側との連携でいろんな機能を実装しやすいので、自作します。
今回使うUnityは2019.4.0f1で基本的なUnityの使い方はわかっている前提で書いていきます、よろしくお願いします。
ライブラリをDLしてくる
UnityでSIPフォンを作る話が全然ないのはUnityで使えるSIPのライブラリが全然存在しないことが原因だと思うんですよね。
一件Unity向けらしきライブラリを見つけたのですがまだ公開されていませんでした。
なんとかUnityで使用されている.NetStandard2.0向けのライブラリが見つかったのでそれを使うことにします。
https://independentsoft.de/sip/index.html
有料のライブラリですが、とりあえず30日間の評価版をDL。 購入する際は作業者一人につき299€を払うか、社内何人でも使える無制限ライセンスが699€です。
Zipを解凍してlab/netstandard2.0をプロジェクトに放り込みます。 中のIndependentsoft.Sip.dllだけでもいいですが、.NetCoreや.NetFramework向けのも同梱されているためそれと間違えないためです。 ライブラリを使うコードでは
using Independentsoft.Sip;
using Independentsoft.Sip.Sdp;
using Independentsoft.Sip.Responses;
辺りの名前空間を宣言しておきましょう
REGISTERする
SIPで通信するためにはSIPサーバーにREGISTERしないといけません。いわゆるログイン、サインインみたいなものです。 アカウントに必要になる情報はSIPサーバーのアドレス、ポート番号、アカウントID、パスワードです。 アカウント作成はサーバー側の処理で作成するものなので、サーバー側にアカウントを作るAPIがないと使用できません、なので割愛。 事前にサーバー側にアカウントを用意しておきましょう。
アカウント情報を管理するオブジェクトを作成します 各項目はシーンに配置してあるInputTextを参照しています
var client = new SipClient(domain.text, int.Parse(port.text),Independentsoft.Sip.ProtocolType.Udp,username.text, passward.text);
ドメインとポート番号と通信方式はUDPであること、ユーザーネームとパスワードを引数に持たせてSIPClientオブジェクトを作成します。 このオブジェクトは今後いろんな場所で出てくることになるので格納する変数は、classフィールドとして宣言しておくのがよいでしょう。
SIPClientオブジェクトにロガーやRequestやResponseが来たときに呼ばれるハンドラーを登録していきます。
logger = new Independentsoft.Sip.Logger();
logger.WriteLog += new WriteLogEventHandler(OnWriteLog);
client.Logger = logger;
client.ReceiveRequest += new ReceiveRequestEventHandler(OnReceiveRequest);
client.ReceiveResponse += new ReceiveResponseEventHandler(OnReceiveResponse);
ローカルIPを取得してport番号と合わせてLocalEndPointを作成 Dns.GetHostName();で取得できるIPaddressの一覧からローカルのIPv4のIPアドレスを選んで使う必要があるが、Androidスマホだとindexが0、WindowsPCだと2の辺りがそれにあたると思います、これに関しては検証不足です。安定する取得方法を考えてください。
string hostname = Dns.GetHostName();
IPAddress[] adrList = Dns.GetHostAddresses(hostname);
System.Net.IPAddress localip = adrList[n];
localIP = localip.ToString();
client.LocalIPEndPoint = new IPEndPoint(localip, int.Parse(port.text));
Clientをサーバーに接続してREGISTER_Requestを送り、REGISTERします サーバーのsipアドレスと、サーバーの自分のアカウントのsipアドレス、ローカルのsipアドレスを登録します。 成功すればStatusCodeが200のResponseが返ってきます。
client.Connect();
var regist_respons = client.Register("sip:" + domain.text + ":" + port.text,
"sip:" + username.text + "@" + domain.text + ":" + port.text,
"sip:" + username.text + "@" + client.LocalIPEndPoint.ToString());
if (regist_respons.Response.StatusCode == 200)
{
debug.log("REGISTER成功");
}
else
{
debug.log("REGISTER失敗");
}
sipアドレスは "sip:アカウント@ホスト名:ポート番号"という構造をしています
REGISTER情報は60秒に一回消えるので、55秒毎とかに再REGISTERしてやるといいと思います (通話中は切れないので通話していないとき)
次回は発着信の機能を作ります。
コメントはありません。