第 8 章 信頼性保障

8.1 信頼性モデル

DTP 実装は以下の信頼性保障を提供 しなければならない

  1. 再開:下位接続中断後に伝送を回復し、既に正常に受信されたデータを再送 してはならない
  2. 確認応答:受信側は正常に受信した Fragment を送信側に確認 しなければならない
  3. 再送:送信側はタイムアウト内に確認応答を受信できなかった場合、未確認 Fragment を再送 しなければならない
  4. セッション永続化:下位接続が中断したときセッション状態を永続化 しなければならない

8.2 再開機構

8.2.1 再開プロトコル

再開はシーケンス番号に基づいて実装 しなければならず、以下のフローに従う:

送信側                              受信側
   |                                   |
   |-- Fragment (seq=1) -------------->|  ✓ 受信
   |-- Fragment (seq=2) -------------->|  ✓ 受信
   |-- Fragment (seq=3) -------------->|  ✓ 受信
   |-- Fragment (seq=4) ------- ✗ ----|  接続切断
   |                                   |
   |        [接続復旧]                  |
   |                                   |
   |<-- ResumeReport (highest=3) ------|
   |                                   |
   |-- Fragment (seq=4) -------------->|  中断点から継続
   |-- Fragment (seq=5) -------------->|

8.2.2 ResumeReport

受信側は接続復旧後に ResumeReport を送信 しなければならない。定義は以下の通り:

interface ResumeReport {
  collectionHighest: SequenceNumber;
  injectionHighest: SequenceNumber;
}
フィールド規範的要件
collectionHighestデータ収集方向において受信側が正常に受信した最高シーケンス番号で なければならない
injectionHighestデータ注入方向において受信側が正常に受信した最高シーケンス番号で なければならない

ある方向で Fragment をまだ受信していない場合、対応するフィールドは -1 または実装定義の「未受信」識別値で なければならない

8.2.3 再開の一貫性

送信側は ResumeReport を受信した後、以下に厳密に従わ なければならない

  1. 次のシーケンス番号から継続highest + 1 から再送信を開始する。
  2. 重複送信しない:シーケンス番号が highest 以下の Fragment を再送信 してはならない
  3. スキップしない:未確認の Fragment(つまりキャッシュ内で受信が確認されていないもの)をスキップ してはならない

8.3 確認応答機構

8.3.1 確認応答の方式

実装は Fragment の受信確認を提供 しなければならない。確認応答は以下のいずれかの方法で実装 してもよい

  1. 明示的 ACK 制御フレーム:受信側が ControlFrame を送信し、controlType = "ack"、details に確認済みの最高シーケンス番号を含める。
  2. 累積 ACK:各データフレームの拡張フィールドに、逆方向の最高受信済みシーケンス番号を携帯させる(推奨)。
  3. バッチ ACK:N 個の Fragment を受信するごとに 1 回 ACK を送信する(実装定義の N、推奨 値は 16)。

具体的な確認応答方式は実装が選択 してもよい が、受信側と送信側は選択された方式について合意 しなければならない

8.3.2 確認応答のタイミング

受信側は以下を満たさ なければならない

  1. Fragment が復号、Agreement 検証、DAG 検証を通過した後にのみ確認できる。
  2. DAG が pending 状態の場合、確認 してはならない(依存関係の解決後に確認するべきである)。
  3. ACK 内の最高シーケンス番号は、確認済みシーケンス番号集合の連続するプレフィックスの最大値で なければならない

8.4 再送機構

8.4.1 再送戦略

送信側は以下の条件下で再送 しなければならない

  1. プロトコルで設定された再送タイムアウト時間内に対応するシーケンス番号の ACK を受信できなかった場合。
  2. ResumeReport を受信した際、未確認の Fragment を再送する。

8.4.2 再送設定

実装は以下の設定可能なパラメータを提供 すべきである

