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  }