まず、ユニバーサルデザイン
1.1アーキテクチャ
1.1.1コミュニケーション図。
次の図は、フロントエンド渡す方法PJSIPに後端からアセンブリとの間のSIPメッセージを示します。
図クラス1.1.2
次の図は、ビュークラスを示してい
1.2エンドポイント
コアSIPスタックは、透明な表現pjsip_endpointあるSIPエンドポイント、エンドポイントの関数であり、以下の特性を有します
L貯蔵施設、すべてのメモリ割り当てられたSIPコンポーネント
すべてのSIPタイマースケジュールコンポーネントの固体列タイマーを備え、Lリアクトル
送信管理インスタンスからL、制御メッセージをSIPメッセージと解析を転送し、印刷を担当するトランスポート・マネージャ。
Lは、単一インスタンスPJLIB IOキュー、proactorモード配信イベントを使用して、IOキューを有します。
lはスレッドセーフポーリング機能を提供し、マルチスレッドアプリケーションを照会することができるとソケットタイマーイベント(任意の共通のスレッドせずに自分自身をPJSIP)
L PJSIP管理モジュール、SIPスタックを拡張PJSIPメインモジュールではなく、メッセージを解析し、印刷に限ら。
LのSIPメッセージは、送信モジュールから受信した、各モジュールに分配されます。
1.2.1メモリプールの割り当てと解放
アプリケーション全体でセキュリティスレッドと強力な政策の一貫性を確保するために、すべてのSIPメモリが割り当てられたエンドポイントを完了するために必要とされています。たとえば、次のキャッシュ・メモリ・プール、未使用のメモリは、将来の使用のために予約なく破壊されます。
エンドポイントは、以下の機能が割り当て、空きメモリプールを提供します
pjsip_endpt_create_pool()
pjsip_endpt_release_pool()
エンドポイントがpjsip_endpt_createを作成するために()である場合には、アプリケーションは、エンドポイントが使用するメモリセルファクトリを指定する必要があります。ライフサイクルのエンドポイントホールドポインタメモリプールの植物を通して、将来の使用のために作成し、メモリを解放します。
1.2.2タイマ管理
エンドポイントは、別のタイマーヒープインスタンスを持って、SIPタイマーの作成およびスケジューリングのすべてのコンポーネントが完了しているエンドポイントを通過する必要があります。エンドポイント管理には、以下の機能タイマを提供します
pjsip_endpt_schedule_timer()
pjsip_endpt_cancel_timer()
poll関数のエンドポイントは、タイマーが期限切れかどうかを確認するために呼び出された場合。
1.2.3ポーリングスタック
エンドポイントは、別の関数(pjsip_endpt_handle_events())の存在タイマーやネットワークのイベントをチェックするために、アプリケーションは、イベントの発生をチェックする準備が待機する時間を指定することができます。
PJSIPは、動作中のスレッドスタック、スタック全体を作成することはありませんポーリング関数が呼び出されると呼ばれているかどうかAPI、アプリケーションによって作成されたスレッドに依存しています。
待機時間を最適化するために、ポーリング機能は、次のような内容のタイマーヒープに依存します:それはタイマーが次の5S期限切れとなる見つけたとき、彼は非ネットワークイベント、アプリケーションの場合には、ソケットのイベントは、長い5S以下にする必要がありますレイテンシ5Sは必要ありません以上のことを待って、当然のことながら、各プラットフォームのタイマーの精度は同じではありません。
1.3互換性スレッドセーフとスレッド
1.3.1スレッドセーフ
ディスカッションスレッドの安全性は幸いなことに、合意を通じて適用され、以下の設計原理が一貫して、より面倒なことですが、。
オブジェクトは、スレッドセーフでなければなりませんが、データ構造は間違いなく、スレッドセーフではありません。
このテーマを参照してください、オブジェクトとシンプルなデータ構造の違いを考えるのが自然であるので、明らかではないが、いくつかの例を提供することができ、より明確に書かれたことがあります。
データ構造の例:
PJLIBデータ構造、例えば:
リットルのリスト、配列、ハッシュテーブル、文字列、メモリプール。
SIPメッセージ、URLを、ヘッダフィールドとSIPメッセージのL個の要素
これらのデータ構造は、それらを含むオブジェクトによって保証スレッドセーフ、スレッドセーフなデータ構造ではありません。データ構造は、スレッドセーフである場合、それは真剣に、プロトコル・スタックおよびオペレーティング・システムのリソース消費のパフォーマンスに影響します。
これとは対照的に、PJSIPオブジェクトは、このような、スレッドセーフである必要があります。
LのPJLIBオブジェクト、例えばioqueue
エンドポイント、トランザクション、ダイアログ等:などのL PJSIPオブジェクト、。
1.3.2複雑
さらに悪いことには、いくつかのオブジェクトは、ヘッダファイルにその声明(pjsip_transactionとpjsip_dialog)を公開していることです。
APIの露出がデータ構造にアクセスする前に、アプリケーションをセキュリティスレッドを保証することができますが、それはpj_mutex_lockでミューテックスオブジェクトを取得する必要があります。
さらに悪いことに、異なるAPIロックダイアログのダイアログ暴露は、アプリケーションがpjsip_dlg_inc_lockとpjsip_dlg_dec_lock()の代替pj_mutex_lockとpj_mutex_unlockを呼び出す必要があります。2つのアプローチが区別されます:
ときに、関数呼び出しダイアログが破壊されないことを保証するために、ダイアログのINC / 12月 なぜならダイアログシーケンスのクラッシュによって引き起こされる破壊のpj_mutex_unlock。
次の例を考えてみます。
pj_mutext_lock(dlg->ミューテックス)
pjsip_dlg_end_session(DLG、...)
pj_mutex_unlock(dlg->ミューテックス)
pjsip_dlg_end_sessionダイアログがいくつかのケースでは破壊される可能性があるため、上記の例では、アプリケーションは、クラッシュすることがあります。たとえば:INVITEトランザクション応答がない、トランザクションがすぐにダイアログがすぐに破壊され、その結果、破壊されます。ダイアログ
ダイアログを増加させることによりINC] / [DECの参照カウントは、このような事態の発生を防止することができます。再end_session、ダイアログが破壊されることはありません場合は、ダイアログがdec_lock機能で破壊される可能性があります。次のようにそのため、正しい呼び出しシーケンスは次のようになります。
Pjsip_dlg_inc_lock(DLG)
Pjsip_dlg_end_session(DLG)
Pjsip_dlg_dec_lock
さらに悪いほとんどの事項は、呼び出しシーケンスのロックは、それ以外の場合は、デッドロックにつながり、正しくなければなりません。たとえば:ダイアログとダイアログトランザクションをロックすると、アプリケーションは、ダイアログミューテックス取得トランザクションミューテックス前に取得しなければならない、あるいは逆の順序で、他のスレッドがロックを取得するとき、デッドロックが発生します。
1.3.3ソリューション
幸いなことに、非常に少数のアプリケーションが直接オブジェクトをロックしますので、上記の問題はほとんど発生しません。アプリケーションがオブジェクトにアクセスするには、オブジェクトのAPIを使用する必要があり、オブジェクトのAPIは、デッドロックやクラッシュを回避するために、ロックの正確さを保証するためにチェックします。
コールバックアプリケーションは、これらのコールバックが呼び出され、オブジェクトを呼び出されるまでロックオブジェクトを取得しています。だから、アプリケーションがロックオブジェクトを取得し、不要な、オブジェクトのデータ構造へのアクセスを確保することができます。