# GS (DtrGuiSrv) <--> GC (GUI Client) 互動分析 ## 系統架構 ``` ┌─────────────────────────────────────────────────────────────────────┐ │ RAIDGuard X 系統架構 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ GC (GUI) │ │ GS (Server) │ │ │ │ RAIDGuard X │◄────────►│ DtrGuiSrv │ │ │ │ (Java Swing) │ Port │ (C Program) │ │ │ │ │ 8922 │ │ │ │ └─────────────────┘ └────────┬────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ In-Band API │ │ │ │ (RAID Controller)│ │ │ │ Port 8922 │ │ │ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘ ``` ## 通訊流程 ### 1. 連線建立 ``` GC (Client) GS (Server) │ │ │──── connect(8922) ─────────────────►│ │◄──── accept() ─────────────────────│ │ │ │──── Phase1: Length ────────────────►│ │◄──── Phase1: Ack ───────────────────│ │ │ │──── Phase2: Data ──────────────────►│ │◄──── Phase2: Response ──────────────│ │ │ │ ... (重複) ... │ │ │ │──── close() ───────────────────────►│ ``` ### 2. 傳輸協議 (TCP Port 8922) GS 作為 TCP Server,監聽 Port 8922。 ```c // cNetWork.c #define DTR_GUI_PORT 8922 SHORT InitialSrvSocket(ULONG SerPortNum, ULONG ClientConnectionAllow) { server_sockfd = socket(AF_INET, SOCK_STREAM, 0x00); bind(server_sockfd, ...); listen(server_sockfd, ClientConnectionAllow); return server_sockfd; } ``` ## 請求類型 | Request Type | 值 | 說明 | |-------------|-----|------| | REQ_INBAND_COMMAND | 0x01 | In-Band 命令 (轉發到 RAID 控制器) | | REQ_SERVER_CONFIG | 0x02 | 伺服器設定 (SMTP, Email 等) | ### Request 格式 ``` ┌─────────────────────────────────────────────────────────────┐ │ Request Package │ ├─────────────────────────────────────────────────────────────┤ │ Byte 0 │ Byte 1 │ Byte 2-3 │ Byte 4+ │ ├─────────────────────────────────────────────────────────────┤ │ Req Type │ Phase Code │ Length │ Data │ │ (0x01/0x02)│ │ (LE) │ │ └─────────────────────────────────────────────────────────────┘ ``` ### Response 格式 ``` ┌─────────────────────────────────────────────────────────────┐ │ Response Package │ ├─────────────────────────────────────────────────────────────┤ │ Byte 0 │ Byte 1 │ Byte 2 │ Byte 3+ │ ├─────────────────────────────────────────────────────────────┤ │ Phase Code │ Req Code │ Ctrl No │ Data / Error Code │ │ 0x50 │ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` ## 處理流程 ### GS 端處理 (cNetWork.c) ```c // 主迴圈 while(1) { client_sockfd = accept(server_sockfd, ...); // 接收請求 GUITrans(client_sockfd, pInBuffer, ...); // Phase 1 GUITrans(client_sockfd, pInBuffer, ...); // Phase 2 // 解析請求類型 switch(pInBuffer[0]) { case REQ_INBAND_COMMAND: // 0x01 // 取得 Controller ID iCtlrID = SNtoCtlrID(sSN); // 轉發到 RAID 控制器 bStatus = HandleInBandReq(&ReqPackage, iCtlrID, &usInBandErrCode); break; case REQ_SERVER_CONFIG: // 0x02 // 處理伺服器設定 bStatus = HandleSrvConfigReq(&ReqPackage); break; } // 發送回應 ServerGUITrans(&ReqPackage); } ``` ## GC 端請求範例 ### 1. 取得頁面資料 (GET_PAGE) ```java // InBandAPI/SendCmd.java // 組建命令 byte[] bCmds = new byte[...]; bCmds[0] = 0x00; // Phase Code bCmds[1] = 0x00; // Request Code bCmds[2] = 0x00; // Controller No bCmds[3] = 0x01; // OpCode: GET_PAGE bCmds[4] = 0x03; // Length bCmds[5] = pageCode; // Page Code (0x00, 0x01, 0x07, etc.) ``` ### 2. 發送密碼 (SEND_PASSWORD) ```java bCmds[3] = 0x1D; // OpCode: SEND_PASSWORD bCmds[4] = 0x08; // Length (8 bytes) // bCmds[5-12] = password bytes ``` ### 3. 取得事件 (Get InBand Event) ```java bCmds[0] = 0xFF; // Phase Code bCmds[1] = 0x00; // Request Code bCmds[2] = 0x00; // Controller No bCmds[3] = 0x02; // OpCode: Get Event ``` ## 資料傳輸函數 ### GS 端 (cNetWork.c) ```c UCHAR GUITrans(SHORT sd, PUCHAR pInBuffer, ULONG InBufferLength, SHORT flg_trans) { while(LastByte) { if(flg_trans == SERVER_READ) { ByteSend = recv(sd, pBaseAddr, LastByte, 0x00); } else if(flg_trans == SERVER_WRITE) { ByteSend = send(sd, pBaseAddr, LastByte, 0x00); } LastByte -= ByteSend; pBaseAddr += ByteSend; } return SYSOK; } UCHAR ServerGUITrans(PNET_REQ_PACKAGE pReqPackage) { // Phase 1: 傳輸長度 if(pReqPackage->direction == SERVER_READ) { // 接收長度 } else { // 發送長度 Phase1Buf[0] = TRANS_PHASE1; Phase1Buf[1] = (Length & 0xFF); Phase1Buf[2] = ((Length >> 8) & 0xFF); } // Phase 2: 傳輸資料 pReqPackage->pOutBuffer[0] = TRANS_PHASE2; GUITrans(..., SERVER_WRITE); return SYSOK; } ``` ## 錯誤處理 ### 錯誤回應格式 ``` Byte 0: Phase Code Byte 1: Request Code Byte 2: Controller Number Byte 3: Error Code Byte 4-5: InBand Error Code (LSB ~ MSB) ``` ### 常見錯誤碼 | 錯誤碼 | 說明 | |--------|------| | 0x50 | 成功 (Success) | | 0x4x | 失敗 (Fail) | | SYSFAIL_SERSVE_RESEND_FAIL | 傳輸失敗 | | SYSFAIL_INBAND_SN_NOT_MATCH | SN 不匹配 | ## 關鍵檔案對應 ### GS 端 (C) | 檔案 | 功能 | |------|------| | cNetWork.c | TCP 網路通訊 | | cInBand.c | In-Band API 處理 | | cPollingEvent.c | 事件輪詢 | | cMail.c | Email 發送 | | cShareMem.c | 共享記憶體 | ### GC 端 (Java) | 檔案 | 功能 | |------|------| | SendCmd.java | TCP 通訊封裝 | | CmdQueue.java | 命令排程 | | PageDataDB.java | 資料儲存 | | frmMain.java | 主介面 | ## 通訊序列圖 ``` GC GS RAID Controller │ │ │ │── TCP Connect(8922) ──►│ │ │◄── Accept ─────────────│ │ │ │ │ │── REQ_INBAND_COMMAND ─►│ │ │ (GET_PAGE) │ │ │ │── InBand Protocol ───────►│ │ │◄── Page Data ───────────│ │◄─ Page Data ──────────│ │ │ │ │ │── REQ_INBAND_COMMAND ─►│ │ │ (SEND_PASSWORD) │ │ │ │── InBand Protocol ───────►│ │ │◄── Status ──────────────│ │◄─ Status ─────────────│ │ │ │ │ │── TCP Close ──────────│ │ ``` ## 連接埠 | Port | 用途 | |------|------| | 8922 | GC ↔ GS 主要通訊 | | 8922 | GS ↔ RAID Controller | | 162 | SNMP Trap (可選) | ## 實作重點 1. **雙向通訊**: GS 同時連接 GC (客戶端) 和 RAID Controller (硬體) 2. **協議轉發**: GS 將 GC 的請求轉發給 RAID Controller 3. **錯誤回傳**: 錯誤從 RAID Controller → GS → GC 4. **長連接**: 使用 TCP keep-alive 維持連線 5. **共享記憶體**: GS 與本機 RAID Driver 共享資料