You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

readwriter.go 7.7 kB

3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. package rpc_client
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. )
  6. import (
  7. getty "github.com/apache/dubbo-getty"
  8. "github.com/pkg/errors"
  9. "vimagination.zapto.org/byteio"
  10. )
  11. import (
  12. "github.com/seata/seata-go/pkg/protocol"
  13. "github.com/seata/seata-go/pkg/protocol/codec"
  14. )
  15. /**
  16. * <pre>
  17. * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  18. * +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  19. * | magic |Proto| Full length | Head | Msg |Seria|Compr| RequestID |
  20. * | code |colVer| (head+body) | Length |Type |lizer|ess | |
  21. * +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
  22. * | |
  23. * | Head Map [Optional] |
  24. * +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
  25. * | |
  26. * | body |
  27. * | |
  28. * | ... ... |
  29. * +-----------------------------------------------------------------------------------------------+
  30. * </pre>
  31. * <p>
  32. * <li>Full Length: include all data </li>
  33. * <li>Head Length: include head data from magic code to head map. </li>
  34. * <li>Body Length: Full Length - Head Length</li>
  35. * </p>
  36. * https://github.com/seata/seata/issues/893
  37. */
  38. const (
  39. SeataV1PackageHeaderReservedLength = 16
  40. )
  41. var (
  42. // RpcPkgHandler
  43. rpcPkgHandler = &RpcPackageHandler{}
  44. )
  45. var (
  46. ErrNotEnoughStream = errors.New("packet stream is not enough")
  47. ErrTooLargePackage = errors.New("package length is exceed the getty package's legal maximum length.")
  48. ErrInvalidPackage = errors.New("invalid rpc package")
  49. ErrIllegalMagic = errors.New("package magic is not right.")
  50. )
  51. type RpcPackageHandler struct{}
  52. type SeataV1PackageHeader struct {
  53. Magic0 byte
  54. Magic1 byte
  55. Version byte
  56. TotalLength uint32
  57. HeadLength uint16
  58. MessageType byte
  59. CodecType byte
  60. CompressType byte
  61. ID uint32
  62. Meta map[string]string
  63. BodyLength uint32
  64. }
  65. func (h *SeataV1PackageHeader) Unmarshal(buf *bytes.Buffer) (int, error) {
  66. bufLen := buf.Len()
  67. if bufLen < SeataV1PackageHeaderReservedLength {
  68. return 0, ErrNotEnoughStream
  69. }
  70. // magic
  71. if err := binary.Read(buf, binary.BigEndian, &(h.Magic0)); err != nil {
  72. return 0, err
  73. }
  74. if err := binary.Read(buf, binary.BigEndian, &(h.Magic1)); err != nil {
  75. return 0, err
  76. }
  77. if h.Magic0 != protocol.MAGIC_CODE_BYTES[0] || h.Magic1 != protocol.MAGIC_CODE_BYTES[1] {
  78. return 0, ErrIllegalMagic
  79. }
  80. // version
  81. if err := binary.Read(buf, binary.BigEndian, &(h.Version)); err != nil {
  82. return 0, err
  83. }
  84. // TODO check version compatible here
  85. // total length
  86. if err := binary.Read(buf, binary.BigEndian, &(h.TotalLength)); err != nil {
  87. return 0, err
  88. }
  89. // head length
  90. if err := binary.Read(buf, binary.BigEndian, &(h.HeadLength)); err != nil {
  91. return 0, err
  92. }
  93. // message type
  94. if err := binary.Read(buf, binary.BigEndian, &(h.MessageType)); err != nil {
  95. return 0, err
  96. }
  97. // codec type
  98. if err := binary.Read(buf, binary.BigEndian, &(h.CodecType)); err != nil {
  99. return 0, err
  100. }
  101. // compress type
  102. if err := binary.Read(buf, binary.BigEndian, &(h.CompressType)); err != nil {
  103. return 0, err
  104. }
  105. // id
  106. if err := binary.Read(buf, binary.BigEndian, &(h.ID)); err != nil {
  107. return 0, err
  108. }
  109. // todo meta map
  110. if h.HeadLength > SeataV1PackageHeaderReservedLength {
  111. headMapLength := h.HeadLength - SeataV1PackageHeaderReservedLength
  112. h.Meta = headMapDecode(buf.Bytes()[:headMapLength])
  113. }
  114. h.BodyLength = h.TotalLength - uint32(h.HeadLength)
  115. return int(h.TotalLength), nil
  116. }
  117. // Read read binary data from to rpc message
  118. func (p *RpcPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
  119. var header SeataV1PackageHeader
  120. buf := bytes.NewBuffer(data)
  121. _, err := header.Unmarshal(buf)
  122. if err != nil {
  123. if err == ErrNotEnoughStream {
  124. // getty case2
  125. return nil, 0, nil
  126. }
  127. // getty case1
  128. return nil, 0, err
  129. }
  130. if uint32(len(data)) < header.TotalLength {
  131. // get case3
  132. return nil, int(header.TotalLength), nil
  133. }
  134. //r := byteio.BigEndianReader{Reader: bytes.NewReader(data)}
  135. rpcMessage := protocol.RpcMessage{
  136. Codec: header.CodecType,
  137. ID: int32(header.ID),
  138. Compressor: header.CompressType,
  139. MessageType: header.MessageType,
  140. HeadMap: header.Meta,
  141. }
  142. if header.MessageType == protocol.MSGTypeHeartbeatRequest {
  143. rpcMessage.Body = protocol.HeartBeatMessagePing
  144. } else if header.MessageType == protocol.MSGTypeHeartbeatResponse {
  145. rpcMessage.Body = protocol.HeartBeatMessagePong
  146. } else {
  147. if header.BodyLength > 0 {
  148. //todo compress
  149. msg, _ := codec.MessageDecoder(header.CodecType, data[header.HeadLength:])
  150. rpcMessage.Body = msg
  151. }
  152. }
  153. return rpcMessage, int(header.TotalLength), nil
  154. }
  155. // Write write rpc message to binary data
  156. func (p *RpcPackageHandler) Write(ss getty.Session, pkg interface{}) ([]byte, error) {
  157. msg, ok := pkg.(protocol.RpcMessage)
  158. if !ok {
  159. return nil, ErrInvalidPackage
  160. }
  161. fullLength := protocol.V1HeadLength
  162. headLength := protocol.V1HeadLength
  163. var result = make([]byte, 0, fullLength)
  164. var b bytes.Buffer
  165. w := byteio.BigEndianWriter{Writer: &b}
  166. result = append(result, protocol.MAGIC_CODE_BYTES[:2]...)
  167. result = append(result, protocol.VERSION)
  168. w.WriteByte(msg.MessageType)
  169. w.WriteByte(msg.Codec)
  170. w.WriteByte(msg.Compressor)
  171. w.WriteInt32(msg.ID)
  172. if msg.HeadMap != nil && len(msg.HeadMap) > 0 {
  173. headMapBytes, headMapLength := headMapEncode(msg.HeadMap)
  174. headLength += headMapLength
  175. fullLength += headMapLength
  176. w.Write(headMapBytes)
  177. }
  178. if msg.MessageType != protocol.MSGTypeHeartbeatRequest &&
  179. msg.MessageType != protocol.MSGTypeHeartbeatResponse {
  180. bodyBytes := codec.MessageEncoder(msg.Codec, msg.Body)
  181. fullLength += len(bodyBytes)
  182. w.Write(bodyBytes)
  183. }
  184. fullLen := int32(fullLength)
  185. headLen := int16(headLength)
  186. result = append(result, []byte{byte(fullLen >> 24), byte(fullLen >> 16), byte(fullLen >> 8), byte(fullLen)}...)
  187. result = append(result, []byte{byte(headLen >> 8), byte(headLen)}...)
  188. result = append(result, b.Bytes()...)
  189. return result, nil
  190. }
  191. func headMapDecode(data []byte) map[string]string {
  192. size := len(data)
  193. if size == 0 {
  194. return nil
  195. }
  196. mp := make(map[string]string)
  197. r := byteio.BigEndianReader{Reader: bytes.NewReader(data)}
  198. readLength := 0
  199. for readLength < size {
  200. var key, value string
  201. lengthK, _, _ := r.ReadUint16()
  202. if lengthK < 0 {
  203. break
  204. } else if lengthK == 0 {
  205. key = ""
  206. } else {
  207. key, _, _ = r.ReadString(int(lengthK))
  208. }
  209. lengthV, _, _ := r.ReadUint16()
  210. if lengthV < 0 {
  211. break
  212. } else if lengthV == 0 {
  213. value = ""
  214. } else {
  215. value, _, _ = r.ReadString(int(lengthV))
  216. }
  217. mp[key] = value
  218. readLength += int(lengthK + lengthV)
  219. }
  220. return mp
  221. }
  222. func headMapEncode(data map[string]string) ([]byte, int) {
  223. var b bytes.Buffer
  224. w := byteio.BigEndianWriter{Writer: &b}
  225. for k, v := range data {
  226. if k == "" {
  227. w.WriteUint16(0)
  228. } else {
  229. w.WriteUint16(uint16(len(k)))
  230. w.WriteString(k)
  231. }
  232. if v == "" {
  233. w.WriteUint16(0)
  234. } else {
  235. w.WriteUint16(uint16(len(v)))
  236. w.WriteString(v)
  237. }
  238. }
  239. return b.Bytes(), b.Len()
  240. }

Go Implementation For Seata