第 9 章 錯誤處理

9.1 錯誤處理模型

DTP 實作 必須 遵循「偵測-通知-恢復」三階段錯誤處理模型:

  1. 偵測:辨識異常情況。
  2. 通知:向對端或上層傳送錯誤資訊。
  3. 恢復:根據錯誤類型採取恢復措施。

實作 不得 在偵測到錯誤時靜默丟棄訊框而不通知。

9.2 錯誤碼體系

DTP 必須 使用以下錯誤碼體系。錯誤碼 必須 是非負整數,按功能模組劃分為八個範圍:

範圍類別處理策略
1xxx訊框處理錯誤丟棄訊框 + 通知傳送方
2xxx加密錯誤丟棄訊框 + 通知傳送方 + 可能觸發金鑰重協商
3xxx約定錯誤丟棄 Fragment + 通知傳送方 + 可能觸發重新協商
4xxxDAG 錯誤拒絕 Fragment + 通知傳送方 或 快取等待
5xxx會話錯誤嘗試恢復會話 + 失敗時關閉並通知上層
6xxx續傳錯誤暫停傳送 + 通知上層應用
7xxx版本錯誤傳送版本不相容通知 + 嘗試降級處理
8xxx權限錯誤拒絕操作 + 通知請求方

9.3 錯誤碼定義

實作 必須 使用以下規範化的錯誤碼定義。不得 使用未列出的錯誤碼。如需擴充,必須 在本規範的後續版本中定義。

9.3.1 訊框處理錯誤(1xxx)

錯誤碼名稱觸發條件
1001FRAME_DESERIALIZATION_FAILED接收到的二進位資料無法反序列化為 LogicalFrame
1002FRAME_INVALID_FORMATLogicalFrame 結構無效或缺少必需欄位

9.3.2 加密錯誤(2xxx)

錯誤碼名稱觸發條件
2001DECRYPTION_FAILEDPayload 解密失敗(錯誤金鑰或資料損壞)
2002KEY_NOT_READYCAP 金鑰交換尚未完成,拒絕資料傳輸

9.3.3 約定錯誤(3xxx)

錯誤碼名稱觸發條件
3001AGREEMENT_NOT_FOUNDFragment 引用了未知 Agreement_ID
3002AGREEMENT_EXPIRED引用的約定已過期(超過 validityPeriod)
3003AGREEMENT_NEGOTIATION_FAILED協商無法完成(逾時、對端拒絕重協商等)

9.3.4 DAG 錯誤(4xxx)

錯誤碼名稱觸發條件
4001DAG_CYCLE_DETECTED加入 Fragment 會形成 DAG 環路
4002DAG_DEPENDENCY_UNRESOLVEDFragment 依賴未在快取逾時內解析

9.3.5 會話錯誤(5xxx)

錯誤碼名稱觸發條件
5001SESSION_NOT_FOUND引用的 Session_ID 不存在
5002SESSION_TIMEOUT會話因不活動逾時
5003SESSION_RESTORE_FAILED重新連線後會話恢復失敗

9.3.6 續傳錯誤(6xxx)

錯誤碼名稱觸發條件
6001BUFFER_FULL傳送方未確認 Fragment 快取達到容量上限
6002RETRANSMISSION_TIMEOUTFragment 重傳逾時未收到確認(重傳次數耗盡)

9.3.7 版本錯誤(7xxx)

錯誤碼名稱觸發條件
7001VERSION_INCOMPATIBLE接收訊框的協定版本號高於自身支援版本

9.3.8 權限錯誤(8xxx)

錯誤碼名稱觸發條件
8001PERMISSION_DENIED當前角色不允許執行該操作
8002OBSERVER_WRITE_DENIED旁觀者嘗試寫入操作(旁觀者唯讀)

9.4 錯誤唯一性

實作 必須 保證錯誤碼的唯一性:

  1. 每個錯誤碼 必須 對應唯一的錯誤類型。
  2. 不同錯誤類型 不得 共用同一錯誤碼。
  3. 實作 不得 重新定義本規範已分配的錯誤碼。

9.5 錯誤通知機制

9.5.1 ErrorNotificationFrame

錯誤通知 必須 透過 ControlFrame 傳遞,定義如下:

