45 lines
1.6 KiB
Markdown
45 lines
1.6 KiB
Markdown
## 心跳机制
|
||
* 边缘主机通过心跳机制来判断主机是否存活(解决弱网环境下websocket链接会经常断开的问题)
|
||
* 边缘主机定期发送 UDP 心跳包,服务端按照 `iot_host` 的心跳检测周期判断是否有收到心跳包。
|
||
* 如果 UDP 心跳丢失但 SSL channel 仍然存在,服务端不会把 host 标记为离线。
|
||
* 如果 UDP 心跳丢失且 SSL channel 也不存在,服务端会把 host 标记为离线。
|
||
|
||
### udp服务器
|
||
* 端口: 18080
|
||
|
||
### 心跳包格式
|
||
旧格式 `<<Len:16, HostUUID/binary>>` 已不再接受。
|
||
|
||
当前心跳包格式:
|
||
|
||
```erlang
|
||
<<
|
||
Version:8,
|
||
UuidLen:16,
|
||
UUID:UuidLen/binary,
|
||
Timestamp:64/unsigned-big,
|
||
Nonce:16/binary,
|
||
Mac:32/binary
|
||
>>
|
||
```
|
||
|
||
字段说明:
|
||
|
||
| 字段 | 说明 |
|
||
| --- | --- |
|
||
| `Version` | 当前固定为 `1`。 |
|
||
| `UuidLen` | `UUID` 的字节数。 |
|
||
| `UUID` | efka 对应的 host UUID。 |
|
||
| `Timestamp` | 秒级 Unix 时间戳。服务端只接受 120 秒时间窗内的心跳。 |
|
||
| `Nonce` | 16 字节随机数,必须加入 HMAC payload,使同一秒内多次心跳的 Mac 不同。当前服务端不保存 nonce。 |
|
||
| `Mac` | HMAC-SHA256 结果,32 字节。 |
|
||
|
||
`Mac` 的计算内容为前面所有字段:
|
||
|
||
```erlang
|
||
Payload = <<Version:8, UuidLen:16, UUID:UuidLen/binary, Timestamp:64/unsigned-big, Nonce:16/binary>>,
|
||
Mac = crypto:mac(hmac, sha256, HeartbeatSecret, Payload)
|
||
```
|
||
|
||
服务端在 `efka_client_store:verify_heartbeat/4` 中校验时间窗和 HMAC。`HeartbeatSecret` 使用 `SHA256(Token)`,其中 `Token` 和 TLS 鉴权使用同一个 auth token。`iot` 侧只保存派生后的 `heartbeat_secret`,不保存明文 token。
|