github.com/cloudwego/kitex@v0.9.0/pkg/remote/trans/default_client_handler.go (about)

     1  /*
     2   * Copyright 2021 CloudWeGo Authors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package trans
    18  
    19  import (
    20  	"context"
    21  	"net"
    22  
    23  	"github.com/cloudwego/kitex/pkg/kerrors"
    24  	"github.com/cloudwego/kitex/pkg/klog"
    25  	"github.com/cloudwego/kitex/pkg/remote"
    26  	"github.com/cloudwego/kitex/pkg/rpcinfo"
    27  	"github.com/cloudwego/kitex/pkg/stats"
    28  )
    29  
    30  // NewDefaultCliTransHandler to provide default impl of cliTransHandler, it can be reused in netpoll, shm-ipc, framework-sdk extensions
    31  func NewDefaultCliTransHandler(opt *remote.ClientOption, ext Extension) (remote.ClientTransHandler, error) {
    32  	return &cliTransHandler{
    33  		opt:   opt,
    34  		codec: opt.Codec,
    35  		ext:   ext,
    36  	}, nil
    37  }
    38  
    39  type cliTransHandler struct {
    40  	opt       *remote.ClientOption
    41  	codec     remote.Codec
    42  	transPipe *remote.TransPipeline
    43  	ext       Extension
    44  }
    45  
    46  // Write implements the remote.ClientTransHandler interface.
    47  func (t *cliTransHandler) Write(ctx context.Context, conn net.Conn, sendMsg remote.Message) (nctx context.Context, err error) {
    48  	var bufWriter remote.ByteBuffer
    49  	rpcinfo.Record(ctx, sendMsg.RPCInfo(), stats.WriteStart, nil)
    50  	defer func() {
    51  		t.ext.ReleaseBuffer(bufWriter, err)
    52  		rpcinfo.Record(ctx, sendMsg.RPCInfo(), stats.WriteFinish, err)
    53  	}()
    54  
    55  	bufWriter = t.ext.NewWriteByteBuffer(ctx, conn, sendMsg)
    56  	sendMsg.SetPayloadCodec(t.opt.PayloadCodec)
    57  	err = t.codec.Encode(ctx, sendMsg, bufWriter)
    58  	if err != nil {
    59  		return ctx, err
    60  	}
    61  	return ctx, bufWriter.Flush()
    62  }
    63  
    64  // Read implements the remote.ClientTransHandler interface.
    65  func (t *cliTransHandler) Read(ctx context.Context, conn net.Conn, recvMsg remote.Message) (nctx context.Context, err error) {
    66  	var bufReader remote.ByteBuffer
    67  	rpcinfo.Record(ctx, recvMsg.RPCInfo(), stats.ReadStart, nil)
    68  	defer func() {
    69  		t.ext.ReleaseBuffer(bufReader, err)
    70  		rpcinfo.Record(ctx, recvMsg.RPCInfo(), stats.ReadFinish, err)
    71  	}()
    72  
    73  	t.ext.SetReadTimeout(ctx, conn, recvMsg.RPCInfo().Config(), recvMsg.RPCRole())
    74  	bufReader = t.ext.NewReadByteBuffer(ctx, conn, recvMsg)
    75  	recvMsg.SetPayloadCodec(t.opt.PayloadCodec)
    76  	err = t.codec.Decode(ctx, recvMsg, bufReader)
    77  	if err != nil {
    78  		if t.ext.IsTimeoutErr(err) {
    79  			err = kerrors.ErrRPCTimeout.WithCause(err)
    80  		}
    81  		return ctx, err
    82  	}
    83  
    84  	return ctx, nil
    85  }
    86  
    87  // OnMessage implements the remote.ClientTransHandler interface.
    88  func (t *cliTransHandler) OnMessage(ctx context.Context, args, result remote.Message) (context.Context, error) {
    89  	// do nothing
    90  	return ctx, nil
    91  }
    92  
    93  // OnInactive implements the remote.ClientTransHandler interface.
    94  func (t *cliTransHandler) OnInactive(ctx context.Context, conn net.Conn) {
    95  	// ineffective now and do nothing
    96  }
    97  
    98  // OnError implements the remote.ClientTransHandler interface.
    99  func (t *cliTransHandler) OnError(ctx context.Context, err error, conn net.Conn) {
   100  	if pe, ok := err.(*kerrors.DetailedError); ok {
   101  		klog.CtxErrorf(ctx, "KITEX: send request error, remote=%s, error=%s\nstack=%s", conn.RemoteAddr(), err.Error(), pe.Stack())
   102  	} else {
   103  		klog.CtxErrorf(ctx, "KITEX: send request error, remote=%s, error=%s", conn.RemoteAddr(), err.Error())
   104  	}
   105  }
   106  
   107  // SetPipeline implements the remote.ClientTransHandler interface.
   108  func (t *cliTransHandler) SetPipeline(p *remote.TransPipeline) {
   109  	t.transPipe = p
   110  }