いろいろ面倒ですね。
ルータはPR300SEです。
REGISTER成功までは簡単でしたが、発着信でおおいに躓きました。
GrandStreamのATAもあるし、AgePhoneアプリもあるので、WireSharkのログをひたすら眺めていれば、いつかは動くはずです。
最初の躓きは気軽にpjsipを叩きたいからチョイスしたために生じた、
pjsua2のサンプルがビルドできないこと
でした。
まぁそれはpjsuaのライブラリのmakefileをのぞき見して適当に回避しました。ヒント:大量のlibをリンクしてやる必要あり
そして最後まで残った488です。
488 Not Acceptable Here
ググれば出てくるのですが、ひかり電話でこのエラーはsdpのネゴで一致するコーデックがないのが原因、という定説があります。pjsipの最新版ではμlawがあるので問題ありません。ありませんが、可能性の芽を摘むためにsdpの出力を抑制するコードを書きました。
この頃のINVITE時のsdpは以下のような感じ
オレオレsipuaのsdpオファー
v=0
o=- 3647430131 3647430131 IN IP4 192.168.22.86
s=pjmedia
b=AS:84
t=0 0
a=X-nat:0
m=audio 4000 RTP/AVP 0
c=IN IP4 192.168.22.86
b=TIAS:64000
a=rtcp:4001 IN IP4 192.168.22.86
a=sendrecv
a=rtpmap:0 PCMU/8000
一方、比較対象のATAは以下のような感じ
ATAのsdp
v=0
o=- 3647566189 3647566189 IN IP4 192.168.22.17
s=-
c=IN IP4 192.168.22.17
t=0 0
m=audio 4002 RTP/AVP 0
c=IN IP4 192.168.22.17
a=sendrecv
a=rtpmap:0 PCMU/8000
a=ptime:20
とにかくsdpが同じになれば動くはずという信念に基づいて、以下の修正を加えていきました。もちろんpjsipは初めて使うので、まずサンプルをpythonからc++に切り替え、ライブラリともども-g付きでビルドしてgdbも数年ぶりに登場です。
・ –fPIC どんなプラットフォーム向けになってるの?
・define PJMEDIA_RTP_PT_TELEPHONE_EVENTS_STR "101" 96じゃなくて101に
・endpt->has_telephone_event = PJ_FALSE; でtelephone-events削除
・if (0 && max_bitrate && pjmedia_add_bandwidth_tias_in_sdp) { でb削除
・define PJSIP_SESS_TIMER_DEF_SE 300
・if (0 && add_min_se) { で MIN_SE: 300
・define PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT 0 でrtcpを削除
・pjmedia_sdp_media_add_attr()で”ptime: 20”(最初はsdp sessionにぶら下げてた)
・pjmedia_sdp_attr_remove_all() でX-nat: 削除
・prm.txOption.headers.push_back()で P-Preferred-Identity:追加
・prm.txOption.headers.push_back()で Require:追加
と言う具合に、以下のようなサンプル修正とpjsip本体のパッチを積み重ねていって、以下に至りました。ほとんどが不要な対応ですw 無駄足というやつですね。
オレオレsipuaのsdpオファー(心が折れる寸前)
v=0
o=- 3647753351 3647753351 IN IP4 192.168.22.86
s=pjmedia
t=0 0
m=audio 4100 RTP/AVP 0
c=IN IP4 192.168.22.86
a=sendrecv
a=rtpmap:0 PCMU/8000
a=ptime:20
状況はこうです。
ATAのsdp(再掲)
v=0
o=- 3647566189 3647566189 IN IP4 192.168.22.17
s=-
c=IN IP4 192.168.22.17
t=0 0
m=audio 4002 RTP/AVP 0
c=IN IP4 192.168.22.17
a=sendrecv
a=rtpmap:0 PCMU/8000
a=ptime:20
ここまで来たのに488が解消せず、完全に心が折れました。
おなじやないかい orz
ですが、ここでAgePhoneのsdpを見てこの4日間で32回目のアハッ体験です。
AgePhoneのsdp
v=0
o=3 820021 820021 IN IP4 192.168.22.2
s=SIP Call
c=IN IP4 192.168.22.2
t=0 0
m=audio 5004 RTP/AVP 0 101
a=rtpmap:0 PCMU/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16,32-36,54
a=ptime:20
a=sendrecv
というわけで、オチは、少なくとも手元環境では
ひかり電話ルータは、
sessionのConnection Informationがないとだめぽ
mediaにあってもだめぽ
ということのようでした。
手元ではpjsua.hでdefineいじったら発着信が可能になりました。
define PJSUA_SDP_SESS_HAS_CONN 1
試す人は、configureのCFLAGSにでも書いておけばいいんじゃないですかね。
#asteriskにとりこまれてるpjsipがどうなってるのか興味がありますが。
***
ほぼブラックボックスを相手にするとたいていこんな感じです。特に今回はFusionでは最初から発着信できましたので、心が何度も折れそうになりました。しかしひかり電話で実現できないと意味がないのです!
実はひかり電話に関しては、関連の実務経験があるので、当時直接見ることができた内部仕様書を記憶していれば瞬殺なわけですが。
当時となりに488のエラー検出条件まで覚えていそうな人はおられました。そういう人が一人か二人いれば、ほかの人は覚えないで済むということでしょうw
当時の無間地獄のような不夜城作業を思い出しましたが、これでなんとか先へ進めそうです。
環境メモ:
pjisp r5138
(リリース版使えば、こんなハマリしなかったのではないかと後悔)
(追記)
タイトル修正しました。
コメント