xlog_package.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. package utils
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "strings"
  8. )
  9. const (
  10. // Magic word
  11. _MAGIC_XLOG_SYSTEM_ uint32 = 0x99A3B417 // ARM的日志发送给PC
  12. // CmdType 命令类型 mainCmd(8bit) + subCmd(8bit)
  13. // mainCmd
  14. _XLOG_CMD_LOG_TO_PC_ uint8 = 0 // 心跳内容, 内容为"[x]\n"
  15. _XLOG_CMD_REPORT_BASICINFO_ uint8 = 1 // 上报sn + mac, 结构为 XlogSiteBaseInfo
  16. _XLOG_CMD_REPLY_BASICINFO_ uint8 = 2 // 回复sn + mac,暂不回复
  17. _XLOG_P2P_EXEC_BASH_CMD_ uint8 = 64 // pc -> SERNAME_UB_SERVER -> xlogv3, 执行远程命令
  18. _XLOG_P2P_BASH_CMD_RESULT_ uint8 = 65 // xlogv3-> SERNAME_UB_SERVER -> pc 返回远程命令执行结果
  19. )
  20. func NewXlogPackageParser(ctx *ConnectContext) *XlogPackageParser {
  21. return &XlogPackageParser{
  22. crypt: NewXlogEncrypt(),
  23. ctx: ctx,
  24. cmdResultStr: "",
  25. Handshake: false,
  26. Buffer: make([]byte, 0),
  27. }
  28. }
  29. // 解析设备握手包
  30. func (parser *XlogPackageParser) ParseXlogHandshakePackage(raw []byte) (*XlogHandshakePackageData, error) {
  31. reader := bytes.NewReader(raw)
  32. // 数据长度校验
  33. if len(raw) != 72 {
  34. return nil, fmt.Errorf("invalid handshake packet: data length error, expected 72, got %d", len(raw))
  35. }
  36. // 解析数据结构
  37. var p XlogHandshakePackage
  38. if err := binary.Read(reader, binary.LittleEndian, &p); err != nil {
  39. return nil, err
  40. }
  41. // 校验数据头
  42. if p.MagicWord != _MAGIC_XLOG_SYSTEM_ {
  43. return nil, errors.New("invalid magic")
  44. }
  45. if p.CmdLen != uint32(len(raw)-8) {
  46. return nil, fmt.Errorf("invalid handshake packet: data length error, CmdLen: %d", p.CmdLen)
  47. }
  48. // 解密数据
  49. handshakeData, err := parser.crypt.DecryptData(p.EncryptData[:])
  50. if err != nil {
  51. return nil, err
  52. }
  53. // 数据长度校验
  54. if len(handshakeData) != (16 + 36) {
  55. return nil, fmt.Errorf("invalid handshake packet: data length error, expected 52, got %d", len(handshakeData))
  56. }
  57. // 解析握手数据结构
  58. var h XlogHandshakePackageData
  59. reader = bytes.NewReader(handshakeData)
  60. if err := binary.Read(reader, binary.LittleEndian, &h); err != nil {
  61. return nil, err
  62. }
  63. fmt.Println(string(bytes.TrimRight(h.DevUuid[:], "\x00")))
  64. // 更新IV
  65. if err := parser.crypt.SetNewIv(h.NewIv[:]); err != nil {
  66. return nil, err
  67. }
  68. return &h, nil
  69. }
  70. // 预解析数据包,数据提取,提取一个完整数据包
  71. func (parser *XlogPackageParser) PreparserXlogPackage(raw []byte) {
  72. // 累积数据
  73. parser.Buffer = append(parser.Buffer, raw...)
  74. buffer := parser.Buffer
  75. for {
  76. // 不够一个包头和长度字段,继续收
  77. if len(buffer) < 8 {
  78. return
  79. }
  80. // 查找合法包头
  81. header := binary.LittleEndian.Uint32(buffer[:4])
  82. if header != _MAGIC_XLOG_SYSTEM_ {
  83. // 丢掉 1 字节,继续找包头
  84. buffer = buffer[1:]
  85. continue
  86. }
  87. // 读取长度
  88. length := binary.LittleEndian.Uint32(buffer[4:8])
  89. totalLen := 8 + int(length)
  90. // 数据是否完整
  91. if len(buffer) < totalLen {
  92. break
  93. }
  94. // 提取完整包
  95. packet := buffer[:totalLen]
  96. // 异步处理
  97. go parser.ParseXlogPackage(packet)
  98. // 移除已处理的数据
  99. parser.Buffer = buffer[totalLen:]
  100. buffer = parser.Buffer
  101. }
  102. }
  103. // 处理设备心跳信息
  104. func (parser XlogPackageParser) handleHeartbeat(raw []byte) {
  105. fmt.Printf("%s - 接收到心跳:%s", parser.ctx.UUID, string(raw))
  106. }
  107. // 处理设备基本信息
  108. func (parser XlogPackageParser) handleSiteBaseInfo(raw []byte) {
  109. // 解析基本信息
  110. infoReader := bytes.NewReader(raw)
  111. var info XlogSiteBaseInfo
  112. if err := binary.Read(infoReader, binary.LittleEndian, &info); err != nil {
  113. fmt.Printf("handleSiteBaseInfo failed: %s\n", err)
  114. return
  115. }
  116. // 更新SN
  117. parser.ctx.SN = string(bytes.TrimRight(info.SN[:], "\x00"))
  118. fmt.Printf("update SN: %s\n", parser.ctx.SN)
  119. fmt.Println("握手成功")
  120. }
  121. // 处理命令执行结果
  122. func (parser *XlogPackageParser) handleCmdResult(raw []byte) {
  123. resStr := string(raw[:])
  124. if strings.HasPrefix(resStr, "\n***above is result of:") {
  125. parser.cmdResultStr = parser.cmdResultStr + resStr
  126. select {
  127. case parser.ctx.DoneChan <- parser.cmdResultStr:
  128. // 成功写入结果
  129. fmt.Printf("%s - 回传结果:%s\n", parser.ctx.UUID, parser.cmdResultStr)
  130. default:
  131. // channel 已经满(说明调用方可能已经超时退出了)
  132. fmt.Printf("%s - DoneChan已满或超时。\n", parser.ctx.UUID)
  133. }
  134. } else {
  135. parser.cmdResultStr = resStr
  136. }
  137. }
  138. // 解析设备数据包
  139. func (parser *XlogPackageParser) ParseXlogPackage(raw []byte) {
  140. // 数据长度校验
  141. headerPackageSize := binary.Size(XlogPackageHeader{})
  142. if len(raw) < headerPackageSize {
  143. fmt.Printf("invalid packet: data length error, expected >= %d, got %d\n", headerPackageSize, len(raw))
  144. return
  145. }
  146. headerRaw := raw[:headerPackageSize] // 非加密头部
  147. headerReader := bytes.NewReader(headerRaw)
  148. // 解析头部
  149. var h XlogPackageHeader
  150. if err := binary.Read(headerReader, binary.LittleEndian, &h); err != nil {
  151. fmt.Printf("XlogPackage header parsing error: %s\n", err.Error())
  152. return
  153. }
  154. if len(raw) > headerPackageSize {
  155. encryptRaw := raw[headerPackageSize:] // 加密数据
  156. // 解密Payload
  157. bodyRaw, err := parser.crypt.DecryptData(encryptRaw)
  158. if err != nil {
  159. fmt.Println("DecryptData error: " + err.Error())
  160. return
  161. }
  162. // 判断包类型
  163. switch h.MainCmd {
  164. case _XLOG_CMD_LOG_TO_PC_:
  165. parser.handleHeartbeat(bodyRaw)
  166. case _XLOG_CMD_REPORT_BASICINFO_:
  167. parser.handleSiteBaseInfo(bodyRaw)
  168. case _XLOG_P2P_BASH_CMD_RESULT_:
  169. parser.handleCmdResult(bodyRaw)
  170. }
  171. }
  172. }
  173. // 创建握手响应包
  174. func (parser XlogPackageParser) CreateXlogHandshakePackage() ([]byte, error) {
  175. encryptData, err := parser.crypt.EncryptData([]byte("0123456789abcdef"))
  176. if err != nil {
  177. return nil, err
  178. }
  179. buf := new(bytes.Buffer)
  180. // 按小端序写入,先写头部
  181. if err := binary.Write(buf, binary.LittleEndian, _MAGIC_XLOG_SYSTEM_); err != nil {
  182. return nil, fmt.Errorf("failed to write XlogHandshakeResponsePackage magic word: %w", err)
  183. }
  184. if err := binary.Write(buf, binary.LittleEndian, uint32(32)); err != nil {
  185. return nil, fmt.Errorf("failed to write XlogHandshakeResponsePackage magic word: %w", err)
  186. }
  187. // 再写 EncryptData
  188. if _, err := buf.Write(encryptData); err != nil {
  189. return nil, fmt.Errorf("failed to write XlogHandshakeResponsePackage EncryptData: %w", err)
  190. }
  191. return buf.Bytes(), nil
  192. }
  193. // 创建发送命令数据包
  194. func (parser XlogPackageParser) CreateXlogCmdPackage(payload []byte) ([]byte, error) {
  195. var dstServiceName [12]byte
  196. copy(dstServiceName[:], "Xlog")
  197. h := XlogPackageHeader{
  198. MagicWord: _MAGIC_XLOG_SYSTEM_,
  199. CmdLen: 0,
  200. MainCmd: _XLOG_P2P_EXEC_BASH_CMD_,
  201. SubCmd: 0,
  202. ControlBitData: 0,
  203. DstServiceName: dstServiceName,
  204. ToBeSendLen: 0,
  205. IgnoredLen: 0,
  206. UpTime: 0,
  207. }
  208. encryptData := []byte{}
  209. if len(payload) > 0 {
  210. encrypted, err := parser.crypt.EncryptData(payload)
  211. if err != nil {
  212. return nil, err
  213. }
  214. encryptData = encrypted
  215. }
  216. // 36是XlogPackageHeader字节数,8是MagicWord + CmdLen字节数
  217. h.CmdLen = uint32(36 + len(encryptData) - 8)
  218. p := XlogPackage{
  219. Header: h,
  220. EncryptPayload: encryptData,
  221. }
  222. buf := new(bytes.Buffer)
  223. // 按小端序写入,先写头部
  224. if err := binary.Write(buf, binary.LittleEndian, p.Header); err != nil {
  225. return nil, fmt.Errorf("failed to write XlogPackage header: %w", err)
  226. }
  227. // 再写 payload
  228. if _, err := buf.Write(p.EncryptPayload); err != nil {
  229. return nil, fmt.Errorf("failed to write XlogPackage payload: %w", err)
  230. }
  231. return buf.Bytes(), nil
  232. }