func recvResponse(ctx context.Context, dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) (err error) {
	defer func() {
		if err != nil {
			if _, ok := err.(transport.ConnectionError); !ok {
				t.CloseStream(stream, err)
			}
		}
	}()
	p := &parser{r: stream}
	var inPayload *stats.InPayload
	if dopts.copts.StatsHandler != nil {
		inPayload = &stats.InPayload{
			Client: true,
		}
	}
	for {
		if c.maxReceiveMessageSize == nil {
			return status.Errorf(codes.Internal, "callInfo maxReceiveMessageSize field uninitialized(nil)")
		}
		var comp encoding.Compressor
		var dc Decompressor
		if rc := stream.RecvCompress(); dopts.dc != nil && dopts.dc.Type() == rc {
			dc = dopts.dc
		} else if rc != "" && rc != encoding.Identity {
			comp = encoding.GetCompressor(rc)
		}
		if err = recv(p, dopts.codec, stream, dc, reply, *c.maxReceiveMessageSize, inPayload, comp); err != nil {
			if err == io.EOF {
				break
			}
			return
		}
	}
	if inPayload != nil && err == io.EOF && stream.Status().Code() == codes.OK {
		dopts.copts.StatsHandler.HandleRPC(ctx, inPayload)
	}
	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.
package grpc
import (
	"io"
	"time"
	"golang.org/x/net/context"
	"golang.org/x/net/trace"
	"google.golang.org/grpc/balancer"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/encoding"
	"google.golang.org/grpc/stats"
	"google.golang.org/grpc/status"
	"google.golang.org/grpc/transport"
)