パラメータデフォルト値(推奨説明
初期再送タイムアウト5 秒最初の再送までの待機時間
再送バックオフ係数2各再送後にタイムアウトを倍にする(指数バックオフ)
最大再送回数5超過後、上位に失敗を通知する
最大再送タイムアウト60 秒再送タイムアウトの上限

実装は指数バックオフアルゴリズムを実装 しなければならない

8.4.3 再送失敗の処理

再送回数が上限を超えた場合:

  1. 送信側は上位アプリケーションに RETRANSMISSION_TIMEOUT エラー(6002)を通知 しなければならない
  2. 送信側はセッションの一時停止または終了をトリガ すべきである(実装定義)。
  3. 実装は無限に再送 してはならない

8.5 キャッシュ管理

8.5.1 未確認 Fragment キャッシュ

送信側は未確認 Fragment キャッシュを維持 しなければならず、以下を満たす:

  1. 送信済みであるが確認応答を受け取っていない各 Fragment はキャッシュ内に保持 しなければならない
  2. 確認応答を受信した後、確認済みの Fragment をキャッシュから削除 しなければならない
  3. キャッシュは容量上限を持た なければならない(実装定義、推奨 値は 1024 個の Fragment または 16 MB 以上)。

8.5.2 キャッシュ満杯時の処理

キャッシュが容量上限に達した場合、送信側は以下を しなければならない

  1. 新しい Fragment の送信を一時停止する。
  2. BUFFER_FULL エラー(6001)を介して上位アプリケーションに通知する。
  3. キャッシュ領域が解放されたことを確認した後、送信を再開する。
  4. Fragment を黙って破棄 してはならない

8.6 セッション管理

8.6.1 セッション確立

CAP が身元検証と鍵交換を完了した後、DTP_Engine は DTP セッションを確立 しなければならない

  1. RFC 4122 に準拠する一意の Session_ID(UUID v4)を生成 しなければならない
  2. Session データ構造を初期化 しなければならない(第 8.6.3 節を参照)。
  3. 状態を WaitingForCAP から SessionEstablished に遷移 しなければならない

8.6.2 セッション状態の維持

DTP_Engine はセッション期間中、双方向の伝送状態を維持 しなければならない

interface DirectionalTransferState {
  currentSequenceNumber: SequenceNumber;
  highestAcknowledgedSequenceNumber: SequenceNumber;
  unacknowledgedFragmentCache: Map<SequenceNumber, Fragment>;
}

実装は各伝送方向に対して独立した DirectionalTransferState を維持 しなければならない

方向フィールド名
データ収集(Terminal → Fay)collectionState
データ注入(Fay → Terminal)injectionState

8.6.3 Session データ構造

完全な Session 構造は以下を含 まなければならない

interface Session {
  sessionId: SessionID;
  masterIdentity: string;
  slaveIdentity: string;
  state: SessionState;
  activeAgreements: Map<AgreementID, Agreement>;
  collectionState: DirectionalTransferState;
  injectionState: DirectionalTransferState;
  createdAt: number;
  lastActivityAt: number;
  timeoutThreshold: number;
}

8.6.4 セッション永続化

下位伝送接続が切断した際、DTP_Engine は以下を しなければならない

  1. 直ちに SessionState を Transmitting から Suspended に遷移する。
  2. 以下の内容を不揮発性ストレージに永続化する:
    • 完全な Session オブジェクト(すべての active な Agreement を含む)
    • 双方向の DirectionalTransferState
    • 未確認 Fragment キャッシュ
  3. 永続化はアトミックで なければならない(すべて成功するか、すべて失敗するかのいずれか)。

8.6.5 セッション復元

下位接続が再確立された後、DTP_Engine は以下の復元フローに従わ なければならない

  1. CAP の再検証を待つ。
  2. CAP 検証成功後、Resuming 状態に入る。
  3. 永続化ストレージから Session 状態を復元する。
  4. 受信側は ResumeReport を送信する(第 8.2.2 節を参照)。
  5. 送信側は ResumeReport に従って中断点から伝送を継続する。
  6. 再開ハンドシェイク完了後、Transmitting に遷移する。

復元失敗の場合、DTP_Engine は以下を しなければならない

  1. Idle 状態に遷移する。
  2. すべての関連リソースを解放する。
  3. SESSION_RESTORE_FAILED エラー(5003)を介して上位に通知する。

8.6.6 セッションタイムアウト

実装はセッションタイムアウト機構を実装 しなければならない

  1. 最後のアクティビティ時刻を記録する lastActivityAt フィールドを維持 しなければならない
  2. now - lastActivityAt > timeoutThreshold のとき、セッションをタイムアウト状態に設定 しなければならない
  3. タイムアウトしたセッションはクローズ しなければならず、関連リソースは解放 しなければならない
  4. デフォルトの timeoutThreshold は 30 分(1,800,000 ms)が 推奨される

8.7 双方向の独立性

実装は 2 つの伝送方向の独立性を厳密に保証 しなければならない

  1. データ収集方向の状態変化は、データ注入方向に影響を与えて はならない
  2. 一方の方向の接続異常は、他方の方向の状態変更を自動的にトリガして はならない(下位接続全体が切断された場合を除く)。
  3. 一方の方向のシーケンス番号は、他方の方向のシーケンス番号空間に入って はならない
  4. 一方の方向のキャッシュは、他方の方向のキャッシュ割り当てを占有 してはならない