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  }