282 lines
11 KiB
Markdown
282 lines
11 KiB
Markdown
# 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 共享資料
|