trpc.group/trpc-go/trpc-go@v1.0.3/codec.go (about)

     1  //
     2  //
     3  // Tencent is pleased to support the open source community by making tRPC available.
     4  //
     5  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     6  // All rights reserved.
     7  //
     8  // If you have downloaded a copy of the tRPC source code from Tencent,
     9  // please note that tRPC source code is licensed under the  Apache 2.0 License,
    10  // A copy of the Apache 2.0 License is included in this file.
    11  //
    12  //
    13  
    14  package trpc
    15  
    16  import (
    17  	"encoding/binary"
    18  	"errors"
    19  	"fmt"
    20  	"io"
    21  	"math"
    22  	"os"
    23  	"path"
    24  	"sync/atomic"
    25  	"time"
    26  
    27  	"trpc.group/trpc-go/trpc-go/codec"
    28  	"trpc.group/trpc-go/trpc-go/errs"
    29  	"trpc.group/trpc-go/trpc-go/internal/attachment"
    30  	"trpc.group/trpc-go/trpc-go/transport"
    31  
    32  	"google.golang.org/protobuf/proto"
    33  	trpcpb "trpc.group/trpc/trpc-protocol/pb/go/trpc"
    34  )
    35  
    36  func init() {
    37  	codec.Register(ProtocolName, DefaultServerCodec, DefaultClientCodec)
    38  	transport.RegisterFramerBuilder(ProtocolName, DefaultFramerBuilder)
    39  }
    40  
    41  // default codec
    42  var (
    43  	DefaultServerCodec = &ServerCodec{
    44  		streamCodec: NewServerStreamCodec(),
    45  	}
    46  	DefaultClientCodec = &ClientCodec{
    47  		streamCodec:   NewClientStreamCodec(),
    48  		defaultCaller: fmt.Sprintf("trpc.client.%s.service", path.Base(os.Args[0])),
    49  	}
    50  	DefaultFramerBuilder = &FramerBuilder{}
    51  
    52  	// DefaultMaxFrameSize is the default max size of frame including attachment,
    53  	// which can be modified if size of the packet is bigger than this.
    54  	DefaultMaxFrameSize = 10 * 1024 * 1024
    55  )
    56  
    57  var (
    58  	errHeadOverflowsUint16       = errors.New("head len overflows uint16")
    59  	errHeadOverflowsUint32       = errors.New("total len overflows uint32")
    60  	errAttachmentOverflowsUint32 = errors.New("attachment len overflows uint32")
    61  )
    62  
    63  type errFrameTooLarge struct {
    64  	maxFrameSize int
    65  }
    66  
    67  // Error implements the error interface and returns the description of the errFrameTooLarge.
    68  func (e *errFrameTooLarge) Error() string {
    69  	return fmt.Sprintf("frame len is larger than MaxFrameSize(%d)", e.maxFrameSize)
    70  }
    71  
    72  // frequently used const variables
    73  const (
    74  	DyeingKey   = "trpc-dyeing-key" // dyeing key
    75  	UserIP      = "trpc-user-ip"    // user ip
    76  	EnvTransfer = "trpc-env"        // env info
    77  
    78  	ProtocolName = "trpc" // protocol name
    79  )
    80  
    81  // trpc protocol codec
    82  const (
    83  	// frame head format:
    84  	// v0:
    85  	// 2 bytes magic + 1 byte frame type + 1 byte stream frame type + 4 bytes total len
    86  	// + 2 bytes pb header len + 4 bytes stream id + 2 bytes reserved
    87  	// v1:
    88  	// 2 bytes magic + 1 byte frame type + 1 byte stream frame type + 4 bytes total len
    89  	// + 2 bytes pb header len + 4 bytes stream id + 1 byte protocol version + 1 byte reserved
    90  	frameHeadLen       = uint16(16)       // total length of frame head: 16 bytes
    91  	protocolVersion0   = uint8(0)         // v0
    92  	protocolVersion1   = uint8(1)         // v1
    93  	curProtocolVersion = protocolVersion1 // current protocol version
    94  )
    95  
    96  // FrameHead is head of the trpc frame.
    97  type FrameHead struct {
    98  	FrameType       uint8  // type of the frame
    99  	StreamFrameType uint8  // type of the stream frame
   100  	TotalLen        uint32 // total length
   101  	HeaderLen       uint16 // header's length
   102  	StreamID        uint32 // stream id for streaming rpc, request id for unary rpc
   103  	ProtocolVersion uint8  // version of protocol
   104  	FrameReserved   uint8  // reserved bits for further development
   105  }
   106  
   107  func newDefaultUnaryFrameHead() *FrameHead {
   108  	return &FrameHead{
   109  		FrameType:       uint8(trpcpb.TrpcDataFrameType_TRPC_UNARY_FRAME), // default unary
   110  		ProtocolVersion: curProtocolVersion,
   111  	}
   112  }
   113  
   114  // extract extracts field values of the FrameHead from the buffer.
   115  func (h *FrameHead) extract(buf []byte) {
   116  	h.FrameType = buf[2]
   117  	h.StreamFrameType = buf[3]
   118  	h.TotalLen = binary.BigEndian.Uint32(buf[4:8])
   119  	h.HeaderLen = binary.BigEndian.Uint16(buf[8:10])
   120  	h.StreamID = binary.BigEndian.Uint32(buf[10:14])
   121  	h.ProtocolVersion = buf[14]
   122  	h.FrameReserved = buf[15]
   123  }
   124  
   125  // construct constructs bytes data for the whole frame.
   126  func (h *FrameHead) construct(header, body, attachment []byte) ([]byte, error) {
   127  	headerLen := len(header)
   128  	if headerLen > math.MaxUint16 {
   129  		return nil, errHeadOverflowsUint16
   130  	}
   131  	attachmentLen := int64(len(attachment))
   132  	if attachmentLen > math.MaxUint32 {
   133  		return nil, errAttachmentOverflowsUint32
   134  	}
   135  	totalLen := int64(frameHeadLen) + int64(headerLen) + int64(len(body)) + attachmentLen
   136  	if totalLen > int64(DefaultMaxFrameSize) {
   137  		return nil, &errFrameTooLarge{maxFrameSize: DefaultMaxFrameSize}
   138  	}
   139  	if totalLen > math.MaxUint32 {
   140  		return nil, errHeadOverflowsUint32
   141  	}
   142  
   143  	// construct the buffer
   144  	buf := make([]byte, totalLen)
   145  	binary.BigEndian.PutUint16(buf[:2], uint16(trpcpb.TrpcMagic_TRPC_MAGIC_VALUE))
   146  	buf[2] = h.FrameType
   147  	buf[3] = h.StreamFrameType
   148  	binary.BigEndian.PutUint32(buf[4:8], uint32(totalLen))
   149  	binary.BigEndian.PutUint16(buf[8:10], uint16(headerLen))
   150  	binary.BigEndian.PutUint32(buf[10:14], h.StreamID)
   151  	buf[14] = h.ProtocolVersion
   152  	buf[15] = h.FrameReserved
   153  
   154  	frameHeadLen := int(frameHeadLen)
   155  	copy(buf[frameHeadLen:frameHeadLen+headerLen], header)
   156  	copy(buf[frameHeadLen+headerLen:frameHeadLen+headerLen+len(body)], body)
   157  	copy(buf[frameHeadLen+headerLen+len(body):], attachment)
   158  	return buf, nil
   159  }
   160  
   161  func (h *FrameHead) isStream() bool {
   162  	return trpcpb.TrpcDataFrameType(h.FrameType) == trpcpb.TrpcDataFrameType_TRPC_STREAM_FRAME
   163  }
   164  
   165  func (h *FrameHead) isUnary() bool {
   166  	return trpcpb.TrpcDataFrameType(h.FrameType) == trpcpb.TrpcDataFrameType_TRPC_UNARY_FRAME
   167  }
   168  
   169  // upgradeProtocol upgrades protocol and sets stream id and request id.
   170  // For compatibility, server should respond the same protocol version as that of the request.
   171  // and client should always send request with the latest protocol version.
   172  func (h *FrameHead) upgradeProtocol(protocolVersion uint8, requestID uint32) {
   173  	h.ProtocolVersion = protocolVersion
   174  	h.StreamID = requestID
   175  }
   176  
   177  // FramerBuilder is an implementation of codec.FramerBuilder.
   178  // Used for trpc protocol.
   179  type FramerBuilder struct{}
   180  
   181  // New implements codec.FramerBuilder.
   182  func (fb *FramerBuilder) New(reader io.Reader) codec.Framer {
   183  	return &framer{
   184  		reader: reader,
   185  	}
   186  }
   187  
   188  // Parse implement multiplexed.FrameParser interface.
   189  func (fb *FramerBuilder) Parse(rc io.Reader) (vid uint32, buf []byte, err error) {
   190  	buf, err = fb.New(rc).ReadFrame()
   191  	if err != nil {
   192  		return 0, nil, err
   193  	}
   194  	return binary.BigEndian.Uint32(buf[10:14]), buf, nil
   195  }
   196  
   197  // framer is an implementation of codec.Framer.
   198  // Used for trpc protocol.
   199  type framer struct {
   200  	reader io.Reader
   201  	header [frameHeadLen]byte
   202  }
   203  
   204  // ReadFrame implements codec.Framer.
   205  func (f *framer) ReadFrame() ([]byte, error) {
   206  	num, err := io.ReadFull(f.reader, f.header[:])
   207  	if err != nil {
   208  		return nil, err
   209  	}
   210  	if num != int(frameHeadLen) {
   211  		return nil, fmt.Errorf("trpc framer: read frame header num %d != %d, invalid", num, int(frameHeadLen))
   212  	}
   213  	magic := binary.BigEndian.Uint16(f.header[:2])
   214  	if magic != uint16(trpcpb.TrpcMagic_TRPC_MAGIC_VALUE) {
   215  		return nil, fmt.Errorf(
   216  			"trpc framer: read framer head magic %d != %d, not match", magic, uint16(trpcpb.TrpcMagic_TRPC_MAGIC_VALUE))
   217  	}
   218  	totalLen := binary.BigEndian.Uint32(f.header[4:8])
   219  	if totalLen < uint32(frameHeadLen) {
   220  		return nil, fmt.Errorf(
   221  			"trpc framer: read frame header total len %d < %d, invalid", totalLen, uint32(frameHeadLen))
   222  	}
   223  
   224  	if totalLen > uint32(DefaultMaxFrameSize) {
   225  		return nil, fmt.Errorf(
   226  			"trpc framer: read frame header total len %d > %d, too large", totalLen, uint32(DefaultMaxFrameSize))
   227  	}
   228  
   229  	msg := make([]byte, totalLen)
   230  	num, err = io.ReadFull(f.reader, msg[frameHeadLen:totalLen])
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  	if num != int(totalLen-uint32(frameHeadLen)) {
   235  		return nil, fmt.Errorf(
   236  			"trpc framer: read frame total num %d != %d, invalid", num, int(totalLen-uint32(frameHeadLen)))
   237  	}
   238  	copy(msg, f.header[:])
   239  	return msg, nil
   240  }
   241  
   242  // IsSafe implements codec.SafeFramer.
   243  // Used for compatibility.
   244  func (f *framer) IsSafe() bool {
   245  	return true
   246  }
   247  
   248  // ServerCodec is an implementation of codec.Codec.
   249  // Used for trpc serverside codec.
   250  type ServerCodec struct {
   251  	streamCodec *ServerStreamCodec
   252  }
   253  
   254  // Decode implements codec.Codec.
   255  // It decodes the reqBuf and updates the msg that already initialized by service handler.
   256  func (s *ServerCodec) Decode(msg codec.Msg, reqBuf []byte) ([]byte, error) {
   257  	if len(reqBuf) < int(frameHeadLen) {
   258  		return nil, errors.New("server decode req buf len invalid")
   259  	}
   260  	frameHead := newDefaultUnaryFrameHead()
   261  	frameHead.extract(reqBuf)
   262  	msg.WithFrameHead(frameHead)
   263  	if frameHead.TotalLen != uint32(len(reqBuf)) {
   264  		return nil, fmt.Errorf("total len %d is not actual buf len %d", frameHead.TotalLen, len(reqBuf))
   265  	}
   266  	if frameHead.FrameType != uint8(trpcpb.TrpcDataFrameType_TRPC_UNARY_FRAME) { // streaming rpc has its own decoding
   267  		rspBody, err := s.streamCodec.Decode(msg, reqBuf)
   268  		if err != nil {
   269  			// if decoding fails, the Close frame with Reset type will be returned to the client
   270  			err := errs.NewFrameError(errs.RetServerDecodeFail, err.Error())
   271  			s.streamCodec.buildResetFrame(msg, frameHead, err)
   272  			return nil, err
   273  		}
   274  		return rspBody, nil
   275  	}
   276  	if frameHead.HeaderLen == 0 { // header not allowed to be empty for unary rpc
   277  		return nil, errors.New("server decode pb head len empty")
   278  	}
   279  
   280  	requestProtocolBegin := uint32(frameHeadLen)
   281  	requestProtocolEnd := requestProtocolBegin + uint32(frameHead.HeaderLen)
   282  	if requestProtocolEnd > uint32(len(reqBuf)) {
   283  		return nil, errors.New("server decode pb head len invalid")
   284  	}
   285  	req := &trpcpb.RequestProtocol{}
   286  	if err := proto.Unmarshal(reqBuf[requestProtocolBegin:requestProtocolEnd], req); err != nil {
   287  		return nil, err
   288  	}
   289  
   290  	attachmentBegin := frameHead.TotalLen - req.AttachmentSize
   291  	if s := uint32(len(reqBuf)) - attachmentBegin; s != req.AttachmentSize {
   292  		return nil, fmt.Errorf("decoding attachment: len of attachment(%d) "+
   293  			"isn't equal to expected AttachmentSize(%d) ", s, req.AttachmentSize)
   294  	}
   295  
   296  	msgWithRequestProtocol(msg, req, reqBuf[attachmentBegin:])
   297  
   298  	requestBodyBegin, requestBodyEnd := requestProtocolEnd, attachmentBegin
   299  	return reqBuf[requestBodyBegin:requestBodyEnd], nil
   300  }
   301  
   302  func msgWithRequestProtocol(msg codec.Msg, req *trpcpb.RequestProtocol, attm []byte) {
   303  	// set server request head
   304  	msg.WithServerReqHead(req)
   305  	// construct response protocol head in advance
   306  	rsp := newResponseProtocol(req)
   307  	msg.WithServerRspHead(rsp)
   308  
   309  	// ---------the following code is to set the essential info-----------//
   310  	// set upstream timeout
   311  	msg.WithRequestTimeout(time.Millisecond * time.Duration(req.GetTimeout()))
   312  	// set upstream service name
   313  	msg.WithCallerServiceName(string(req.GetCaller()))
   314  	msg.WithCalleeServiceName(string(req.GetCallee()))
   315  	// set server handler method name
   316  	msg.WithServerRPCName(string(req.GetFunc()))
   317  	// set body serialization type
   318  	msg.WithSerializationType(int(req.GetContentType()))
   319  	// set body compression type
   320  	msg.WithCompressType(int(req.GetContentEncoding()))
   321  	// set dyeing mark
   322  	msg.WithDyeing((req.GetMessageType() & uint32(trpcpb.TrpcMessageType_TRPC_DYEING_MESSAGE)) != 0)
   323  	// parse tracing MetaData, set MetaData into msg
   324  	if len(req.TransInfo) > 0 {
   325  		msg.WithServerMetaData(req.GetTransInfo())
   326  		// mark with dyeing key
   327  		if bs, ok := req.TransInfo[DyeingKey]; ok {
   328  			msg.WithDyeingKey(string(bs))
   329  		}
   330  		// transmit env info
   331  		if envs, ok := req.TransInfo[EnvTransfer]; ok {
   332  			msg.WithEnvTransfer(string(envs))
   333  		}
   334  	}
   335  	// set call type
   336  	msg.WithCallType(codec.RequestType(req.GetCallType()))
   337  	if len(attm) != 0 {
   338  		attachment.SetServerRequestAttachment(msg, attm)
   339  	}
   340  }
   341  
   342  // Encode implements codec.Codec.
   343  // It encodes the rspBody to binary data and returns it to client.
   344  func (s *ServerCodec) Encode(msg codec.Msg, rspBody []byte) ([]byte, error) {
   345  	frameHead := loadOrStoreDefaultUnaryFrameHead(msg)
   346  	if frameHead.isStream() {
   347  		return s.streamCodec.Encode(msg, rspBody)
   348  	}
   349  	if !frameHead.isUnary() {
   350  		return nil, errUnknownFrameType
   351  	}
   352  
   353  	rspProtocol := getAndInitResponseProtocol(msg)
   354  
   355  	var attm []byte
   356  	if a, ok := attachment.ServerResponseAttachment(msg); ok {
   357  		var err error
   358  		if attm, err = io.ReadAll(a); err != nil {
   359  			return nil, fmt.Errorf("encoding attachment: %w", err)
   360  		}
   361  	}
   362  	rspProtocol.AttachmentSize = uint32(len(attm))
   363  
   364  	rspHead, err := proto.Marshal(rspProtocol)
   365  	if err != nil {
   366  		return nil, err
   367  	}
   368  
   369  	rspBuf, err := frameHead.construct(rspHead, rspBody, attm)
   370  	if errors.Is(err, errHeadOverflowsUint16) {
   371  		return handleEncodeErr(rspProtocol, frameHead, rspBody, err)
   372  	}
   373  	var frameTooLargeErr *errFrameTooLarge
   374  	if errors.As(err, &frameTooLargeErr) || errors.Is(err, errHeadOverflowsUint32) {
   375  		// If frame len is larger than DefaultMaxFrameSize or overflows uint32, set rspBody nil.
   376  		return handleEncodeErr(rspProtocol, frameHead, nil, err)
   377  	}
   378  	return rspBuf, err
   379  }
   380  
   381  // getAndInitResponseProtocol returns rsp head from msg and initialize the rsp with msg.
   382  // If rsp head is not found from msg, a new rsp head will be created and initialized.
   383  func getAndInitResponseProtocol(msg codec.Msg) *trpcpb.ResponseProtocol {
   384  	rsp, ok := msg.ServerRspHead().(*trpcpb.ResponseProtocol)
   385  	if !ok {
   386  		if req, ok := msg.ServerReqHead().(*trpcpb.RequestProtocol); ok {
   387  			rsp = newResponseProtocol(req)
   388  		} else {
   389  			rsp = &trpcpb.ResponseProtocol{}
   390  		}
   391  	}
   392  
   393  	// update serialization and compression type
   394  	rsp.ContentType = uint32(msg.SerializationType())
   395  	rsp.ContentEncoding = uint32(msg.CompressType())
   396  
   397  	// convert error returned by server handler to ret code in response protocol head
   398  	if err := msg.ServerRspErr(); err != nil {
   399  		rsp.ErrorMsg = []byte(err.Msg)
   400  		if err.Type == errs.ErrorTypeFramework {
   401  			rsp.Ret = int32(err.Code)
   402  		} else {
   403  			rsp.FuncRet = int32(err.Code)
   404  		}
   405  	}
   406  
   407  	if len(msg.ServerMetaData()) > 0 {
   408  		if rsp.TransInfo == nil {
   409  			rsp.TransInfo = make(map[string][]byte)
   410  		}
   411  		for k, v := range msg.ServerMetaData() {
   412  			rsp.TransInfo[k] = v
   413  		}
   414  	}
   415  
   416  	return rsp
   417  }
   418  
   419  func newResponseProtocol(req *trpcpb.RequestProtocol) *trpcpb.ResponseProtocol {
   420  	return &trpcpb.ResponseProtocol{
   421  		Version:         uint32(trpcpb.TrpcProtoVersion_TRPC_PROTO_V1),
   422  		CallType:        req.CallType,
   423  		RequestId:       req.RequestId,
   424  		MessageType:     req.MessageType,
   425  		ContentType:     req.ContentType,
   426  		ContentEncoding: req.ContentEncoding,
   427  	}
   428  }
   429  
   430  // handleEncodeErr handles encode err and returns RetServerEncodeFail.
   431  func handleEncodeErr(
   432  	rsp *trpcpb.ResponseProtocol,
   433  	frameHead *FrameHead,
   434  	rspBody []byte,
   435  	encodeErr error,
   436  ) ([]byte, error) {
   437  	// discard all TransInfo and return RetServerEncodeFail
   438  	// cover the original no matter what
   439  	rsp.TransInfo = nil
   440  	rsp.Ret = int32(errs.RetServerEncodeFail)
   441  	rsp.ErrorMsg = []byte(encodeErr.Error())
   442  	rspHead, err := proto.Marshal(rsp)
   443  	if err != nil {
   444  		return nil, err
   445  	}
   446  	// if error still occurs, response will be discarded.
   447  	// client will be notified as conn closed
   448  	return frameHead.construct(rspHead, rspBody, nil)
   449  }
   450  
   451  // ClientCodec is an implementation of codec.Codec.
   452  // Used for trpc clientside codec.
   453  type ClientCodec struct {
   454  	streamCodec   *ClientStreamCodec
   455  	defaultCaller string // trpc.app.server.service
   456  	requestID     uint32 // global unique request id
   457  }
   458  
   459  // Encode implements codec.Codec.
   460  // It encodes reqBody into binary data. New msg will be cloned by client stub.
   461  func (c *ClientCodec) Encode(msg codec.Msg, reqBody []byte) (reqBuf []byte, err error) {
   462  	frameHead := loadOrStoreDefaultUnaryFrameHead(msg)
   463  	if frameHead.isStream() {
   464  		return c.streamCodec.Encode(msg, reqBody)
   465  	}
   466  	if !frameHead.isUnary() {
   467  		return nil, errUnknownFrameType
   468  	}
   469  
   470  	// create a new framehead without modifying the original one
   471  	// to avoid overwriting the requestID of the original framehead.
   472  	frameHead = newDefaultUnaryFrameHead()
   473  	req, err := loadOrStoreDefaultRequestProtocol(msg)
   474  	if err != nil {
   475  		return nil, err
   476  	}
   477  
   478  	// request id atomically increases by 1, ensuring that each request id is unique.
   479  	requestID := atomic.AddUint32(&c.requestID, 1)
   480  	frameHead.upgradeProtocol(curProtocolVersion, requestID)
   481  	msg.WithRequestID(requestID)
   482  
   483  	var attm []byte
   484  	if a, ok := attachment.ClientRequestAttachment(msg); ok {
   485  		if attm, err = io.ReadAll(a); err != nil {
   486  			return nil, fmt.Errorf("encoding attachment: %w", err)
   487  		}
   488  	}
   489  	req.AttachmentSize = uint32(len(attm))
   490  
   491  	updateRequestProtocol(req, updateCallerServiceName(msg, c.defaultCaller))
   492  
   493  	reqHead, err := proto.Marshal(req)
   494  	if err != nil {
   495  		return nil, err
   496  	}
   497  	return frameHead.construct(reqHead, reqBody, attm)
   498  }
   499  
   500  // loadOrStoreDefaultRequestProtocol loads the existing RequestProtocol from msg if present.
   501  // Otherwise, it stores default UnaryRequestProtocol created to msg and returns the default RequestProtocol.
   502  func loadOrStoreDefaultRequestProtocol(msg codec.Msg) (*trpcpb.RequestProtocol, error) {
   503  	if req := msg.ClientReqHead(); req != nil {
   504  		// client req head not being nil means it's created on purpose and set to
   505  		// record request protocol head
   506  		req, ok := req.(*trpcpb.RequestProtocol)
   507  		if !ok {
   508  			return nil, errors.New("client encode req head type invalid, must be trpc request protocol head")
   509  		}
   510  		return req, nil
   511  	}
   512  
   513  	req := newDefaultUnaryRequestProtocol()
   514  	msg.WithClientReqHead(req)
   515  	return req, nil
   516  }
   517  
   518  func newDefaultUnaryRequestProtocol() *trpcpb.RequestProtocol {
   519  	return &trpcpb.RequestProtocol{
   520  		Version:  uint32(trpcpb.TrpcProtoVersion_TRPC_PROTO_V1),
   521  		CallType: uint32(trpcpb.TrpcCallType_TRPC_UNARY_CALL),
   522  	}
   523  }
   524  
   525  // update updates CallerServiceName of msg with name
   526  func updateCallerServiceName(msg codec.Msg, name string) codec.Msg {
   527  	if msg.CallerServiceName() == "" {
   528  		msg.WithCallerServiceName(name)
   529  	}
   530  	return msg
   531  }
   532  
   533  // update updates req with requestID and  msg.
   534  func updateRequestProtocol(req *trpcpb.RequestProtocol, msg codec.Msg) {
   535  	req.RequestId = msg.RequestID()
   536  	req.Caller = []byte(msg.CallerServiceName())
   537  	// set callee service name
   538  	req.Callee = []byte(msg.CalleeServiceName())
   539  	// set backend rpc name
   540  	req.Func = []byte(msg.ClientRPCName())
   541  	// set backend serialization type
   542  	req.ContentType = uint32(msg.SerializationType())
   543  	// set backend compression type
   544  	req.ContentEncoding = uint32(msg.CompressType())
   545  	// set rest timeout for downstream
   546  	req.Timeout = uint32(msg.RequestTimeout() / time.Millisecond)
   547  	// set dyeing info
   548  	if msg.Dyeing() {
   549  		req.MessageType = req.MessageType | uint32(trpcpb.TrpcMessageType_TRPC_DYEING_MESSAGE)
   550  	}
   551  	// set client transinfo
   552  	req.TransInfo = setClientTransInfo(msg, req.TransInfo)
   553  	// set call type
   554  	req.CallType = uint32(msg.CallType())
   555  }
   556  
   557  // setClientTransInfo sets client TransInfo.
   558  func setClientTransInfo(msg codec.Msg, trans map[string][]byte) map[string][]byte {
   559  	// set MetaData
   560  	if len(msg.ClientMetaData()) > 0 {
   561  		if trans == nil {
   562  			trans = make(map[string][]byte)
   563  		}
   564  		for k, v := range msg.ClientMetaData() {
   565  			trans[k] = v
   566  		}
   567  	}
   568  	if len(msg.DyeingKey()) > 0 {
   569  		if trans == nil {
   570  			trans = make(map[string][]byte)
   571  		}
   572  		trans[DyeingKey] = []byte(msg.DyeingKey())
   573  	}
   574  	if len(msg.EnvTransfer()) > 0 {
   575  		if trans == nil {
   576  			trans = make(map[string][]byte)
   577  		}
   578  		trans[EnvTransfer] = []byte(msg.EnvTransfer())
   579  	} else {
   580  		// if msg.EnvTransfer() empty, transmitted env info in req.TransInfo should be cleared
   581  		if _, ok := trans[EnvTransfer]; ok {
   582  			trans[EnvTransfer] = nil
   583  		}
   584  	}
   585  	return trans
   586  }
   587  
   588  // Decode implements codec.Codec.
   589  // It decodes rspBuf into rspBody.
   590  func (c *ClientCodec) Decode(msg codec.Msg, rspBuf []byte) (rspBody []byte, err error) {
   591  	if len(rspBuf) < int(frameHeadLen) {
   592  		return nil, errors.New("client decode rsp buf len invalid")
   593  	}
   594  	frameHead := newDefaultUnaryFrameHead()
   595  	frameHead.extract(rspBuf)
   596  	msg.WithFrameHead(frameHead)
   597  	if frameHead.TotalLen != uint32(len(rspBuf)) {
   598  		return nil, fmt.Errorf("total len %d is not actual buf len %d", frameHead.TotalLen, len(rspBuf))
   599  	}
   600  	if trpcpb.TrpcDataFrameType(frameHead.FrameType) != trpcpb.TrpcDataFrameType_TRPC_UNARY_FRAME {
   601  		return c.streamCodec.Decode(msg, rspBuf)
   602  	}
   603  	if frameHead.HeaderLen == 0 {
   604  		return nil, errors.New("client decode pb head len empty")
   605  	}
   606  
   607  	responseProtocolBegin := uint32(frameHeadLen)
   608  	responseProtocolEnd := responseProtocolBegin + uint32(frameHead.HeaderLen)
   609  	if responseProtocolEnd > uint32(len(rspBuf)) {
   610  		return nil, errors.New("client decode pb head len invalid")
   611  	}
   612  	rsp, err := loadOrStoreResponseHead(msg)
   613  	if err != nil {
   614  		return nil, err
   615  	}
   616  	if err := proto.Unmarshal(rspBuf[responseProtocolBegin:responseProtocolEnd], rsp); err != nil {
   617  		return nil, err
   618  	}
   619  
   620  	attachmentBegin := frameHead.TotalLen - rsp.AttachmentSize
   621  	if s := uint32(len(rspBuf)) - attachmentBegin; rsp.AttachmentSize != s {
   622  		return nil, fmt.Errorf("decoding attachment:(%d) len of attachment"+
   623  			"isn't equal to expected AttachmentSize(%d)", s, rsp.AttachmentSize)
   624  	}
   625  	if err := updateMsg(msg, frameHead, rsp, rspBuf[attachmentBegin:]); err != nil {
   626  		return nil, err
   627  	}
   628  
   629  	bodyBegin, bodyEnd := responseProtocolEnd, attachmentBegin
   630  	return rspBuf[bodyBegin:bodyEnd], nil
   631  }
   632  
   633  func loadOrStoreResponseHead(msg codec.Msg) (*trpcpb.ResponseProtocol, error) {
   634  	// client rsp head being nil means no need to record backend response protocol head
   635  	// most of the time, response head is not set and should be created here.
   636  	rsp := msg.ClientRspHead()
   637  	if rsp == nil {
   638  		rsp := &trpcpb.ResponseProtocol{}
   639  		msg.WithClientRspHead(rsp)
   640  		return rsp, nil
   641  	}
   642  
   643  	// client rsp head not being nil means it's created on purpose and set to
   644  	// record response protocol head
   645  	{
   646  		rsp, ok := rsp.(*trpcpb.ResponseProtocol)
   647  		if !ok {
   648  			return nil, errors.New("client decode rsp head type invalid, must be trpc response protocol head")
   649  		}
   650  		return rsp, nil
   651  	}
   652  }
   653  
   654  // loadOrStoreDefaultUnaryFrameHead loads the existing frameHead from msg if present.
   655  // Otherwise, it stores default Unary FrameHead to msg, and returns the default Unary FrameHead.
   656  func loadOrStoreDefaultUnaryFrameHead(msg codec.Msg) *FrameHead {
   657  	frameHead, ok := msg.FrameHead().(*FrameHead)
   658  	if !ok {
   659  		frameHead = newDefaultUnaryFrameHead()
   660  		msg.WithFrameHead(frameHead)
   661  	}
   662  	return frameHead
   663  }
   664  
   665  func updateMsg(msg codec.Msg, frameHead *FrameHead, rsp *trpcpb.ResponseProtocol, attm []byte) error {
   666  	msg.WithFrameHead(frameHead)
   667  	msg.WithCompressType(int(rsp.GetContentEncoding()))
   668  	msg.WithSerializationType(int(rsp.GetContentType()))
   669  
   670  	// reset client metadata if new transinfo is returned with response
   671  	if len(rsp.TransInfo) > 0 {
   672  		md := msg.ClientMetaData()
   673  		if len(md) == 0 {
   674  			md = codec.MetaData{}
   675  		}
   676  		for k, v := range rsp.TransInfo {
   677  			md[k] = v
   678  		}
   679  		msg.WithClientMetaData(md)
   680  	}
   681  
   682  	// if retcode is not 0, a converted error should be returned
   683  	if rsp.GetRet() != 0 {
   684  		err := &errs.Error{
   685  			Type: errs.ErrorTypeCalleeFramework,
   686  			Code: trpcpb.TrpcRetCode(rsp.GetRet()),
   687  			Desc: ProtocolName,
   688  			Msg:  string(rsp.GetErrorMsg()),
   689  		}
   690  		msg.WithClientRspErr(err)
   691  	} else if rsp.GetFuncRet() != 0 {
   692  		msg.WithClientRspErr(errs.New(int(rsp.GetFuncRet()), string(rsp.GetErrorMsg())))
   693  	}
   694  
   695  	// error should be returned immediately for request id mismatch
   696  	req, err := loadOrStoreDefaultRequestProtocol(msg)
   697  	if err == nil && rsp.RequestId != req.RequestId {
   698  		return fmt.Errorf("rsp request_id %d different from req request_id %d", rsp.RequestId, req.RequestId)
   699  	}
   700  
   701  	// handle protocol upgrading
   702  	frameHead.upgradeProtocol(curProtocolVersion, rsp.RequestId)
   703  	msg.WithRequestID(rsp.RequestId)
   704  
   705  	if len(attm) != 0 {
   706  		attachment.SetClientResponseAttachment(msg, attm)
   707  	}
   708  	return nil
   709  }