interface ErrorNotificationFrame {
  frameType: "control";
  controlType: "error_notification";
  errorCode: DTPErrorCode;
  errorMessage: string;
  relatedFrameId?: FragmentID;
  relatedAgreementId?: AgreementID;
  details?: Record<string, unknown>;
}
欄位規範性要求
frameType必須"control"
controlType必須"error_notification"
errorCode必須 為 9.3 節定義的錯誤碼之一
errorMessage必須 為人類可讀的錯誤描述。 使用對端可理解的語言
relatedFrameId可選。當錯誤由特定訊框觸發時 必須 包含該訊框的 fragmentId
relatedAgreementId可選。當錯誤與特定約定相關時 必須 包含 Agreement_ID
details可選 包含偵錯用的額外資訊

9.5.2 錯誤通知傳輸

ErrorNotificationFrame 必須 透過常規 LogicalFrame 通道傳輸,必須 加密 Payload。

如錯誤本身導致無法加密(例如 KEY_NOT_READY 錯誤),實作 透過實作定義的頻外通道返回錯誤,但 不得 在加密通道中以明文傳送錯誤。

9.6 關鍵錯誤處理流程

9.6.1 反序列化失敗(1001)

接收到的 LogicalFrame 無法反序列化時,接收方 必須

  1. 丟棄該訊框。
  2. 傳送 FRAME_DESERIALIZATION_FAILED 錯誤通知。
  3. 不得 因反序列化失敗而關閉會話。

9.6.2 解密失敗(2001)

接收到的 Payload 無法解密時,接收方 必須

  1. 丟棄該訊框。
  2. 傳送 DECRYPTION_FAILED 錯誤通知。
  3. 計數連續解密失敗次數。
  4. 如連續失敗超過閾值(推薦 3 次), 觸發 CAP 重新金鑰交換。

9.6.3 DAG 環路偵測(4001)

偵測到 DAG 環路時:

  1. 接收方 必須 拒絕該 Fragment。
  2. 必須 返回 DAG_CYCLE_DETECTED 錯誤。
  3. 不得 將 Fragment 加入 DAG。
  4. 不得 影響已存在 Fragment 的狀態。

9.6.4 未知約定(3001)

Fragment 引用了未知 Agreement_ID 時:

  1. 接收方 必須 丟棄 Fragment。
  2. 返回 AGREEMENT_NOT_FOUND 錯誤。
  3. 觸發重新協商(實作定義)。

9.6.5 金鑰未就緒(2002)

CAP 金鑰交換尚未完成時嘗試傳送資料:

  1. DTP_Engine 必須 拒絕傳送。
  2. 必須 返回 KEY_NOT_READY 錯誤給上層呼叫方。
  3. 不得 在通訊通道中以明文形式回應。

9.6.6 快取已滿(6001)

未確認 Fragment 快取達到上限時:

  1. 傳送方 必須 暫停傳送新 Fragment。
  2. 傳送 BUFFER_FULL 通知給上層應用。
  3. 在確認釋放快取空間後恢復傳送。
  4. 不得 丟棄已快取的 Fragment。

9.6.7 重傳逾時(6002)

Fragment 重傳次數耗盡時:

  1. 傳送方 必須 通知上層應用 RETRANSMISSION_TIMEOUT 錯誤。
  2. 觸發會話暫停或終止。
  3. 不得 無限重傳。

9.6.8 版本不相容(7001)

接收到協定版本不相容的訊框時(詳見第 10 章):

  1. 接收方 必須 不處理該訊框。
  2. 必須 返回 VERSION_INCOMPATIBLE 錯誤。
  3. 必須 在錯誤的 details 欄位中包含自身支援的最高版本號。

9.6.9 權限拒絕(8001、8002)

非法的角色操作時:

  1. DTP_Engine 必須 拒絕該操作。
  2. 旁觀者寫入操作 必須 返回 OBSERVER_WRITE_DENIED(8002)。
  3. 其他權限拒絕 必須 返回 PERMISSION_DENIED(8001)。

9.7 錯誤恢復策略

實作 必須 按錯誤類型採取相應恢復策略:

錯誤類別恢復策略
1xxx 訊框處理丟棄訊框,記錄日誌,繼續接收後續訊框
2xxx 加密單次失敗丟棄訊框,連續失敗觸發金鑰重協商
3xxx 約定丟棄 Fragment,可能觸發重新協商
4xxx DAG環路:拒絕;未解析:快取等待
5xxx 會話嘗試恢復會話;失敗則關閉
6xxx 續傳暫停傳送,等待對端回應或上層介入
7xxx 版本傳送版本通知;嘗試降級處理
8xxx 權限拒絕操作,不得 自動重試

實作 不得 在權限錯誤(8xxx)發生時自動重試相同操作。