github.com/volts-dev/volts@v0.0.0-20240120094013-5e9c65924106/transport/message.go (about) 1 package transport 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 "io" 9 10 "github.com/volts-dev/utils" 11 "github.com/volts-dev/volts/codec" 12 ) 13 14 const ( 15 MagicNumber byte = 0x08 16 17 // Request is message type of request 18 MT_ERROR MessageType = iota 19 MT_REQUEST 20 MT_RESPONSE // Response is message type of response 21 ) 22 const ( // TODO 9 重要修复状态修改不一致问题 23 StatusOK MessageStatusType = iota // Normal Not an error; returned on success. 24 // Error indicates some errors occur. 25 StatusError 26 //Internal errors. This means that some invariants expected by the underlying system have been broken. This error code is reserved for serious errors. 27 StatusInternalError 28 // The caller does not have permission to execute the specified operation. StatusForbidden must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED instead for those errors). StatusForbidden must not be used if the caller can not be identified (use UNAUTHENTICATED instead for those errors). This error code does not imply the request is valid or the requested entity exists or satisfies other pre-conditions. 29 StatusForbidden 30 StatusNotFound 31 StatusUnknown 32 StatusAborted 33 // The operation is not implemented or is not supported/enabled in this service. 34 StatusNotImplemented 35 // The service is currently unavailable. This is most likely a transient condition, which can be corrected by retrying with a backoff. Note that it is not always safe to retry non-idempotent operations. 36 StatusServiceUnavailable 37 // The request does not have valid authentication credentials for the operation. 38 StatusUnauthorized 39 ) 40 const ( 41 // None does not compress. 42 None CompressType = iota 43 // Gzip uses gzip compression. 44 Gzip 45 ) 46 47 var ( // MaxMessageLength is the max length of a message. 48 // Default is 0 that means does not limit length of messages. 49 // It is used to validate when read messages from io.Reader. 50 MaxMessageLength = 0 51 // ErrMetaKVMissing some keys or values are mssing. 52 ErrMetaKVMissing = errors.New("wrong metadata lines. some keys or values are missing") 53 // ErrMessageToLong message is too long 54 ErrMessageToLong = errors.New("message is too long") 55 ) 56 57 type ( 58 // byte-order mark is the first part of Message and has fixed size. 59 // Format: 60 Bom [12]byte 61 /** 62 * Bom Protocol 63 * +-------MagicNumber(1Byte)-------|------MessageType(Byte)--------+ 64 * +----------------------------------------------------------------+ 65 * | 0| LENGTH | 66 * +----------------------------------------------------------------+ 67 * | 0| HEADER MAGIC | FLAGS | 68 * +----------------------------------------------------------------+ 69 * | SEQUENCE NUMBER | 70 * +----------------------------------------------------------------+ 71 * | 0| Header Size(/32) | ... 72 * +--------------------------------- 73 * 74 * Message is of variable size: 75 * (and starts at offset 14) 76 * 77 * +----------------------------------------------------------------+ 78 * | Bom 12 79 * +----------------------------------------------------------------+ 80 * | Path 81 * +----------------------------------------------------------------+ 82 * | Header | 83 * +----------------------------------------------------------------+ 84 * | INFO 0 ID (uint8) | INFO 0 DATA ... 85 * +----------------------------------------------------------------+ 86 * | ... ... | 87 * +----------------------------------------------------------------+ 88 * | | 89 * | PAYLOAD | 90 * | | 91 * +----------------------------------------------------------------+ 92 */ 93 // MessageType is message type of requests and resposnes. 94 MessageType byte 95 // MessageStatusType is status of messages. 96 MessageStatusType byte 97 // CompressType defines decompression type. 98 CompressType byte 99 100 IHeader interface { 101 Add(key, value string) 102 Set(key, value string) 103 Get(key string) string 104 //has(key string) bool 105 Del(key string) 106 } 107 108 Message struct { 109 *Bom // 字节码 110 //Service string // service path 111 //Endpoint string // method path 112 Path string // the path 113 Header map[string]string // 消息头 114 Body []byte // 消息主体 115 Payload []byte // 消息主体中的内容 116 117 } 118 ) 119 120 // NewMessage creates an empty message. 121 func newMessage() *Message { 122 bom := Bom([12]byte{}) 123 bom[0] = MagicNumber 124 125 return &Message{ 126 Bom: &bom, 127 Header: make(map[string]string), //TODO 优化替代或者删除 128 129 } 130 } 131 132 // Read reads a message from r. 133 func ReadMessage(r io.Reader) (*Message, error) { 134 msg := newMessage() 135 err := msg.Decode(r) 136 if err != nil { 137 return nil, err 138 } 139 return msg, nil 140 } 141 142 // CheckMagicNumber checks whether header starts rpc magic number. 143 func (self Bom) CheckMagicNumber() bool { 144 return self[0] == MagicNumber 145 } 146 147 // Version returns version of rpc protocol. 148 func (self Bom) Version() byte { 149 return self[1] 150 } 151 152 // SetVersion sets version for this Bom. 153 func (self *Bom) SetVersion(v byte) { 154 self[1] = v 155 } 156 157 // MessageType returns the message type. 158 func (self Bom) MessageType() MessageType { 159 return MessageType(self[2]&0x80) >> 7 160 } 161 162 // SetMessageType sets message type. 163 func (self *Bom) SetMessageType(mt MessageType) { 164 self[2] = self[2] | (byte(mt) << 7) 165 } 166 167 // IsHeartbeat returns whether the message is heartbeat message. 168 func (self Bom) IsHeartbeat() bool { 169 return self[2]&0x40 == 0x40 170 } 171 172 // SetHeartbeat sets the heartbeat flag. 173 func (self *Bom) SetHeartbeat(hb bool) { 174 if hb { 175 self[2] = self[2] | 0x40 176 } else { 177 self[2] = self[2] &^ 0x40 178 } 179 } 180 181 // IsOneway returns whether the message is one-way message. 182 // If true, server won't send responses. 183 func (self Bom) IsOneway() bool { 184 return self[2]&0x20 == 0x20 185 } 186 187 // SetOneway sets the oneway flag. 188 func (self *Bom) SetOneway(oneway bool) { 189 if oneway { 190 self[2] = self[2] | 0x20 191 } else { 192 self[2] = self[2] &^ 0x20 193 } 194 } 195 196 // CompressType returns compression type of messages. 197 func (self Bom) CompressType() CompressType { 198 return CompressType((self[2] & 0x1C) >> 2) 199 } 200 201 // SetCompressType sets the compression type. 202 func (self *Bom) SetCompressType(ct CompressType) { 203 self[2] = (self[2] &^ 0x1C) | ((byte(ct) << 2) & 0x1C) 204 } 205 206 // MessageStatusType returns the message status type. 207 func (self Bom) MessageStatusType() MessageStatusType { 208 return MessageStatusType(self[2] & 0x03) 209 } 210 211 // SetMessageStatusType sets message status type. 212 func (self *Bom) SetMessageStatusType(mt MessageStatusType) { 213 self[2] = (self[2] &^ 0x03) | (byte(mt) & 0x03) 214 } 215 216 // SerializeType returns serialization type of payload. 217 func (self Bom) SerializeType() codec.SerializeType { 218 return codec.SerializeType((self[3])) 219 } 220 221 // SetSerializeType sets the serialization type. 222 func (self *Bom) SetSerializeType(st codec.SerializeType) { 223 self[3] = self[3] | byte(st) 224 } 225 226 // Seq returns sequence number of messages. 227 func (self Bom) Seq() uint64 { 228 return binary.BigEndian.Uint64(self[4:]) 229 } 230 231 // SetSeq sets sequence number. 232 func (self *Bom) SetSeq(seq uint64) { 233 binary.BigEndian.PutUint64(self[4:], seq) 234 } 235 236 var zeroHeaderArray Bom 237 var zeroHeader = zeroHeaderArray[1:] 238 239 func resetHeader(h *Bom) { 240 copy(h[1:], zeroHeader) 241 } 242 243 // len,string,len,string,...... 244 func encodeMetadata(m map[string]string) []byte { 245 if len(m) == 0 { 246 return []byte{} 247 } 248 var buf bytes.Buffer 249 var d = make([]byte, 4) 250 for k, v := range m { 251 binary.BigEndian.PutUint32(d, uint32(len(k))) 252 buf.Write(d) 253 buf.Write(utils.StringToSliceByte(k)) 254 binary.BigEndian.PutUint32(d, uint32(len(v))) 255 buf.Write(d) 256 buf.Write(utils.StringToSliceByte(v)) 257 } 258 return buf.Bytes() 259 } 260 261 func decodeMetadata(l uint32, data []byte) (map[string]string, error) { 262 m := make(map[string]string, 10) 263 n := uint32(0) 264 for n < l { 265 // parse one key and value 266 // key 267 sl := binary.BigEndian.Uint32(data[n : n+4]) 268 n = n + 4 269 if n+sl > l-4 { 270 return m, ErrMetaKVMissing 271 } 272 k := utils.SliceByteToString(data[n : n+sl]) 273 n = n + sl 274 275 // value 276 sl = binary.BigEndian.Uint32(data[n : n+4]) 277 n = n + 4 278 if n+sl > l { 279 return m, ErrMetaKVMissing 280 } 281 v := utils.SliceByteToString(data[n : n+sl]) 282 n = n + sl 283 m[k] = v 284 } 285 286 return m, nil 287 } 288 289 // Encode encodes messages. 290 func (m Message) Encode() []byte { 291 meta := encodeMetadata(m.Header) 292 293 path_len := len(m.Path) 294 spL := len(m.Header["ServicePath"]) 295 smL := len(m.Header["ServiceMethod"]) 296 297 totalL := (4 + path_len) + (4 + spL) + (4 + smL) + (4 + len(meta)) + (4 + len(m.Payload)) 298 299 // header + dataLen + spLen + sp + smLen + sm + metaL + meta + payloadLen + payload 300 metaStart := 12 + 4 + (4 + path_len) + (4 + spL) + (4 + smL) 301 302 payLoadStart := metaStart + (4 + len(meta)) 303 l := 12 + 4 + totalL 304 305 data := make([]byte, l) 306 copy(data, m.Bom[:]) 307 308 //totalLen 309 310 binary.BigEndian.PutUint32(data[12:16], uint32(totalL)) 311 312 binary.BigEndian.PutUint32(data[16:20], uint32(path_len)) 313 copy(data[20:20+path_len], utils.StringToSliceByte(m.Path)) 314 315 bgn := 20 + path_len 316 end := 24 + path_len 317 binary.BigEndian.PutUint32(data[bgn:end], uint32(spL)) 318 copy(data[end:end+spL], utils.StringToSliceByte(m.Header["ServicePath"])) 319 320 bgn = end 321 binary.BigEndian.PutUint32(data[bgn:bgn+4], uint32(smL)) 322 copy(data[bgn+4:metaStart], utils.StringToSliceByte(m.Header["ServiceMethod"])) 323 324 binary.BigEndian.PutUint32(data[metaStart:metaStart+4], uint32(len(meta))) 325 copy(data[metaStart+4:], meta) 326 327 binary.BigEndian.PutUint32(data[payLoadStart:payLoadStart+4], uint32(len(m.Payload))) 328 copy(data[payLoadStart+4:], m.Payload) 329 330 return data 331 } 332 333 // Decode decodes a message from reader. 334 func (m *Message) Decode(r io.Reader) error { 335 var err error 336 // validate rest length for each step? 337 338 //buf := make([]byte, 1) 339 /* _, err = r.Read(m.Bom[:1]) 340 if err != nil { 341 log.Dbg("TMessage.Decode", m.Bom[:], err.Error()) 342 return err 343 }*/ 344 345 // parse Bom 346 _, err = io.ReadFull(r, m.Bom[:1]) 347 if err != nil { 348 return err 349 } 350 351 if !m.Bom.CheckMagicNumber() { 352 return fmt.Errorf("wrong magic number: %v", m.Bom[0]) 353 } 354 355 _, err = io.ReadFull(r, m.Bom[1:]) 356 if err != nil { 357 return err 358 } 359 360 //total 361 lenData := poolUint32Data.Get().(*[]byte) 362 _, err = io.ReadFull(r, *lenData) 363 if err != nil { 364 poolUint32Data.Put(lenData) 365 return err 366 } 367 l := binary.BigEndian.Uint32(*lenData) 368 poolUint32Data.Put(lenData) 369 370 if MaxMessageLength > 0 && int(l) > MaxMessageLength { 371 return ErrMessageToLong 372 } 373 374 data := make([]byte, int(l)) 375 _, err = io.ReadFull(r, data) 376 if err != nil { 377 return err 378 } 379 m.Body = data 380 381 n := 0 382 // parse Path 383 l = binary.BigEndian.Uint32(data[n:4]) 384 n = n + 4 385 nEnd := n + int(l) 386 m.Path = utils.SliceByteToString(data[n:nEnd]) 387 n = nEnd 388 389 // parse servicePath 390 l = binary.BigEndian.Uint32(data[n : n+4]) 391 n = n + 4 392 nEnd = n + int(l) 393 m.Header["ServicePath"] = utils.SliceByteToString(data[n:nEnd]) 394 n = nEnd 395 396 // parse serviceMethod 397 l = binary.BigEndian.Uint32(data[n : n+4]) 398 n = n + 4 399 nEnd = n + int(l) 400 m.Header["ServiceMethod"] = utils.SliceByteToString(data[n:nEnd]) 401 n = nEnd 402 403 // parse meta 404 l = binary.BigEndian.Uint32(data[n : n+4]) 405 n = n + 4 406 nEnd = n + int(l) 407 408 if l > 0 { 409 metadata, err := decodeMetadata(l, data[n:nEnd]) 410 if err != nil { 411 return err 412 } 413 for k, v := range metadata { 414 m.Header[k] = v 415 } 416 } 417 n = nEnd 418 419 // parse payload 420 l = binary.BigEndian.Uint32(data[n : n+4]) 421 _ = l 422 n = n + 4 423 m.Payload = data[n:] 424 425 return err 426 } 427 428 // Clone clones from an message. 429 func (m Message) CloneTo(msg *Message) *Message { 430 var bom Bom 431 copy(bom[:], m.Bom[:]) 432 msg.Bom = &bom 433 msg.Header["ServicePath"] = m.Header["ServicePath"] 434 msg.Header["ServiceMethod"] = m.Header["ServiceMethod"] 435 return msg 436 } 437 438 // Reset clean data of this message but keep allocated data 439 func (m *Message) Reset() { 440 resetHeader(m.Bom) 441 m.Header = make(map[string]string) 442 m.Payload = m.Payload[:0] 443 m.Body = m.Body[:0] 444 }