SipProfile.getSendKeepAlive は、keep alive を行うかどうかを取得します。
keep alive について、リファレンスでは以下のようにあるだけです。
the flag of sending SIP keep-alive messages
SipProfile.Builder setSendKeepAlive
boolean:true if sending keep-alive message is required, false otherwise
以下も、keep alive の記述はありません。
ので、android のソースコードから動作を調べることにしました。
参考にしたバージョン
android 7.0 のソースコードを参考にすることにしました。以下のサイトで調べました。
結論
- REGISTER リクエストの成功後、定期的に OPTIONS リクエストを送信する。
- 送信間隔は、20 ~ 120 秒。
- OPTIONS リクエストの応答がない場合、OPTIONS レスポンスを確認し RPORT の変更があった場合、REGISTER リクエストを送信する。
- WIFI を使用していると判断される場合 (※1) は、SipProfile.getKeepAlive が false でもこの動作をする。
※1 ... SipService.isBehindNAT を参照。WIFI を使用しているかどうかは、IP アドレスにより判断している。
ソースコードの調査
SipProfile.getSendKeepAlive の呼び出し箇所
SipProfile.getSendKeepAlive メソッドを呼び出す個所は SipAutoReg.onRegistrationDone 。
SipService.isBehindNAT メソッドが true を返す、または、SipProfile.getSendKeepAlive メソッドが true を返す、場合、SipAutoReg.startKeepAliveProcess メソッドを実行。
以降の呼び出しは以下の通り。
SipAutoReg.onRegistrationDone
→ SigAutoReg.startKeepAliveProcess
→ SipSessionImpl.startKeepAliveProcess
→ SipKeepAlive.start
SipKeepAlive クラス start メソッド
SipKeepAlive.start
引数 interval により、タイマ (mWakeupTimer) を開始。
SipKeepAlive.run
タイマにより、run メソッドが実行。SipKeepAlive.sendKeepAlive メソッドを実行。
SipKeepAlive.sendKeepAlive
SipHelper.sendOptions メソッドを実行。SipHelper.sendOptions は OPTIONS リクエストを送信している。
SipSessionImple.startSessionTimer メソッドでは、SessionTimer を作成。SessionTimer は start メソッドの引数 timeout が経過すると SipSessionImpl.onError を実行する。(応答のタイムアウト判定)
SessionTimer クラス
onError を実行されないためには、SessionTimer.cancel を実行する必要がある。
SipSessionTimer.cancel メソッドの呼び出し元 (keep alive に関連するものだけ) をたどると
SipSessionTimer.cancel
← SipSessionImpl.cancelSessionTimer
← SipKeepAlive.process
← SipSessionImpl.process
← SipSessionGroup.process
← SipSessionGroup.processResponse … レスポンスの受信の際に呼ばれるはず
また、タイムアウト時の呼び出しは以下の通り。
SessionTimer.timeout
→ SipSessionImpl.onError
→ SipSessionImpl.endCallOnError
→ SipSessionListenerProxy.onError (SipSessionImpl.startKeepAlive で SipKeepAlive をセット)
→ SipKeepAlive.onError
→ SipAutoReg.onError (SipKeepAlive.startKeepAliveProcess の引数 callback へ通知)
SipKeepAlive.process
SipKeepAlive.process メソッドは、レスポンスを解析する。
RPORTが変更されている場合、SipKeepAlive.stop にて、mWakeupTimer を停止。SipSessionImpl.reset も呼ばれ、SipSessionImpl.cancelSessionTimer も呼ばれる。(Keep Alive 動作の停止)
RPORTが変更されていない場合、SipSessionImpl.cancelSessionTimer を呼ぶ。(応答タイムアウト判定のキャンセル)
KeepAliveProccessCallback.onResponse を呼び出し。 これは SipAutoReg が実装している。
SipAutoReg.onResponse , SipAutoReg.onError
SipAutoReg.onResponse
portChanged が true であれば、SipSessionImpl.register を実行。
SipSessionImpl.register は、REGISTER リクエストの送信を行う。
SipAutoReg.onError
SipAutoReg.onResponse(true) を実行。
その他
SipService.isBehindNAT
引数に String 型の変数をとり、10.*.*.*
、172.16.*.*
、192.168.*.*
のいずれかに該当する場合、true を返す。
wifi を使用している場合は、大抵これらのアドレスに該当する。SipProfile.getSendKeepAlive によらず、keep alive が有効になる。
keep alive の送信間隔の変更
送信間隔の変更は、SipKeepAliveProcessCallback で行っている。
このクラスも OPTIONS リクエストを送信している。
(このあたりよくわからないが、SipServiceで保持されるインスタンスは1つだけなのでいいのかな)
送信間隔変更時は以下のような呼び出しになる。
SipKeepAliveProcessCallback.onResponse
→ SipService.onKeepAliveIntervalChanged()
→ SipSessionGroupExt.onKeepAliveIntervalChanged
→ SipAutoReg.onKeepAliveIntervalChanged
→ SipAutoReg.startKeepAliveProcess
TODO
keep alive の動作は大体わかったので、SipAutoReg の使用箇所を調べる。
SipAutoReg の使用箇所
SipAutoReg クラスは、SipSessionGroupExt クラスで使用されている。
SipSessionGroupExt クラスは、SipService.createGroup , SipService.createGroup で作成される。
これらは、SipService.createSession , SipService.open , SipService.open3 で使用される。