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 5.5 kB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package server
  2. import (
  3. "bytes"
  4. "github.com/dubbogo/getty"
  5. "github.com/pkg/errors"
  6. "github.com/dk-lockdown/seata-golang/protocal"
  7. "github.com/dk-lockdown/seata-golang/protocal/codec"
  8. "vimagination.zapto.org/byteio"
  9. )
  10. /**
  11. * <pre>
  12. * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  13. * +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  14. * | magic |Proto| Full length | Head | Msg |Seria|Compr| RequestId |
  15. * | code |colVer| (head+body) | Length |Type |lizer|ess | |
  16. * +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
  17. * | |
  18. * | Head Map [Optional] |
  19. * +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
  20. * | |
  21. * | body |
  22. * | |
  23. * | ... ... |
  24. * +-----------------------------------------------------------------------------------------------+
  25. * </pre>
  26. * <p>
  27. * <li>Full Length: include all data </li>
  28. * <li>Head Length: include head data from magic code to head map. </li>
  29. * <li>Body Length: Full Length - Head Length</li>
  30. * </p>
  31. * https://github.com/seata/seata/issues/893
  32. */
  33. var (
  34. RpcServerPkgHandler = &RpcServerPackageHandler{}
  35. )
  36. type RpcServerPackageHandler struct{}
  37. func (p *RpcServerPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
  38. r := byteio.BigEndianReader{Reader:bytes.NewReader(data)}
  39. b0,_ := r.ReadByte()
  40. b1,_ := r.ReadByte()
  41. if b0 != protocal.MAGIC_CODE_BYTES[0] || b1 != protocal.MAGIC_CODE_BYTES[1] {
  42. return nil,0,errors.Errorf("Unknown magic code: %b,%b",b0,b1)
  43. }
  44. r.ReadByte()
  45. // TODO check version compatible here
  46. fullLength,_,_ := r.ReadInt32()
  47. headLength,_,_ := r.ReadInt16()
  48. messageType,_ := r.ReadByte()
  49. codecType,_ := r.ReadByte()
  50. compressorType,_ := r.ReadByte()
  51. requestId,_,_ := r.ReadInt32()
  52. rpcMessage := protocal.RpcMessage{
  53. Codec:codecType,
  54. Id:requestId,
  55. Compressor:compressorType,
  56. MessageType:messageType,
  57. }
  58. headMapLength := headLength - protocal.V1_HEAD_LENGTH
  59. if headMapLength > 0 {
  60. rpcMessage.HeadMap = headMapDecode(data[protocal.V1_HEAD_LENGTH+1:headMapLength])
  61. }
  62. if messageType == protocal.MSGTYPE_HEARTBEAT_REQUEST {
  63. rpcMessage.Body = protocal.HeartBeatMessagePing
  64. } else if messageType == protocal.MSGTYPE_HEARTBEAT_RESPONSE {
  65. rpcMessage.Body = protocal.HeartBeatMessagePong
  66. } else {
  67. bodyLength := fullLength - int32(headLength)
  68. if bodyLength > 0 {
  69. //todo compress
  70. msg,_ := codec.MessageDecoder(codecType,data[headLength:])
  71. rpcMessage.Body = msg
  72. }
  73. }
  74. return rpcMessage, int(fullLength), nil
  75. }
  76. func (p *RpcServerPackageHandler) Write(ss getty.Session, pkg interface{}) ([]byte, error) {
  77. var result = make([]byte,0)
  78. msg := pkg.(protocal.RpcMessage)
  79. fullLength := protocal.V1_HEAD_LENGTH
  80. headLength := protocal.V1_HEAD_LENGTH
  81. var b bytes.Buffer
  82. w := byteio.BigEndianWriter{Writer: &b}
  83. result = append(result, protocal.MAGIC_CODE_BYTES[:2]...)
  84. result = append(result, protocal.VERSION)
  85. w.WriteByte(msg.MessageType)
  86. w.WriteByte(msg.Codec)
  87. w.WriteByte(msg.Compressor)
  88. w.WriteInt32(msg.Id)
  89. if msg.HeadMap != nil && len(msg.HeadMap) > 0 {
  90. headMapBytes,headMapLength := headMapEncode(msg.HeadMap)
  91. headLength += headMapLength
  92. fullLength += headMapLength
  93. w.Write(headMapBytes)
  94. }
  95. if msg.MessageType != protocal.MSGTYPE_HEARTBEAT_REQUEST &&
  96. msg.MessageType != protocal.MSGTYPE_HEARTBEAT_RESPONSE {
  97. bodyBytes := codec.MessageEncoder(msg.Codec,msg.Body)
  98. fullLength += len(bodyBytes)
  99. w.Write(bodyBytes)
  100. }
  101. fullLen := int32(fullLength)
  102. headLen := int16(headLength)
  103. result = append(result, []byte{ byte(fullLen>>26),byte(fullLen>>16),byte(fullLen>>8),byte(fullLen) }...)
  104. result = append(result, []byte{ byte(headLen>>8),byte(headLen) }...)
  105. result = append(result,b.Bytes()...)
  106. return result, nil
  107. }
  108. func headMapDecode(data []byte) map[string]string {
  109. mp := make(map[string]string)
  110. size := len(data)
  111. if size == 0 {
  112. return mp
  113. }
  114. r := byteio.BigEndianReader{Reader:bytes.NewReader(data)}
  115. readLength := 0
  116. for {
  117. if readLength >= size { break }
  118. var key, value string
  119. lengthK,_,_ := r.ReadUint16()
  120. if lengthK < 0 {
  121. break
  122. } else if lengthK == 0 {
  123. key = ""
  124. } else {
  125. key,_,_ = r.ReadString(int(lengthK))
  126. }
  127. lengthV,_,_ := r.ReadUint16()
  128. if lengthV < 0 {
  129. break
  130. } else if lengthV == 0 {
  131. value = ""
  132. } else {
  133. value,_,_ = r.ReadString(int(lengthV))
  134. }
  135. mp[key] = value
  136. readLength += int(lengthK + lengthV)
  137. }
  138. return mp
  139. }
  140. func headMapEncode(data map[string]string) ([]byte,int) {
  141. var b bytes.Buffer
  142. w := byteio.BigEndianWriter{Writer: &b}
  143. for k,v := range data{
  144. if k == "" {
  145. w.WriteUint16(0)
  146. } else {
  147. w.WriteUint16(uint16(len(k)))
  148. w.WriteString(k)
  149. }
  150. if v == "" {
  151. w.WriteUint16(0)
  152. } else {
  153. w.WriteUint16(uint16(len(v)))
  154. w.WriteString(v)
  155. }
  156. }
  157. return b.Bytes(),b.Len()
  158. }

Go Implementation For Seata