github.com/nyan233/littlerpc@v0.4.6-0.20230316182519-0c8d5c48abaf/core/protocol/message/message.go (about) 1 package message 2 3 import ( 4 container2 "github.com/nyan233/littlerpc/core/container" 5 ) 6 7 const ( 8 MagicNumber uint8 = 0x45 9 // Call 表示这是一条调用的消息 10 Call uint8 = 0x10 11 // Return 表示这是一条调用返回消息 12 Return uint8 = 0x18 13 // ContextCancel 用户服务端接收的context.Context的取消API 14 ContextCancel uint8 = 0x24 15 // Ping Ping消息 16 Ping uint8 = 0x33 17 // Pong Pong消息 18 Pong uint8 = 0x35 19 20 // BaseLen 的基本长度 21 BaseLen = _ScopeLength + 4 + 8 22 // DefaultPacker TODO: 将Encoder改为Packer 23 DefaultPacker string = "text" // encoding == text 24 DefaultCodec string = "json" // codec == text 25 26 ErrorCode string = "code" 27 ErrorMessage string = "message" 28 ErrorMore string = "bin" 29 ContextId string = "context-id" 30 CodecScheme string = "codec" 31 // PackerScheme TODO: 将Encoder改为Packer 32 PackerScheme string = "packer" 33 ) 34 35 const ( 36 _ScopeLength = 2 37 _ServiceName = 1 38 _Metadata = 1 39 _PayloadLayout = 1 40 ) 41 42 type Getter interface { 43 First() uint8 44 BaseLength() int 45 Length() uint32 46 GetAndSetLength() uint32 47 GetMsgType() uint8 48 GetServiceName() string 49 GetMsgId() uint64 50 Payloads() container2.Slice[byte] 51 PayloadsIterator() *container2.Iterator[[]byte] 52 MinMux() int 53 } 54 55 type Setter interface { 56 GetAndSetLength() uint32 57 SetMsgType(msgTyp uint8) 58 SetServiceName(serviceName string) 59 SetMsgId(msgId uint64) 60 AppendPayloads(p []byte) 61 ReWritePayload(p []byte) 62 SetPayloads(payloads []byte) 63 Reset() 64 } 65 66 type GetterSetter interface { 67 Getter 68 Setter 69 } 70 71 func New() *Message { 72 return &Message{ 73 MetaData: container2.NewSliceMap[string, string](4), 74 scope: [2]uint8{MagicNumber}, 75 payloadLayout: make([]uint32, 0, 2), 76 payloads: make([]byte, 0, 1024), 77 } 78 } 79 80 // Message 是对一次RPC调用传递的数据的描述 81 // 封装的方法均不是线程安全的 82 // DecodeHeader会修改一些内部值,调用时需要注意顺序 83 // 为了使用一致性的API,在访问内部一些简单的属性时,请使用Getxx方法 84 // 在设置一些值的过程中可能需要调整其它值,所以请使用Setxx方法 85 type Message struct { 86 // int/uint数值统一使用大端序 87 // [0] == Magic (魔数,表示这是由littlerpc客户端发起或者服务端回复) 88 // [1] == MsgType (call/return & ping/pong) 89 scope [2]uint8 90 // 消息ID,用于表示一次完整的call/return的回复 91 msgId uint64 92 // 载荷数据的总长度 93 payloadLength uint32 94 // 实例名和调用方法名的布局 95 // Length (1 Byte) | ServiceName 96 serviceName string 97 // NOTE: 98 // 有效载荷和元数据的范围 99 // 在Mux模式中MetaData及其Desc必须能在一个MuxBlock下被装下,否则将会丢失数据 100 // 元数据的布局 101 // NMetaData(1 Byte)|Key-Size(4 Byte)|Value-Size(4 Byte)|Key|Size 102 // Example : 103 // "hello":"world","world:hello" 104 // OutPut: 105 // 0x00000002|0x00000005|0x00000005|hello|world|0x00000005|0x00000005|world|hello 106 MetaData *container2.SliceMap[string, string] 107 // 有效载荷数据的布局描述 108 // Format : 109 // NArgs(1 Byte)|Arg1-Size(4 Byte)|Arg2-Size(4 Byte)|Arg3-Size(4 Byte) 110 // Example : 111 // {"mypyload1":"haha"},{"mypyload2":"hehe"} 112 // OutPut: 113 // 0x00000002|0x00000014|0x00000014 114 payloadLayout container2.Slice[uint32] 115 // 调用参数序列化后的载荷数据 116 // 如果被压缩了那么在反序列化时,最后剩下的数据均为参数载荷 117 payloads container2.Slice[byte] 118 } 119 120 // BaseLength 获取基本数据的长度防止输入过短的数据导致panic 121 func (m *Message) BaseLength() int { 122 ml := m.MinMux() 123 // MinMux + NameLayout + NMetaData + NArgs 124 return ml + _PayloadLayout + _ServiceName + _Metadata 125 } 126 127 // Length 根据结构计算序列化之后的数据长度, 长度存在时直接返回结果 128 // 不会设置m.payloadLength 129 func (m *Message) Length() uint32 { 130 if m.payloadLength > 0 { 131 return m.payloadLength 132 } 133 // desc : Scope & MsgId & PayloadLength & ServiceName & MetaData & Args 134 baseLen := m.MinMux() + _ServiceName + _Metadata + _PayloadLayout 135 // InstanceName & MethodName 136 baseLen += len(m.serviceName) 137 if m.MetaData != nil && m.MetaData.Len() > 0 { 138 // Key&Value Struct MetaData 139 baseLen += (m.MetaData.Len() * 4) * 2 140 // Key & Value Size 141 m.MetaData.Range(func(k, v string) bool { 142 baseLen += len(k) + len(v) 143 return true 144 }) 145 } 146 // NArgs 147 baseLen += m.payloadLayout.Len() * 4 148 baseLen += m.payloads.Len() 149 return uint32(baseLen) 150 } 151 152 func (m *Message) GetAndSetLength() uint32 { 153 m.payloadLength = m.Length() 154 return m.Length() 155 } 156 157 func (m *Message) First() uint8 { 158 return m.scope[0] 159 } 160 161 func (m *Message) GetMsgType() uint8 { 162 return m.scope[1] 163 } 164 165 func (m *Message) SetMsgType(msgTyp uint8) { 166 m.scope[1] = msgTyp 167 } 168 169 func (m *Message) GetServiceName() string { 170 return m.serviceName 171 } 172 173 func (m *Message) SetServiceName(s string) { 174 m.serviceName = s 175 } 176 177 func (m *Message) GetMsgId() uint64 { 178 return m.msgId 179 } 180 181 func (m *Message) SetMsgId(msgId uint64) { 182 m.msgId = msgId 183 } 184 185 func (m *Message) AppendPayloads(p []byte) { 186 m.payloads = append(m.payloads, p...) 187 m.payloadLayout = append(m.payloadLayout, uint32(len(p))) 188 } 189 190 func (m *Message) Payloads() container2.Slice[byte] { 191 return m.payloads 192 } 193 194 func (m *Message) ReWritePayload(p []byte) { 195 m.payloads.Reset() 196 m.payloads.Append(p) 197 } 198 199 func (m *Message) SetPayloads(payloads []byte) { 200 m.payloads = payloads 201 } 202 203 func (m *Message) PayloadsIterator() *container2.Iterator[[]byte] { 204 rangCount := 0 205 var length int 206 if m.payloadLayout == nil || m.payloadLayout.Len() == 0 { 207 length = 0 208 } else { 209 length = m.payloadLayout.Len() 210 } 211 return container2.NewIterator[[]byte](length, false, func(current int) []byte { 212 if current+1 == m.payloadLayout.Len() { 213 return m.payloads[rangCount : rangCount+int(m.payloadLayout[current])] 214 } 215 old := rangCount 216 rangCount += int(m.payloadLayout[current]) 217 return m.payloads[old:rangCount] 218 }, func() { 219 rangCount = 0 220 }) 221 } 222 223 func (m *Message) MinMux() int { 224 // Scope + MsgId + PayloadLength 225 return len(m.scope) + 8 + 4 226 } 227 228 // Reset 给内存复用的操作提供一致性的语义 229 func (m *Message) Reset() { 230 m.scope = [...]uint8{MagicNumber, 0} 231 m.serviceName = "" 232 m.msgId = 0 233 m.payloadLength = 0 234 m.MetaData.Reset() 235 m.payloadLayout.Reset() 236 m.payloads.Reset() 237 }