第 8 章 信頼性保障
8.1 信頼性モデル
DTP 実装は以下の信頼性保障を提供 しなければならない:
- 再開:下位接続中断後に伝送を回復し、既に正常に受信されたデータを再送 してはならない。
- 確認応答:受信側は正常に受信した Fragment を送信側に確認 しなければならない。
- 再送:送信側はタイムアウト内に確認応答を受信できなかった場合、未確認 Fragment を再送 しなければならない。
- セッション永続化:下位接続が中断したときセッション状態を永続化 しなければならない。
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 を受信した後、以下に厳密に従わ なければならない:
- 次のシーケンス番号から継続:
highest + 1から再送信を開始する。 - 重複送信しない:シーケンス番号が
highest以下の Fragment を再送信 してはならない。 - スキップしない:未確認の Fragment(つまりキャッシュ内で受信が確認されていないもの)をスキップ してはならない。
8.3 確認応答機構
8.3.1 確認応答の方式
実装は Fragment の受信確認を提供 しなければならない。確認応答は以下のいずれかの方法で実装 してもよい:
- 明示的 ACK 制御フレーム:受信側が ControlFrame を送信し、
controlType = "ack"、details に確認済みの最高シーケンス番号を含める。 - 累積 ACK:各データフレームの拡張フィールドに、逆方向の最高受信済みシーケンス番号を携帯させる(推奨)。
- バッチ ACK:N 個の Fragment を受信するごとに 1 回 ACK を送信する(実装定義の N、推奨 値は 16)。
具体的な確認応答方式は実装が選択 してもよい が、受信側と送信側は選択された方式について合意 しなければならない。
8.3.2 確認応答のタイミング
受信側は以下を満たさ なければならない:
- Fragment が復号、Agreement 検証、DAG 検証を通過した後にのみ確認できる。
- DAG が
pending状態の場合、確認 してはならない(依存関係の解決後に確認するべきである)。 - ACK 内の最高シーケンス番号は、確認済みシーケンス番号集合の連続するプレフィックスの最大値で なければならない。
8.4 再送機構
8.4.1 再送戦略
送信側は以下の条件下で再送 しなければならない:
- プロトコルで設定された再送タイムアウト時間内に対応するシーケンス番号の ACK を受信できなかった場合。
- ResumeReport を受信した際、未確認の Fragment を再送する。
8.4.2 再送設定
実装は以下の設定可能なパラメータを提供 すべきである:
| パラメータ | デフォルト値(推奨) | 説明 |
|---|---|---|
| 初期再送タイムアウト | 5 秒 | 最初の再送までの待機時間 |
| 再送バックオフ係数 | 2 | 各再送後にタイムアウトを倍にする(指数バックオフ) |
| 最大再送回数 | 5 | 超過後、上位に失敗を通知する |
| 最大再送タイムアウト | 60 秒 | 再送タイムアウトの上限 |
実装は指数バックオフアルゴリズムを実装 しなければならない。
8.4.3 再送失敗の処理
再送回数が上限を超えた場合:
- 送信側は上位アプリケーションに
RETRANSMISSION_TIMEOUTエラー(6002)を通知 しなければならない。 - 送信側はセッションの一時停止または終了をトリガ すべきである(実装定義)。
- 実装は無限に再送 してはならない。
8.5 キャッシュ管理
8.5.1 未確認 Fragment キャッシュ
送信側は未確認 Fragment キャッシュを維持 しなければならず、以下を満たす:
- 送信済みであるが確認応答を受け取っていない各 Fragment はキャッシュ内に保持 しなければならない。
- 確認応答を受信した後、確認済みの Fragment をキャッシュから削除 しなければならない。
- キャッシュは容量上限を持た なければならない(実装定義、推奨 値は 1024 個の Fragment または 16 MB 以上)。
8.5.2 キャッシュ満杯時の処理
キャッシュが容量上限に達した場合、送信側は以下を しなければならない:
- 新しい Fragment の送信を一時停止する。
BUFFER_FULLエラー(6001)を介して上位アプリケーションに通知する。- キャッシュ領域が解放されたことを確認した後、送信を再開する。
- Fragment を黙って破棄 してはならない。
8.6 セッション管理
8.6.1 セッション確立
CAP が身元検証と鍵交換を完了した後、DTP_Engine は DTP セッションを確立 しなければならない:
- RFC 4122 に準拠する一意の Session_ID(UUID v4)を生成 しなければならない。
- Session データ構造を初期化 しなければならない(第 8.6.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 は以下を しなければならない:
- 直ちに SessionState を
TransmittingからSuspendedに遷移する。 - 以下の内容を不揮発性ストレージに永続化する:
- 完全な Session オブジェクト(すべての active な Agreement を含む)
- 双方向の DirectionalTransferState
- 未確認 Fragment キャッシュ
- 永続化はアトミックで なければならない(すべて成功するか、すべて失敗するかのいずれか)。
8.6.5 セッション復元
下位接続が再確立された後、DTP_Engine は以下の復元フローに従わ なければならない:
- CAP の再検証を待つ。
- CAP 検証成功後、
Resuming状態に入る。 - 永続化ストレージから Session 状態を復元する。
- 受信側は ResumeReport を送信する(第 8.2.2 節を参照)。
- 送信側は ResumeReport に従って中断点から伝送を継続する。
- 再開ハンドシェイク完了後、
Transmittingに遷移する。
復元失敗の場合、DTP_Engine は以下を しなければならない:
Idle状態に遷移する。- すべての関連リソースを解放する。
SESSION_RESTORE_FAILEDエラー(5003)を介して上位に通知する。
8.6.6 セッションタイムアウト
実装はセッションタイムアウト機構を実装 しなければならない:
- 最後のアクティビティ時刻を記録する
lastActivityAtフィールドを維持 しなければならない。 now - lastActivityAt > timeoutThresholdのとき、セッションをタイムアウト状態に設定 しなければならない。- タイムアウトしたセッションはクローズ しなければならず、関連リソースは解放 しなければならない。
- デフォルトの
timeoutThresholdは 30 分(1,800,000 ms)が 推奨される。
8.7 双方向の独立性
実装は 2 つの伝送方向の独立性を厳密に保証 しなければならない:
- データ収集方向の状態変化は、データ注入方向に影響を与えて はならない。
- 一方の方向の接続異常は、他方の方向の状態変更を自動的にトリガして はならない(下位接続全体が切断された場合を除く)。
- 一方の方向のシーケンス番号は、他方の方向のシーケンス番号空間に入って はならない。
- 一方の方向のキャッシュは、他方の方向のキャッシュ割り当てを占有 してはならない。
