// recvResponse receives and parses an RPC response. // On error, it returns the error and indicates whether the call should be retried. // // TODO(zhaoq): Check whether the received message sequence is valid. func recvResponse(dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) error { // Try to acquire header metadata from the server if there is any. var err error defer func() { if err != nil { if _, ok := err.(transport.ConnectionError); !ok { t.CloseStream(stream, err) } } }() c.headerMD, err = stream.Header() if err != nil { return err } p := &parser{r: stream} for { if err = recv(p, dopts.codec, stream, dopts.dc, reply, math.MaxInt32); err != nil { if err == io.EOF { break } return err } } c.trailerMD = stream.Trailer() return nil }
// recvResponse receives and parses an RPC response. // On error, it returns the error and indicates whether the call should be retried. // // TODO(zhaoq): Check whether the received message sequence is valid. func recvResponse(dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) error { // Try to acquire header metadata from the server if there is any. // 如何接受请求呢? // 1. 和处理的Http请求类似, 首先是: 处理Header var err error c.headerMD, err = stream.Header() if err != nil { return err } // 2. 然后处理stream p := &parser{r: stream} for { // stream --> (parser) --> msg --> decompress --> unmarshal --> reply // Iter 1: 读取到Reply // Iter 2: 读取失败,碰到EOF if err = recv(p, dopts.codec, stream, dopts.dc, reply); err != nil { // 似乎需要等待stream的EOF if err == io.EOF { break } return err } } // 3. 获取Trailer? c.trailerMD = stream.Trailer() return nil }
// recvResponse receives and parses an RPC response. // On error, it returns the error and indicates whether the call should be retried. // // TODO(zhaoq): Check whether the received message sequence is valid. func recvResponse(dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) error { // Try to acquire header metadata from the server if there is any. var err error c.headerMD, err = stream.Header() if err != nil { return err } p := &parser{r: stream} for { if err = recv(p, dopts.codec, stream, dopts.dc, reply); err != nil { if err == io.EOF { break } return err } } c.trailerMD = stream.Trailer() return nil }
// recv receives and parses an RPC response. // On error, it returns the error and indicates whether the call should be retried. // // TODO(zhaoq): Check whether the received message sequence is valid. func recv(t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply proto.Message) error { // Try to acquire header metadata from the server if there is any. var err error c.headerMD, err = stream.Header() if err != nil { return err } p := &parser{s: stream} for { if err = recvProto(p, reply); err != nil { if err == io.EOF { break } return err } } c.trailerMD = stream.Trailer() return nil }
// recvResponse receives and parses an RPC response. // On error, it returns the error and indicates whether the call should be retried. // // TODO(zhaoq): Check whether the received message sequence is valid. // TODO ctx is used for stats collection and processing. It is the context passed from the application. func recvResponse(ctx context.Context, dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) (err error) { // Try to acquire header metadata from the server if there is any. defer func() { if err != nil { if _, ok := err.(transport.ConnectionError); !ok { t.CloseStream(stream, err) } } }() c.headerMD, err = stream.Header() if err != nil { return } p := &parser{r: stream} var inPayload *stats.InPayload if stats.On() { inPayload = &stats.InPayload{ Client: true, } } for { if err = recv(p, dopts.codec, stream, dopts.dc, reply, math.MaxInt32, inPayload); err != nil { if err == io.EOF { break } return } } if inPayload != nil && err == io.EOF && stream.StatusCode() == codes.OK { // TODO in the current implementation, inTrailer may be handled before inPayload in some cases. // Fix the order if necessary. stats.Handle(ctx, inPayload) } c.trailerMD = stream.Trailer() return nil }