packet.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. package packet
  2. import (
  3. "bytes"
  4. "compress/zlib"
  5. "errors"
  6. "fmt"
  7. "hash/crc32"
  8. "io"
  9. "log"
  10. "mtp20access/utils"
  11. "net"
  12. )
  13. /************协议格式************************************
  14. WTAS协议是交易系统与管理客户端/会员系统之间的通信协议,由报文头 + 报文体两部分组成
  15. 标识 类型 字节数 内容 说明
  16. HeadTag byte 1 0xFF 头标记
  17. Length uint 4 包总长度,包括头长度
  18. FunCode uint 4 功能号(为0代表心跳,心跳数据体长度为0)
  19. SessionId uint 4 会话ID,由交易接入(代理)维护
  20. Mode byte 1 内容类型,0:ProtoBuff,1:Json,2:Zip + ProtBuff,…
  21. Version byte 1 版本号
  22. SerialNumber uint 4 通讯报文序号
  23. 数据体 业务结构体,ProtoBuf. 数据体格式: 头部 4 节字 + 内容 + 8 节字 掩码, 解密的时候只解内容部分
  24. CRC byte 4 报文校验和
  25. FootTag byte 1 0x00 尾标记
  26. 数据体前,包头长度=19, 空包长度=24
  27. #define MAXKEY "B0FB83E39A5EBFAABE471362A58393FF"
  28. #define TRANSKEY "F7A72DE7D6264530F01BA49BC73EB873"
  29. *******************************************************/
  30. // MiPacket 协议包结构体
  31. type MiPacket struct {
  32. Length uint32 // 包总长度
  33. FunCode uint32 // 功能能
  34. SessionId uint32 // 数据包的sid
  35. Mode uint32 // 业务数据体的格式 0:ProtoBuff,1:Json,2:Zip + ProtoBuff
  36. SerialNumber uint32 // 通信流水号
  37. Data []byte // 业务数据体
  38. CRC uint32 // CRC
  39. OriMsg []byte // 原始包数据
  40. }
  41. // EnPack 打包,根据现有的数据内容重新打包,无任何数据时打出来的是心跳包
  42. // 这里不对数据体进行加密, 如需加密,请先加密再设置进来
  43. func (p *MiPacket) EnPack() []byte {
  44. p.Length = uint32(len(p.Data)) + 24 // 空包长度24
  45. buf := make([]byte, 0) // 缓冲区
  46. buf = append(buf, byte(0xFF)) // HeadTag 0xFF
  47. buf = append(buf, utils.UintToBytes(p.Length)...) // Length
  48. buf = append(buf, utils.UintToBytes(p.FunCode)...) // FunCode
  49. buf = append(buf, utils.UintToBytes(p.SessionId)...) // SessionId
  50. buf = append(buf, byte(0)) // Mode
  51. buf = append(buf, byte(0)) // Version
  52. buf = append(buf, utils.UintToBytes(p.SerialNumber)...) // SerialNumber
  53. buf = append(buf, p.Data...) // 数据体 body
  54. p.CRC = crc32.Update(58861227, crc32.IEEETable, buf[0:19]) //
  55. buf = append(buf, utils.UintToBytes(p.CRC)...) // CRC
  56. buf = append(buf, byte(0)) // FootTag
  57. return buf
  58. }
  59. // UnPackHead 解包头
  60. // @buf length must be >=19
  61. func (p *MiPacket) UnPackHead(buf []byte) error {
  62. if len(buf) < 19 {
  63. return errors.New("header len error")
  64. }
  65. if buf[0] != 0xFF {
  66. return errors.New("header flag error")
  67. }
  68. p.Length = utils.BytesToUint32(buf[1:5]) // Length
  69. p.FunCode = utils.BytesToUint32(buf[5:9]) // FunCode
  70. p.SessionId = utils.BytesToUint32(buf[9:13]) // SessionId
  71. p.SerialNumber = utils.BytesToUint32(buf[15:19]) // SerialNumber
  72. p.Mode = uint32(buf[13]) // Mode
  73. if p.Length > 1024*10000 || p.Length < 24 {
  74. fmt.Println("packet too big or len error, len:", p.Length)
  75. return fmt.Errorf("invalid len, must in[24,1024000]")
  76. }
  77. return nil
  78. }
  79. // HeaderLen 包头长度, HeaderTag~SerialNumber 的长度
  80. // 用于tcp接收数据时第一部分的长度
  81. func (p *MiPacket) HeaderLen() uint32 {
  82. return 19
  83. }
  84. // BodyLen 除包头外的长度, 含FootTag
  85. // 用于tcp接收数据时第二部分的长度
  86. func (p *MiPacket) BodyLen() uint32 {
  87. return p.Length - 19
  88. }
  89. // FuncCode 功能号
  90. func (p *MiPacket) FuncCode() int {
  91. return int(p.FunCode)
  92. }
  93. // UnPack 从指定的缓冲区解包
  94. // 注意:不解密业务数据体, 可用 DecodeData 方法进行解密
  95. // @buf 完整的包数据内容
  96. func (p *MiPacket) UnPack(buf []byte) error {
  97. err := p.UnPackHead(buf[:19])
  98. if err != nil {
  99. return err
  100. }
  101. if len(buf) != int(p.Length) {
  102. err := fmt.Errorf("packet length err")
  103. log.Println(err)
  104. return err
  105. }
  106. //长度24为心跳包, 非心跳包时保存数据体内容
  107. //包头前面19字节+4个字节数据体加密长度, 所以从23开始
  108. //包尾5个字节,但是加密的数据体后8个字节掩码不需要, 所以是 p.length-13
  109. if len(buf) != 24 {
  110. p.Data = buf[23 : p.Length-13]
  111. }
  112. p.OriMsg = buf[:]
  113. return nil
  114. }
  115. // DecodeData 解密业务数据体内容
  116. // @mode 数据体类型 0:ProtoBuff,1:Json,2:Zip + ProtoBuff
  117. // @msg 业务数据体
  118. func (p *MiPacket) DecodeData(mode uint32, msg []byte) ([]byte, error) {
  119. if mode == 2 {
  120. b := bytes.NewReader(msg)
  121. r, err := zlib.NewReader(b)
  122. if err != nil {
  123. return nil, err
  124. }
  125. var out bytes.Buffer
  126. _, _ = io.Copy(&out, r)
  127. _ = r.Close()
  128. msg = out.Bytes()
  129. }
  130. return Decrypt(msg, AESKey, true)
  131. }
  132. // EncodeData 加密码业务数据体内容
  133. func (p *MiPacket) EncodeData(mode uint32, msg []byte) ([]byte, error) {
  134. buf := msg
  135. if mode == 2 {
  136. var b bytes.Buffer
  137. w := zlib.NewWriter(&b)
  138. _, err := w.Write(msg)
  139. if err != nil {
  140. return nil, err
  141. }
  142. _ = w.Close()
  143. buf = b.Bytes()
  144. }
  145. return Encrypt(buf, AESKey, true)
  146. }
  147. // SetData 设置业务数据, 不含通信包头、CRC等字段
  148. func (p *MiPacket) SetData(buf []byte) {
  149. p.Data = buf[:]
  150. }
  151. // SetOriMsg 设置原始包数据
  152. func (p *MiPacket) SetOriMsg(arg ...[]byte) {
  153. if p.OriMsg == nil {
  154. p.OriMsg = make([]byte, 0)
  155. }
  156. for i := range arg {
  157. p.OriMsg = append(p.OriMsg, arg[i]...)
  158. }
  159. }
  160. // GetOriMsg 获取解包的原始数据
  161. func (p *MiPacket) GetOriMsg() []byte {
  162. return p.OriMsg
  163. }
  164. // RebuildForNewSid 设置新的通信流水号(sessionId)且重新打包
  165. func (p *MiPacket) RebuildForNewSid(sessionId uint32) {
  166. // 从某个位置开始, 替换一段内容
  167. f := func(buf []byte, pos int, newBuf []byte) {
  168. for i := 0; i < len(newBuf); i++ {
  169. buf[pos] = newBuf[i]
  170. pos++
  171. }
  172. }
  173. p.SessionId = sessionId
  174. s := utils.UintToBytes(p.SessionId)
  175. f(p.OriMsg, 9, s)
  176. p.CRC = crc32.Update(58861227, crc32.IEEETable, p.OriMsg[0:19])
  177. crc := utils.UintToBytes(p.CRC)
  178. f(p.OriMsg, len(p.OriMsg)-5, crc)
  179. }
  180. // ReadMessage 从指定tcp链接读取一个协议包
  181. // @返回值 []byte 未解包的原始数据包, 如果需获取业务数据内容,
  182. // 请调用UnPack方法后取成员变量 Data 的内容
  183. func (p *MiPacket) ReadMessage(conn *net.Conn) ([]byte, error) {
  184. p.OriMsg = make([]byte, 0)
  185. if conn == nil {
  186. return p.OriMsg, fmt.Errorf("conn is nil")
  187. }
  188. headerBuf := make([]byte, p.HeaderLen())
  189. nRead, err := io.ReadFull(*conn, headerBuf)
  190. if err != nil || nRead != len(headerBuf) {
  191. return p.OriMsg, fmt.Errorf("read header data error, maybe conn closed:%v", err)
  192. }
  193. err = p.UnPackHead(headerBuf)
  194. if err != nil {
  195. return p.OriMsg, err
  196. }
  197. dataBuf := make([]byte, p.BodyLen())
  198. nRead, err = io.ReadFull(*conn, dataBuf)
  199. if err != nil || nRead != len(dataBuf) {
  200. return p.OriMsg, fmt.Errorf("read data error, maybe conn closed:%v", err)
  201. }
  202. p.SetOriMsg(headerBuf, dataBuf)
  203. return p.OriMsg, nil
  204. }
  205. // HeaderInfo 头部信息, 功能号、sid、流水号、长度等
  206. func (p *MiPacket) HeaderInfo() string {
  207. return fmt.Sprintf("funcode[%d] sid[%d] serial[%d] iLen:%d",
  208. p.FunCode, p.SessionId, p.SerialNumber, p.Length)
  209. }
  210. // BuildPacket 创建包
  211. // @bCrypto 是否对数据进行加密
  212. func BuildPacket(funCode, sessionId, serialNum uint32, msg []byte, bCrypto bool) ([]byte, error) {
  213. p := new(MiPacket)
  214. p.FunCode = funCode
  215. p.SessionId = sessionId
  216. p.SerialNumber = serialNum
  217. if bCrypto && len(msg) > 0 {
  218. buf, _ := Encrypt(msg, AESKey, true)
  219. p.Data = buf
  220. return p.EnPack(), nil
  221. }
  222. p.Data = msg
  223. return p.EnPack(), nil
  224. }