util.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. package conn
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "fmt"
  6. "log"
  7. "slices"
  8. "git.me9.top/git/tinymq/config"
  9. "git.me9.top/git/tinymq/util"
  10. "git.me9.top/git/tinymq/util/pool"
  11. )
  12. // 验证包编码,其中输出的数据需要回收
  13. func AuthPackageEncode(proto string, version uint8, channel string, auth []byte, compress bool) (buf []byte) {
  14. protoLen := len(proto)
  15. protoLenMax := 0xFF
  16. if protoLen > protoLenMax {
  17. proto = proto[0:protoLenMax]
  18. protoLen = protoLenMax
  19. }
  20. channelLen := len(channel)
  21. channelLenMax := 0xFFFF
  22. if channelLen > channelLenMax {
  23. channel = channel[0:channelLenMax]
  24. channelLen = channelLenMax
  25. }
  26. // id(65502)+proto(string)+version(uint8)+option(byte)+channel(string)+auth([]byte)
  27. dlen := 2 + 1 + protoLen + 1 + 1 + 2 + channelLen + len(auth)
  28. buf = pool.Get(dlen)
  29. index := 0
  30. binary.BigEndian.PutUint16(buf[index:index+2], config.ID_AUTH)
  31. index += 2
  32. buf[index] = byte(protoLen)
  33. index++
  34. copy(buf[index:index+protoLen], []byte(proto))
  35. index += protoLen
  36. buf[index] = version
  37. index++
  38. // 指示是否支持压缩
  39. if compress {
  40. buf[index] = 0x01
  41. } else {
  42. buf[index] = 0
  43. }
  44. index++
  45. binary.BigEndian.PutUint16(buf[index:index+2], uint16(channelLen))
  46. index += 2
  47. copy(buf[index:index+channelLen], []byte(channel))
  48. index += channelLen
  49. copy(buf[index:], auth)
  50. return
  51. }
  52. // 验证包解码
  53. // id(65502)+proto(string)+version(uint8)+option(byte)+channel(string)+auth([]byte)
  54. func AuthPackageDecode(msg []byte, recycle bool) (proto string, version uint8, compress bool, channel string, auth []byte, err error) {
  55. // 避免错误的数据包,出现数组越界的错误
  56. defer func() {
  57. if recycle {
  58. pool.Put(msg)
  59. }
  60. if r := recover(); r != nil {
  61. err = fmt.Errorf("recovered from panic: %v", r)
  62. return
  63. }
  64. }()
  65. msgLen := len(msg)
  66. if msgLen < 9 {
  67. err = errors.New("wrong message length")
  68. return
  69. }
  70. index := 0
  71. id := binary.BigEndian.Uint16(msg[index : index+2])
  72. if id != config.ID_AUTH {
  73. err = fmt.Errorf("wrong message id: %d", id)
  74. return
  75. }
  76. index += 2
  77. protoLen := int(msg[index])
  78. if protoLen < 2 {
  79. err = errors.New("wrong proto length")
  80. return
  81. }
  82. index++
  83. proto = string(msg[index : index+protoLen])
  84. index += protoLen
  85. version = msg[index]
  86. index++
  87. compress = (msg[index] & 0x01) != 0
  88. index++
  89. channelLen := int(binary.BigEndian.Uint16(msg[index : index+2]))
  90. if channelLen < 2 {
  91. err = errors.New("wrong channel length")
  92. return
  93. }
  94. index += 2
  95. channel = string(msg[index : index+channelLen])
  96. index += channelLen
  97. if recycle {
  98. auth = slices.Clone(msg[index:])
  99. } else {
  100. auth = msg[index:]
  101. }
  102. return
  103. }
  104. // 请求包
  105. func RequestPackageEncode(id uint16, cmd string, data []byte, compress bool, cf *config.Config) (buf []byte) {
  106. // 为了区分请求还是响应包,命令字符串不能超过127个字节
  107. cmdLenMax := 0x7F
  108. cmdLen := len(cmd)
  109. if cmdLen > cmdLenMax {
  110. cmd = cmd[0:cmdLenMax]
  111. cmdLen = cmdLenMax
  112. }
  113. dlen := len(data)
  114. if compress && dlen > 0 {
  115. compressedData, ok, _ := util.CompressData(data)
  116. // id(uint16)+cmdLen(byte)+len(cmd)+option(byte)+len(data)
  117. ddlen := 2 + 1 + cmdLen + 1 + len(compressedData)
  118. buf = pool.Get(ddlen)
  119. index := 0
  120. binary.BigEndian.PutUint16(buf[index:index+2], id)
  121. index += 2
  122. buf[index] = byte(cmdLen)
  123. index++
  124. copy(buf[index:index+cmdLen], cmd)
  125. index += cmdLen
  126. if ok {
  127. buf[index] = 0x01
  128. if cf.PrintMsg {
  129. log.Println("[CompressData]", len(data), "->", len(compressedData))
  130. }
  131. } else {
  132. buf[index] = 0
  133. }
  134. index++
  135. copy(buf[index:], compressedData)
  136. } else {
  137. ddlen := 2 + 1 + cmdLen + dlen
  138. buf = pool.Get(ddlen)
  139. index := 0
  140. binary.BigEndian.PutUint16(buf[index:index+2], id)
  141. index += 2
  142. buf[index] = byte(cmdLen)
  143. index++
  144. copy(buf[index:index+cmdLen], cmd)
  145. index += cmdLen
  146. copy(buf[index:], data)
  147. }
  148. return
  149. }
  150. // 响应数据包
  151. // 网络格式:[id, stateCode, data]
  152. func ResponsePackageEncode(id uint16, state uint8, data []byte, compress bool, cf *config.Config) (buf []byte) {
  153. dlen := len(data)
  154. if compress && dlen > 0 {
  155. compressedData, ok, _ := util.CompressData(data)
  156. ddlen := 2 + 1 + 1 + len(compressedData)
  157. buf = pool.Get(ddlen)
  158. index := 0
  159. binary.BigEndian.PutUint16(buf[index:index+2], id)
  160. index += 2
  161. buf[index] = state | 0x80
  162. index++
  163. if ok {
  164. buf[index] = 0x001
  165. if cf.PrintMsg {
  166. log.Println("[CompressData]", len(data), "->", len(compressedData))
  167. }
  168. } else {
  169. buf[index] = 0
  170. }
  171. index++
  172. copy(buf[index:], compressedData)
  173. } else {
  174. ddlen := 2 + 1 + len(data)
  175. buf = pool.Get(ddlen)
  176. index := 0
  177. binary.BigEndian.PutUint16(buf[index:index+2], id)
  178. index += 2
  179. buf[index] = state | 0x80
  180. index++
  181. copy(buf[index:], data)
  182. }
  183. return
  184. }
  185. func PingPackageEncode(id uint16) (buf []byte) {
  186. buf = pool.Get(2)
  187. index := 0
  188. binary.BigEndian.PutUint16(buf[index:index+2], id)
  189. return
  190. }
  191. // 解析收到的数据包
  192. func PackageDecode(msg []byte, recycle bool, compress bool, cf *config.Config) (msgType MsgType, id uint16, cmd string, state uint8, data []byte, err error) {
  193. if recycle {
  194. defer pool.Put(msg)
  195. }
  196. id = binary.BigEndian.Uint16(msg[0:2])
  197. if id > config.ID_MAX {
  198. switch id {
  199. case config.ID_PROXY_CONNECT: // 代理连接请求
  200. msgType = MsgProxyConnect
  201. // 请求代理的地址
  202. if recycle {
  203. data = slices.Clone(msg[2:])
  204. } else {
  205. data = msg[2:]
  206. }
  207. return
  208. case config.ID_PROXY_RESULT: // 代理请求执行结果
  209. msgType = MsgProxyResult
  210. // 错误信息
  211. if recycle {
  212. data = slices.Clone(msg[2:])
  213. } else {
  214. data = msg[2:]
  215. }
  216. // 如果没有错误信息则表示成功
  217. if len(data) <= 0 {
  218. state = config.STATE_OK
  219. }
  220. return
  221. }
  222. err = fmt.Errorf("wrong message id: %d", id)
  223. return
  224. }
  225. // ping信息
  226. if len(msg) == 2 {
  227. msgType = MsgPing
  228. return
  229. }
  230. cmdx := msg[2]
  231. if (cmdx & 0x80) == 0 {
  232. // 请求包
  233. msgType = MsgRequest
  234. cmdLen := int(cmdx)
  235. cmd = string(msg[3 : cmdLen+3])
  236. data = msg[cmdLen+3:]
  237. } else {
  238. // 响应数据包
  239. msgType = MsgResponse
  240. state = cmdx & 0x7F
  241. data = msg[3:]
  242. }
  243. dataLen := len(data)
  244. if compress && dataLen > 1 {
  245. var ok bool
  246. data, ok, err = util.UncompressData(data)
  247. if !ok && recycle {
  248. data = slices.Clone(data)
  249. }
  250. if ok && cf.PrintMsg {
  251. log.Println("[UncompressData]", dataLen, "->", len(data))
  252. }
  253. } else if recycle && dataLen > 0 {
  254. data = slices.Clone(data)
  255. }
  256. return
  257. }