第 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. 一方の方向のキャッシュは、他方の方向のキャッシュ割り当てを占有 してはならない。